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