1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/compiler/ast-graph-builder.h" 6 7#include "src/compiler.h" 8#include "src/compiler/control-builders.h" 9#include "src/compiler/machine-operator.h" 10#include "src/compiler/node-properties.h" 11#include "src/compiler/node-properties-inl.h" 12#include "src/full-codegen.h" 13#include "src/parser.h" 14#include "src/scopes.h" 15 16namespace v8 { 17namespace internal { 18namespace compiler { 19 20AstGraphBuilder::AstGraphBuilder(CompilationInfo* info, JSGraph* jsgraph) 21 : StructuredGraphBuilder(jsgraph->graph(), jsgraph->common()), 22 info_(info), 23 jsgraph_(jsgraph), 24 globals_(0, info->zone()), 25 breakable_(NULL), 26 execution_context_(NULL) { 27 InitializeAstVisitor(info->zone()); 28} 29 30 31Node* AstGraphBuilder::GetFunctionClosure() { 32 if (!function_closure_.is_set()) { 33 // Parameter -1 is special for the function closure 34 const Operator* op = common()->Parameter(-1); 35 Node* node = NewNode(op, graph()->start()); 36 function_closure_.set(node); 37 } 38 return function_closure_.get(); 39} 40 41 42Node* AstGraphBuilder::GetFunctionContext() { 43 if (!function_context_.is_set()) { 44 // Parameter (arity + 1) is special for the outer context of the function 45 const Operator* op = common()->Parameter(info()->num_parameters() + 1); 46 Node* node = NewNode(op, graph()->start()); 47 function_context_.set(node); 48 } 49 return function_context_.get(); 50} 51 52 53bool AstGraphBuilder::CreateGraph() { 54 Scope* scope = info()->scope(); 55 DCHECK(graph() != NULL); 56 57 // Set up the basic structure of the graph. 58 int parameter_count = info()->num_parameters(); 59 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); 60 61 // Initialize the top-level environment. 62 Environment env(this, scope, graph()->start()); 63 set_environment(&env); 64 65 // Build node to initialize local function context. 66 Node* closure = GetFunctionClosure(); 67 Node* outer = GetFunctionContext(); 68 Node* inner = BuildLocalFunctionContext(outer, closure); 69 70 // Push top-level function scope for the function body. 71 ContextScope top_context(this, scope, inner); 72 73 // Build the arguments object if it is used. 74 BuildArgumentsObject(scope->arguments()); 75 76 // Emit tracing call if requested to do so. 77 if (FLAG_trace) { 78 NewNode(javascript()->Runtime(Runtime::kTraceEnter, 0)); 79 } 80 81 // Visit implicit declaration of the function name. 82 if (scope->is_function_scope() && scope->function() != NULL) { 83 VisitVariableDeclaration(scope->function()); 84 } 85 86 // Visit declarations within the function scope. 87 VisitDeclarations(scope->declarations()); 88 89 // TODO(mstarzinger): This should do an inlined stack check. 90 Node* node = NewNode(javascript()->Runtime(Runtime::kStackGuard, 0)); 91 PrepareFrameState(node, BailoutId::FunctionEntry()); 92 93 // Visit statements in the function body. 94 VisitStatements(info()->function()->body()); 95 if (HasStackOverflow()) return false; 96 97 // Emit tracing call if requested to do so. 98 if (FLAG_trace) { 99 // TODO(mstarzinger): Only traces implicit return. 100 Node* return_value = jsgraph()->UndefinedConstant(); 101 NewNode(javascript()->Runtime(Runtime::kTraceExit, 1), return_value); 102 } 103 104 // Return 'undefined' in case we can fall off the end. 105 Node* control = NewNode(common()->Return(), jsgraph()->UndefinedConstant()); 106 UpdateControlDependencyToLeaveFunction(control); 107 108 // Finish the basic structure of the graph. 109 environment()->UpdateControlDependency(exit_control()); 110 graph()->SetEnd(NewNode(common()->End())); 111 112 return true; 113} 114 115 116// Left-hand side can only be a property, a global or a variable slot. 117enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 118 119 120// Determine the left-hand side kind of an assignment. 121static LhsKind DetermineLhsKind(Expression* expr) { 122 Property* property = expr->AsProperty(); 123 DCHECK(expr->IsValidReferenceExpression()); 124 LhsKind lhs_kind = 125 (property == NULL) ? VARIABLE : (property->key()->IsPropertyName()) 126 ? NAMED_PROPERTY 127 : KEYED_PROPERTY; 128 return lhs_kind; 129} 130 131 132// Helper to find an existing shared function info in the baseline code for the 133// given function literal. Used to canonicalize SharedFunctionInfo objects. 134static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( 135 Code* unoptimized_code, FunctionLiteral* expr) { 136 int start_position = expr->start_position(); 137 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) { 138 RelocInfo* rinfo = it.rinfo(); 139 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; 140 Object* obj = rinfo->target_object(); 141 if (obj->IsSharedFunctionInfo()) { 142 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); 143 if (shared->start_position() == start_position) { 144 return Handle<SharedFunctionInfo>(shared); 145 } 146 } 147 } 148 return Handle<SharedFunctionInfo>(); 149} 150 151 152StructuredGraphBuilder::Environment* AstGraphBuilder::CopyEnvironment( 153 StructuredGraphBuilder::Environment* env) { 154 return new (zone()) Environment(*reinterpret_cast<Environment*>(env)); 155} 156 157 158AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder, 159 Scope* scope, 160 Node* control_dependency) 161 : StructuredGraphBuilder::Environment(builder, control_dependency), 162 parameters_count_(scope->num_parameters() + 1), 163 locals_count_(scope->num_stack_slots()), 164 parameters_node_(NULL), 165 locals_node_(NULL), 166 stack_node_(NULL) { 167 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); 168 169 // Bind the receiver variable. 170 Node* receiver = builder->graph()->NewNode(common()->Parameter(0), 171 builder->graph()->start()); 172 values()->push_back(receiver); 173 174 // Bind all parameter variables. The parameter indices are shifted by 1 175 // (receiver is parameter index -1 but environment index 0). 176 for (int i = 0; i < scope->num_parameters(); ++i) { 177 Node* parameter = builder->graph()->NewNode(common()->Parameter(i + 1), 178 builder->graph()->start()); 179 values()->push_back(parameter); 180 } 181 182 // Bind all local variables to undefined. 183 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); 184 values()->insert(values()->end(), locals_count(), undefined_constant); 185} 186 187 188AstGraphBuilder::Environment::Environment(const Environment& copy) 189 : StructuredGraphBuilder::Environment( 190 static_cast<StructuredGraphBuilder::Environment>(copy)), 191 parameters_count_(copy.parameters_count_), 192 locals_count_(copy.locals_count_), 193 parameters_node_(copy.parameters_node_), 194 locals_node_(copy.locals_node_), 195 stack_node_(copy.stack_node_) {} 196 197 198void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values, 199 int offset, int count) { 200 bool should_update = false; 201 Node** env_values = (count == 0) ? NULL : &values()->at(offset); 202 if (*state_values == NULL || (*state_values)->InputCount() != count) { 203 should_update = true; 204 } else { 205 DCHECK(static_cast<size_t>(offset + count) <= values()->size()); 206 for (int i = 0; i < count; i++) { 207 if ((*state_values)->InputAt(i) != env_values[i]) { 208 should_update = true; 209 break; 210 } 211 } 212 } 213 if (should_update) { 214 const Operator* op = common()->StateValues(count); 215 (*state_values) = graph()->NewNode(op, count, env_values); 216 } 217} 218 219 220Node* AstGraphBuilder::Environment::Checkpoint( 221 BailoutId ast_id, OutputFrameStateCombine combine) { 222 UpdateStateValues(¶meters_node_, 0, parameters_count()); 223 UpdateStateValues(&locals_node_, parameters_count(), locals_count()); 224 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), 225 stack_height()); 226 227 const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine); 228 229 return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_, 230 GetContext(), 231 builder()->jsgraph()->UndefinedConstant()); 232} 233 234 235AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, 236 Expression::Context kind) 237 : kind_(kind), owner_(own), outer_(own->ast_context()) { 238 owner()->set_ast_context(this); // Push. 239#ifdef DEBUG 240 original_height_ = environment()->stack_height(); 241#endif 242} 243 244 245AstGraphBuilder::AstContext::~AstContext() { 246 owner()->set_ast_context(outer_); // Pop. 247} 248 249 250AstGraphBuilder::AstEffectContext::~AstEffectContext() { 251 DCHECK(environment()->stack_height() == original_height_); 252} 253 254 255AstGraphBuilder::AstValueContext::~AstValueContext() { 256 DCHECK(environment()->stack_height() == original_height_ + 1); 257} 258 259 260AstGraphBuilder::AstTestContext::~AstTestContext() { 261 DCHECK(environment()->stack_height() == original_height_ + 1); 262} 263 264 265void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) { 266 // The value is ignored. 267} 268 269 270void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) { 271 environment()->Push(value); 272} 273 274 275void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) { 276 environment()->Push(owner()->BuildToBoolean(value)); 277} 278 279 280Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return NULL; } 281 282 283Node* AstGraphBuilder::AstValueContext::ConsumeValue() { 284 return environment()->Pop(); 285} 286 287 288Node* AstGraphBuilder::AstTestContext::ConsumeValue() { 289 return environment()->Pop(); 290} 291 292 293AstGraphBuilder::BreakableScope* AstGraphBuilder::BreakableScope::FindBreakable( 294 BreakableStatement* target) { 295 BreakableScope* current = this; 296 while (current != NULL && current->target_ != target) { 297 owner_->environment()->Drop(current->drop_extra_); 298 current = current->next_; 299 } 300 DCHECK(current != NULL); // Always found (unless stack is malformed). 301 return current; 302} 303 304 305void AstGraphBuilder::BreakableScope::BreakTarget(BreakableStatement* stmt) { 306 FindBreakable(stmt)->control_->Break(); 307} 308 309 310void AstGraphBuilder::BreakableScope::ContinueTarget(BreakableStatement* stmt) { 311 FindBreakable(stmt)->control_->Continue(); 312} 313 314 315void AstGraphBuilder::VisitForValueOrNull(Expression* expr) { 316 if (expr == NULL) { 317 return environment()->Push(jsgraph()->NullConstant()); 318 } 319 VisitForValue(expr); 320} 321 322 323void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) { 324 for (int i = 0; i < exprs->length(); ++i) { 325 VisitForValue(exprs->at(i)); 326 } 327} 328 329 330void AstGraphBuilder::VisitForValue(Expression* expr) { 331 AstValueContext for_value(this); 332 if (!HasStackOverflow()) { 333 expr->Accept(this); 334 } 335} 336 337 338void AstGraphBuilder::VisitForEffect(Expression* expr) { 339 AstEffectContext for_effect(this); 340 if (!HasStackOverflow()) { 341 expr->Accept(this); 342 } 343} 344 345 346void AstGraphBuilder::VisitForTest(Expression* expr) { 347 AstTestContext for_condition(this); 348 if (!HasStackOverflow()) { 349 expr->Accept(this); 350 } 351} 352 353 354void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { 355 Variable* variable = decl->proxy()->var(); 356 VariableMode mode = decl->mode(); 357 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; 358 switch (variable->location()) { 359 case Variable::UNALLOCATED: { 360 Handle<Oddball> value = variable->binding_needs_init() 361 ? isolate()->factory()->the_hole_value() 362 : isolate()->factory()->undefined_value(); 363 globals()->Add(variable->name(), zone()); 364 globals()->Add(value, zone()); 365 break; 366 } 367 case Variable::PARAMETER: 368 case Variable::LOCAL: 369 if (hole_init) { 370 Node* value = jsgraph()->TheHoleConstant(); 371 environment()->Bind(variable, value); 372 } 373 break; 374 case Variable::CONTEXT: 375 if (hole_init) { 376 Node* value = jsgraph()->TheHoleConstant(); 377 const Operator* op = javascript()->StoreContext(0, variable->index()); 378 NewNode(op, current_context(), value); 379 } 380 break; 381 case Variable::LOOKUP: 382 UNIMPLEMENTED(); 383 } 384} 385 386 387void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { 388 Variable* variable = decl->proxy()->var(); 389 switch (variable->location()) { 390 case Variable::UNALLOCATED: { 391 Handle<SharedFunctionInfo> function = 392 Compiler::BuildFunctionInfo(decl->fun(), info()->script(), info()); 393 // Check for stack-overflow exception. 394 if (function.is_null()) return SetStackOverflow(); 395 globals()->Add(variable->name(), zone()); 396 globals()->Add(function, zone()); 397 break; 398 } 399 case Variable::PARAMETER: 400 case Variable::LOCAL: { 401 VisitForValue(decl->fun()); 402 Node* value = environment()->Pop(); 403 environment()->Bind(variable, value); 404 break; 405 } 406 case Variable::CONTEXT: { 407 VisitForValue(decl->fun()); 408 Node* value = environment()->Pop(); 409 const Operator* op = javascript()->StoreContext(0, variable->index()); 410 NewNode(op, current_context(), value); 411 break; 412 } 413 case Variable::LOOKUP: 414 UNIMPLEMENTED(); 415 } 416} 417 418 419void AstGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) { 420 UNREACHABLE(); 421} 422 423 424void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) { 425 UNREACHABLE(); 426} 427 428 429void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) { 430 UNREACHABLE(); 431} 432 433 434void AstGraphBuilder::VisitModuleLiteral(ModuleLiteral* modl) { UNREACHABLE(); } 435 436 437void AstGraphBuilder::VisitModuleVariable(ModuleVariable* modl) { 438 UNREACHABLE(); 439} 440 441 442void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); } 443 444 445void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); } 446 447 448void AstGraphBuilder::VisitBlock(Block* stmt) { 449 BlockBuilder block(this); 450 BreakableScope scope(this, stmt, &block, 0); 451 if (stmt->labels() != NULL) block.BeginBlock(); 452 if (stmt->scope() == NULL) { 453 // Visit statements in the same scope, no declarations. 454 VisitStatements(stmt->statements()); 455 } else { 456 const Operator* op = javascript()->CreateBlockContext(); 457 Node* scope_info = jsgraph()->Constant(stmt->scope()->GetScopeInfo()); 458 Node* context = NewNode(op, scope_info, GetFunctionClosure()); 459 ContextScope scope(this, stmt->scope(), context); 460 461 // Visit declarations and statements in a block scope. 462 VisitDeclarations(stmt->scope()->declarations()); 463 VisitStatements(stmt->statements()); 464 } 465 if (stmt->labels() != NULL) block.EndBlock(); 466} 467 468 469void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { 470 UNREACHABLE(); 471} 472 473 474void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { 475 VisitForEffect(stmt->expression()); 476} 477 478 479void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { 480 // Do nothing. 481} 482 483 484void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) { 485 IfBuilder compare_if(this); 486 VisitForTest(stmt->condition()); 487 Node* condition = environment()->Pop(); 488 compare_if.If(condition); 489 compare_if.Then(); 490 Visit(stmt->then_statement()); 491 compare_if.Else(); 492 Visit(stmt->else_statement()); 493 compare_if.End(); 494} 495 496 497void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { 498 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); 499 breakable()->ContinueTarget(stmt->target()); 500 set_environment(env); 501} 502 503 504void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { 505 StructuredGraphBuilder::Environment* env = environment()->CopyAsUnreachable(); 506 breakable()->BreakTarget(stmt->target()); 507 set_environment(env); 508} 509 510 511void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 512 VisitForValue(stmt->expression()); 513 Node* result = environment()->Pop(); 514 Node* control = NewNode(common()->Return(), result); 515 UpdateControlDependencyToLeaveFunction(control); 516} 517 518 519void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) { 520 VisitForValue(stmt->expression()); 521 Node* value = environment()->Pop(); 522 const Operator* op = javascript()->CreateWithContext(); 523 Node* context = NewNode(op, value, GetFunctionClosure()); 524 ContextScope scope(this, stmt->scope(), context); 525 Visit(stmt->statement()); 526} 527 528 529void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 530 ZoneList<CaseClause*>* clauses = stmt->cases(); 531 SwitchBuilder compare_switch(this, clauses->length()); 532 BreakableScope scope(this, stmt, &compare_switch, 0); 533 compare_switch.BeginSwitch(); 534 int default_index = -1; 535 536 // Keep the switch value on the stack until a case matches. 537 VisitForValue(stmt->tag()); 538 Node* tag = environment()->Top(); 539 540 // Iterate over all cases and create nodes for label comparison. 541 for (int i = 0; i < clauses->length(); i++) { 542 CaseClause* clause = clauses->at(i); 543 544 // The default is not a test, remember index. 545 if (clause->is_default()) { 546 default_index = i; 547 continue; 548 } 549 550 // Create nodes to perform label comparison as if via '==='. The switch 551 // value is still on the operand stack while the label is evaluated. 552 VisitForValue(clause->label()); 553 Node* label = environment()->Pop(); 554 const Operator* op = javascript()->StrictEqual(); 555 Node* condition = NewNode(op, tag, label); 556 compare_switch.BeginLabel(i, condition); 557 558 // Discard the switch value at label match. 559 environment()->Pop(); 560 compare_switch.EndLabel(); 561 } 562 563 // Discard the switch value and mark the default case. 564 environment()->Pop(); 565 if (default_index >= 0) { 566 compare_switch.DefaultAt(default_index); 567 } 568 569 // Iterate over all cases and create nodes for case bodies. 570 for (int i = 0; i < clauses->length(); i++) { 571 CaseClause* clause = clauses->at(i); 572 compare_switch.BeginCase(i); 573 VisitStatements(clause->statements()); 574 compare_switch.EndCase(); 575 } 576 577 compare_switch.EndSwitch(); 578} 579 580 581void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 582 LoopBuilder while_loop(this); 583 while_loop.BeginLoop(); 584 VisitIterationBody(stmt, &while_loop, 0); 585 while_loop.EndBody(); 586 VisitForTest(stmt->cond()); 587 Node* condition = environment()->Pop(); 588 while_loop.BreakUnless(condition); 589 while_loop.EndLoop(); 590} 591 592 593void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 594 LoopBuilder while_loop(this); 595 while_loop.BeginLoop(); 596 VisitForTest(stmt->cond()); 597 Node* condition = environment()->Pop(); 598 while_loop.BreakUnless(condition); 599 VisitIterationBody(stmt, &while_loop, 0); 600 while_loop.EndBody(); 601 while_loop.EndLoop(); 602} 603 604 605void AstGraphBuilder::VisitForStatement(ForStatement* stmt) { 606 LoopBuilder for_loop(this); 607 VisitIfNotNull(stmt->init()); 608 for_loop.BeginLoop(); 609 if (stmt->cond() != NULL) { 610 VisitForTest(stmt->cond()); 611 Node* condition = environment()->Pop(); 612 for_loop.BreakUnless(condition); 613 } 614 VisitIterationBody(stmt, &for_loop, 0); 615 for_loop.EndBody(); 616 VisitIfNotNull(stmt->next()); 617 for_loop.EndLoop(); 618} 619 620 621// TODO(dcarney): this is a big function. Try to clean up some. 622void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { 623 VisitForValue(stmt->subject()); 624 Node* obj = environment()->Pop(); 625 // Check for undefined or null before entering loop. 626 IfBuilder is_undefined(this); 627 Node* is_undefined_cond = 628 NewNode(javascript()->StrictEqual(), obj, jsgraph()->UndefinedConstant()); 629 is_undefined.If(is_undefined_cond); 630 is_undefined.Then(); 631 is_undefined.Else(); 632 { 633 IfBuilder is_null(this); 634 Node* is_null_cond = 635 NewNode(javascript()->StrictEqual(), obj, jsgraph()->NullConstant()); 636 is_null.If(is_null_cond); 637 is_null.Then(); 638 is_null.Else(); 639 // Convert object to jsobject. 640 // PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 641 obj = NewNode(javascript()->ToObject(), obj); 642 environment()->Push(obj); 643 // TODO(dcarney): should do a fast enum cache check here to skip runtime. 644 environment()->Push(obj); 645 Node* cache_type = ProcessArguments( 646 javascript()->Runtime(Runtime::kGetPropertyNamesFast, 1), 1); 647 // TODO(dcarney): these next runtime calls should be removed in favour of 648 // a few simplified instructions. 649 environment()->Push(obj); 650 environment()->Push(cache_type); 651 Node* cache_pair = 652 ProcessArguments(javascript()->Runtime(Runtime::kForInInit, 2), 2); 653 // cache_type may have been replaced. 654 Node* cache_array = NewNode(common()->Projection(0), cache_pair); 655 cache_type = NewNode(common()->Projection(1), cache_pair); 656 environment()->Push(cache_type); 657 environment()->Push(cache_array); 658 Node* cache_length = ProcessArguments( 659 javascript()->Runtime(Runtime::kForInCacheArrayLength, 2), 2); 660 { 661 // TODO(dcarney): this check is actually supposed to be for the 662 // empty enum case only. 663 IfBuilder have_no_properties(this); 664 Node* empty_array_cond = NewNode(javascript()->StrictEqual(), 665 cache_length, jsgraph()->ZeroConstant()); 666 have_no_properties.If(empty_array_cond); 667 have_no_properties.Then(); 668 // Pop obj and skip loop. 669 environment()->Pop(); 670 have_no_properties.Else(); 671 { 672 // Construct the rest of the environment. 673 environment()->Push(cache_type); 674 environment()->Push(cache_array); 675 environment()->Push(cache_length); 676 environment()->Push(jsgraph()->ZeroConstant()); 677 // PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 678 LoopBuilder for_loop(this); 679 for_loop.BeginLoop(); 680 // Check loop termination condition. 681 Node* index = environment()->Peek(0); 682 Node* exit_cond = 683 NewNode(javascript()->LessThan(), index, cache_length); 684 // TODO(jarin): provide real bailout id. 685 PrepareFrameState(exit_cond, BailoutId::None()); 686 for_loop.BreakUnless(exit_cond); 687 // TODO(dcarney): this runtime call should be a handful of 688 // simplified instructions that 689 // basically produce 690 // value = array[index] 691 environment()->Push(obj); 692 environment()->Push(cache_array); 693 environment()->Push(cache_type); 694 environment()->Push(index); 695 Node* pair = 696 ProcessArguments(javascript()->Runtime(Runtime::kForInNext, 4), 4); 697 Node* value = NewNode(common()->Projection(0), pair); 698 Node* should_filter = NewNode(common()->Projection(1), pair); 699 environment()->Push(value); 700 { 701 // Test if FILTER_KEY needs to be called. 702 IfBuilder test_should_filter(this); 703 Node* should_filter_cond = 704 NewNode(javascript()->StrictEqual(), should_filter, 705 jsgraph()->TrueConstant()); 706 test_should_filter.If(should_filter_cond); 707 test_should_filter.Then(); 708 value = environment()->Pop(); 709 Node* builtins = BuildLoadBuiltinsObject(); 710 Node* function = BuildLoadObjectField( 711 builtins, 712 JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY)); 713 // Callee. 714 environment()->Push(function); 715 // Receiver. 716 environment()->Push(obj); 717 // Args. 718 environment()->Push(value); 719 // result is either the string key or Smi(0) indicating the property 720 // is gone. 721 Node* res = ProcessArguments( 722 javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3); 723 // TODO(jarin): provide real bailout id. 724 PrepareFrameState(res, BailoutId::None()); 725 Node* property_missing = NewNode(javascript()->StrictEqual(), res, 726 jsgraph()->ZeroConstant()); 727 { 728 IfBuilder is_property_missing(this); 729 is_property_missing.If(property_missing); 730 is_property_missing.Then(); 731 // Inc counter and continue. 732 Node* index_inc = 733 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); 734 // TODO(jarin): provide real bailout id. 735 PrepareFrameState(index_inc, BailoutId::None()); 736 environment()->Poke(0, index_inc); 737 for_loop.Continue(); 738 is_property_missing.Else(); 739 is_property_missing.End(); 740 } 741 // Replace 'value' in environment. 742 environment()->Push(res); 743 test_should_filter.Else(); 744 test_should_filter.End(); 745 } 746 value = environment()->Pop(); 747 // Bind value and do loop body. 748 VisitForInAssignment(stmt->each(), value); 749 VisitIterationBody(stmt, &for_loop, 5); 750 for_loop.EndBody(); 751 // Inc counter and continue. 752 Node* index_inc = 753 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); 754 // TODO(jarin): provide real bailout id. 755 PrepareFrameState(index_inc, BailoutId::None()); 756 environment()->Poke(0, index_inc); 757 for_loop.EndLoop(); 758 environment()->Drop(5); 759 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 760 } 761 have_no_properties.End(); 762 } 763 is_null.End(); 764 } 765 is_undefined.End(); 766} 767 768 769void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { 770 VisitForValue(stmt->subject()); 771 environment()->Pop(); 772 // TODO(turbofan): create and use loop builder. 773} 774 775 776void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 777 UNREACHABLE(); 778} 779 780 781void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 782 UNREACHABLE(); 783} 784 785 786void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 787 // TODO(turbofan): Do we really need a separate reloc-info for this? 788 Node* node = NewNode(javascript()->Runtime(Runtime::kDebugBreak, 0)); 789 PrepareFrameState(node, stmt->DebugBreakId()); 790} 791 792 793void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 794 Node* context = current_context(); 795 796 // Build a new shared function info if we cannot find one in the baseline 797 // code. We also have a stack overflow if the recursive compilation did. 798 Handle<SharedFunctionInfo> shared_info = 799 SearchSharedFunctionInfo(info()->shared_info()->code(), expr); 800 if (shared_info.is_null()) { 801 shared_info = Compiler::BuildFunctionInfo(expr, info()->script(), info()); 802 CHECK(!shared_info.is_null()); // TODO(mstarzinger): Set stack overflow? 803 } 804 805 // Create node to instantiate a new closure. 806 Node* info = jsgraph()->Constant(shared_info); 807 Node* pretenure = expr->pretenure() ? jsgraph()->TrueConstant() 808 : jsgraph()->FalseConstant(); 809 const Operator* op = javascript()->Runtime(Runtime::kNewClosure, 3); 810 Node* value = NewNode(op, context, info, pretenure); 811 ast_context()->ProduceValue(value); 812} 813 814 815void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) { 816 // TODO(arv): Implement. 817 UNREACHABLE(); 818} 819 820 821void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { 822 UNREACHABLE(); 823} 824 825 826void AstGraphBuilder::VisitConditional(Conditional* expr) { 827 IfBuilder compare_if(this); 828 VisitForTest(expr->condition()); 829 Node* condition = environment()->Pop(); 830 compare_if.If(condition); 831 compare_if.Then(); 832 Visit(expr->then_expression()); 833 compare_if.Else(); 834 Visit(expr->else_expression()); 835 compare_if.End(); 836 ast_context()->ReplaceValue(); 837} 838 839 840void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 841 Node* value = BuildVariableLoad(expr->var(), expr->id()); 842 ast_context()->ProduceValue(value); 843} 844 845 846void AstGraphBuilder::VisitLiteral(Literal* expr) { 847 Node* value = jsgraph()->Constant(expr->value()); 848 ast_context()->ProduceValue(value); 849} 850 851 852void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 853 Node* closure = GetFunctionClosure(); 854 855 // Create node to materialize a regular expression literal. 856 Node* literals_array = 857 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); 858 Node* literal_index = jsgraph()->Constant(expr->literal_index()); 859 Node* pattern = jsgraph()->Constant(expr->pattern()); 860 Node* flags = jsgraph()->Constant(expr->flags()); 861 const Operator* op = 862 javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4); 863 Node* literal = NewNode(op, literals_array, literal_index, pattern, flags); 864 ast_context()->ProduceValue(literal); 865} 866 867 868void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 869 Node* closure = GetFunctionClosure(); 870 871 // Create node to deep-copy the literal boilerplate. 872 expr->BuildConstantProperties(isolate()); 873 Node* literals_array = 874 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); 875 Node* literal_index = jsgraph()->Constant(expr->literal_index()); 876 Node* constants = jsgraph()->Constant(expr->constant_properties()); 877 Node* flags = jsgraph()->Constant(expr->ComputeFlags()); 878 const Operator* op = javascript()->Runtime(Runtime::kCreateObjectLiteral, 4); 879 Node* literal = NewNode(op, literals_array, literal_index, constants, flags); 880 881 // The object is expected on the operand stack during computation of the 882 // property values and is the value of the entire expression. 883 environment()->Push(literal); 884 885 // Mark all computed expressions that are bound to a key that is shadowed by 886 // a later occurrence of the same key. For the marked expressions, no store 887 // code is emitted. 888 expr->CalculateEmitStore(zone()); 889 890 // Create nodes to store computed values into the literal. 891 AccessorTable accessor_table(zone()); 892 for (int i = 0; i < expr->properties()->length(); i++) { 893 ObjectLiteral::Property* property = expr->properties()->at(i); 894 if (property->IsCompileTimeValue()) continue; 895 896 Literal* key = property->key(); 897 switch (property->kind()) { 898 case ObjectLiteral::Property::CONSTANT: 899 UNREACHABLE(); 900 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 901 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); 902 // Fall through. 903 case ObjectLiteral::Property::COMPUTED: { 904 // It is safe to use [[Put]] here because the boilerplate already 905 // contains computed properties with an uninitialized value. 906 if (key->value()->IsInternalizedString()) { 907 if (property->emit_store()) { 908 VisitForValue(property->value()); 909 Node* value = environment()->Pop(); 910 Unique<Name> name = MakeUnique(key->AsPropertyName()); 911 Node* store = NewNode(javascript()->StoreNamed(strict_mode(), name), 912 literal, value); 913 PrepareFrameState(store, key->id()); 914 } else { 915 VisitForEffect(property->value()); 916 } 917 break; 918 } 919 environment()->Push(literal); // Duplicate receiver. 920 VisitForValue(property->key()); 921 VisitForValue(property->value()); 922 Node* value = environment()->Pop(); 923 Node* key = environment()->Pop(); 924 Node* receiver = environment()->Pop(); 925 if (property->emit_store()) { 926 Node* strict = jsgraph()->Constant(SLOPPY); 927 const Operator* op = javascript()->Runtime(Runtime::kSetProperty, 4); 928 NewNode(op, receiver, key, value, strict); 929 } 930 break; 931 } 932 case ObjectLiteral::Property::PROTOTYPE: { 933 environment()->Push(literal); // Duplicate receiver. 934 VisitForValue(property->value()); 935 Node* value = environment()->Pop(); 936 Node* receiver = environment()->Pop(); 937 if (property->emit_store()) { 938 const Operator* op = javascript()->Runtime(Runtime::kSetPrototype, 2); 939 NewNode(op, receiver, value); 940 } 941 break; 942 } 943 case ObjectLiteral::Property::GETTER: 944 accessor_table.lookup(key)->second->getter = property->value(); 945 break; 946 case ObjectLiteral::Property::SETTER: 947 accessor_table.lookup(key)->second->setter = property->value(); 948 break; 949 } 950 } 951 952 // Create nodes to define accessors, using only a single call to the runtime 953 // for each pair of corresponding getters and setters. 954 for (AccessorTable::Iterator it = accessor_table.begin(); 955 it != accessor_table.end(); ++it) { 956 VisitForValue(it->first); 957 VisitForValueOrNull(it->second->getter); 958 VisitForValueOrNull(it->second->setter); 959 Node* setter = environment()->Pop(); 960 Node* getter = environment()->Pop(); 961 Node* name = environment()->Pop(); 962 Node* attr = jsgraph()->Constant(NONE); 963 const Operator* op = 964 javascript()->Runtime(Runtime::kDefineAccessorPropertyUnchecked, 5); 965 Node* call = NewNode(op, literal, name, getter, setter, attr); 966 PrepareFrameState(call, it->first->id()); 967 } 968 969 // Transform literals that contain functions to fast properties. 970 if (expr->has_function()) { 971 const Operator* op = javascript()->Runtime(Runtime::kToFastProperties, 1); 972 NewNode(op, literal); 973 } 974 975 ast_context()->ProduceValue(environment()->Pop()); 976} 977 978 979void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 980 Node* closure = GetFunctionClosure(); 981 982 // Create node to deep-copy the literal boilerplate. 983 expr->BuildConstantElements(isolate()); 984 Node* literals_array = 985 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); 986 Node* literal_index = jsgraph()->Constant(expr->literal_index()); 987 Node* constants = jsgraph()->Constant(expr->constant_elements()); 988 Node* flags = jsgraph()->Constant(expr->ComputeFlags()); 989 const Operator* op = javascript()->Runtime(Runtime::kCreateArrayLiteral, 4); 990 Node* literal = NewNode(op, literals_array, literal_index, constants, flags); 991 992 // The array and the literal index are both expected on the operand stack 993 // during computation of the element values. 994 environment()->Push(literal); 995 environment()->Push(literal_index); 996 997 // Create nodes to evaluate all the non-constant subexpressions and to store 998 // them into the newly cloned array. 999 for (int i = 0; i < expr->values()->length(); i++) { 1000 Expression* subexpr = expr->values()->at(i); 1001 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 1002 1003 VisitForValue(subexpr); 1004 Node* value = environment()->Pop(); 1005 Node* index = jsgraph()->Constant(i); 1006 Node* store = NewNode(javascript()->StoreProperty(strict_mode()), literal, 1007 index, value); 1008 PrepareFrameState(store, expr->GetIdForElement(i)); 1009 } 1010 1011 environment()->Pop(); // Array literal index. 1012 ast_context()->ProduceValue(environment()->Pop()); 1013} 1014 1015 1016void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) { 1017 DCHECK(expr->IsValidReferenceExpression()); 1018 1019 // Left-hand side can only be a property, a global or a variable slot. 1020 Property* property = expr->AsProperty(); 1021 LhsKind assign_type = DetermineLhsKind(expr); 1022 1023 // Evaluate LHS expression and store the value. 1024 switch (assign_type) { 1025 case VARIABLE: { 1026 Variable* var = expr->AsVariableProxy()->var(); 1027 // TODO(jarin) Fill in the correct bailout id. 1028 BuildVariableAssignment(var, value, Token::ASSIGN, BailoutId::None()); 1029 break; 1030 } 1031 case NAMED_PROPERTY: { 1032 environment()->Push(value); 1033 VisitForValue(property->obj()); 1034 Node* object = environment()->Pop(); 1035 value = environment()->Pop(); 1036 Unique<Name> name = 1037 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); 1038 Node* store = 1039 NewNode(javascript()->StoreNamed(strict_mode(), name), object, value); 1040 // TODO(jarin) Fill in the correct bailout id. 1041 PrepareFrameState(store, BailoutId::None()); 1042 break; 1043 } 1044 case KEYED_PROPERTY: { 1045 environment()->Push(value); 1046 VisitForValue(property->obj()); 1047 VisitForValue(property->key()); 1048 Node* key = environment()->Pop(); 1049 Node* object = environment()->Pop(); 1050 value = environment()->Pop(); 1051 Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object, 1052 key, value); 1053 // TODO(jarin) Fill in the correct bailout id. 1054 PrepareFrameState(store, BailoutId::None()); 1055 break; 1056 } 1057 } 1058} 1059 1060 1061void AstGraphBuilder::VisitAssignment(Assignment* expr) { 1062 DCHECK(expr->target()->IsValidReferenceExpression()); 1063 1064 // Left-hand side can only be a property, a global or a variable slot. 1065 Property* property = expr->target()->AsProperty(); 1066 LhsKind assign_type = DetermineLhsKind(expr->target()); 1067 1068 // Evaluate LHS expression. 1069 switch (assign_type) { 1070 case VARIABLE: 1071 // Nothing to do here. 1072 break; 1073 case NAMED_PROPERTY: 1074 VisitForValue(property->obj()); 1075 break; 1076 case KEYED_PROPERTY: { 1077 VisitForValue(property->obj()); 1078 VisitForValue(property->key()); 1079 break; 1080 } 1081 } 1082 1083 // Evaluate the value and potentially handle compound assignments by loading 1084 // the left-hand side value and performing a binary operation. 1085 if (expr->is_compound()) { 1086 Node* old_value = NULL; 1087 switch (assign_type) { 1088 case VARIABLE: { 1089 Variable* variable = expr->target()->AsVariableProxy()->var(); 1090 old_value = BuildVariableLoad(variable, expr->target()->id()); 1091 break; 1092 } 1093 case NAMED_PROPERTY: { 1094 Node* object = environment()->Top(); 1095 Unique<Name> name = 1096 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); 1097 old_value = NewNode(javascript()->LoadNamed(name), object); 1098 PrepareFrameState(old_value, property->LoadId(), kPushOutput); 1099 break; 1100 } 1101 case KEYED_PROPERTY: { 1102 Node* key = environment()->Top(); 1103 Node* object = environment()->Peek(1); 1104 old_value = NewNode(javascript()->LoadProperty(), object, key); 1105 PrepareFrameState(old_value, property->LoadId(), kPushOutput); 1106 break; 1107 } 1108 } 1109 environment()->Push(old_value); 1110 VisitForValue(expr->value()); 1111 Node* right = environment()->Pop(); 1112 Node* left = environment()->Pop(); 1113 Node* value = BuildBinaryOp(left, right, expr->binary_op()); 1114 PrepareFrameState(value, expr->binary_operation()->id(), kPushOutput); 1115 environment()->Push(value); 1116 } else { 1117 VisitForValue(expr->value()); 1118 } 1119 1120 // Store the value. 1121 Node* value = environment()->Pop(); 1122 switch (assign_type) { 1123 case VARIABLE: { 1124 Variable* variable = expr->target()->AsVariableProxy()->var(); 1125 BuildVariableAssignment(variable, value, expr->op(), 1126 expr->AssignmentId()); 1127 break; 1128 } 1129 case NAMED_PROPERTY: { 1130 Node* object = environment()->Pop(); 1131 Unique<Name> name = 1132 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); 1133 Node* store = 1134 NewNode(javascript()->StoreNamed(strict_mode(), name), object, value); 1135 PrepareFrameState(store, expr->AssignmentId()); 1136 break; 1137 } 1138 case KEYED_PROPERTY: { 1139 Node* key = environment()->Pop(); 1140 Node* object = environment()->Pop(); 1141 Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object, 1142 key, value); 1143 PrepareFrameState(store, expr->AssignmentId()); 1144 break; 1145 } 1146 } 1147 1148 ast_context()->ProduceValue(value); 1149} 1150 1151 1152void AstGraphBuilder::VisitYield(Yield* expr) { 1153 VisitForValue(expr->generator_object()); 1154 VisitForValue(expr->expression()); 1155 environment()->Pop(); 1156 environment()->Pop(); 1157 // TODO(turbofan): VisitYield 1158 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); 1159} 1160 1161 1162void AstGraphBuilder::VisitThrow(Throw* expr) { 1163 VisitForValue(expr->exception()); 1164 Node* exception = environment()->Pop(); 1165 const Operator* op = javascript()->Runtime(Runtime::kThrow, 1); 1166 Node* value = NewNode(op, exception); 1167 ast_context()->ProduceValue(value); 1168} 1169 1170 1171void AstGraphBuilder::VisitProperty(Property* expr) { 1172 Node* value; 1173 if (expr->key()->IsPropertyName()) { 1174 VisitForValue(expr->obj()); 1175 Node* object = environment()->Pop(); 1176 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); 1177 value = NewNode(javascript()->LoadNamed(name), object); 1178 } else { 1179 VisitForValue(expr->obj()); 1180 VisitForValue(expr->key()); 1181 Node* key = environment()->Pop(); 1182 Node* object = environment()->Pop(); 1183 value = NewNode(javascript()->LoadProperty(), object, key); 1184 } 1185 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); 1186 ast_context()->ProduceValue(value); 1187} 1188 1189 1190void AstGraphBuilder::VisitCall(Call* expr) { 1191 Expression* callee = expr->expression(); 1192 Call::CallType call_type = expr->GetCallType(isolate()); 1193 1194 // Prepare the callee and the receiver to the function call. This depends on 1195 // the semantics of the underlying call type. 1196 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; 1197 Node* receiver_value = NULL; 1198 Node* callee_value = NULL; 1199 bool possibly_eval = false; 1200 switch (call_type) { 1201 case Call::GLOBAL_CALL: { 1202 Variable* variable = callee->AsVariableProxy()->var(); 1203 callee_value = BuildVariableLoad(variable, expr->expression()->id()); 1204 receiver_value = jsgraph()->UndefinedConstant(); 1205 break; 1206 } 1207 case Call::LOOKUP_SLOT_CALL: { 1208 Variable* variable = callee->AsVariableProxy()->var(); 1209 DCHECK(variable->location() == Variable::LOOKUP); 1210 Node* name = jsgraph()->Constant(variable->name()); 1211 const Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); 1212 Node* pair = NewNode(op, current_context(), name); 1213 callee_value = NewNode(common()->Projection(0), pair); 1214 receiver_value = NewNode(common()->Projection(1), pair); 1215 break; 1216 } 1217 case Call::PROPERTY_CALL: { 1218 Property* property = callee->AsProperty(); 1219 VisitForValue(property->obj()); 1220 Node* object = environment()->Top(); 1221 if (property->key()->IsPropertyName()) { 1222 Unique<Name> name = 1223 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); 1224 callee_value = NewNode(javascript()->LoadNamed(name), object); 1225 } else { 1226 VisitForValue(property->key()); 1227 Node* key = environment()->Pop(); 1228 callee_value = NewNode(javascript()->LoadProperty(), object, key); 1229 } 1230 PrepareFrameState(callee_value, property->LoadId(), kPushOutput); 1231 receiver_value = environment()->Pop(); 1232 // Note that a PROPERTY_CALL requires the receiver to be wrapped into an 1233 // object for sloppy callees. This could also be modeled explicitly here, 1234 // thereby obsoleting the need for a flag to the call operator. 1235 flags = CALL_AS_METHOD; 1236 break; 1237 } 1238 case Call::POSSIBLY_EVAL_CALL: 1239 possibly_eval = true; 1240 // Fall through. 1241 case Call::OTHER_CALL: 1242 VisitForValue(callee); 1243 callee_value = environment()->Pop(); 1244 receiver_value = jsgraph()->UndefinedConstant(); 1245 break; 1246 } 1247 1248 // The callee and the receiver both have to be pushed onto the operand stack 1249 // before arguments are being evaluated. 1250 environment()->Push(callee_value); 1251 environment()->Push(receiver_value); 1252 1253 // Evaluate all arguments to the function call, 1254 ZoneList<Expression*>* args = expr->arguments(); 1255 VisitForValues(args); 1256 1257 // Resolve callee and receiver for a potential direct eval call. This block 1258 // will mutate the callee and receiver values pushed onto the environment. 1259 if (possibly_eval && args->length() > 0) { 1260 int arg_count = args->length(); 1261 1262 // Extract callee and source string from the environment. 1263 Node* callee = environment()->Peek(arg_count + 1); 1264 Node* source = environment()->Peek(arg_count - 1); 1265 1266 // Create node to ask for help resolving potential eval call. This will 1267 // provide a fully resolved callee and the corresponding receiver. 1268 Node* function = GetFunctionClosure(); 1269 Node* receiver = environment()->Lookup(info()->scope()->receiver()); 1270 Node* strict = jsgraph()->Constant(strict_mode()); 1271 Node* position = jsgraph()->Constant(info()->scope()->start_position()); 1272 const Operator* op = 1273 javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 6); 1274 Node* pair = 1275 NewNode(op, callee, source, function, receiver, strict, position); 1276 Node* new_callee = NewNode(common()->Projection(0), pair); 1277 Node* new_receiver = NewNode(common()->Projection(1), pair); 1278 1279 // Patch callee and receiver on the environment. 1280 environment()->Poke(arg_count + 1, new_callee); 1281 environment()->Poke(arg_count + 0, new_receiver); 1282 } 1283 1284 // Create node to perform the function call. 1285 const Operator* call = javascript()->Call(args->length() + 2, flags); 1286 Node* value = ProcessArguments(call, args->length() + 2); 1287 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); 1288 ast_context()->ProduceValue(value); 1289} 1290 1291 1292void AstGraphBuilder::VisitCallNew(CallNew* expr) { 1293 VisitForValue(expr->expression()); 1294 1295 // Evaluate all arguments to the construct call. 1296 ZoneList<Expression*>* args = expr->arguments(); 1297 VisitForValues(args); 1298 1299 // Create node to perform the construct call. 1300 const Operator* call = javascript()->CallNew(args->length() + 1); 1301 Node* value = ProcessArguments(call, args->length() + 1); 1302 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); 1303 ast_context()->ProduceValue(value); 1304} 1305 1306 1307void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { 1308 Handle<String> name = expr->name(); 1309 1310 // The callee and the receiver both have to be pushed onto the operand stack 1311 // before arguments are being evaluated. 1312 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; 1313 Node* receiver_value = BuildLoadBuiltinsObject(); 1314 Unique<String> unique = MakeUnique(name); 1315 Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); 1316 // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft 1317 // refuses to optimize functions with jsruntime calls). 1318 PrepareFrameState(callee_value, BailoutId::None(), kPushOutput); 1319 environment()->Push(callee_value); 1320 environment()->Push(receiver_value); 1321 1322 // Evaluate all arguments to the JS runtime call. 1323 ZoneList<Expression*>* args = expr->arguments(); 1324 VisitForValues(args); 1325 1326 // Create node to perform the JS runtime call. 1327 const Operator* call = javascript()->Call(args->length() + 2, flags); 1328 Node* value = ProcessArguments(call, args->length() + 2); 1329 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); 1330 ast_context()->ProduceValue(value); 1331} 1332 1333 1334void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 1335 const Runtime::Function* function = expr->function(); 1336 1337 // Handle calls to runtime functions implemented in JavaScript separately as 1338 // the call follows JavaScript ABI and the callee is statically unknown. 1339 if (expr->is_jsruntime()) { 1340 DCHECK(function == NULL && expr->name()->length() > 0); 1341 return VisitCallJSRuntime(expr); 1342 } 1343 1344 // Evaluate all arguments to the runtime call. 1345 ZoneList<Expression*>* args = expr->arguments(); 1346 VisitForValues(args); 1347 1348 // Create node to perform the runtime call. 1349 Runtime::FunctionId functionId = function->function_id; 1350 const Operator* call = javascript()->Runtime(functionId, args->length()); 1351 Node* value = ProcessArguments(call, args->length()); 1352 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); 1353 ast_context()->ProduceValue(value); 1354} 1355 1356 1357void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 1358 switch (expr->op()) { 1359 case Token::DELETE: 1360 return VisitDelete(expr); 1361 case Token::VOID: 1362 return VisitVoid(expr); 1363 case Token::TYPEOF: 1364 return VisitTypeof(expr); 1365 case Token::NOT: 1366 return VisitNot(expr); 1367 default: 1368 UNREACHABLE(); 1369 } 1370} 1371 1372 1373void AstGraphBuilder::VisitCountOperation(CountOperation* expr) { 1374 DCHECK(expr->expression()->IsValidReferenceExpression()); 1375 1376 // Left-hand side can only be a property, a global or a variable slot. 1377 Property* property = expr->expression()->AsProperty(); 1378 LhsKind assign_type = DetermineLhsKind(expr->expression()); 1379 1380 // Reserve space for result of postfix operation. 1381 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect(); 1382 if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant()); 1383 1384 // Evaluate LHS expression and get old value. 1385 Node* old_value = NULL; 1386 int stack_depth = -1; 1387 switch (assign_type) { 1388 case VARIABLE: { 1389 Variable* variable = expr->expression()->AsVariableProxy()->var(); 1390 old_value = BuildVariableLoad(variable, expr->expression()->id()); 1391 stack_depth = 0; 1392 break; 1393 } 1394 case NAMED_PROPERTY: { 1395 VisitForValue(property->obj()); 1396 Node* object = environment()->Top(); 1397 Unique<Name> name = 1398 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); 1399 old_value = NewNode(javascript()->LoadNamed(name), object); 1400 PrepareFrameState(old_value, property->LoadId(), kPushOutput); 1401 stack_depth = 1; 1402 break; 1403 } 1404 case KEYED_PROPERTY: { 1405 VisitForValue(property->obj()); 1406 VisitForValue(property->key()); 1407 Node* key = environment()->Top(); 1408 Node* object = environment()->Peek(1); 1409 old_value = NewNode(javascript()->LoadProperty(), object, key); 1410 PrepareFrameState(old_value, property->LoadId(), kPushOutput); 1411 stack_depth = 2; 1412 break; 1413 } 1414 } 1415 1416 // Convert old value into a number. 1417 old_value = NewNode(javascript()->ToNumber(), old_value); 1418 1419 // Save result for postfix expressions at correct stack depth. 1420 if (is_postfix) environment()->Poke(stack_depth, old_value); 1421 1422 // Create node to perform +1/-1 operation. 1423 Node* value = 1424 BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op()); 1425 // TODO(jarin) Insert proper bailout id here (will need to change 1426 // full code generator). 1427 PrepareFrameState(value, BailoutId::None()); 1428 1429 // Store the value. 1430 switch (assign_type) { 1431 case VARIABLE: { 1432 Variable* variable = expr->expression()->AsVariableProxy()->var(); 1433 environment()->Push(value); 1434 BuildVariableAssignment(variable, value, expr->op(), 1435 expr->AssignmentId()); 1436 environment()->Pop(); 1437 break; 1438 } 1439 case NAMED_PROPERTY: { 1440 Node* object = environment()->Pop(); 1441 Unique<Name> name = 1442 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); 1443 Node* store = 1444 NewNode(javascript()->StoreNamed(strict_mode(), name), object, value); 1445 environment()->Push(value); 1446 PrepareFrameState(store, expr->AssignmentId()); 1447 environment()->Pop(); 1448 break; 1449 } 1450 case KEYED_PROPERTY: { 1451 Node* key = environment()->Pop(); 1452 Node* object = environment()->Pop(); 1453 Node* store = NewNode(javascript()->StoreProperty(strict_mode()), object, 1454 key, value); 1455 environment()->Push(value); 1456 PrepareFrameState(store, expr->AssignmentId()); 1457 environment()->Pop(); 1458 break; 1459 } 1460 } 1461 1462 // Restore old value for postfix expressions. 1463 if (is_postfix) value = environment()->Pop(); 1464 1465 ast_context()->ProduceValue(value); 1466} 1467 1468 1469void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 1470 switch (expr->op()) { 1471 case Token::COMMA: 1472 return VisitComma(expr); 1473 case Token::OR: 1474 case Token::AND: 1475 return VisitLogicalExpression(expr); 1476 default: { 1477 VisitForValue(expr->left()); 1478 VisitForValue(expr->right()); 1479 Node* right = environment()->Pop(); 1480 Node* left = environment()->Pop(); 1481 Node* value = BuildBinaryOp(left, right, expr->op()); 1482 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); 1483 ast_context()->ProduceValue(value); 1484 } 1485 } 1486} 1487 1488 1489void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 1490 const Operator* op; 1491 switch (expr->op()) { 1492 case Token::EQ: 1493 op = javascript()->Equal(); 1494 break; 1495 case Token::NE: 1496 op = javascript()->NotEqual(); 1497 break; 1498 case Token::EQ_STRICT: 1499 op = javascript()->StrictEqual(); 1500 break; 1501 case Token::NE_STRICT: 1502 op = javascript()->StrictNotEqual(); 1503 break; 1504 case Token::LT: 1505 op = javascript()->LessThan(); 1506 break; 1507 case Token::GT: 1508 op = javascript()->GreaterThan(); 1509 break; 1510 case Token::LTE: 1511 op = javascript()->LessThanOrEqual(); 1512 break; 1513 case Token::GTE: 1514 op = javascript()->GreaterThanOrEqual(); 1515 break; 1516 case Token::INSTANCEOF: 1517 op = javascript()->InstanceOf(); 1518 break; 1519 case Token::IN: 1520 op = javascript()->HasProperty(); 1521 break; 1522 default: 1523 op = NULL; 1524 UNREACHABLE(); 1525 } 1526 VisitForValue(expr->left()); 1527 VisitForValue(expr->right()); 1528 Node* right = environment()->Pop(); 1529 Node* left = environment()->Pop(); 1530 Node* value = NewNode(op, left, right); 1531 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); 1532 ast_context()->ProduceValue(value); 1533} 1534 1535 1536void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) { 1537 Node* value = GetFunctionClosure(); 1538 ast_context()->ProduceValue(value); 1539} 1540 1541 1542void AstGraphBuilder::VisitSuperReference(SuperReference* expr) { 1543 UNREACHABLE(); 1544} 1545 1546 1547void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); } 1548 1549 1550void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) { 1551 DCHECK(globals()->is_empty()); 1552 AstVisitor::VisitDeclarations(declarations); 1553 if (globals()->is_empty()) return; 1554 Handle<FixedArray> data = 1555 isolate()->factory()->NewFixedArray(globals()->length(), TENURED); 1556 for (int i = 0; i < globals()->length(); ++i) data->set(i, *globals()->at(i)); 1557 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | 1558 DeclareGlobalsNativeFlag::encode(info()->is_native()) | 1559 DeclareGlobalsStrictMode::encode(strict_mode()); 1560 Node* flags = jsgraph()->Constant(encoded_flags); 1561 Node* pairs = jsgraph()->Constant(data); 1562 const Operator* op = javascript()->Runtime(Runtime::kDeclareGlobals, 3); 1563 NewNode(op, current_context(), pairs, flags); 1564 globals()->Rewind(0); 1565} 1566 1567 1568void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { 1569 if (stmt == NULL) return; 1570 Visit(stmt); 1571} 1572 1573 1574void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt, 1575 LoopBuilder* loop, int drop_extra) { 1576 BreakableScope scope(this, stmt, loop, drop_extra); 1577 Visit(stmt->body()); 1578} 1579 1580 1581void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { 1582 Node* value; 1583 if (expr->expression()->IsVariableProxy()) { 1584 // Delete of an unqualified identifier is only allowed in classic mode but 1585 // deleting "this" is allowed in all language modes. 1586 Variable* variable = expr->expression()->AsVariableProxy()->var(); 1587 DCHECK(strict_mode() == SLOPPY || variable->is_this()); 1588 value = BuildVariableDelete(variable); 1589 } else if (expr->expression()->IsProperty()) { 1590 Property* property = expr->expression()->AsProperty(); 1591 VisitForValue(property->obj()); 1592 VisitForValue(property->key()); 1593 Node* key = environment()->Pop(); 1594 Node* object = environment()->Pop(); 1595 value = NewNode(javascript()->DeleteProperty(strict_mode()), object, key); 1596 } else { 1597 VisitForEffect(expr->expression()); 1598 value = jsgraph()->TrueConstant(); 1599 } 1600 ast_context()->ProduceValue(value); 1601} 1602 1603 1604void AstGraphBuilder::VisitVoid(UnaryOperation* expr) { 1605 VisitForEffect(expr->expression()); 1606 Node* value = jsgraph()->UndefinedConstant(); 1607 ast_context()->ProduceValue(value); 1608} 1609 1610 1611void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { 1612 Node* operand; 1613 if (expr->expression()->IsVariableProxy()) { 1614 // Typeof does not throw a reference error on global variables, hence we 1615 // perform a non-contextual load in case the operand is a variable proxy. 1616 Variable* variable = expr->expression()->AsVariableProxy()->var(); 1617 operand = 1618 BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL); 1619 } else { 1620 VisitForValue(expr->expression()); 1621 operand = environment()->Pop(); 1622 } 1623 Node* value = NewNode(javascript()->TypeOf(), operand); 1624 ast_context()->ProduceValue(value); 1625} 1626 1627 1628void AstGraphBuilder::VisitNot(UnaryOperation* expr) { 1629 VisitForValue(expr->expression()); 1630 Node* operand = environment()->Pop(); 1631 // TODO(mstarzinger): Possible optimization when we are in effect context. 1632 Node* value = NewNode(javascript()->UnaryNot(), operand); 1633 ast_context()->ProduceValue(value); 1634} 1635 1636 1637void AstGraphBuilder::VisitComma(BinaryOperation* expr) { 1638 VisitForEffect(expr->left()); 1639 Visit(expr->right()); 1640 ast_context()->ReplaceValue(); 1641} 1642 1643 1644void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { 1645 bool is_logical_and = expr->op() == Token::AND; 1646 IfBuilder compare_if(this); 1647 VisitForValue(expr->left()); 1648 Node* condition = environment()->Top(); 1649 compare_if.If(BuildToBoolean(condition)); 1650 compare_if.Then(); 1651 if (is_logical_and) { 1652 environment()->Pop(); 1653 Visit(expr->right()); 1654 } else if (ast_context()->IsEffect()) { 1655 environment()->Pop(); 1656 } 1657 compare_if.Else(); 1658 if (!is_logical_and) { 1659 environment()->Pop(); 1660 Visit(expr->right()); 1661 } else if (ast_context()->IsEffect()) { 1662 environment()->Pop(); 1663 } 1664 compare_if.End(); 1665 ast_context()->ReplaceValue(); 1666} 1667 1668 1669Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) { 1670 DCHECK(environment()->stack_height() >= arity); 1671 Node** all = info()->zone()->NewArray<Node*>(arity); 1672 for (int i = arity - 1; i >= 0; --i) { 1673 all[i] = environment()->Pop(); 1674 } 1675 Node* value = NewNode(op, arity, all); 1676 return value; 1677} 1678 1679 1680Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) { 1681 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 1682 if (heap_slots <= 0) return context; 1683 set_current_context(context); 1684 1685 // Allocate a new local context. 1686 const Operator* op = javascript()->CreateFunctionContext(); 1687 Node* local_context = NewNode(op, closure); 1688 set_current_context(local_context); 1689 1690 // Copy parameters into context if necessary. 1691 int num_parameters = info()->scope()->num_parameters(); 1692 for (int i = 0; i < num_parameters; i++) { 1693 Variable* variable = info()->scope()->parameter(i); 1694 if (!variable->IsContextSlot()) continue; 1695 // Temporary parameter node. The parameter indices are shifted by 1 1696 // (receiver is parameter index -1 but environment index 0). 1697 Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start()); 1698 // Context variable (at bottom of the context chain). 1699 DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope())); 1700 const Operator* op = javascript()->StoreContext(0, variable->index()); 1701 NewNode(op, local_context, parameter); 1702 } 1703 1704 return local_context; 1705} 1706 1707 1708Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { 1709 if (arguments == NULL) return NULL; 1710 1711 // Allocate and initialize a new arguments object. 1712 Node* callee = GetFunctionClosure(); 1713 const Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1); 1714 Node* object = NewNode(op, callee); 1715 1716 // Assign the object to the arguments variable. 1717 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); 1718 // This should never lazy deopt, so it is fine to send invalid bailout id. 1719 BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None()); 1720 1721 return object; 1722} 1723 1724 1725Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole, 1726 Node* not_hole) { 1727 IfBuilder hole_check(this); 1728 Node* the_hole = jsgraph()->TheHoleConstant(); 1729 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); 1730 hole_check.If(check); 1731 hole_check.Then(); 1732 environment()->Push(for_hole); 1733 hole_check.Else(); 1734 environment()->Push(not_hole); 1735 hole_check.End(); 1736 return environment()->Pop(); 1737} 1738 1739 1740Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable, 1741 Node* not_hole) { 1742 IfBuilder hole_check(this); 1743 Node* the_hole = jsgraph()->TheHoleConstant(); 1744 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); 1745 hole_check.If(check); 1746 hole_check.Then(); 1747 environment()->Push(BuildThrowReferenceError(variable)); 1748 hole_check.Else(); 1749 environment()->Push(not_hole); 1750 hole_check.End(); 1751 return environment()->Pop(); 1752} 1753 1754 1755Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, 1756 BailoutId bailout_id, 1757 ContextualMode contextual_mode) { 1758 Node* the_hole = jsgraph()->TheHoleConstant(); 1759 VariableMode mode = variable->mode(); 1760 switch (variable->location()) { 1761 case Variable::UNALLOCATED: { 1762 // Global var, const, or let variable. 1763 Node* global = BuildLoadGlobalObject(); 1764 Unique<Name> name = MakeUnique(variable->name()); 1765 const Operator* op = javascript()->LoadNamed(name, contextual_mode); 1766 Node* node = NewNode(op, global); 1767 PrepareFrameState(node, bailout_id, kPushOutput); 1768 return node; 1769 } 1770 case Variable::PARAMETER: 1771 case Variable::LOCAL: { 1772 // Local var, const, or let variable. 1773 Node* value = environment()->Lookup(variable); 1774 if (mode == CONST_LEGACY) { 1775 // Perform check for uninitialized legacy const variables. 1776 if (value->op() == the_hole->op()) { 1777 value = jsgraph()->UndefinedConstant(); 1778 } else if (value->opcode() == IrOpcode::kPhi) { 1779 Node* undefined = jsgraph()->UndefinedConstant(); 1780 value = BuildHoleCheckSilent(value, undefined, value); 1781 } 1782 } else if (mode == LET || mode == CONST) { 1783 // Perform check for uninitialized let/const variables. 1784 if (value->op() == the_hole->op()) { 1785 value = BuildThrowReferenceError(variable); 1786 } else if (value->opcode() == IrOpcode::kPhi) { 1787 value = BuildHoleCheckThrow(value, variable, value); 1788 } 1789 } 1790 return value; 1791 } 1792 case Variable::CONTEXT: { 1793 // Context variable (potentially up the context chain). 1794 int depth = current_scope()->ContextChainLength(variable->scope()); 1795 bool immutable = variable->maybe_assigned() == kNotAssigned; 1796 const Operator* op = 1797 javascript()->LoadContext(depth, variable->index(), immutable); 1798 Node* value = NewNode(op, current_context()); 1799 // TODO(titzer): initialization checks are redundant for already 1800 // initialized immutable context loads, but only specialization knows. 1801 // Maybe specializer should be a parameter to the graph builder? 1802 if (mode == CONST_LEGACY) { 1803 // Perform check for uninitialized legacy const variables. 1804 Node* undefined = jsgraph()->UndefinedConstant(); 1805 value = BuildHoleCheckSilent(value, undefined, value); 1806 } else if (mode == LET || mode == CONST) { 1807 // Perform check for uninitialized let/const variables. 1808 value = BuildHoleCheckThrow(value, variable, value); 1809 } 1810 return value; 1811 } 1812 case Variable::LOOKUP: { 1813 // Dynamic lookup of context variable (anywhere in the chain). 1814 Node* name = jsgraph()->Constant(variable->name()); 1815 Runtime::FunctionId function_id = 1816 (contextual_mode == CONTEXTUAL) 1817 ? Runtime::kLoadLookupSlot 1818 : Runtime::kLoadLookupSlotNoReferenceError; 1819 const Operator* op = javascript()->Runtime(function_id, 2); 1820 Node* pair = NewNode(op, current_context(), name); 1821 return NewNode(common()->Projection(0), pair); 1822 } 1823 } 1824 UNREACHABLE(); 1825 return NULL; 1826} 1827 1828 1829Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) { 1830 switch (variable->location()) { 1831 case Variable::UNALLOCATED: { 1832 // Global var, const, or let variable. 1833 Node* global = BuildLoadGlobalObject(); 1834 Node* name = jsgraph()->Constant(variable->name()); 1835 const Operator* op = javascript()->DeleteProperty(strict_mode()); 1836 return NewNode(op, global, name); 1837 } 1838 case Variable::PARAMETER: 1839 case Variable::LOCAL: 1840 case Variable::CONTEXT: 1841 // Local var, const, or let variable or context variable. 1842 return variable->is_this() ? jsgraph()->TrueConstant() 1843 : jsgraph()->FalseConstant(); 1844 case Variable::LOOKUP: { 1845 // Dynamic lookup of context variable (anywhere in the chain). 1846 Node* name = jsgraph()->Constant(variable->name()); 1847 const Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2); 1848 return NewNode(op, current_context(), name); 1849 } 1850 } 1851 UNREACHABLE(); 1852 return NULL; 1853} 1854 1855 1856Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, 1857 Token::Value op, 1858 BailoutId bailout_id) { 1859 Node* the_hole = jsgraph()->TheHoleConstant(); 1860 VariableMode mode = variable->mode(); 1861 switch (variable->location()) { 1862 case Variable::UNALLOCATED: { 1863 // Global var, const, or let variable. 1864 Node* global = BuildLoadGlobalObject(); 1865 Unique<Name> name = MakeUnique(variable->name()); 1866 const Operator* op = javascript()->StoreNamed(strict_mode(), name); 1867 Node* store = NewNode(op, global, value); 1868 PrepareFrameState(store, bailout_id); 1869 return store; 1870 } 1871 case Variable::PARAMETER: 1872 case Variable::LOCAL: 1873 // Local var, const, or let variable. 1874 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { 1875 // Perform an initialization check for legacy const variables. 1876 Node* current = environment()->Lookup(variable); 1877 if (current->op() != the_hole->op()) { 1878 value = BuildHoleCheckSilent(current, value, current); 1879 } 1880 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { 1881 // Non-initializing assignments to legacy const is ignored. 1882 return value; 1883 } else if (mode == LET && op != Token::INIT_LET) { 1884 // Perform an initialization check for let declared variables. 1885 // Also note that the dynamic hole-check is only done to ensure that 1886 // this does not break in the presence of do-expressions within the 1887 // temporal dead zone of a let declared variable. 1888 Node* current = environment()->Lookup(variable); 1889 if (current->op() == the_hole->op()) { 1890 value = BuildThrowReferenceError(variable); 1891 } else if (value->opcode() == IrOpcode::kPhi) { 1892 value = BuildHoleCheckThrow(current, variable, value); 1893 } 1894 } else if (mode == CONST && op != Token::INIT_CONST) { 1895 // All assignments to const variables are early errors. 1896 UNREACHABLE(); 1897 } 1898 environment()->Bind(variable, value); 1899 return value; 1900 case Variable::CONTEXT: { 1901 // Context variable (potentially up the context chain). 1902 int depth = current_scope()->ContextChainLength(variable->scope()); 1903 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { 1904 // Perform an initialization check for legacy const variables. 1905 const Operator* op = 1906 javascript()->LoadContext(depth, variable->index(), false); 1907 Node* current = NewNode(op, current_context()); 1908 value = BuildHoleCheckSilent(current, value, current); 1909 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { 1910 // Non-initializing assignments to legacy const is ignored. 1911 return value; 1912 } else if (mode == LET && op != Token::INIT_LET) { 1913 // Perform an initialization check for let declared variables. 1914 const Operator* op = 1915 javascript()->LoadContext(depth, variable->index(), false); 1916 Node* current = NewNode(op, current_context()); 1917 value = BuildHoleCheckThrow(current, variable, value); 1918 } else if (mode == CONST && op != Token::INIT_CONST) { 1919 // All assignments to const variables are early errors. 1920 UNREACHABLE(); 1921 } 1922 const Operator* op = javascript()->StoreContext(depth, variable->index()); 1923 return NewNode(op, current_context(), value); 1924 } 1925 case Variable::LOOKUP: { 1926 // Dynamic lookup of context variable (anywhere in the chain). 1927 Node* name = jsgraph()->Constant(variable->name()); 1928 Node* strict = jsgraph()->Constant(strict_mode()); 1929 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for 1930 // initializations of const declarations. 1931 const Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4); 1932 return NewNode(op, value, current_context(), name, strict); 1933 } 1934 } 1935 UNREACHABLE(); 1936 return NULL; 1937} 1938 1939 1940Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) { 1941 // TODO(sigurds) Use simplified load here once it is ready. 1942 Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object, 1943 jsgraph()->Int32Constant(offset - kHeapObjectTag)); 1944 return field_load; 1945} 1946 1947 1948Node* AstGraphBuilder::BuildLoadBuiltinsObject() { 1949 Node* global = BuildLoadGlobalObject(); 1950 Node* builtins = 1951 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); 1952 return builtins; 1953} 1954 1955 1956Node* AstGraphBuilder::BuildLoadGlobalObject() { 1957 Node* context = GetFunctionContext(); 1958 const Operator* load_op = 1959 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); 1960 return NewNode(load_op, context); 1961} 1962 1963 1964Node* AstGraphBuilder::BuildToBoolean(Node* value) { 1965 // TODO(mstarzinger): Possible optimization is to NOP for boolean values. 1966 return NewNode(javascript()->ToBoolean(), value); 1967} 1968 1969 1970Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) { 1971 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. 1972 Node* variable_name = jsgraph()->Constant(variable->name()); 1973 const Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1); 1974 return NewNode(op, variable_name); 1975} 1976 1977 1978Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { 1979 const Operator* js_op; 1980 switch (op) { 1981 case Token::BIT_OR: 1982 js_op = javascript()->BitwiseOr(); 1983 break; 1984 case Token::BIT_AND: 1985 js_op = javascript()->BitwiseAnd(); 1986 break; 1987 case Token::BIT_XOR: 1988 js_op = javascript()->BitwiseXor(); 1989 break; 1990 case Token::SHL: 1991 js_op = javascript()->ShiftLeft(); 1992 break; 1993 case Token::SAR: 1994 js_op = javascript()->ShiftRight(); 1995 break; 1996 case Token::SHR: 1997 js_op = javascript()->ShiftRightLogical(); 1998 break; 1999 case Token::ADD: 2000 js_op = javascript()->Add(); 2001 break; 2002 case Token::SUB: 2003 js_op = javascript()->Subtract(); 2004 break; 2005 case Token::MUL: 2006 js_op = javascript()->Multiply(); 2007 break; 2008 case Token::DIV: 2009 js_op = javascript()->Divide(); 2010 break; 2011 case Token::MOD: 2012 js_op = javascript()->Modulus(); 2013 break; 2014 default: 2015 UNREACHABLE(); 2016 js_op = NULL; 2017 } 2018 return NewNode(js_op, left, right); 2019} 2020 2021 2022void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id, 2023 OutputFrameStateCombine combine) { 2024 if (OperatorProperties::HasFrameStateInput(node->op())) { 2025 DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() == 2026 IrOpcode::kDead); 2027 NodeProperties::ReplaceFrameStateInput( 2028 node, environment()->Checkpoint(ast_id, combine)); 2029 } 2030} 2031 2032} 2033} 2034} // namespace v8::internal::compiler 2035