1 // Copyright 2015 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/interpreter/bytecode-generator.h" 6 7 #include "src/ast/compile-time-value.h" 8 #include "src/ast/scopes.h" 9 #include "src/code-stubs.h" 10 #include "src/compilation-info.h" 11 #include "src/compiler.h" 12 #include "src/interpreter/bytecode-flags.h" 13 #include "src/interpreter/bytecode-label.h" 14 #include "src/interpreter/bytecode-register-allocator.h" 15 #include "src/interpreter/control-flow-builders.h" 16 #include "src/objects.h" 17 #include "src/parsing/parse-info.h" 18 #include "src/parsing/token.h" 19 20 namespace v8 { 21 namespace internal { 22 namespace interpreter { 23 24 // Scoped class tracking context objects created by the visitor. Represents 25 // mutations of the context chain within the function body, allowing pushing and 26 // popping of the current {context_register} during visitation. 27 class BytecodeGenerator::ContextScope BASE_EMBEDDED { 28 public: 29 ContextScope(BytecodeGenerator* generator, Scope* scope, 30 bool should_pop_context = true) 31 : generator_(generator), 32 scope_(scope), 33 outer_(generator_->execution_context()), 34 register_(Register::current_context()), 35 depth_(0), 36 should_pop_context_(should_pop_context) { 37 if (outer_) { 38 depth_ = outer_->depth_ + 1; 39 40 // Push the outer context into a new context register. 41 Register outer_context_reg(builder()->first_context_register().index() + 42 outer_->depth_); 43 outer_->set_register(outer_context_reg); 44 generator_->builder()->PushContext(outer_context_reg); 45 } 46 generator_->set_execution_context(this); 47 } 48 49 ~ContextScope() { 50 if (outer_ && should_pop_context_) { 51 DCHECK_EQ(register_.index(), Register::current_context().index()); 52 generator_->builder()->PopContext(outer_->reg()); 53 outer_->set_register(register_); 54 } 55 generator_->set_execution_context(outer_); 56 } 57 58 // Returns the depth of the given |scope| for the current execution context. 59 int ContextChainDepth(Scope* scope) { 60 return scope_->ContextChainLength(scope); 61 } 62 63 // Returns the execution context at |depth| in the current context chain if it 64 // is a function local execution context, otherwise returns nullptr. 65 ContextScope* Previous(int depth) { 66 if (depth > depth_) { 67 return nullptr; 68 } 69 70 ContextScope* previous = this; 71 for (int i = depth; i > 0; --i) { 72 previous = previous->outer_; 73 } 74 return previous; 75 } 76 77 Scope* scope() const { return scope_; } 78 Register reg() const { return register_; } 79 bool ShouldPopContext() { return should_pop_context_; } 80 81 private: 82 const BytecodeArrayBuilder* builder() const { return generator_->builder(); } 83 84 void set_register(Register reg) { register_ = reg; } 85 86 BytecodeGenerator* generator_; 87 Scope* scope_; 88 ContextScope* outer_; 89 Register register_; 90 int depth_; 91 bool should_pop_context_; 92 }; 93 94 // Scoped class for tracking control statements entered by the 95 // visitor. The pattern derives AstGraphBuilder::ControlScope. 96 class BytecodeGenerator::ControlScope BASE_EMBEDDED { 97 public: 98 explicit ControlScope(BytecodeGenerator* generator) 99 : generator_(generator), outer_(generator->execution_control()), 100 context_(generator->execution_context()) { 101 generator_->set_execution_control(this); 102 } 103 virtual ~ControlScope() { generator_->set_execution_control(outer()); } 104 105 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } 106 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } 107 void ReturnAccumulator() { PerformCommand(CMD_RETURN, nullptr); } 108 void ReThrowAccumulator() { PerformCommand(CMD_RETHROW, nullptr); } 109 110 class DeferredCommands; 111 112 protected: 113 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_RETHROW }; 114 void PerformCommand(Command command, Statement* statement); 115 virtual bool Execute(Command command, Statement* statement) = 0; 116 117 BytecodeGenerator* generator() const { return generator_; } 118 ControlScope* outer() const { return outer_; } 119 ContextScope* context() const { return context_; } 120 121 private: 122 BytecodeGenerator* generator_; 123 ControlScope* outer_; 124 ContextScope* context_; 125 126 DISALLOW_COPY_AND_ASSIGN(ControlScope); 127 }; 128 129 // Helper class for a try-finally control scope. It can record intercepted 130 // control-flow commands that cause entry into a finally-block, and re-apply 131 // them after again leaving that block. Special tokens are used to identify 132 // paths going through the finally-block to dispatch after leaving the block. 133 class BytecodeGenerator::ControlScope::DeferredCommands final { 134 public: 135 DeferredCommands(BytecodeGenerator* generator, Register token_register, 136 Register result_register) 137 : generator_(generator), 138 deferred_(generator->zone()), 139 token_register_(token_register), 140 result_register_(result_register) {} 141 142 // One recorded control-flow command. 143 struct Entry { 144 Command command; // The command type being applied on this path. 145 Statement* statement; // The target statement for the command or {nullptr}. 146 int token; // A token identifying this particular path. 147 }; 148 149 // Records a control-flow command while entering the finally-block. This also 150 // generates a new dispatch token that identifies one particular path. This 151 // expects the result to be in the accumulator. 152 void RecordCommand(Command command, Statement* statement) { 153 int token = static_cast<int>(deferred_.size()); 154 deferred_.push_back({command, statement, token}); 155 156 builder()->StoreAccumulatorInRegister(result_register_); 157 builder()->LoadLiteral(Smi::FromInt(token)); 158 builder()->StoreAccumulatorInRegister(token_register_); 159 } 160 161 // Records the dispatch token to be used to identify the re-throw path when 162 // the finally-block has been entered through the exception handler. This 163 // expects the exception to be in the accumulator. 164 void RecordHandlerReThrowPath() { 165 // The accumulator contains the exception object. 166 RecordCommand(CMD_RETHROW, nullptr); 167 } 168 169 // Records the dispatch token to be used to identify the implicit fall-through 170 // path at the end of a try-block into the corresponding finally-block. 171 void RecordFallThroughPath() { 172 builder()->LoadLiteral(Smi::FromInt(-1)); 173 builder()->StoreAccumulatorInRegister(token_register_); 174 } 175 176 // Applies all recorded control-flow commands after the finally-block again. 177 // This generates a dynamic dispatch on the token from the entry point. 178 void ApplyDeferredCommands() { 179 // The fall-through path is covered by the default case, hence +1 here. 180 SwitchBuilder dispatch(builder(), static_cast<int>(deferred_.size() + 1)); 181 for (size_t i = 0; i < deferred_.size(); ++i) { 182 Entry& entry = deferred_[i]; 183 builder()->LoadLiteral(Smi::FromInt(entry.token)); 184 builder()->CompareOperation(Token::EQ_STRICT, token_register_); 185 dispatch.Case(static_cast<int>(i)); 186 } 187 dispatch.DefaultAt(static_cast<int>(deferred_.size())); 188 for (size_t i = 0; i < deferred_.size(); ++i) { 189 Entry& entry = deferred_[i]; 190 dispatch.SetCaseTarget(static_cast<int>(i)); 191 builder()->LoadAccumulatorWithRegister(result_register_); 192 execution_control()->PerformCommand(entry.command, entry.statement); 193 } 194 dispatch.SetCaseTarget(static_cast<int>(deferred_.size())); 195 } 196 197 BytecodeArrayBuilder* builder() { return generator_->builder(); } 198 ControlScope* execution_control() { return generator_->execution_control(); } 199 200 private: 201 BytecodeGenerator* generator_; 202 ZoneVector<Entry> deferred_; 203 Register token_register_; 204 Register result_register_; 205 }; 206 207 // Scoped class for dealing with control flow reaching the function level. 208 class BytecodeGenerator::ControlScopeForTopLevel final 209 : public BytecodeGenerator::ControlScope { 210 public: 211 explicit ControlScopeForTopLevel(BytecodeGenerator* generator) 212 : ControlScope(generator) {} 213 214 protected: 215 bool Execute(Command command, Statement* statement) override { 216 switch (command) { 217 case CMD_BREAK: // We should never see break/continue in top-level. 218 case CMD_CONTINUE: 219 UNREACHABLE(); 220 case CMD_RETURN: 221 generator()->BuildReturn(); 222 return true; 223 case CMD_RETHROW: 224 generator()->BuildReThrow(); 225 return true; 226 } 227 return false; 228 } 229 }; 230 231 // Scoped class for enabling break inside blocks and switch blocks. 232 class BytecodeGenerator::ControlScopeForBreakable final 233 : public BytecodeGenerator::ControlScope { 234 public: 235 ControlScopeForBreakable(BytecodeGenerator* generator, 236 BreakableStatement* statement, 237 BreakableControlFlowBuilder* control_builder) 238 : ControlScope(generator), 239 statement_(statement), 240 control_builder_(control_builder) {} 241 242 protected: 243 bool Execute(Command command, Statement* statement) override { 244 if (statement != statement_) return false; 245 switch (command) { 246 case CMD_BREAK: 247 control_builder_->Break(); 248 return true; 249 case CMD_CONTINUE: 250 case CMD_RETURN: 251 case CMD_RETHROW: 252 break; 253 } 254 return false; 255 } 256 257 private: 258 Statement* statement_; 259 BreakableControlFlowBuilder* control_builder_; 260 }; 261 262 // Scoped class for enabling 'break' and 'continue' in iteration 263 // constructs, e.g. do...while, while..., for... 264 class BytecodeGenerator::ControlScopeForIteration final 265 : public BytecodeGenerator::ControlScope { 266 public: 267 ControlScopeForIteration(BytecodeGenerator* generator, 268 IterationStatement* statement, 269 LoopBuilder* loop_builder) 270 : ControlScope(generator), 271 statement_(statement), 272 loop_builder_(loop_builder) { 273 generator->loop_depth_++; 274 } 275 ~ControlScopeForIteration() { generator()->loop_depth_--; } 276 277 protected: 278 bool Execute(Command command, Statement* statement) override { 279 if (statement != statement_) return false; 280 switch (command) { 281 case CMD_BREAK: 282 loop_builder_->Break(); 283 return true; 284 case CMD_CONTINUE: 285 loop_builder_->Continue(); 286 return true; 287 case CMD_RETURN: 288 case CMD_RETHROW: 289 break; 290 } 291 return false; 292 } 293 294 private: 295 Statement* statement_; 296 LoopBuilder* loop_builder_; 297 }; 298 299 // Scoped class for enabling 'throw' in try-catch constructs. 300 class BytecodeGenerator::ControlScopeForTryCatch final 301 : public BytecodeGenerator::ControlScope { 302 public: 303 ControlScopeForTryCatch(BytecodeGenerator* generator, 304 TryCatchBuilder* try_catch_builder) 305 : ControlScope(generator) {} 306 307 protected: 308 bool Execute(Command command, Statement* statement) override { 309 switch (command) { 310 case CMD_BREAK: 311 case CMD_CONTINUE: 312 case CMD_RETURN: 313 break; 314 case CMD_RETHROW: 315 generator()->BuildReThrow(); 316 return true; 317 } 318 return false; 319 } 320 }; 321 322 // Scoped class for enabling control flow through try-finally constructs. 323 class BytecodeGenerator::ControlScopeForTryFinally final 324 : public BytecodeGenerator::ControlScope { 325 public: 326 ControlScopeForTryFinally(BytecodeGenerator* generator, 327 TryFinallyBuilder* try_finally_builder, 328 DeferredCommands* commands) 329 : ControlScope(generator), 330 try_finally_builder_(try_finally_builder), 331 commands_(commands) {} 332 333 protected: 334 bool Execute(Command command, Statement* statement) override { 335 switch (command) { 336 case CMD_BREAK: 337 case CMD_CONTINUE: 338 case CMD_RETURN: 339 case CMD_RETHROW: 340 commands_->RecordCommand(command, statement); 341 try_finally_builder_->LeaveTry(); 342 return true; 343 } 344 return false; 345 } 346 347 private: 348 TryFinallyBuilder* try_finally_builder_; 349 DeferredCommands* commands_; 350 }; 351 352 void BytecodeGenerator::ControlScope::PerformCommand(Command command, 353 Statement* statement) { 354 ControlScope* current = this; 355 ContextScope* context = generator()->execution_context(); 356 // Pop context to the expected depth but do not pop the outermost context. 357 if (context != current->context() && context->ShouldPopContext()) { 358 generator()->builder()->PopContext(current->context()->reg()); 359 } 360 do { 361 if (current->Execute(command, statement)) { 362 return; 363 } 364 current = current->outer(); 365 if (current->context() != context && context->ShouldPopContext()) { 366 // Pop context to the expected depth. 367 // TODO(rmcilroy): Only emit a single context pop. 368 generator()->builder()->PopContext(current->context()->reg()); 369 } 370 } while (current != nullptr); 371 UNREACHABLE(); 372 } 373 374 class BytecodeGenerator::RegisterAllocationScope { 375 public: 376 explicit RegisterAllocationScope(BytecodeGenerator* generator) 377 : generator_(generator), 378 outer_next_register_index_( 379 generator->register_allocator()->next_register_index()) {} 380 381 virtual ~RegisterAllocationScope() { 382 generator_->register_allocator()->ReleaseRegisters( 383 outer_next_register_index_); 384 } 385 386 private: 387 BytecodeGenerator* generator_; 388 int outer_next_register_index_; 389 390 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope); 391 }; 392 393 // Scoped base class for determining how the result of an expression will be 394 // used. 395 class BytecodeGenerator::ExpressionResultScope { 396 public: 397 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) 398 : generator_(generator), 399 kind_(kind), 400 outer_(generator->execution_result()), 401 allocator_(generator) { 402 generator_->set_execution_result(this); 403 } 404 405 virtual ~ExpressionResultScope() { 406 generator_->set_execution_result(outer_); 407 } 408 409 bool IsEffect() const { return kind_ == Expression::kEffect; } 410 bool IsValue() const { return kind_ == Expression::kValue; } 411 bool IsTest() const { return kind_ == Expression::kTest; } 412 413 TestResultScope* AsTest() { 414 DCHECK(IsTest()); 415 return reinterpret_cast<TestResultScope*>(this); 416 } 417 418 private: 419 BytecodeGenerator* generator_; 420 Expression::Context kind_; 421 ExpressionResultScope* outer_; 422 RegisterAllocationScope allocator_; 423 424 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); 425 }; 426 427 // Scoped class used when the result of the current expression is not 428 // expected to produce a result. 429 class BytecodeGenerator::EffectResultScope final 430 : public ExpressionResultScope { 431 public: 432 explicit EffectResultScope(BytecodeGenerator* generator) 433 : ExpressionResultScope(generator, Expression::kEffect) {} 434 }; 435 436 // Scoped class used when the result of the current expression to be 437 // evaluated should go into the interpreter's accumulator. 438 class BytecodeGenerator::ValueResultScope final : public ExpressionResultScope { 439 public: 440 explicit ValueResultScope(BytecodeGenerator* generator) 441 : ExpressionResultScope(generator, Expression::kValue) {} 442 }; 443 444 // Scoped class used when the result of the current expression to be 445 // evaluated is only tested with jumps to two branches. 446 class BytecodeGenerator::TestResultScope final : public ExpressionResultScope { 447 public: 448 TestResultScope(BytecodeGenerator* generator, BytecodeLabels* then_labels, 449 BytecodeLabels* else_labels, TestFallthrough fallthrough) 450 : ExpressionResultScope(generator, Expression::kTest), 451 then_labels_(then_labels), 452 else_labels_(else_labels), 453 fallthrough_(fallthrough), 454 result_consumed_by_test_(false) {} 455 456 // Used when code special cases for TestResultScope and consumes any 457 // possible value by testing and jumping to a then/else label. 458 void SetResultConsumedByTest() { 459 result_consumed_by_test_ = true; 460 } 461 462 bool ResultConsumedByTest() { return result_consumed_by_test_; } 463 464 BytecodeLabel* NewThenLabel() { return then_labels_->New(); } 465 BytecodeLabel* NewElseLabel() { return else_labels_->New(); } 466 467 BytecodeLabels* then_labels() const { return then_labels_; } 468 BytecodeLabels* else_labels() const { return else_labels_; } 469 470 TestFallthrough fallthrough() const { return fallthrough_; } 471 TestFallthrough inverted_fallthrough() const { 472 switch (fallthrough_) { 473 case TestFallthrough::kThen: 474 return TestFallthrough::kElse; 475 case TestFallthrough::kElse: 476 return TestFallthrough::kThen; 477 default: 478 return TestFallthrough::kNone; 479 } 480 } 481 482 private: 483 BytecodeLabels* then_labels_; 484 BytecodeLabels* else_labels_; 485 TestFallthrough fallthrough_; 486 bool result_consumed_by_test_; 487 488 DISALLOW_COPY_AND_ASSIGN(TestResultScope); 489 }; 490 491 // Used to build a list of global declaration initial value pairs. 492 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject { 493 public: 494 explicit GlobalDeclarationsBuilder(Zone* zone) 495 : declarations_(0, zone), 496 constant_pool_entry_(0), 497 has_constant_pool_entry_(false) {} 498 499 void AddFunctionDeclaration(FeedbackVectorSlot slot, FunctionLiteral* func) { 500 DCHECK(!slot.IsInvalid()); 501 declarations_.push_back(std::make_pair(slot, func)); 502 } 503 504 void AddUndefinedDeclaration(FeedbackVectorSlot slot) { 505 DCHECK(!slot.IsInvalid()); 506 declarations_.push_back(std::make_pair(slot, nullptr)); 507 } 508 509 Handle<FixedArray> AllocateDeclarationPairs(CompilationInfo* info) { 510 DCHECK(has_constant_pool_entry_); 511 int array_index = 0; 512 Handle<FixedArray> pairs = info->isolate()->factory()->NewFixedArray( 513 static_cast<int>(declarations_.size() * 2), TENURED); 514 for (std::pair<FeedbackVectorSlot, FunctionLiteral*> declaration : 515 declarations_) { 516 FunctionLiteral* func = declaration.second; 517 Handle<Object> initial_value; 518 if (func == nullptr) { 519 initial_value = info->isolate()->factory()->undefined_value(); 520 } else { 521 initial_value = 522 Compiler::GetSharedFunctionInfo(func, info->script(), info); 523 } 524 525 // Return a null handle if any initial values can't be created. Caller 526 // will set stack overflow. 527 if (initial_value.is_null()) return Handle<FixedArray>(); 528 529 pairs->set(array_index++, Smi::FromInt(declaration.first.ToInt())); 530 pairs->set(array_index++, *initial_value); 531 } 532 return pairs; 533 } 534 535 size_t constant_pool_entry() { 536 DCHECK(has_constant_pool_entry_); 537 return constant_pool_entry_; 538 } 539 540 void set_constant_pool_entry(size_t constant_pool_entry) { 541 DCHECK(!empty()); 542 DCHECK(!has_constant_pool_entry_); 543 constant_pool_entry_ = constant_pool_entry; 544 has_constant_pool_entry_ = true; 545 } 546 547 bool empty() { return declarations_.empty(); } 548 549 private: 550 ZoneVector<std::pair<FeedbackVectorSlot, FunctionLiteral*>> declarations_; 551 size_t constant_pool_entry_; 552 bool has_constant_pool_entry_; 553 }; 554 555 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) 556 : zone_(info->zone()), 557 builder_(new (zone()) BytecodeArrayBuilder( 558 info->isolate(), info->zone(), info->num_parameters_including_this(), 559 info->scope()->MaxNestedContextChainLength(), 560 info->scope()->num_stack_slots(), info->literal(), 561 info->SourcePositionRecordingMode())), 562 info_(info), 563 scope_(info->scope()), 564 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())), 565 global_declarations_(0, info->zone()), 566 function_literals_(0, info->zone()), 567 native_function_literals_(0, info->zone()), 568 execution_control_(nullptr), 569 execution_context_(nullptr), 570 execution_result_(nullptr), 571 generator_resume_points_(info->literal()->yield_count(), info->zone()), 572 generator_state_(), 573 loop_depth_(0), 574 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), 575 empty_fixed_array_(info->isolate()->factory()->empty_fixed_array()) { 576 AstValueFactory* ast_value_factory = info->parse_info()->ast_value_factory(); 577 const AstRawString* prototype_string = ast_value_factory->prototype_string(); 578 ast_value_factory->Internalize(info->isolate()); 579 prototype_string_ = prototype_string->string(); 580 } 581 582 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { 583 AllocateDeferredConstants(); 584 if (HasStackOverflow()) return Handle<BytecodeArray>(); 585 return builder()->ToBytecodeArray(isolate); 586 } 587 588 void BytecodeGenerator::AllocateDeferredConstants() { 589 // Build global declaration pair arrays. 590 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { 591 Handle<FixedArray> declarations = 592 globals_builder->AllocateDeclarationPairs(info()); 593 if (declarations.is_null()) return SetStackOverflow(); 594 builder()->InsertConstantPoolEntryAt(globals_builder->constant_pool_entry(), 595 declarations); 596 } 597 598 // Find or build shared function infos. 599 for (std::pair<FunctionLiteral*, size_t> literal : function_literals_) { 600 FunctionLiteral* expr = literal.first; 601 Handle<SharedFunctionInfo> shared_info = 602 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); 603 if (shared_info.is_null()) return SetStackOverflow(); 604 builder()->InsertConstantPoolEntryAt(literal.second, shared_info); 605 } 606 607 // Find or build shared function infos for the native function templates. 608 for (std::pair<NativeFunctionLiteral*, size_t> literal : 609 native_function_literals_) { 610 NativeFunctionLiteral* expr = literal.first; 611 Handle<SharedFunctionInfo> shared_info = 612 Compiler::GetSharedFunctionInfoForNative(expr->extension(), 613 expr->name()); 614 if (shared_info.is_null()) return SetStackOverflow(); 615 builder()->InsertConstantPoolEntryAt(literal.second, shared_info); 616 } 617 } 618 619 void BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) { 620 DisallowHeapAllocation no_allocation; 621 DisallowHandleAllocation no_handles; 622 DisallowHandleDereference no_deref; 623 624 InitializeAstVisitor(stack_limit); 625 626 // Initialize the incoming context. 627 ContextScope incoming_context(this, scope(), false); 628 629 // Initialize control scope. 630 ControlScopeForTopLevel control(this); 631 632 RegisterAllocationScope register_scope(this); 633 634 if (IsResumableFunction(info()->literal()->kind())) { 635 generator_state_ = register_allocator()->NewRegister(); 636 VisitGeneratorPrologue(); 637 } 638 639 if (scope()->NeedsContext()) { 640 // Push a new inner context scope for the function. 641 BuildNewLocalActivationContext(); 642 ContextScope local_function_context(this, scope(), false); 643 BuildLocalActivationContextInitialization(); 644 GenerateBytecodeBody(); 645 } else { 646 GenerateBytecodeBody(); 647 } 648 649 // In generator functions, we may not have visited every yield in the AST 650 // since we skip some obviously dead code. Hence the generated bytecode may 651 // contain jumps to unbound labels (resume points that will never be used). 652 // We bind these now. 653 for (auto& label : generator_resume_points_) { 654 if (!label.is_bound()) builder()->Bind(&label); 655 } 656 657 // Emit an implicit return instruction in case control flow can fall off the 658 // end of the function without an explicit return being present on all paths. 659 if (builder()->RequiresImplicitReturn()) { 660 builder()->LoadUndefined(); 661 BuildReturn(); 662 } 663 DCHECK(!builder()->RequiresImplicitReturn()); 664 } 665 666 void BytecodeGenerator::GenerateBytecodeBody() { 667 // Build the arguments object if it is used. 668 VisitArgumentsObject(scope()->arguments()); 669 670 // Build rest arguments array if it is used. 671 Variable* rest_parameter = scope()->rest_parameter(); 672 VisitRestArgumentsArray(rest_parameter); 673 674 // Build assignment to {.this_function} variable if it is used. 675 VisitThisFunctionVariable(scope()->this_function_var()); 676 677 // Build assignment to {new.target} variable if it is used. 678 VisitNewTargetVariable(scope()->new_target_var()); 679 680 // Emit tracing call if requested to do so. 681 if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter); 682 683 // Visit declarations within the function scope. 684 VisitDeclarations(scope()->declarations()); 685 686 // Emit initializing assignments for module namespace imports (if any). 687 VisitModuleNamespaceImports(); 688 689 // Perform a stack-check before the body. 690 builder()->StackCheck(info()->literal()->start_position()); 691 692 // Visit statements in the function body. 693 VisitStatements(info()->literal()->body()); 694 } 695 696 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index, 697 size_t size, 698 ZoneVector<BytecodeLabel>& targets) { 699 // TODO(neis): Optimize this by using a proper jump table. 700 DCHECK_LE(start_index + size, targets.size()); 701 for (size_t i = start_index; i < start_index + size; i++) { 702 builder() 703 ->LoadLiteral(Smi::FromInt(static_cast<int>(i))) 704 .CompareOperation(Token::Value::EQ_STRICT, index) 705 .JumpIfTrue(&(targets[i])); 706 } 707 BuildAbort(BailoutReason::kInvalidJumpTableIndex); 708 } 709 710 void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt, 711 LoopBuilder* loop_builder) { 712 // Recall that stmt->yield_count() is always zero inside ordinary 713 // (i.e. non-generator) functions. 714 715 // Collect all labels for generator resume points within the loop (if any) so 716 // that they can be bound to the loop header below. Also create fresh labels 717 // for these resume points, to be used inside the loop. 718 ZoneVector<BytecodeLabel> resume_points_in_loop(zone()); 719 size_t first_yield = stmt->first_yield_id(); 720 DCHECK_LE(first_yield + stmt->yield_count(), generator_resume_points_.size()); 721 for (size_t id = first_yield; id < first_yield + stmt->yield_count(); id++) { 722 auto& label = generator_resume_points_[id]; 723 resume_points_in_loop.push_back(label); 724 generator_resume_points_[id] = BytecodeLabel(); 725 } 726 727 loop_builder->LoopHeader(&resume_points_in_loop); 728 729 if (stmt->yield_count() > 0) { 730 // If we are not resuming, fall through to loop body. 731 // If we are resuming, perform state dispatch. 732 BytecodeLabel not_resuming; 733 builder() 734 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) 735 .CompareOperation(Token::Value::EQ, generator_state_) 736 .JumpIfTrue(¬_resuming); 737 BuildIndexedJump(generator_state_, first_yield, 738 stmt->yield_count(), generator_resume_points_); 739 builder()->Bind(¬_resuming); 740 } 741 } 742 743 void BytecodeGenerator::VisitGeneratorPrologue() { 744 // The generator resume trampoline abuses the new.target register both to 745 // indicate that this is a resume call and to pass in the generator object. 746 // In ordinary calls, new.target is always undefined because generator 747 // functions are non-constructable. 748 Register generator_object = Register::new_target(); 749 BytecodeLabel regular_call; 750 builder() 751 ->LoadAccumulatorWithRegister(generator_object) 752 .JumpIfUndefined(®ular_call); 753 754 // This is a resume call. Restore registers and perform state dispatch. 755 // (The current context has already been restored by the trampoline.) 756 builder() 757 ->ResumeGenerator(generator_object) 758 .StoreAccumulatorInRegister(generator_state_); 759 BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(), 760 generator_resume_points_); 761 762 builder() 763 ->Bind(®ular_call) 764 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) 765 .StoreAccumulatorInRegister(generator_state_); 766 // This is a regular call. Fall through to the ordinary function prologue, 767 // after which we will run into the generator object creation and other extra 768 // code inserted by the parser. 769 } 770 771 void BytecodeGenerator::VisitBlock(Block* stmt) { 772 // Visit declarations and statements. 773 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { 774 BuildNewLocalBlockContext(stmt->scope()); 775 ContextScope scope(this, stmt->scope()); 776 VisitBlockDeclarationsAndStatements(stmt); 777 } else { 778 VisitBlockDeclarationsAndStatements(stmt); 779 } 780 } 781 782 void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) { 783 BlockBuilder block_builder(builder()); 784 ControlScopeForBreakable execution_control(this, stmt, &block_builder); 785 if (stmt->scope() != nullptr) { 786 VisitDeclarations(stmt->scope()->declarations()); 787 } 788 VisitStatements(stmt->statements()); 789 if (stmt->labels() != nullptr) block_builder.EndBlock(); 790 } 791 792 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { 793 Variable* variable = decl->proxy()->var(); 794 switch (variable->location()) { 795 case VariableLocation::UNALLOCATED: { 796 DCHECK(!variable->binding_needs_init()); 797 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); 798 globals_builder()->AddUndefinedDeclaration(slot); 799 break; 800 } 801 case VariableLocation::LOCAL: 802 if (variable->binding_needs_init()) { 803 Register destination(variable->index()); 804 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); 805 } 806 break; 807 case VariableLocation::PARAMETER: 808 if (variable->binding_needs_init()) { 809 // The parameter indices are shifted by 1 (receiver is variable 810 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 811 Register destination(builder()->Parameter(variable->index() + 1)); 812 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); 813 } 814 break; 815 case VariableLocation::CONTEXT: 816 if (variable->binding_needs_init()) { 817 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); 818 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(), 819 variable->index(), 0); 820 } 821 break; 822 case VariableLocation::LOOKUP: { 823 DCHECK_EQ(VAR, variable->mode()); 824 DCHECK(!variable->binding_needs_init()); 825 826 Register name = register_allocator()->NewRegister(); 827 828 builder() 829 ->LoadLiteral(variable->name()) 830 .StoreAccumulatorInRegister(name) 831 .CallRuntime(Runtime::kDeclareEvalVar, name); 832 break; 833 } 834 case VariableLocation::MODULE: 835 if (variable->IsExport() && variable->binding_needs_init()) { 836 builder()->LoadTheHole(); 837 BuildVariableAssignment(variable, Token::INIT, 838 FeedbackVectorSlot::Invalid(), 839 HoleCheckMode::kElided); 840 } 841 // Nothing to do for imports. 842 break; 843 } 844 } 845 846 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { 847 Variable* variable = decl->proxy()->var(); 848 DCHECK(variable->mode() == LET || variable->mode() == VAR); 849 switch (variable->location()) { 850 case VariableLocation::UNALLOCATED: { 851 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); 852 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); 853 break; 854 } 855 case VariableLocation::PARAMETER: 856 case VariableLocation::LOCAL: { 857 VisitForAccumulatorValue(decl->fun()); 858 BuildVariableAssignment(variable, Token::INIT, 859 FeedbackVectorSlot::Invalid(), 860 HoleCheckMode::kElided); 861 break; 862 } 863 case VariableLocation::CONTEXT: { 864 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); 865 VisitForAccumulatorValue(decl->fun()); 866 builder()->StoreContextSlot(execution_context()->reg(), variable->index(), 867 0); 868 break; 869 } 870 case VariableLocation::LOOKUP: { 871 RegisterList args = register_allocator()->NewRegisterList(2); 872 builder() 873 ->LoadLiteral(variable->name()) 874 .StoreAccumulatorInRegister(args[0]); 875 VisitForAccumulatorValue(decl->fun()); 876 builder()->StoreAccumulatorInRegister(args[1]).CallRuntime( 877 Runtime::kDeclareEvalFunction, args); 878 break; 879 } 880 case VariableLocation::MODULE: 881 DCHECK_EQ(variable->mode(), LET); 882 DCHECK(variable->IsExport()); 883 VisitForAccumulatorValue(decl->fun()); 884 BuildVariableAssignment(variable, Token::INIT, 885 FeedbackVectorSlot::Invalid(), 886 HoleCheckMode::kElided); 887 break; 888 } 889 } 890 891 void BytecodeGenerator::VisitModuleNamespaceImports() { 892 if (!scope()->is_module_scope()) return; 893 894 RegisterAllocationScope register_scope(this); 895 Register module_request = register_allocator()->NewRegister(); 896 897 ModuleDescriptor* descriptor = scope()->AsModuleScope()->module(); 898 for (auto entry : descriptor->namespace_imports()) { 899 builder() 900 ->LoadLiteral(Smi::FromInt(entry->module_request)) 901 .StoreAccumulatorInRegister(module_request) 902 .CallRuntime(Runtime::kGetModuleNamespace, module_request); 903 Variable* var = scope()->LookupLocal(entry->local_name); 904 DCHECK_NOT_NULL(var); 905 BuildVariableAssignment(var, Token::INIT, FeedbackVectorSlot::Invalid(), 906 HoleCheckMode::kElided); 907 } 908 } 909 910 void BytecodeGenerator::VisitDeclarations(Declaration::List* declarations) { 911 RegisterAllocationScope register_scope(this); 912 DCHECK(globals_builder()->empty()); 913 for (Declaration* decl : *declarations) { 914 RegisterAllocationScope register_scope(this); 915 Visit(decl); 916 } 917 if (globals_builder()->empty()) return; 918 919 globals_builder()->set_constant_pool_entry( 920 builder()->AllocateConstantPoolEntry()); 921 int encoded_flags = info()->GetDeclareGlobalsFlags(); 922 923 // Emit code to declare globals. 924 RegisterList args = register_allocator()->NewRegisterList(3); 925 builder() 926 ->LoadConstantPoolEntry(globals_builder()->constant_pool_entry()) 927 .StoreAccumulatorInRegister(args[0]) 928 .LoadLiteral(Smi::FromInt(encoded_flags)) 929 .StoreAccumulatorInRegister(args[1]) 930 .MoveRegister(Register::function_closure(), args[2]) 931 .CallRuntime(Runtime::kDeclareGlobalsForInterpreter, args); 932 933 // Push and reset globals builder. 934 global_declarations_.push_back(globals_builder()); 935 globals_builder_ = new (zone()) GlobalDeclarationsBuilder(zone()); 936 } 937 938 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { 939 for (int i = 0; i < statements->length(); i++) { 940 // Allocate an outer register allocations scope for the statement. 941 RegisterAllocationScope allocation_scope(this); 942 Statement* stmt = statements->at(i); 943 Visit(stmt); 944 if (stmt->IsJump()) break; 945 } 946 } 947 948 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 949 builder()->SetStatementPosition(stmt); 950 VisitForEffect(stmt->expression()); 951 } 952 953 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 954 } 955 956 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { 957 builder()->SetStatementPosition(stmt); 958 if (stmt->condition()->ToBooleanIsTrue()) { 959 // Generate then block unconditionally as always true. 960 Visit(stmt->then_statement()); 961 } else if (stmt->condition()->ToBooleanIsFalse()) { 962 // Generate else block unconditionally if it exists. 963 if (stmt->HasElseStatement()) { 964 Visit(stmt->else_statement()); 965 } 966 } else { 967 // TODO(oth): If then statement is BreakStatement or 968 // ContinueStatement we can reduce number of generated 969 // jump/jump_ifs here. See BasicLoops test. 970 BytecodeLabel end_label; 971 BytecodeLabels then_labels(zone()), else_labels(zone()); 972 VisitForTest(stmt->condition(), &then_labels, &else_labels, 973 TestFallthrough::kThen); 974 975 then_labels.Bind(builder()); 976 Visit(stmt->then_statement()); 977 978 if (stmt->HasElseStatement()) { 979 builder()->Jump(&end_label); 980 else_labels.Bind(builder()); 981 Visit(stmt->else_statement()); 982 } else { 983 else_labels.Bind(builder()); 984 } 985 builder()->Bind(&end_label); 986 } 987 } 988 989 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( 990 SloppyBlockFunctionStatement* stmt) { 991 Visit(stmt->statement()); 992 } 993 994 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { 995 builder()->SetStatementPosition(stmt); 996 execution_control()->Continue(stmt->target()); 997 } 998 999 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 1000 builder()->SetStatementPosition(stmt); 1001 execution_control()->Break(stmt->target()); 1002 } 1003 1004 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 1005 builder()->SetStatementPosition(stmt); 1006 VisitForAccumulatorValue(stmt->expression()); 1007 execution_control()->ReturnAccumulator(); 1008 } 1009 1010 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 1011 builder()->SetStatementPosition(stmt); 1012 VisitForAccumulatorValue(stmt->expression()); 1013 BuildNewLocalWithContext(stmt->scope()); 1014 VisitInScope(stmt->statement(), stmt->scope()); 1015 } 1016 1017 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 1018 // We need this scope because we visit for register values. We have to 1019 // maintain a execution result scope where registers can be allocated. 1020 ZoneList<CaseClause*>* clauses = stmt->cases(); 1021 SwitchBuilder switch_builder(builder(), clauses->length()); 1022 ControlScopeForBreakable scope(this, stmt, &switch_builder); 1023 int default_index = -1; 1024 1025 builder()->SetStatementPosition(stmt); 1026 1027 // Keep the switch value in a register until a case matches. 1028 Register tag = VisitForRegisterValue(stmt->tag()); 1029 1030 // Iterate over all cases and create nodes for label comparison. 1031 for (int i = 0; i < clauses->length(); i++) { 1032 CaseClause* clause = clauses->at(i); 1033 1034 // The default is not a test, remember index. 1035 if (clause->is_default()) { 1036 default_index = i; 1037 continue; 1038 } 1039 1040 // Perform label comparison as if via '===' with tag. 1041 VisitForAccumulatorValue(clause->label()); 1042 builder()->CompareOperation( 1043 Token::Value::EQ_STRICT, tag, 1044 feedback_index(clause->CompareOperationFeedbackSlot())); 1045 switch_builder.Case(i); 1046 } 1047 1048 if (default_index >= 0) { 1049 // Emit default jump if there is a default case. 1050 switch_builder.DefaultAt(default_index); 1051 } else { 1052 // Otherwise if we have reached here none of the cases matched, so jump to 1053 // the end. 1054 switch_builder.Break(); 1055 } 1056 1057 // Iterate over all cases and create the case bodies. 1058 for (int i = 0; i < clauses->length(); i++) { 1059 CaseClause* clause = clauses->at(i); 1060 switch_builder.SetCaseTarget(i); 1061 VisitStatements(clause->statements()); 1062 } 1063 switch_builder.BindBreakTarget(); 1064 } 1065 1066 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { 1067 // Handled entirely in VisitSwitchStatement. 1068 UNREACHABLE(); 1069 } 1070 1071 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt, 1072 LoopBuilder* loop_builder) { 1073 ControlScopeForIteration execution_control(this, stmt, loop_builder); 1074 builder()->StackCheck(stmt->position()); 1075 Visit(stmt->body()); 1076 loop_builder->BindContinueTarget(); 1077 } 1078 1079 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 1080 LoopBuilder loop_builder(builder()); 1081 if (stmt->cond()->ToBooleanIsFalse()) { 1082 VisitIterationBody(stmt, &loop_builder); 1083 } else if (stmt->cond()->ToBooleanIsTrue()) { 1084 VisitIterationHeader(stmt, &loop_builder); 1085 VisitIterationBody(stmt, &loop_builder); 1086 loop_builder.JumpToHeader(loop_depth_); 1087 } else { 1088 VisitIterationHeader(stmt, &loop_builder); 1089 VisitIterationBody(stmt, &loop_builder); 1090 builder()->SetExpressionAsStatementPosition(stmt->cond()); 1091 BytecodeLabels loop_backbranch(zone()); 1092 VisitForTest(stmt->cond(), &loop_backbranch, loop_builder.break_labels(), 1093 TestFallthrough::kThen); 1094 loop_backbranch.Bind(builder()); 1095 loop_builder.JumpToHeader(loop_depth_); 1096 } 1097 loop_builder.EndLoop(); 1098 } 1099 1100 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 1101 if (stmt->cond()->ToBooleanIsFalse()) { 1102 // If the condition is false there is no need to generate the loop. 1103 return; 1104 } 1105 1106 LoopBuilder loop_builder(builder()); 1107 VisitIterationHeader(stmt, &loop_builder); 1108 if (!stmt->cond()->ToBooleanIsTrue()) { 1109 builder()->SetExpressionAsStatementPosition(stmt->cond()); 1110 BytecodeLabels loop_body(zone()); 1111 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), 1112 TestFallthrough::kThen); 1113 loop_body.Bind(builder()); 1114 } 1115 VisitIterationBody(stmt, &loop_builder); 1116 loop_builder.JumpToHeader(loop_depth_); 1117 loop_builder.EndLoop(); 1118 } 1119 1120 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 1121 if (stmt->init() != nullptr) { 1122 Visit(stmt->init()); 1123 } 1124 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { 1125 // If the condition is known to be false there is no need to generate 1126 // body, next or condition blocks. Init block should be generated. 1127 return; 1128 } 1129 1130 LoopBuilder loop_builder(builder()); 1131 VisitIterationHeader(stmt, &loop_builder); 1132 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { 1133 builder()->SetExpressionAsStatementPosition(stmt->cond()); 1134 BytecodeLabels loop_body(zone()); 1135 VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(), 1136 TestFallthrough::kThen); 1137 loop_body.Bind(builder()); 1138 } 1139 VisitIterationBody(stmt, &loop_builder); 1140 if (stmt->next() != nullptr) { 1141 builder()->SetStatementPosition(stmt->next()); 1142 Visit(stmt->next()); 1143 } 1144 loop_builder.JumpToHeader(loop_depth_); 1145 loop_builder.EndLoop(); 1146 } 1147 1148 void BytecodeGenerator::VisitForInAssignment(Expression* expr, 1149 FeedbackVectorSlot slot) { 1150 DCHECK(expr->IsValidReferenceExpression()); 1151 1152 // Evaluate assignment starting with the value to be stored in the 1153 // accumulator. 1154 Property* property = expr->AsProperty(); 1155 LhsKind assign_type = Property::GetAssignType(property); 1156 switch (assign_type) { 1157 case VARIABLE: { 1158 VariableProxy* proxy = expr->AsVariableProxy(); 1159 BuildVariableAssignment(proxy->var(), Token::ASSIGN, slot, 1160 proxy->hole_check_mode()); 1161 break; 1162 } 1163 case NAMED_PROPERTY: { 1164 RegisterAllocationScope register_scope(this); 1165 Register value = register_allocator()->NewRegister(); 1166 builder()->StoreAccumulatorInRegister(value); 1167 Register object = VisitForRegisterValue(property->obj()); 1168 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); 1169 builder()->LoadAccumulatorWithRegister(value); 1170 builder()->StoreNamedProperty(object, name, feedback_index(slot), 1171 language_mode()); 1172 break; 1173 } 1174 case KEYED_PROPERTY: { 1175 RegisterAllocationScope register_scope(this); 1176 Register value = register_allocator()->NewRegister(); 1177 builder()->StoreAccumulatorInRegister(value); 1178 Register object = VisitForRegisterValue(property->obj()); 1179 Register key = VisitForRegisterValue(property->key()); 1180 builder()->LoadAccumulatorWithRegister(value); 1181 builder()->StoreKeyedProperty(object, key, feedback_index(slot), 1182 language_mode()); 1183 break; 1184 } 1185 case NAMED_SUPER_PROPERTY: { 1186 RegisterAllocationScope register_scope(this); 1187 RegisterList args = register_allocator()->NewRegisterList(4); 1188 builder()->StoreAccumulatorInRegister(args[3]); 1189 SuperPropertyReference* super_property = 1190 property->obj()->AsSuperPropertyReference(); 1191 VisitForRegisterValue(super_property->this_var(), args[0]); 1192 VisitForRegisterValue(super_property->home_object(), args[1]); 1193 builder() 1194 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) 1195 .StoreAccumulatorInRegister(args[2]) 1196 .CallRuntime(StoreToSuperRuntimeId(), args); 1197 break; 1198 } 1199 case KEYED_SUPER_PROPERTY: { 1200 RegisterAllocationScope register_scope(this); 1201 RegisterList args = register_allocator()->NewRegisterList(4); 1202 builder()->StoreAccumulatorInRegister(args[3]); 1203 SuperPropertyReference* super_property = 1204 property->obj()->AsSuperPropertyReference(); 1205 VisitForRegisterValue(super_property->this_var(), args[0]); 1206 VisitForRegisterValue(super_property->home_object(), args[1]); 1207 VisitForRegisterValue(property->key(), args[2]); 1208 builder()->CallRuntime(StoreKeyedToSuperRuntimeId(), args); 1209 break; 1210 } 1211 } 1212 } 1213 1214 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { 1215 if (stmt->subject()->IsNullLiteral() || 1216 stmt->subject()->IsUndefinedLiteral()) { 1217 // ForIn generates lots of code, skip if it wouldn't produce any effects. 1218 return; 1219 } 1220 1221 LoopBuilder loop_builder(builder()); 1222 BytecodeLabel subject_null_label, subject_undefined_label; 1223 1224 // Prepare the state for executing ForIn. 1225 builder()->SetExpressionAsStatementPosition(stmt->subject()); 1226 VisitForAccumulatorValue(stmt->subject()); 1227 builder()->JumpIfUndefined(&subject_undefined_label); 1228 builder()->JumpIfNull(&subject_null_label); 1229 Register receiver = register_allocator()->NewRegister(); 1230 builder()->ConvertAccumulatorToObject(receiver); 1231 1232 // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext. 1233 RegisterList triple = register_allocator()->NewRegisterList(3); 1234 Register cache_length = triple[2]; 1235 builder()->ForInPrepare(receiver, triple); 1236 1237 // Set up loop counter 1238 Register index = register_allocator()->NewRegister(); 1239 builder()->LoadLiteral(Smi::kZero); 1240 builder()->StoreAccumulatorInRegister(index); 1241 1242 // The loop 1243 VisitIterationHeader(stmt, &loop_builder); 1244 builder()->SetExpressionAsStatementPosition(stmt->each()); 1245 builder()->ForInContinue(index, cache_length); 1246 loop_builder.BreakIfFalse(); 1247 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); 1248 builder()->ForInNext(receiver, index, triple.Truncate(2), 1249 feedback_index(slot)); 1250 loop_builder.ContinueIfUndefined(); 1251 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); 1252 VisitIterationBody(stmt, &loop_builder); 1253 builder()->ForInStep(index); 1254 builder()->StoreAccumulatorInRegister(index); 1255 loop_builder.JumpToHeader(loop_depth_); 1256 loop_builder.EndLoop(); 1257 builder()->Bind(&subject_null_label); 1258 builder()->Bind(&subject_undefined_label); 1259 } 1260 1261 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 1262 LoopBuilder loop_builder(builder()); 1263 1264 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator()); 1265 VisitForEffect(stmt->assign_iterator()); 1266 1267 VisitIterationHeader(stmt, &loop_builder); 1268 builder()->SetExpressionAsStatementPosition(stmt->next_result()); 1269 VisitForEffect(stmt->next_result()); 1270 VisitForAccumulatorValue(stmt->result_done()); 1271 loop_builder.BreakIfTrue(); 1272 1273 VisitForEffect(stmt->assign_each()); 1274 VisitIterationBody(stmt, &loop_builder); 1275 loop_builder.JumpToHeader(loop_depth_); 1276 loop_builder.EndLoop(); 1277 } 1278 1279 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { 1280 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); 1281 1282 // Preserve the context in a dedicated register, so that it can be restored 1283 // when the handler is entered by the stack-unwinding machinery. 1284 // TODO(mstarzinger): Be smarter about register allocation. 1285 Register context = register_allocator()->NewRegister(); 1286 builder()->MoveRegister(Register::current_context(), context); 1287 1288 // Evaluate the try-block inside a control scope. This simulates a handler 1289 // that is intercepting 'throw' control commands. 1290 try_control_builder.BeginTry(context); 1291 { 1292 ControlScopeForTryCatch scope(this, &try_control_builder); 1293 Visit(stmt->try_block()); 1294 } 1295 try_control_builder.EndTry(); 1296 1297 // Create a catch scope that binds the exception. 1298 BuildNewLocalCatchContext(stmt->variable(), stmt->scope()); 1299 builder()->StoreAccumulatorInRegister(context); 1300 1301 // If requested, clear message object as we enter the catch block. 1302 if (stmt->clear_pending_message()) { 1303 builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage); 1304 } 1305 1306 // Load the catch context into the accumulator. 1307 builder()->LoadAccumulatorWithRegister(context); 1308 1309 // Evaluate the catch-block. 1310 VisitInScope(stmt->catch_block(), stmt->scope()); 1311 try_control_builder.EndCatch(); 1312 } 1313 1314 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1315 TryFinallyBuilder try_control_builder(builder(), stmt->catch_prediction()); 1316 1317 // We keep a record of all paths that enter the finally-block to be able to 1318 // dispatch to the correct continuation point after the statements in the 1319 // finally-block have been evaluated. 1320 // 1321 // The try-finally construct can enter the finally-block in three ways: 1322 // 1. By exiting the try-block normally, falling through at the end. 1323 // 2. By exiting the try-block with a function-local control flow transfer 1324 // (i.e. through break/continue/return statements). 1325 // 3. By exiting the try-block with a thrown exception. 1326 // 1327 // The result register semantics depend on how the block was entered: 1328 // - ReturnStatement: It represents the return value being returned. 1329 // - ThrowStatement: It represents the exception being thrown. 1330 // - BreakStatement/ContinueStatement: Undefined and not used. 1331 // - Falling through into finally-block: Undefined and not used. 1332 Register token = register_allocator()->NewRegister(); 1333 Register result = register_allocator()->NewRegister(); 1334 ControlScope::DeferredCommands commands(this, token, result); 1335 1336 // Preserve the context in a dedicated register, so that it can be restored 1337 // when the handler is entered by the stack-unwinding machinery. 1338 // TODO(mstarzinger): Be smarter about register allocation. 1339 Register context = register_allocator()->NewRegister(); 1340 builder()->MoveRegister(Register::current_context(), context); 1341 1342 // Evaluate the try-block inside a control scope. This simulates a handler 1343 // that is intercepting all control commands. 1344 try_control_builder.BeginTry(context); 1345 { 1346 ControlScopeForTryFinally scope(this, &try_control_builder, &commands); 1347 Visit(stmt->try_block()); 1348 } 1349 try_control_builder.EndTry(); 1350 1351 // Record fall-through and exception cases. 1352 commands.RecordFallThroughPath(); 1353 try_control_builder.LeaveTry(); 1354 try_control_builder.BeginHandler(); 1355 commands.RecordHandlerReThrowPath(); 1356 1357 // Pending message object is saved on entry. 1358 try_control_builder.BeginFinally(); 1359 Register message = context; // Reuse register. 1360 1361 // Clear message object as we enter the finally block. 1362 builder() 1363 ->CallRuntime(Runtime::kInterpreterClearPendingMessage) 1364 .StoreAccumulatorInRegister(message); 1365 1366 // Evaluate the finally-block. 1367 Visit(stmt->finally_block()); 1368 try_control_builder.EndFinally(); 1369 1370 // Pending message object is restored on exit. 1371 builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message); 1372 1373 // Dynamic dispatch after the finally-block. 1374 commands.ApplyDeferredCommands(); 1375 } 1376 1377 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { 1378 builder()->SetStatementPosition(stmt); 1379 builder()->Debugger(); 1380 } 1381 1382 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 1383 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(), 1384 scope()->is_function_scope()); 1385 size_t entry = builder()->AllocateConstantPoolEntry(); 1386 builder()->CreateClosure(entry, flags); 1387 function_literals_.push_back(std::make_pair(expr, entry)); 1388 } 1389 1390 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { 1391 VisitClassLiteralForRuntimeDefinition(expr); 1392 1393 // Load the "prototype" from the constructor. 1394 RegisterList args = register_allocator()->NewRegisterList(2); 1395 Register literal = args[0]; 1396 Register prototype = args[1]; 1397 FeedbackVectorSlot slot = expr->PrototypeSlot(); 1398 builder() 1399 ->StoreAccumulatorInRegister(literal) 1400 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) 1401 .StoreAccumulatorInRegister(prototype); 1402 1403 VisitClassLiteralProperties(expr, literal, prototype); 1404 builder()->CallRuntime(Runtime::kToFastProperties, literal); 1405 // Assign to class variable. 1406 if (expr->class_variable_proxy() != nullptr) { 1407 VariableProxy* proxy = expr->class_variable_proxy(); 1408 FeedbackVectorSlot slot = expr->NeedsProxySlot() 1409 ? expr->ProxySlot() 1410 : FeedbackVectorSlot::Invalid(); 1411 BuildVariableAssignment(proxy->var(), Token::INIT, slot, 1412 HoleCheckMode::kElided); 1413 } 1414 } 1415 1416 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( 1417 ClassLiteral* expr) { 1418 RegisterAllocationScope register_scope(this); 1419 RegisterList args = register_allocator()->NewRegisterList(4); 1420 VisitForAccumulatorValueOrTheHole(expr->extends()); 1421 builder()->StoreAccumulatorInRegister(args[0]); 1422 VisitForRegisterValue(expr->constructor(), args[1]); 1423 builder() 1424 ->LoadLiteral(Smi::FromInt(expr->start_position())) 1425 .StoreAccumulatorInRegister(args[2]) 1426 .LoadLiteral(Smi::FromInt(expr->end_position())) 1427 .StoreAccumulatorInRegister(args[3]) 1428 .CallRuntime(Runtime::kDefineClass, args); 1429 } 1430 1431 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, 1432 Register literal, 1433 Register prototype) { 1434 RegisterAllocationScope register_scope(this); 1435 RegisterList args = register_allocator()->NewRegisterList(5); 1436 Register receiver = args[0], key = args[1], value = args[2], attr = args[3], 1437 set_function_name = args[4]; 1438 1439 bool attr_assigned = false; 1440 Register old_receiver = Register::invalid_value(); 1441 1442 // Create nodes to store method values into the literal. 1443 for (int i = 0; i < expr->properties()->length(); i++) { 1444 ClassLiteral::Property* property = expr->properties()->at(i); 1445 1446 // Set-up receiver. 1447 Register new_receiver = property->is_static() ? literal : prototype; 1448 if (new_receiver != old_receiver) { 1449 builder()->MoveRegister(new_receiver, receiver); 1450 old_receiver = new_receiver; 1451 } 1452 1453 VisitForAccumulatorValue(property->key()); 1454 builder()->ConvertAccumulatorToName(key); 1455 1456 if (property->is_static() && property->is_computed_name()) { 1457 // The static prototype property is read only. We handle the non computed 1458 // property name case in the parser. Since this is the only case where we 1459 // need to check for an own read only property we special case this so we 1460 // do not need to do this for every property. 1461 BytecodeLabel done; 1462 builder() 1463 ->LoadLiteral(prototype_string()) 1464 .CompareOperation(Token::Value::EQ_STRICT, key) 1465 .JumpIfFalse(&done) 1466 .CallRuntime(Runtime::kThrowStaticPrototypeError) 1467 .Bind(&done); 1468 } 1469 1470 VisitForRegisterValue(property->value(), value); 1471 VisitSetHomeObject(value, receiver, property); 1472 1473 if (!attr_assigned) { 1474 builder() 1475 ->LoadLiteral(Smi::FromInt(DONT_ENUM)) 1476 .StoreAccumulatorInRegister(attr); 1477 attr_assigned = true; 1478 } 1479 1480 switch (property->kind()) { 1481 case ClassLiteral::Property::METHOD: { 1482 builder() 1483 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName())) 1484 .StoreAccumulatorInRegister(set_function_name) 1485 .CallRuntime(Runtime::kDefineDataPropertyInLiteral, args); 1486 break; 1487 } 1488 case ClassLiteral::Property::GETTER: { 1489 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 1490 args.Truncate(4)); 1491 break; 1492 } 1493 case ClassLiteral::Property::SETTER: { 1494 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 1495 args.Truncate(4)); 1496 break; 1497 } 1498 case ClassLiteral::Property::FIELD: { 1499 UNREACHABLE(); 1500 break; 1501 } 1502 } 1503 } 1504 } 1505 1506 void BytecodeGenerator::VisitNativeFunctionLiteral( 1507 NativeFunctionLiteral* expr) { 1508 size_t entry = builder()->AllocateConstantPoolEntry(); 1509 builder()->CreateClosure(entry, NOT_TENURED); 1510 native_function_literals_.push_back(std::make_pair(expr, entry)); 1511 } 1512 1513 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { 1514 VisitBlock(expr->block()); 1515 VisitVariableProxy(expr->result()); 1516 } 1517 1518 void BytecodeGenerator::VisitConditional(Conditional* expr) { 1519 if (expr->condition()->ToBooleanIsTrue()) { 1520 // Generate then block unconditionally as always true. 1521 VisitForAccumulatorValue(expr->then_expression()); 1522 } else if (expr->condition()->ToBooleanIsFalse()) { 1523 // Generate else block unconditionally if it exists. 1524 VisitForAccumulatorValue(expr->else_expression()); 1525 } else { 1526 BytecodeLabel end_label; 1527 BytecodeLabels then_labels(zone()), else_labels(zone()); 1528 1529 VisitForTest(expr->condition(), &then_labels, &else_labels, 1530 TestFallthrough::kThen); 1531 1532 then_labels.Bind(builder()); 1533 VisitForAccumulatorValue(expr->then_expression()); 1534 builder()->Jump(&end_label); 1535 1536 else_labels.Bind(builder()); 1537 VisitForAccumulatorValue(expr->else_expression()); 1538 builder()->Bind(&end_label); 1539 } 1540 } 1541 1542 void BytecodeGenerator::VisitLiteral(Literal* expr) { 1543 if (!execution_result()->IsEffect()) { 1544 const AstValue* raw_value = expr->raw_value(); 1545 if (raw_value->IsSmi()) { 1546 builder()->LoadLiteral(raw_value->AsSmi()); 1547 } else if (raw_value->IsUndefined()) { 1548 builder()->LoadUndefined(); 1549 } else if (raw_value->IsTrue()) { 1550 builder()->LoadTrue(); 1551 } else if (raw_value->IsFalse()) { 1552 builder()->LoadFalse(); 1553 } else if (raw_value->IsNull()) { 1554 builder()->LoadNull(); 1555 } else if (raw_value->IsTheHole()) { 1556 builder()->LoadTheHole(); 1557 } else { 1558 builder()->LoadLiteral(raw_value->value()); 1559 } 1560 } 1561 } 1562 1563 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1564 // Materialize a regular expression literal. 1565 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(), 1566 expr->flags()); 1567 } 1568 1569 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1570 // Copy the literal boilerplate. 1571 uint8_t flags = CreateObjectLiteralFlags::Encode( 1572 FastCloneShallowObjectStub::IsSupported(expr), 1573 FastCloneShallowObjectStub::PropertiesCount(expr->properties_count()), 1574 expr->ComputeFlags()); 1575 // If constant properties is an empty fixed array, use our cached 1576 // empty_fixed_array to ensure it's only added to the constant pool once. 1577 Handle<FixedArray> constant_properties = expr->properties_count() == 0 1578 ? empty_fixed_array() 1579 : expr->constant_properties(); 1580 Register literal = register_allocator()->NewRegister(); 1581 builder()->CreateObjectLiteral(constant_properties, expr->literal_index(), 1582 flags, literal); 1583 1584 // Store computed values into the literal. 1585 int property_index = 0; 1586 AccessorTable accessor_table(zone()); 1587 for (; property_index < expr->properties()->length(); property_index++) { 1588 ObjectLiteral::Property* property = expr->properties()->at(property_index); 1589 if (property->is_computed_name()) break; 1590 if (property->IsCompileTimeValue()) continue; 1591 1592 RegisterAllocationScope inner_register_scope(this); 1593 Literal* key = property->key()->AsLiteral(); 1594 switch (property->kind()) { 1595 case ObjectLiteral::Property::CONSTANT: 1596 UNREACHABLE(); 1597 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1598 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); 1599 // Fall through. 1600 case ObjectLiteral::Property::COMPUTED: { 1601 // It is safe to use [[Put]] here because the boilerplate already 1602 // contains computed properties with an uninitialized value. 1603 if (key->IsStringLiteral()) { 1604 DCHECK(key->IsPropertyName()); 1605 if (property->emit_store()) { 1606 VisitForAccumulatorValue(property->value()); 1607 if (FunctionLiteral::NeedsHomeObject(property->value())) { 1608 RegisterAllocationScope register_scope(this); 1609 Register value = register_allocator()->NewRegister(); 1610 builder()->StoreAccumulatorInRegister(value); 1611 builder()->StoreNamedProperty( 1612 literal, key->AsPropertyName(), 1613 feedback_index(property->GetSlot(0)), language_mode()); 1614 VisitSetHomeObject(value, literal, property, 1); 1615 } else { 1616 builder()->StoreNamedProperty( 1617 literal, key->AsPropertyName(), 1618 feedback_index(property->GetSlot(0)), language_mode()); 1619 } 1620 } else { 1621 VisitForEffect(property->value()); 1622 } 1623 } else { 1624 RegisterList args = register_allocator()->NewRegisterList(4); 1625 1626 builder()->MoveRegister(literal, args[0]); 1627 VisitForRegisterValue(property->key(), args[1]); 1628 VisitForRegisterValue(property->value(), args[2]); 1629 if (property->emit_store()) { 1630 builder() 1631 ->LoadLiteral(Smi::FromInt(SLOPPY)) 1632 .StoreAccumulatorInRegister(args[3]) 1633 .CallRuntime(Runtime::kSetProperty, args); 1634 Register value = args[2]; 1635 VisitSetHomeObject(value, literal, property); 1636 } 1637 } 1638 break; 1639 } 1640 case ObjectLiteral::Property::PROTOTYPE: { 1641 DCHECK(property->emit_store()); 1642 RegisterList args = register_allocator()->NewRegisterList(2); 1643 builder()->MoveRegister(literal, args[0]); 1644 VisitForRegisterValue(property->value(), args[1]); 1645 builder()->CallRuntime(Runtime::kInternalSetPrototype, args); 1646 break; 1647 } 1648 case ObjectLiteral::Property::GETTER: 1649 if (property->emit_store()) { 1650 accessor_table.lookup(key)->second->getter = property; 1651 } 1652 break; 1653 case ObjectLiteral::Property::SETTER: 1654 if (property->emit_store()) { 1655 accessor_table.lookup(key)->second->setter = property; 1656 } 1657 break; 1658 } 1659 } 1660 1661 // Define accessors, using only a single call to the runtime for each pair of 1662 // corresponding getters and setters. 1663 for (AccessorTable::Iterator it = accessor_table.begin(); 1664 it != accessor_table.end(); ++it) { 1665 RegisterAllocationScope inner_register_scope(this); 1666 RegisterList args = register_allocator()->NewRegisterList(5); 1667 builder()->MoveRegister(literal, args[0]); 1668 VisitForRegisterValue(it->first, args[1]); 1669 VisitObjectLiteralAccessor(literal, it->second->getter, args[2]); 1670 VisitObjectLiteralAccessor(literal, it->second->setter, args[3]); 1671 builder() 1672 ->LoadLiteral(Smi::FromInt(NONE)) 1673 .StoreAccumulatorInRegister(args[4]) 1674 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, args); 1675 } 1676 1677 // Object literals have two parts. The "static" part on the left contains no 1678 // computed property names, and so we can compute its map ahead of time; see 1679 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts 1680 // with the first computed property name and continues with all properties to 1681 // its right. All the code from above initializes the static component of the 1682 // object literal, and arranges for the map of the result to reflect the 1683 // static order in which the keys appear. For the dynamic properties, we 1684 // compile them into a series of "SetOwnProperty" runtime calls. This will 1685 // preserve insertion order. 1686 for (; property_index < expr->properties()->length(); property_index++) { 1687 ObjectLiteral::Property* property = expr->properties()->at(property_index); 1688 RegisterAllocationScope inner_register_scope(this); 1689 1690 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { 1691 DCHECK(property->emit_store()); 1692 RegisterList args = register_allocator()->NewRegisterList(2); 1693 builder()->MoveRegister(literal, args[0]); 1694 VisitForRegisterValue(property->value(), args[1]); 1695 builder()->CallRuntime(Runtime::kInternalSetPrototype, args); 1696 continue; 1697 } 1698 1699 switch (property->kind()) { 1700 case ObjectLiteral::Property::CONSTANT: 1701 case ObjectLiteral::Property::COMPUTED: 1702 case ObjectLiteral::Property::MATERIALIZED_LITERAL: { 1703 RegisterList args = register_allocator()->NewRegisterList(5); 1704 builder()->MoveRegister(literal, args[0]); 1705 VisitForAccumulatorValue(property->key()); 1706 builder()->ConvertAccumulatorToName(args[1]); 1707 VisitForRegisterValue(property->value(), args[2]); 1708 VisitSetHomeObject(args[2], literal, property); 1709 builder() 1710 ->LoadLiteral(Smi::FromInt(NONE)) 1711 .StoreAccumulatorInRegister(args[3]) 1712 .LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName())) 1713 .StoreAccumulatorInRegister(args[4]); 1714 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, args); 1715 break; 1716 } 1717 case ObjectLiteral::Property::GETTER: 1718 case ObjectLiteral::Property::SETTER: { 1719 RegisterList args = register_allocator()->NewRegisterList(4); 1720 builder()->MoveRegister(literal, args[0]); 1721 VisitForAccumulatorValue(property->key()); 1722 builder()->ConvertAccumulatorToName(args[1]); 1723 VisitForRegisterValue(property->value(), args[2]); 1724 VisitSetHomeObject(args[2], literal, property); 1725 builder() 1726 ->LoadLiteral(Smi::FromInt(NONE)) 1727 .StoreAccumulatorInRegister(args[3]); 1728 Runtime::FunctionId function_id = 1729 property->kind() == ObjectLiteral::Property::GETTER 1730 ? Runtime::kDefineGetterPropertyUnchecked 1731 : Runtime::kDefineSetterPropertyUnchecked; 1732 builder()->CallRuntime(function_id, args); 1733 break; 1734 } 1735 case ObjectLiteral::Property::PROTOTYPE: 1736 UNREACHABLE(); // Handled specially above. 1737 break; 1738 } 1739 } 1740 1741 builder()->LoadAccumulatorWithRegister(literal); 1742 } 1743 1744 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1745 // Deep-copy the literal boilerplate. 1746 int runtime_flags = expr->ComputeFlags(); 1747 bool use_fast_shallow_clone = 1748 (runtime_flags & ArrayLiteral::kShallowElements) != 0 && 1749 expr->values()->length() <= JSArray::kInitialMaxFastElementArray; 1750 uint8_t flags = 1751 CreateArrayLiteralFlags::Encode(use_fast_shallow_clone, runtime_flags); 1752 builder()->CreateArrayLiteral(expr->constant_elements(), 1753 expr->literal_index(), flags); 1754 Register index, literal; 1755 1756 // Evaluate all the non-constant subexpressions and store them into the 1757 // newly cloned array. 1758 bool literal_in_accumulator = true; 1759 for (int array_index = 0; array_index < expr->values()->length(); 1760 array_index++) { 1761 Expression* subexpr = expr->values()->at(array_index); 1762 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 1763 DCHECK(!subexpr->IsSpread()); 1764 1765 if (literal_in_accumulator) { 1766 index = register_allocator()->NewRegister(); 1767 literal = register_allocator()->NewRegister(); 1768 builder()->StoreAccumulatorInRegister(literal); 1769 literal_in_accumulator = false; 1770 } 1771 1772 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot(); 1773 builder() 1774 ->LoadLiteral(Smi::FromInt(array_index)) 1775 .StoreAccumulatorInRegister(index); 1776 VisitForAccumulatorValue(subexpr); 1777 builder()->StoreKeyedProperty(literal, index, feedback_index(slot), 1778 language_mode()); 1779 } 1780 1781 if (!literal_in_accumulator) { 1782 // Restore literal array into accumulator. 1783 builder()->LoadAccumulatorWithRegister(literal); 1784 } 1785 } 1786 1787 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 1788 builder()->SetExpressionPosition(proxy); 1789 BuildVariableLoad(proxy->var(), proxy->VariableFeedbackSlot(), 1790 proxy->hole_check_mode()); 1791 } 1792 1793 void BytecodeGenerator::BuildVariableLoad(Variable* variable, 1794 FeedbackVectorSlot slot, 1795 HoleCheckMode hole_check_mode, 1796 TypeofMode typeof_mode) { 1797 switch (variable->location()) { 1798 case VariableLocation::LOCAL: { 1799 Register source(Register(variable->index())); 1800 // We need to load the variable into the accumulator, even when in a 1801 // VisitForRegisterScope, in order to avoid register aliasing if 1802 // subsequent expressions assign to the same variable. 1803 builder()->LoadAccumulatorWithRegister(source); 1804 if (hole_check_mode == HoleCheckMode::kRequired) { 1805 BuildThrowIfHole(variable->name()); 1806 } 1807 break; 1808 } 1809 case VariableLocation::PARAMETER: { 1810 // The parameter indices are shifted by 1 (receiver is variable 1811 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1812 Register source = builder()->Parameter(variable->index() + 1); 1813 // We need to load the variable into the accumulator, even when in a 1814 // VisitForRegisterScope, in order to avoid register aliasing if 1815 // subsequent expressions assign to the same variable. 1816 builder()->LoadAccumulatorWithRegister(source); 1817 if (hole_check_mode == HoleCheckMode::kRequired) { 1818 BuildThrowIfHole(variable->name()); 1819 } 1820 break; 1821 } 1822 case VariableLocation::UNALLOCATED: { 1823 builder()->LoadGlobal(feedback_index(slot), typeof_mode); 1824 break; 1825 } 1826 case VariableLocation::CONTEXT: { 1827 int depth = execution_context()->ContextChainDepth(variable->scope()); 1828 ContextScope* context = execution_context()->Previous(depth); 1829 Register context_reg; 1830 if (context) { 1831 context_reg = context->reg(); 1832 depth = 0; 1833 } else { 1834 context_reg = execution_context()->reg(); 1835 } 1836 1837 builder()->LoadContextSlot(context_reg, variable->index(), depth); 1838 if (hole_check_mode == HoleCheckMode::kRequired) { 1839 BuildThrowIfHole(variable->name()); 1840 } 1841 break; 1842 } 1843 case VariableLocation::LOOKUP: { 1844 switch (variable->mode()) { 1845 case DYNAMIC_LOCAL: { 1846 Variable* local_variable = variable->local_if_not_shadowed(); 1847 int depth = 1848 execution_context()->ContextChainDepth(local_variable->scope()); 1849 builder()->LoadLookupContextSlot(variable->name(), typeof_mode, 1850 local_variable->index(), depth); 1851 if (hole_check_mode == HoleCheckMode::kRequired) { 1852 BuildThrowIfHole(variable->name()); 1853 } 1854 break; 1855 } 1856 case DYNAMIC_GLOBAL: { 1857 int depth = scope()->ContextChainLengthUntilOutermostSloppyEval(); 1858 builder()->LoadLookupGlobalSlot(variable->name(), typeof_mode, 1859 feedback_index(slot), depth); 1860 break; 1861 } 1862 default: 1863 builder()->LoadLookupSlot(variable->name(), typeof_mode); 1864 } 1865 break; 1866 } 1867 case VariableLocation::MODULE: { 1868 int depth = execution_context()->ContextChainDepth(variable->scope()); 1869 builder()->LoadModuleVariable(variable->index(), depth); 1870 if (hole_check_mode == HoleCheckMode::kRequired) { 1871 BuildThrowIfHole(variable->name()); 1872 } 1873 break; 1874 } 1875 } 1876 } 1877 1878 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( 1879 Variable* variable, FeedbackVectorSlot slot, HoleCheckMode hole_check_mode, 1880 TypeofMode typeof_mode) { 1881 ValueResultScope accumulator_result(this); 1882 BuildVariableLoad(variable, slot, hole_check_mode, typeof_mode); 1883 } 1884 1885 void BytecodeGenerator::BuildReturn() { 1886 if (FLAG_trace) { 1887 RegisterAllocationScope register_scope(this); 1888 Register result = register_allocator()->NewRegister(); 1889 // Runtime returns {result} value, preserving accumulator. 1890 builder()->StoreAccumulatorInRegister(result).CallRuntime( 1891 Runtime::kTraceExit, result); 1892 } 1893 builder()->Return(); 1894 } 1895 1896 void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); } 1897 1898 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) { 1899 RegisterAllocationScope register_scope(this); 1900 Register reason = register_allocator()->NewRegister(); 1901 builder() 1902 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason))) 1903 .StoreAccumulatorInRegister(reason) 1904 .CallRuntime(Runtime::kAbort, reason); 1905 } 1906 1907 void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) { 1908 RegisterAllocationScope register_scope(this); 1909 Register name_reg = register_allocator()->NewRegister(); 1910 builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime( 1911 Runtime::kThrowReferenceError, name_reg); 1912 } 1913 1914 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) { 1915 // TODO(interpreter): Can the parser reduce the number of checks 1916 // performed? Or should there be a ThrowIfHole bytecode. 1917 BytecodeLabel no_reference_error; 1918 builder()->JumpIfNotHole(&no_reference_error); 1919 BuildThrowReferenceError(name); 1920 builder()->Bind(&no_reference_error); 1921 } 1922 1923 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) { 1924 // TODO(interpreter): Can the parser reduce the number of checks 1925 // performed? Or should there be a ThrowIfNotHole bytecode. 1926 BytecodeLabel no_reference_error, reference_error; 1927 builder() 1928 ->JumpIfNotHole(&reference_error) 1929 .Jump(&no_reference_error) 1930 .Bind(&reference_error); 1931 BuildThrowReferenceError(name); 1932 builder()->Bind(&no_reference_error); 1933 } 1934 1935 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, 1936 Token::Value op) { 1937 if (variable->is_this() && variable->mode() == CONST && op == Token::INIT) { 1938 // Perform an initialization check for 'this'. 'this' variable is the 1939 // only variable able to trigger bind operations outside the TDZ 1940 // via 'super' calls. 1941 BuildThrowIfNotHole(variable->name()); 1942 } else { 1943 // Perform an initialization check for let/const declared variables. 1944 // E.g. let x = (x = 20); is not allowed. 1945 DCHECK(IsLexicalVariableMode(variable->mode())); 1946 BuildThrowIfHole(variable->name()); 1947 } 1948 } 1949 1950 void BytecodeGenerator::BuildVariableAssignment(Variable* variable, 1951 Token::Value op, 1952 FeedbackVectorSlot slot, 1953 HoleCheckMode hole_check_mode) { 1954 VariableMode mode = variable->mode(); 1955 RegisterAllocationScope assignment_register_scope(this); 1956 BytecodeLabel end_label; 1957 switch (variable->location()) { 1958 case VariableLocation::PARAMETER: 1959 case VariableLocation::LOCAL: { 1960 Register destination; 1961 if (VariableLocation::PARAMETER == variable->location()) { 1962 destination = Register(builder()->Parameter(variable->index() + 1)); 1963 } else { 1964 destination = Register(variable->index()); 1965 } 1966 1967 if (hole_check_mode == HoleCheckMode::kRequired) { 1968 // Load destination to check for hole. 1969 Register value_temp = register_allocator()->NewRegister(); 1970 builder() 1971 ->StoreAccumulatorInRegister(value_temp) 1972 .LoadAccumulatorWithRegister(destination); 1973 1974 BuildHoleCheckForVariableAssignment(variable, op); 1975 builder()->LoadAccumulatorWithRegister(value_temp); 1976 } 1977 1978 if (mode != CONST || op == Token::INIT) { 1979 builder()->StoreAccumulatorInRegister(destination); 1980 } else if (variable->throw_on_const_assignment(language_mode())) { 1981 builder()->CallRuntime(Runtime::kThrowConstAssignError); 1982 } 1983 break; 1984 } 1985 case VariableLocation::UNALLOCATED: { 1986 builder()->StoreGlobal(variable->name(), feedback_index(slot), 1987 language_mode()); 1988 break; 1989 } 1990 case VariableLocation::CONTEXT: { 1991 int depth = execution_context()->ContextChainDepth(variable->scope()); 1992 ContextScope* context = execution_context()->Previous(depth); 1993 Register context_reg; 1994 1995 if (context) { 1996 context_reg = context->reg(); 1997 depth = 0; 1998 } else { 1999 context_reg = execution_context()->reg(); 2000 } 2001 2002 if (hole_check_mode == HoleCheckMode::kRequired) { 2003 // Load destination to check for hole. 2004 Register value_temp = register_allocator()->NewRegister(); 2005 builder() 2006 ->StoreAccumulatorInRegister(value_temp) 2007 .LoadContextSlot(context_reg, variable->index(), depth); 2008 2009 BuildHoleCheckForVariableAssignment(variable, op); 2010 builder()->LoadAccumulatorWithRegister(value_temp); 2011 } 2012 2013 if (mode != CONST || op == Token::INIT) { 2014 builder()->StoreContextSlot(context_reg, variable->index(), depth); 2015 } else if (variable->throw_on_const_assignment(language_mode())) { 2016 builder()->CallRuntime(Runtime::kThrowConstAssignError); 2017 } 2018 break; 2019 } 2020 case VariableLocation::LOOKUP: { 2021 builder()->StoreLookupSlot(variable->name(), language_mode()); 2022 break; 2023 } 2024 case VariableLocation::MODULE: { 2025 DCHECK(IsDeclaredVariableMode(mode)); 2026 2027 if (mode == CONST && op != Token::INIT) { 2028 builder()->CallRuntime(Runtime::kThrowConstAssignError); 2029 break; 2030 } 2031 2032 // If we don't throw above, we know that we're dealing with an 2033 // export because imports are const and we do not generate initializing 2034 // assignments for them. 2035 DCHECK(variable->IsExport()); 2036 2037 int depth = execution_context()->ContextChainDepth(variable->scope()); 2038 if (hole_check_mode == HoleCheckMode::kRequired) { 2039 Register value_temp = register_allocator()->NewRegister(); 2040 builder() 2041 ->StoreAccumulatorInRegister(value_temp) 2042 .LoadModuleVariable(variable->index(), depth); 2043 BuildHoleCheckForVariableAssignment(variable, op); 2044 builder()->LoadAccumulatorWithRegister(value_temp); 2045 } 2046 builder()->StoreModuleVariable(variable->index(), depth); 2047 break; 2048 } 2049 } 2050 } 2051 2052 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 2053 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); 2054 Register object, key; 2055 RegisterList super_property_args; 2056 Handle<String> name; 2057 2058 // Left-hand side can only be a property, a global or a variable slot. 2059 Property* property = expr->target()->AsProperty(); 2060 LhsKind assign_type = Property::GetAssignType(property); 2061 2062 // Evaluate LHS expression. 2063 switch (assign_type) { 2064 case VARIABLE: 2065 // Nothing to do to evaluate variable assignment LHS. 2066 break; 2067 case NAMED_PROPERTY: { 2068 object = VisitForRegisterValue(property->obj()); 2069 name = property->key()->AsLiteral()->AsPropertyName(); 2070 break; 2071 } 2072 case KEYED_PROPERTY: { 2073 object = VisitForRegisterValue(property->obj()); 2074 key = VisitForRegisterValue(property->key()); 2075 break; 2076 } 2077 case NAMED_SUPER_PROPERTY: { 2078 super_property_args = register_allocator()->NewRegisterList(4); 2079 SuperPropertyReference* super_property = 2080 property->obj()->AsSuperPropertyReference(); 2081 VisitForRegisterValue(super_property->this_var(), super_property_args[0]); 2082 VisitForRegisterValue(super_property->home_object(), 2083 super_property_args[1]); 2084 builder() 2085 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) 2086 .StoreAccumulatorInRegister(super_property_args[2]); 2087 break; 2088 } 2089 case KEYED_SUPER_PROPERTY: { 2090 super_property_args = register_allocator()->NewRegisterList(4); 2091 SuperPropertyReference* super_property = 2092 property->obj()->AsSuperPropertyReference(); 2093 VisitForRegisterValue(super_property->this_var(), super_property_args[0]); 2094 VisitForRegisterValue(super_property->home_object(), 2095 super_property_args[1]); 2096 VisitForRegisterValue(property->key(), super_property_args[2]); 2097 break; 2098 } 2099 } 2100 2101 // Evaluate the value and potentially handle compound assignments by loading 2102 // the left-hand side value and performing a binary operation. 2103 if (expr->is_compound()) { 2104 Register old_value = register_allocator()->NewRegister(); 2105 switch (assign_type) { 2106 case VARIABLE: { 2107 VariableProxy* proxy = expr->target()->AsVariableProxy(); 2108 BuildVariableLoad(proxy->var(), proxy->VariableFeedbackSlot(), 2109 proxy->hole_check_mode()); 2110 builder()->StoreAccumulatorInRegister(old_value); 2111 break; 2112 } 2113 case NAMED_PROPERTY: { 2114 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); 2115 builder() 2116 ->LoadNamedProperty(object, name, feedback_index(slot)) 2117 .StoreAccumulatorInRegister(old_value); 2118 break; 2119 } 2120 case KEYED_PROPERTY: { 2121 // Key is already in accumulator at this point due to evaluating the 2122 // LHS above. 2123 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); 2124 builder() 2125 ->LoadKeyedProperty(object, feedback_index(slot)) 2126 .StoreAccumulatorInRegister(old_value); 2127 break; 2128 } 2129 case NAMED_SUPER_PROPERTY: { 2130 builder() 2131 ->CallRuntime(Runtime::kLoadFromSuper, 2132 super_property_args.Truncate(3)) 2133 .StoreAccumulatorInRegister(old_value); 2134 break; 2135 } 2136 case KEYED_SUPER_PROPERTY: { 2137 builder() 2138 ->CallRuntime(Runtime::kLoadKeyedFromSuper, 2139 super_property_args.Truncate(3)) 2140 .StoreAccumulatorInRegister(old_value); 2141 break; 2142 } 2143 } 2144 VisitForAccumulatorValue(expr->value()); 2145 FeedbackVectorSlot slot = 2146 expr->binary_operation()->BinaryOperationFeedbackSlot(); 2147 builder()->BinaryOperation(expr->binary_op(), old_value, 2148 feedback_index(slot)); 2149 } else { 2150 VisitForAccumulatorValue(expr->value()); 2151 } 2152 2153 // Store the value. 2154 builder()->SetExpressionPosition(expr); 2155 FeedbackVectorSlot slot = expr->AssignmentSlot(); 2156 switch (assign_type) { 2157 case VARIABLE: { 2158 // TODO(oth): The BuildVariableAssignment() call is hard to reason about. 2159 // Is the value in the accumulator safe? Yes, but scary. 2160 VariableProxy* proxy = expr->target()->AsVariableProxy(); 2161 BuildVariableAssignment(proxy->var(), expr->op(), slot, 2162 proxy->hole_check_mode()); 2163 break; 2164 } 2165 case NAMED_PROPERTY: 2166 builder()->StoreNamedProperty(object, name, feedback_index(slot), 2167 language_mode()); 2168 break; 2169 case KEYED_PROPERTY: 2170 builder()->StoreKeyedProperty(object, key, feedback_index(slot), 2171 language_mode()); 2172 break; 2173 case NAMED_SUPER_PROPERTY: { 2174 builder() 2175 ->StoreAccumulatorInRegister(super_property_args[3]) 2176 .CallRuntime(StoreToSuperRuntimeId(), super_property_args); 2177 break; 2178 } 2179 case KEYED_SUPER_PROPERTY: { 2180 builder() 2181 ->StoreAccumulatorInRegister(super_property_args[3]) 2182 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); 2183 break; 2184 } 2185 } 2186 } 2187 2188 void BytecodeGenerator::VisitYield(Yield* expr) { 2189 builder()->SetExpressionPosition(expr); 2190 Register value = VisitForRegisterValue(expr->expression()); 2191 2192 Register generator = VisitForRegisterValue(expr->generator_object()); 2193 2194 // Save context, registers, and state. Then return. 2195 builder() 2196 ->LoadLiteral(Smi::FromInt(expr->yield_id())) 2197 .SuspendGenerator(generator) 2198 .LoadAccumulatorWithRegister(value) 2199 .Return(); // Hard return (ignore any finally blocks). 2200 2201 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); 2202 // Upon resume, we continue here. 2203 2204 { 2205 RegisterAllocationScope register_scope(this); 2206 2207 // Update state to indicate that we have finished resuming. Loop headers 2208 // rely on this. 2209 builder() 2210 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) 2211 .StoreAccumulatorInRegister(generator_state_); 2212 2213 Register input = register_allocator()->NewRegister(); 2214 builder() 2215 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator) 2216 .StoreAccumulatorInRegister(input); 2217 2218 Register resume_mode = register_allocator()->NewRegister(); 2219 builder() 2220 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator) 2221 .StoreAccumulatorInRegister(resume_mode); 2222 2223 // Now dispatch on resume mode. 2224 2225 BytecodeLabel resume_with_next; 2226 BytecodeLabel resume_with_return; 2227 BytecodeLabel resume_with_throw; 2228 2229 builder() 2230 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext)) 2231 .CompareOperation(Token::EQ_STRICT, resume_mode) 2232 .JumpIfTrue(&resume_with_next) 2233 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow)) 2234 .CompareOperation(Token::EQ_STRICT, resume_mode) 2235 .JumpIfTrue(&resume_with_throw) 2236 .Jump(&resume_with_return); 2237 2238 builder()->Bind(&resume_with_return); 2239 { 2240 RegisterList args = register_allocator()->NewRegisterList(2); 2241 builder() 2242 ->MoveRegister(input, args[0]) 2243 .LoadTrue() 2244 .StoreAccumulatorInRegister(args[1]) 2245 .CallRuntime(Runtime::kInlineCreateIterResultObject, args); 2246 execution_control()->ReturnAccumulator(); 2247 } 2248 2249 builder()->Bind(&resume_with_throw); 2250 builder()->SetExpressionPosition(expr); 2251 builder()->LoadAccumulatorWithRegister(input); 2252 if (expr->rethrow_on_exception()) { 2253 builder()->ReThrow(); 2254 } else { 2255 builder()->Throw(); 2256 } 2257 2258 builder()->Bind(&resume_with_next); 2259 builder()->LoadAccumulatorWithRegister(input); 2260 } 2261 } 2262 2263 void BytecodeGenerator::VisitThrow(Throw* expr) { 2264 VisitForAccumulatorValue(expr->exception()); 2265 builder()->SetExpressionPosition(expr); 2266 builder()->Throw(); 2267 } 2268 2269 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { 2270 LhsKind property_kind = Property::GetAssignType(expr); 2271 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); 2272 builder()->SetExpressionPosition(expr); 2273 switch (property_kind) { 2274 case VARIABLE: 2275 UNREACHABLE(); 2276 case NAMED_PROPERTY: { 2277 builder()->LoadNamedProperty(obj, 2278 expr->key()->AsLiteral()->AsPropertyName(), 2279 feedback_index(slot)); 2280 break; 2281 } 2282 case KEYED_PROPERTY: { 2283 VisitForAccumulatorValue(expr->key()); 2284 builder()->LoadKeyedProperty(obj, feedback_index(slot)); 2285 break; 2286 } 2287 case NAMED_SUPER_PROPERTY: 2288 VisitNamedSuperPropertyLoad(expr, Register::invalid_value()); 2289 break; 2290 case KEYED_SUPER_PROPERTY: 2291 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value()); 2292 break; 2293 } 2294 } 2295 2296 void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj, 2297 Property* expr, 2298 Register destination) { 2299 ValueResultScope result_scope(this); 2300 VisitPropertyLoad(obj, expr); 2301 builder()->StoreAccumulatorInRegister(destination); 2302 } 2303 2304 void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property, 2305 Register opt_receiver_out) { 2306 RegisterAllocationScope register_scope(this); 2307 SuperPropertyReference* super_property = 2308 property->obj()->AsSuperPropertyReference(); 2309 RegisterList args = register_allocator()->NewRegisterList(3); 2310 VisitForRegisterValue(super_property->this_var(), args[0]); 2311 VisitForRegisterValue(super_property->home_object(), args[1]); 2312 builder() 2313 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) 2314 .StoreAccumulatorInRegister(args[2]) 2315 .CallRuntime(Runtime::kLoadFromSuper, args); 2316 2317 if (opt_receiver_out.is_valid()) { 2318 builder()->MoveRegister(args[0], opt_receiver_out); 2319 } 2320 } 2321 2322 void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property, 2323 Register opt_receiver_out) { 2324 RegisterAllocationScope register_scope(this); 2325 SuperPropertyReference* super_property = 2326 property->obj()->AsSuperPropertyReference(); 2327 RegisterList args = register_allocator()->NewRegisterList(3); 2328 VisitForRegisterValue(super_property->this_var(), args[0]); 2329 VisitForRegisterValue(super_property->home_object(), args[1]); 2330 VisitForRegisterValue(property->key(), args[2]); 2331 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, args); 2332 2333 if (opt_receiver_out.is_valid()) { 2334 builder()->MoveRegister(args[0], opt_receiver_out); 2335 } 2336 } 2337 2338 void BytecodeGenerator::VisitProperty(Property* expr) { 2339 LhsKind property_kind = Property::GetAssignType(expr); 2340 if (property_kind != NAMED_SUPER_PROPERTY && 2341 property_kind != KEYED_SUPER_PROPERTY) { 2342 Register obj = VisitForRegisterValue(expr->obj()); 2343 VisitPropertyLoad(obj, expr); 2344 } else { 2345 VisitPropertyLoad(Register::invalid_value(), expr); 2346 } 2347 } 2348 2349 void BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args, 2350 RegisterList* arg_regs) { 2351 // Visit arguments. 2352 for (int i = 0; i < static_cast<int>(args->length()); i++) { 2353 VisitAndPushIntoRegisterList(args->at(i), arg_regs); 2354 } 2355 } 2356 2357 void BytecodeGenerator::VisitCall(Call* expr) { 2358 Expression* callee_expr = expr->expression(); 2359 Call::CallType call_type = expr->GetCallType(); 2360 2361 if (call_type == Call::SUPER_CALL) { 2362 return VisitCallSuper(expr); 2363 } 2364 2365 Register callee = register_allocator()->NewRegister(); 2366 // Grow the args list as we visit receiver / arguments to avoid allocating all 2367 // the registers up-front. Otherwise these registers are unavailable during 2368 // receiver / argument visiting and we can end up with memory leaks due to 2369 // registers keeping objects alive. 2370 RegisterList args = register_allocator()->NewGrowableRegisterList(); 2371 2372 // Prepare the callee and the receiver to the function call. This depends on 2373 // the semantics of the underlying call type. 2374 switch (call_type) { 2375 case Call::NAMED_PROPERTY_CALL: 2376 case Call::KEYED_PROPERTY_CALL: { 2377 Property* property = callee_expr->AsProperty(); 2378 VisitAndPushIntoRegisterList(property->obj(), &args); 2379 VisitPropertyLoadForRegister(args[0], property, callee); 2380 break; 2381 } 2382 case Call::GLOBAL_CALL: { 2383 // Receiver is undefined for global calls. 2384 BuildPushUndefinedIntoRegisterList(&args); 2385 // Load callee as a global variable. 2386 VariableProxy* proxy = callee_expr->AsVariableProxy(); 2387 BuildVariableLoadForAccumulatorValue(proxy->var(), 2388 proxy->VariableFeedbackSlot(), 2389 proxy->hole_check_mode()); 2390 builder()->StoreAccumulatorInRegister(callee); 2391 break; 2392 } 2393 case Call::WITH_CALL: { 2394 Register receiver = register_allocator()->GrowRegisterList(&args); 2395 DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot()); 2396 { 2397 RegisterAllocationScope inner_register_scope(this); 2398 Register name = register_allocator()->NewRegister(); 2399 2400 // Call %LoadLookupSlotForCall to get the callee and receiver. 2401 DCHECK(Register::AreContiguous(callee, receiver)); 2402 RegisterList result_pair(callee.index(), 2); 2403 USE(receiver); 2404 Variable* variable = callee_expr->AsVariableProxy()->var(); 2405 builder() 2406 ->LoadLiteral(variable->name()) 2407 .StoreAccumulatorInRegister(name) 2408 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 2409 result_pair); 2410 } 2411 break; 2412 } 2413 case Call::OTHER_CALL: { 2414 BuildPushUndefinedIntoRegisterList(&args); 2415 VisitForRegisterValue(callee_expr, callee); 2416 break; 2417 } 2418 case Call::NAMED_SUPER_PROPERTY_CALL: { 2419 Register receiver = register_allocator()->GrowRegisterList(&args); 2420 Property* property = callee_expr->AsProperty(); 2421 VisitNamedSuperPropertyLoad(property, receiver); 2422 builder()->StoreAccumulatorInRegister(callee); 2423 break; 2424 } 2425 case Call::KEYED_SUPER_PROPERTY_CALL: { 2426 Register receiver = register_allocator()->GrowRegisterList(&args); 2427 Property* property = callee_expr->AsProperty(); 2428 VisitKeyedSuperPropertyLoad(property, receiver); 2429 builder()->StoreAccumulatorInRegister(callee); 2430 break; 2431 } 2432 case Call::SUPER_CALL: 2433 UNREACHABLE(); 2434 break; 2435 } 2436 2437 // Evaluate all arguments to the function call and store in sequential args 2438 // registers. 2439 VisitArguments(expr->arguments(), &args); 2440 CHECK_EQ(expr->arguments()->length() + 1, args.register_count()); 2441 2442 // Resolve callee for a potential direct eval call. This block will mutate the 2443 // callee value. 2444 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) { 2445 RegisterAllocationScope inner_register_scope(this); 2446 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source 2447 // strings and function closure, and loading language and 2448 // position. 2449 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6); 2450 builder() 2451 ->MoveRegister(callee, runtime_call_args[0]) 2452 .MoveRegister(args[1], runtime_call_args[1]) 2453 .MoveRegister(Register::function_closure(), runtime_call_args[2]) 2454 .LoadLiteral(Smi::FromInt(language_mode())) 2455 .StoreAccumulatorInRegister(runtime_call_args[3]) 2456 .LoadLiteral( 2457 Smi::FromInt(execution_context()->scope()->start_position())) 2458 .StoreAccumulatorInRegister(runtime_call_args[4]) 2459 .LoadLiteral(Smi::FromInt(expr->position())) 2460 .StoreAccumulatorInRegister(runtime_call_args[5]); 2461 2462 // Call ResolvePossiblyDirectEval and modify the callee. 2463 builder() 2464 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args) 2465 .StoreAccumulatorInRegister(callee); 2466 } 2467 2468 builder()->SetExpressionPosition(expr); 2469 2470 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); 2471 builder()->Call(callee, args, feedback_slot_index, call_type, 2472 expr->tail_call_mode()); 2473 } 2474 2475 void BytecodeGenerator::VisitCallSuper(Call* expr) { 2476 RegisterAllocationScope register_scope(this); 2477 SuperCallReference* super = expr->expression()->AsSuperCallReference(); 2478 2479 // Prepare the constructor to the super call. 2480 Register this_function = VisitForRegisterValue(super->this_function_var()); 2481 builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function); 2482 2483 Register constructor = this_function; // Re-use dead this_function register. 2484 builder()->StoreAccumulatorInRegister(constructor); 2485 2486 RegisterList args = register_allocator()->NewGrowableRegisterList(); 2487 VisitArguments(expr->arguments(), &args); 2488 2489 // The new target is loaded into the accumulator from the 2490 // {new.target} variable. 2491 VisitForAccumulatorValue(super->new_target_var()); 2492 2493 // Call construct. 2494 builder()->SetExpressionPosition(expr); 2495 // TODO(turbofan): For now we do gather feedback on super constructor 2496 // calls, utilizing the existing machinery to inline the actual call 2497 // target and the JSCreate for the implicit receiver allocation. This 2498 // is not an ideal solution for super constructor calls, but it gets 2499 // the job done for now. In the long run we might want to revisit this 2500 // and come up with a better way. 2501 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); 2502 builder()->New(constructor, args, feedback_slot_index); 2503 } 2504 2505 void BytecodeGenerator::VisitCallNew(CallNew* expr) { 2506 Register constructor = VisitForRegisterValue(expr->expression()); 2507 RegisterList args = register_allocator()->NewGrowableRegisterList(); 2508 VisitArguments(expr->arguments(), &args); 2509 2510 builder()->SetExpressionPosition(expr); 2511 // The accumulator holds new target which is the same as the 2512 // constructor for CallNew. 2513 builder() 2514 ->LoadAccumulatorWithRegister(constructor) 2515 .New(constructor, args, feedback_index(expr->CallNewFeedbackSlot())); 2516 } 2517 2518 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2519 if (expr->is_jsruntime()) { 2520 RegisterList args = register_allocator()->NewGrowableRegisterList(); 2521 // Allocate a register for the receiver and load it with undefined. 2522 BuildPushUndefinedIntoRegisterList(&args); 2523 VisitArguments(expr->arguments(), &args); 2524 builder()->CallJSRuntime(expr->context_index(), args); 2525 } else { 2526 // Evaluate all arguments to the runtime call. 2527 RegisterList args = register_allocator()->NewGrowableRegisterList(); 2528 VisitArguments(expr->arguments(), &args); 2529 Runtime::FunctionId function_id = expr->function()->function_id; 2530 builder()->CallRuntime(function_id, args); 2531 } 2532 } 2533 2534 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { 2535 VisitForEffect(expr->expression()); 2536 builder()->LoadUndefined(); 2537 } 2538 2539 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { 2540 if (expr->expression()->IsVariableProxy()) { 2541 // Typeof does not throw a reference error on global variables, hence we 2542 // perform a non-contextual load in case the operand is a variable proxy. 2543 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2544 BuildVariableLoadForAccumulatorValue( 2545 proxy->var(), proxy->VariableFeedbackSlot(), proxy->hole_check_mode(), 2546 INSIDE_TYPEOF); 2547 } else { 2548 VisitForAccumulatorValue(expr->expression()); 2549 } 2550 builder()->TypeOf(); 2551 } 2552 2553 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { 2554 if (execution_result()->IsEffect()) { 2555 VisitForEffect(expr->expression()); 2556 } else if (execution_result()->IsTest()) { 2557 TestResultScope* test_result = execution_result()->AsTest(); 2558 // No actual logical negation happening, we just swap the control flow by 2559 // swapping the target labels and the fallthrough branch. 2560 VisitForTest(expr->expression(), test_result->else_labels(), 2561 test_result->then_labels(), 2562 test_result->inverted_fallthrough()); 2563 test_result->SetResultConsumedByTest(); 2564 } else { 2565 VisitForAccumulatorValue(expr->expression()); 2566 builder()->LogicalNot(); 2567 } 2568 } 2569 2570 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2571 switch (expr->op()) { 2572 case Token::Value::NOT: 2573 VisitNot(expr); 2574 break; 2575 case Token::Value::TYPEOF: 2576 VisitTypeOf(expr); 2577 break; 2578 case Token::Value::VOID: 2579 VisitVoid(expr); 2580 break; 2581 case Token::Value::DELETE: 2582 VisitDelete(expr); 2583 break; 2584 case Token::Value::BIT_NOT: 2585 case Token::Value::ADD: 2586 case Token::Value::SUB: 2587 // These operators are converted to an equivalent binary operators in 2588 // the parser. These operators are not expected to be visited here. 2589 UNREACHABLE(); 2590 default: 2591 UNREACHABLE(); 2592 } 2593 } 2594 2595 void BytecodeGenerator::VisitDelete(UnaryOperation* expr) { 2596 if (expr->expression()->IsProperty()) { 2597 // Delete of an object property is allowed both in sloppy 2598 // and strict modes. 2599 Property* property = expr->expression()->AsProperty(); 2600 Register object = VisitForRegisterValue(property->obj()); 2601 VisitForAccumulatorValue(property->key()); 2602 builder()->Delete(object, language_mode()); 2603 } else if (expr->expression()->IsVariableProxy()) { 2604 // Delete of an unqualified identifier is allowed in sloppy mode but is 2605 // not allowed in strict mode. Deleting 'this' is allowed in both modes. 2606 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2607 Variable* variable = proxy->var(); 2608 DCHECK(is_sloppy(language_mode()) || variable->is_this()); 2609 switch (variable->location()) { 2610 case VariableLocation::UNALLOCATED: { 2611 // Global var, let, const or variables not explicitly declared. 2612 Register native_context = register_allocator()->NewRegister(); 2613 Register global_object = register_allocator()->NewRegister(); 2614 builder() 2615 ->LoadContextSlot(execution_context()->reg(), 2616 Context::NATIVE_CONTEXT_INDEX, 0) 2617 .StoreAccumulatorInRegister(native_context) 2618 .LoadContextSlot(native_context, Context::EXTENSION_INDEX, 0) 2619 .StoreAccumulatorInRegister(global_object) 2620 .LoadLiteral(variable->name()) 2621 .Delete(global_object, language_mode()); 2622 break; 2623 } 2624 case VariableLocation::PARAMETER: 2625 case VariableLocation::LOCAL: 2626 case VariableLocation::CONTEXT: { 2627 // Deleting local var/let/const, context variables, and arguments 2628 // does not have any effect. 2629 if (variable->is_this()) { 2630 builder()->LoadTrue(); 2631 } else { 2632 builder()->LoadFalse(); 2633 } 2634 break; 2635 } 2636 case VariableLocation::LOOKUP: { 2637 Register name_reg = register_allocator()->NewRegister(); 2638 builder() 2639 ->LoadLiteral(variable->name()) 2640 .StoreAccumulatorInRegister(name_reg) 2641 .CallRuntime(Runtime::kDeleteLookupSlot, name_reg); 2642 break; 2643 } 2644 default: 2645 UNREACHABLE(); 2646 } 2647 } else { 2648 // Delete of an unresolvable reference returns true. 2649 VisitForEffect(expr->expression()); 2650 builder()->LoadTrue(); 2651 } 2652 } 2653 2654 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { 2655 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); 2656 2657 // Left-hand side can only be a property, a global or a variable slot. 2658 Property* property = expr->expression()->AsProperty(); 2659 LhsKind assign_type = Property::GetAssignType(property); 2660 2661 bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect(); 2662 2663 // Evaluate LHS expression and get old value. 2664 Register object, key, old_value; 2665 RegisterList super_property_args; 2666 Handle<String> name; 2667 switch (assign_type) { 2668 case VARIABLE: { 2669 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2670 BuildVariableLoadForAccumulatorValue(proxy->var(), 2671 proxy->VariableFeedbackSlot(), 2672 proxy->hole_check_mode()); 2673 break; 2674 } 2675 case NAMED_PROPERTY: { 2676 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); 2677 object = VisitForRegisterValue(property->obj()); 2678 name = property->key()->AsLiteral()->AsPropertyName(); 2679 builder()->LoadNamedProperty(object, name, feedback_index(slot)); 2680 break; 2681 } 2682 case KEYED_PROPERTY: { 2683 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); 2684 object = VisitForRegisterValue(property->obj()); 2685 // Use visit for accumulator here since we need the key in the accumulator 2686 // for the LoadKeyedProperty. 2687 key = register_allocator()->NewRegister(); 2688 VisitForAccumulatorValue(property->key()); 2689 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty( 2690 object, feedback_index(slot)); 2691 break; 2692 } 2693 case NAMED_SUPER_PROPERTY: { 2694 super_property_args = register_allocator()->NewRegisterList(4); 2695 RegisterList load_super_args = super_property_args.Truncate(3); 2696 SuperPropertyReference* super_property = 2697 property->obj()->AsSuperPropertyReference(); 2698 VisitForRegisterValue(super_property->this_var(), load_super_args[0]); 2699 VisitForRegisterValue(super_property->home_object(), load_super_args[1]); 2700 builder() 2701 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) 2702 .StoreAccumulatorInRegister(load_super_args[2]) 2703 .CallRuntime(Runtime::kLoadFromSuper, load_super_args); 2704 break; 2705 } 2706 case KEYED_SUPER_PROPERTY: { 2707 super_property_args = register_allocator()->NewRegisterList(4); 2708 RegisterList load_super_args = super_property_args.Truncate(3); 2709 SuperPropertyReference* super_property = 2710 property->obj()->AsSuperPropertyReference(); 2711 VisitForRegisterValue(super_property->this_var(), load_super_args[0]); 2712 VisitForRegisterValue(super_property->home_object(), load_super_args[1]); 2713 VisitForRegisterValue(property->key(), load_super_args[2]); 2714 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, load_super_args); 2715 break; 2716 } 2717 } 2718 2719 // Save result for postfix expressions. 2720 if (is_postfix) { 2721 // Convert old value into a number before saving it. 2722 old_value = register_allocator()->NewRegister(); 2723 builder() 2724 ->ConvertAccumulatorToNumber(old_value) 2725 .LoadAccumulatorWithRegister(old_value); 2726 } 2727 2728 // Perform +1/-1 operation. 2729 FeedbackVectorSlot slot = expr->CountBinaryOpFeedbackSlot(); 2730 builder()->CountOperation(expr->binary_op(), feedback_index(slot)); 2731 2732 // Store the value. 2733 builder()->SetExpressionPosition(expr); 2734 FeedbackVectorSlot feedback_slot = expr->CountSlot(); 2735 switch (assign_type) { 2736 case VARIABLE: { 2737 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2738 BuildVariableAssignment(proxy->var(), expr->op(), feedback_slot, 2739 proxy->hole_check_mode()); 2740 break; 2741 } 2742 case NAMED_PROPERTY: { 2743 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot), 2744 language_mode()); 2745 break; 2746 } 2747 case KEYED_PROPERTY: { 2748 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot), 2749 language_mode()); 2750 break; 2751 } 2752 case NAMED_SUPER_PROPERTY: { 2753 builder() 2754 ->StoreAccumulatorInRegister(super_property_args[3]) 2755 .CallRuntime(StoreToSuperRuntimeId(), super_property_args); 2756 break; 2757 } 2758 case KEYED_SUPER_PROPERTY: { 2759 builder() 2760 ->StoreAccumulatorInRegister(super_property_args[3]) 2761 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); 2762 break; 2763 } 2764 } 2765 2766 // Restore old value for postfix expressions. 2767 if (is_postfix) { 2768 builder()->LoadAccumulatorWithRegister(old_value); 2769 } 2770 } 2771 2772 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) { 2773 switch (binop->op()) { 2774 case Token::COMMA: 2775 VisitCommaExpression(binop); 2776 break; 2777 case Token::OR: 2778 VisitLogicalOrExpression(binop); 2779 break; 2780 case Token::AND: 2781 VisitLogicalAndExpression(binop); 2782 break; 2783 default: 2784 VisitArithmeticExpression(binop); 2785 break; 2786 } 2787 } 2788 2789 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { 2790 Register lhs = VisitForRegisterValue(expr->left()); 2791 VisitForAccumulatorValue(expr->right()); 2792 builder()->SetExpressionPosition(expr); 2793 FeedbackVectorSlot slot = expr->CompareOperationFeedbackSlot(); 2794 builder()->CompareOperation(expr->op(), lhs, feedback_index(slot)); 2795 } 2796 2797 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { 2798 // TODO(rmcilroy): Special case "x * 1.0" and "x * -1" which are generated for 2799 // +x and -x by the parser. 2800 Register lhs = VisitForRegisterValue(expr->left()); 2801 VisitForAccumulatorValue(expr->right()); 2802 FeedbackVectorSlot slot = expr->BinaryOperationFeedbackSlot(); 2803 builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot)); 2804 } 2805 2806 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } 2807 2808 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { 2809 UNREACHABLE(); 2810 } 2811 2812 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { 2813 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 2814 } 2815 2816 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { 2817 // Handled by VisitCall(). 2818 UNREACHABLE(); 2819 } 2820 2821 void BytecodeGenerator::VisitSuperPropertyReference( 2822 SuperPropertyReference* expr) { 2823 builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError); 2824 } 2825 2826 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { 2827 VisitForEffect(binop->left()); 2828 Visit(binop->right()); 2829 } 2830 2831 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { 2832 Expression* left = binop->left(); 2833 Expression* right = binop->right(); 2834 2835 if (execution_result()->IsTest()) { 2836 TestResultScope* test_result = execution_result()->AsTest(); 2837 2838 if (left->ToBooleanIsTrue()) { 2839 builder()->Jump(test_result->NewThenLabel()); 2840 } else if (left->ToBooleanIsFalse() && right->ToBooleanIsFalse()) { 2841 builder()->Jump(test_result->NewElseLabel()); 2842 } else { 2843 BytecodeLabels test_right(zone()); 2844 VisitForTest(left, test_result->then_labels(), &test_right, 2845 TestFallthrough::kElse); 2846 test_right.Bind(builder()); 2847 VisitForTest(right, test_result->then_labels(), 2848 test_result->else_labels(), test_result->fallthrough()); 2849 } 2850 test_result->SetResultConsumedByTest(); 2851 } else { 2852 if (left->ToBooleanIsTrue()) { 2853 VisitForAccumulatorValue(left); 2854 } else if (left->ToBooleanIsFalse()) { 2855 VisitForAccumulatorValue(right); 2856 } else { 2857 BytecodeLabel end_label; 2858 VisitForAccumulatorValue(left); 2859 builder()->JumpIfTrue(&end_label); 2860 VisitForAccumulatorValue(right); 2861 builder()->Bind(&end_label); 2862 } 2863 } 2864 } 2865 2866 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { 2867 Expression* left = binop->left(); 2868 Expression* right = binop->right(); 2869 2870 if (execution_result()->IsTest()) { 2871 TestResultScope* test_result = execution_result()->AsTest(); 2872 2873 if (left->ToBooleanIsFalse()) { 2874 builder()->Jump(test_result->NewElseLabel()); 2875 } else if (left->ToBooleanIsTrue() && right->ToBooleanIsTrue()) { 2876 builder()->Jump(test_result->NewThenLabel()); 2877 } else { 2878 BytecodeLabels test_right(zone()); 2879 VisitForTest(left, &test_right, test_result->else_labels(), 2880 TestFallthrough::kThen); 2881 test_right.Bind(builder()); 2882 VisitForTest(right, test_result->then_labels(), 2883 test_result->else_labels(), test_result->fallthrough()); 2884 } 2885 test_result->SetResultConsumedByTest(); 2886 } else { 2887 if (left->ToBooleanIsFalse()) { 2888 VisitForAccumulatorValue(left); 2889 } else if (left->ToBooleanIsTrue()) { 2890 VisitForAccumulatorValue(right); 2891 } else { 2892 BytecodeLabel end_label; 2893 VisitForAccumulatorValue(left); 2894 builder()->JumpIfFalse(&end_label); 2895 VisitForAccumulatorValue(right); 2896 builder()->Bind(&end_label); 2897 } 2898 } 2899 } 2900 2901 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { 2902 Visit(expr->expression()); 2903 } 2904 2905 void BytecodeGenerator::BuildNewLocalActivationContext() { 2906 ValueResultScope value_execution_result(this); 2907 Scope* scope = this->scope(); 2908 2909 // Create the appropriate context. 2910 if (scope->is_script_scope()) { 2911 RegisterList args = register_allocator()->NewRegisterList(2); 2912 builder() 2913 ->LoadAccumulatorWithRegister(Register::function_closure()) 2914 .StoreAccumulatorInRegister(args[0]) 2915 .LoadLiteral(scope->scope_info()) 2916 .StoreAccumulatorInRegister(args[1]) 2917 .CallRuntime(Runtime::kNewScriptContext, args); 2918 } else if (scope->is_module_scope()) { 2919 // We don't need to do anything for the outer script scope. 2920 DCHECK(scope->outer_scope()->is_script_scope()); 2921 2922 // A JSFunction representing a module is called with the module object as 2923 // its sole argument, which we pass on to PushModuleContext. 2924 RegisterList args = register_allocator()->NewRegisterList(3); 2925 builder() 2926 ->MoveRegister(builder()->Parameter(1), args[0]) 2927 .LoadAccumulatorWithRegister(Register::function_closure()) 2928 .StoreAccumulatorInRegister(args[1]) 2929 .LoadLiteral(scope->scope_info()) 2930 .StoreAccumulatorInRegister(args[2]) 2931 .CallRuntime(Runtime::kPushModuleContext, args); 2932 } else { 2933 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 2934 if (slot_count <= FastNewFunctionContextStub::kMaximumSlots) { 2935 builder()->CreateFunctionContext(slot_count); 2936 } else { 2937 builder()->CallRuntime(Runtime::kNewFunctionContext, 2938 Register::function_closure()); 2939 } 2940 } 2941 } 2942 2943 void BytecodeGenerator::BuildLocalActivationContextInitialization() { 2944 DeclarationScope* scope = this->scope(); 2945 2946 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { 2947 Variable* variable = scope->receiver(); 2948 Register receiver(builder()->Parameter(0)); 2949 // Context variable (at bottom of the context chain). 2950 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); 2951 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( 2952 execution_context()->reg(), variable->index(), 0); 2953 } 2954 2955 // Copy parameters into context if necessary. 2956 int num_parameters = scope->num_parameters(); 2957 for (int i = 0; i < num_parameters; i++) { 2958 Variable* variable = scope->parameter(i); 2959 if (!variable->IsContextSlot()) continue; 2960 2961 // The parameter indices are shifted by 1 (receiver is variable 2962 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 2963 Register parameter(builder()->Parameter(i + 1)); 2964 // Context variable (at bottom of the context chain). 2965 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); 2966 builder()->LoadAccumulatorWithRegister(parameter).StoreContextSlot( 2967 execution_context()->reg(), variable->index(), 0); 2968 } 2969 } 2970 2971 void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) { 2972 ValueResultScope value_execution_result(this); 2973 DCHECK(scope->is_block_scope()); 2974 2975 VisitFunctionClosureForContext(); 2976 builder()->CreateBlockContext(scope->scope_info()); 2977 } 2978 2979 void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) { 2980 ValueResultScope value_execution_result(this); 2981 2982 Register extension_object = register_allocator()->NewRegister(); 2983 2984 builder()->ConvertAccumulatorToObject(extension_object); 2985 VisitFunctionClosureForContext(); 2986 builder()->CreateWithContext(extension_object, scope->scope_info()); 2987 } 2988 2989 void BytecodeGenerator::BuildNewLocalCatchContext(Variable* variable, 2990 Scope* scope) { 2991 ValueResultScope value_execution_result(this); 2992 DCHECK(variable->IsContextSlot()); 2993 2994 Register exception = register_allocator()->NewRegister(); 2995 builder()->StoreAccumulatorInRegister(exception); 2996 VisitFunctionClosureForContext(); 2997 builder()->CreateCatchContext(exception, variable->name(), 2998 scope->scope_info()); 2999 } 3000 3001 void BytecodeGenerator::VisitObjectLiteralAccessor( 3002 Register home_object, ObjectLiteralProperty* property, Register value_out) { 3003 if (property == nullptr) { 3004 builder()->LoadNull().StoreAccumulatorInRegister(value_out); 3005 } else { 3006 VisitForRegisterValue(property->value(), value_out); 3007 VisitSetHomeObject(value_out, home_object, property); 3008 } 3009 } 3010 3011 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, 3012 LiteralProperty* property, 3013 int slot_number) { 3014 Expression* expr = property->value(); 3015 if (FunctionLiteral::NeedsHomeObject(expr)) { 3016 FeedbackVectorSlot slot = property->GetSlot(slot_number); 3017 builder() 3018 ->LoadAccumulatorWithRegister(home_object) 3019 .StoreNamedProperty(value, home_object_symbol(), feedback_index(slot), 3020 language_mode()); 3021 } 3022 } 3023 3024 void BytecodeGenerator::VisitArgumentsObject(Variable* variable) { 3025 if (variable == nullptr) return; 3026 3027 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); 3028 3029 // Allocate and initialize a new arguments object and assign to the 3030 // {arguments} variable. 3031 CreateArgumentsType type = 3032 is_strict(language_mode()) || !info()->has_simple_parameters() 3033 ? CreateArgumentsType::kUnmappedArguments 3034 : CreateArgumentsType::kMappedArguments; 3035 builder()->CreateArguments(type); 3036 BuildVariableAssignment(variable, Token::ASSIGN, 3037 FeedbackVectorSlot::Invalid(), 3038 HoleCheckMode::kElided); 3039 } 3040 3041 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) { 3042 if (rest == nullptr) return; 3043 3044 // Allocate and initialize a new rest parameter and assign to the {rest} 3045 // variable. 3046 builder()->CreateArguments(CreateArgumentsType::kRestParameter); 3047 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); 3048 BuildVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid(), 3049 HoleCheckMode::kElided); 3050 } 3051 3052 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { 3053 if (variable == nullptr) return; 3054 3055 // Store the closure we were called with in the given variable. 3056 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 3057 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid(), 3058 HoleCheckMode::kElided); 3059 } 3060 3061 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { 3062 if (variable == nullptr) return; 3063 3064 // Store the new target we were called with in the given variable. 3065 builder()->LoadAccumulatorWithRegister(Register::new_target()); 3066 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid(), 3067 HoleCheckMode::kElided); 3068 3069 // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer 3070 // and we need to make sure {BytecodeRegisterOptimizer} flushes its state 3071 // before a local variable containing the <new.target> is used. Using a label 3072 // as below flushes the entire pipeline, we should be more specific here. 3073 BytecodeLabel flush_state_label; 3074 builder()->Bind(&flush_state_label); 3075 } 3076 3077 void BytecodeGenerator::VisitFunctionClosureForContext() { 3078 ValueResultScope value_execution_result(this); 3079 DeclarationScope* closure_scope = 3080 execution_context()->scope()->GetClosureScope(); 3081 if (closure_scope->is_script_scope()) { 3082 // Contexts nested in the native context have a canonical empty function as 3083 // their closure, not the anonymous closure containing the global code. 3084 Register native_context = register_allocator()->NewRegister(); 3085 builder() 3086 ->LoadContextSlot(execution_context()->reg(), 3087 Context::NATIVE_CONTEXT_INDEX, 0) 3088 .StoreAccumulatorInRegister(native_context) 3089 .LoadContextSlot(native_context, Context::CLOSURE_INDEX, 0); 3090 } else if (closure_scope->is_eval_scope()) { 3091 // Contexts created by a call to eval have the same closure as the 3092 // context calling eval, not the anonymous closure containing the eval 3093 // code. Fetch it from the context. 3094 builder()->LoadContextSlot(execution_context()->reg(), 3095 Context::CLOSURE_INDEX, 0); 3096 } else { 3097 DCHECK(closure_scope->is_function_scope() || 3098 closure_scope->is_module_scope()); 3099 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 3100 } 3101 } 3102 3103 // Visits the expression |expr| and places the result in the accumulator. 3104 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { 3105 ValueResultScope accumulator_scope(this); 3106 Visit(expr); 3107 } 3108 3109 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { 3110 if (expr == nullptr) { 3111 builder()->LoadTheHole(); 3112 } else { 3113 VisitForAccumulatorValue(expr); 3114 } 3115 } 3116 3117 // Visits the expression |expr| and discards the result. 3118 void BytecodeGenerator::VisitForEffect(Expression* expr) { 3119 EffectResultScope effect_scope(this); 3120 Visit(expr); 3121 } 3122 3123 // Visits the expression |expr| and returns the register containing 3124 // the expression result. 3125 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { 3126 VisitForAccumulatorValue(expr); 3127 Register result = register_allocator()->NewRegister(); 3128 builder()->StoreAccumulatorInRegister(result); 3129 return result; 3130 } 3131 3132 // Visits the expression |expr| and stores the expression result in 3133 // |destination|. 3134 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, 3135 Register destination) { 3136 ValueResultScope register_scope(this); 3137 Visit(expr); 3138 builder()->StoreAccumulatorInRegister(destination); 3139 } 3140 3141 // Visits the expression |expr| and pushes the result into a new register 3142 // added to the end of |reg_list|. 3143 void BytecodeGenerator::VisitAndPushIntoRegisterList(Expression* expr, 3144 RegisterList* reg_list) { 3145 { 3146 ValueResultScope register_scope(this); 3147 Visit(expr); 3148 } 3149 // Grow the register list after visiting the expression to avoid reserving 3150 // the register across the expression evaluation, which could cause memory 3151 // leaks for deep expressions due to dead objects being kept alive by pointers 3152 // in registers. 3153 Register destination = register_allocator()->GrowRegisterList(reg_list); 3154 builder()->StoreAccumulatorInRegister(destination); 3155 } 3156 3157 void BytecodeGenerator::BuildPushUndefinedIntoRegisterList( 3158 RegisterList* reg_list) { 3159 Register reg = register_allocator()->GrowRegisterList(reg_list); 3160 builder()->LoadUndefined().StoreAccumulatorInRegister(reg); 3161 } 3162 3163 // Visits the expression |expr| for testing its boolean value and jumping to the 3164 // |then| or |other| label depending on value and short-circuit semantics 3165 void BytecodeGenerator::VisitForTest(Expression* expr, 3166 BytecodeLabels* then_labels, 3167 BytecodeLabels* else_labels, 3168 TestFallthrough fallthrough) { 3169 bool result_consumed; 3170 { 3171 // To make sure that all temporary registers are returned before generating 3172 // jumps below, we ensure that the result scope is deleted before doing so. 3173 // Dead registers might be materialized otherwise. 3174 TestResultScope test_result(this, then_labels, else_labels, fallthrough); 3175 Visit(expr); 3176 result_consumed = test_result.ResultConsumedByTest(); 3177 } 3178 if (!result_consumed) { 3179 switch (fallthrough) { 3180 case TestFallthrough::kThen: 3181 builder()->JumpIfFalse(else_labels->New()); 3182 break; 3183 case TestFallthrough::kElse: 3184 builder()->JumpIfTrue(then_labels->New()); 3185 break; 3186 case TestFallthrough::kNone: 3187 builder()->JumpIfTrue(then_labels->New()); 3188 builder()->Jump(else_labels->New()); 3189 } 3190 } 3191 } 3192 3193 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { 3194 ContextScope context_scope(this, scope); 3195 DCHECK(scope->declarations()->is_empty()); 3196 Visit(stmt); 3197 } 3198 3199 LanguageMode BytecodeGenerator::language_mode() const { 3200 return execution_context()->scope()->language_mode(); 3201 } 3202 3203 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 3204 return TypeFeedbackVector::GetIndex(slot); 3205 } 3206 3207 Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() { 3208 return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict 3209 : Runtime::kStoreToSuper_Sloppy; 3210 } 3211 3212 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { 3213 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict 3214 : Runtime::kStoreKeyedToSuper_Sloppy; 3215 } 3216 3217 } // namespace interpreter 3218 } // namespace internal 3219 } // namespace v8 3220