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/compiler.h" 9 #include "src/interpreter/bytecode-register-allocator.h" 10 #include "src/interpreter/control-flow-builders.h" 11 #include "src/objects.h" 12 #include "src/parsing/parser.h" 13 #include "src/parsing/token.h" 14 15 namespace v8 { 16 namespace internal { 17 namespace interpreter { 18 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_(generator_->NextContextRegister()), 31 depth_(0), 32 should_pop_context_(should_pop_context) { 33 if (outer_) { 34 depth_ = outer_->depth_ + 1; 35 generator_->builder()->PushContext(register_); 36 } 37 generator_->set_execution_context(this); 38 } 39 40 ~ContextScope() { 41 if (outer_ && should_pop_context_) { 42 generator_->builder()->PopContext(outer_->reg()); 43 } 44 generator_->set_execution_context(outer_); 45 } 46 47 // Returns the depth of the given |scope| for the current execution context. 48 int ContextChainDepth(Scope* scope) { 49 return scope_->ContextChainLength(scope); 50 } 51 52 // Returns the execution context at |depth| in the current context chain if it 53 // is a function local execution context, otherwise returns nullptr. 54 ContextScope* Previous(int depth) { 55 if (depth > depth_) { 56 return nullptr; 57 } 58 59 ContextScope* previous = this; 60 for (int i = depth; i > 0; --i) { 61 previous = previous->outer_; 62 } 63 return previous; 64 } 65 66 Scope* scope() const { return scope_; } 67 Register reg() const { return register_; } 68 69 private: 70 BytecodeGenerator* generator_; 71 Scope* scope_; 72 ContextScope* outer_; 73 Register register_; 74 int depth_; 75 bool should_pop_context_; 76 }; 77 78 79 // Scoped class for tracking control statements entered by the 80 // visitor. The pattern derives AstGraphBuilder::ControlScope. 81 class BytecodeGenerator::ControlScope BASE_EMBEDDED { 82 public: 83 explicit ControlScope(BytecodeGenerator* generator) 84 : generator_(generator), outer_(generator->execution_control()) { 85 generator_->set_execution_control(this); 86 } 87 virtual ~ControlScope() { generator_->set_execution_control(outer()); } 88 89 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } 90 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } 91 92 protected: 93 enum Command { CMD_BREAK, CMD_CONTINUE }; 94 void PerformCommand(Command command, Statement* statement); 95 virtual bool Execute(Command command, Statement* statement) = 0; 96 97 BytecodeGenerator* generator() const { return generator_; } 98 ControlScope* outer() const { return outer_; } 99 100 private: 101 BytecodeGenerator* generator_; 102 ControlScope* outer_; 103 104 DISALLOW_COPY_AND_ASSIGN(ControlScope); 105 }; 106 107 108 // Scoped class for enabling break inside blocks and switch blocks. 109 class BytecodeGenerator::ControlScopeForBreakable final 110 : public BytecodeGenerator::ControlScope { 111 public: 112 ControlScopeForBreakable(BytecodeGenerator* generator, 113 BreakableStatement* statement, 114 BreakableControlFlowBuilder* control_builder) 115 : ControlScope(generator), 116 statement_(statement), 117 control_builder_(control_builder) {} 118 119 protected: 120 virtual bool Execute(Command command, Statement* statement) { 121 if (statement != statement_) return false; 122 switch (command) { 123 case CMD_BREAK: 124 control_builder_->Break(); 125 return true; 126 case CMD_CONTINUE: 127 break; 128 } 129 return false; 130 } 131 132 private: 133 Statement* statement_; 134 BreakableControlFlowBuilder* control_builder_; 135 }; 136 137 138 // Scoped class for enabling 'break' and 'continue' in iteration 139 // constructs, e.g. do...while, while..., for... 140 class BytecodeGenerator::ControlScopeForIteration final 141 : public BytecodeGenerator::ControlScope { 142 public: 143 ControlScopeForIteration(BytecodeGenerator* generator, 144 IterationStatement* statement, 145 LoopBuilder* loop_builder) 146 : ControlScope(generator), 147 statement_(statement), 148 loop_builder_(loop_builder) {} 149 150 protected: 151 virtual bool Execute(Command command, Statement* statement) { 152 if (statement != statement_) return false; 153 switch (command) { 154 case CMD_BREAK: 155 loop_builder_->Break(); 156 return true; 157 case CMD_CONTINUE: 158 loop_builder_->Continue(); 159 return true; 160 } 161 return false; 162 } 163 164 private: 165 Statement* statement_; 166 LoopBuilder* loop_builder_; 167 }; 168 169 170 void BytecodeGenerator::ControlScope::PerformCommand(Command command, 171 Statement* statement) { 172 ControlScope* current = this; 173 do { 174 if (current->Execute(command, statement)) return; 175 current = current->outer(); 176 } while (current != nullptr); 177 UNREACHABLE(); 178 } 179 180 181 class BytecodeGenerator::RegisterAllocationScope { 182 public: 183 explicit RegisterAllocationScope(BytecodeGenerator* generator) 184 : generator_(generator), 185 outer_(generator->register_allocator()), 186 allocator_(builder()) { 187 generator_->set_register_allocator(this); 188 } 189 190 virtual ~RegisterAllocationScope() { 191 generator_->set_register_allocator(outer_); 192 } 193 194 Register NewRegister() { 195 RegisterAllocationScope* current_scope = generator()->register_allocator(); 196 if ((current_scope == this) || 197 (current_scope->outer() == this && 198 !current_scope->allocator_.HasConsecutiveAllocations())) { 199 // Regular case - Allocating registers in current or outer context. 200 // VisitForRegisterValue allocates register in outer context. 201 return allocator_.NewRegister(); 202 } else { 203 // If it is required to allocate a register other than current or outer 204 // scopes, allocate a new temporary register. It might be expensive to 205 // walk the full context chain and compute the list of consecutive 206 // reservations in the innerscopes. 207 UNIMPLEMENTED(); 208 return Register(-1); 209 } 210 } 211 212 void PrepareForConsecutiveAllocations(size_t count) { 213 allocator_.PrepareForConsecutiveAllocations(count); 214 } 215 216 Register NextConsecutiveRegister() { 217 return allocator_.NextConsecutiveRegister(); 218 } 219 220 bool RegisterIsAllocatedInThisScope(Register reg) const { 221 return allocator_.RegisterIsAllocatedInThisScope(reg); 222 } 223 224 RegisterAllocationScope* outer() const { return outer_; } 225 226 private: 227 BytecodeGenerator* generator() const { return generator_; } 228 BytecodeArrayBuilder* builder() const { return generator_->builder(); } 229 230 BytecodeGenerator* generator_; 231 RegisterAllocationScope* outer_; 232 BytecodeRegisterAllocator allocator_; 233 234 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope); 235 }; 236 237 238 // Scoped base class for determining where the result of an expression 239 // is stored. 240 class BytecodeGenerator::ExpressionResultScope { 241 public: 242 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) 243 : generator_(generator), 244 kind_(kind), 245 outer_(generator->execution_result()), 246 allocator_(generator), 247 result_identified_(false) { 248 generator_->set_execution_result(this); 249 } 250 251 virtual ~ExpressionResultScope() { 252 generator_->set_execution_result(outer_); 253 DCHECK(result_identified()); 254 } 255 256 bool IsEffect() const { return kind_ == Expression::kEffect; } 257 bool IsValue() const { return kind_ == Expression::kValue; } 258 259 virtual void SetResultInAccumulator() = 0; 260 virtual void SetResultInRegister(Register reg) = 0; 261 262 protected: 263 ExpressionResultScope* outer() const { return outer_; } 264 BytecodeArrayBuilder* builder() const { return generator_->builder(); } 265 const RegisterAllocationScope* allocator() const { return &allocator_; } 266 267 void set_result_identified() { 268 DCHECK(!result_identified()); 269 result_identified_ = true; 270 } 271 272 bool result_identified() const { return result_identified_; } 273 274 private: 275 BytecodeGenerator* generator_; 276 Expression::Context kind_; 277 ExpressionResultScope* outer_; 278 RegisterAllocationScope allocator_; 279 bool result_identified_; 280 281 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); 282 }; 283 284 285 // Scoped class used when the result of the current expression is not 286 // expected to produce a result. 287 class BytecodeGenerator::EffectResultScope final 288 : public ExpressionResultScope { 289 public: 290 explicit EffectResultScope(BytecodeGenerator* generator) 291 : ExpressionResultScope(generator, Expression::kEffect) { 292 set_result_identified(); 293 } 294 295 virtual void SetResultInAccumulator() {} 296 virtual void SetResultInRegister(Register reg) {} 297 }; 298 299 300 // Scoped class used when the result of the current expression to be 301 // evaluated should go into the interpreter's accumulator register. 302 class BytecodeGenerator::AccumulatorResultScope final 303 : public ExpressionResultScope { 304 public: 305 explicit AccumulatorResultScope(BytecodeGenerator* generator) 306 : ExpressionResultScope(generator, Expression::kValue) {} 307 308 virtual void SetResultInAccumulator() { set_result_identified(); } 309 310 virtual void SetResultInRegister(Register reg) { 311 builder()->LoadAccumulatorWithRegister(reg); 312 set_result_identified(); 313 } 314 }; 315 316 317 // Scoped class used when the result of the current expression to be 318 // evaluated should go into an interpreter register. 319 class BytecodeGenerator::RegisterResultScope final 320 : public ExpressionResultScope { 321 public: 322 explicit RegisterResultScope(BytecodeGenerator* generator) 323 : ExpressionResultScope(generator, Expression::kValue) {} 324 325 virtual void SetResultInAccumulator() { 326 result_register_ = allocator()->outer()->NewRegister(); 327 builder()->StoreAccumulatorInRegister(result_register_); 328 set_result_identified(); 329 } 330 331 virtual void SetResultInRegister(Register reg) { 332 DCHECK(builder()->RegisterIsParameterOrLocal(reg) || 333 (builder()->RegisterIsTemporary(reg) && 334 !allocator()->RegisterIsAllocatedInThisScope(reg))); 335 result_register_ = reg; 336 set_result_identified(); 337 } 338 339 Register ResultRegister() const { return result_register_; } 340 341 private: 342 Register result_register_; 343 }; 344 345 346 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) 347 : isolate_(isolate), 348 zone_(zone), 349 builder_(isolate, zone), 350 info_(nullptr), 351 scope_(nullptr), 352 globals_(0, zone), 353 execution_control_(nullptr), 354 execution_context_(nullptr), 355 execution_result_(nullptr), 356 register_allocator_(nullptr) { 357 InitializeAstVisitor(isolate); 358 } 359 360 361 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 362 set_info(info); 363 set_scope(info->scope()); 364 365 // Initialize the incoming context. 366 ContextScope incoming_context(this, scope(), false); 367 368 builder()->set_parameter_count(info->num_parameters_including_this()); 369 builder()->set_locals_count(scope()->num_stack_slots()); 370 builder()->set_context_count(scope()->MaxNestedContextChainLength()); 371 372 // Build function context only if there are context allocated variables. 373 if (scope()->NeedsContext()) { 374 // Push a new inner context scope for the function. 375 VisitNewLocalFunctionContext(); 376 ContextScope local_function_context(this, scope(), false); 377 VisitBuildLocalActivationContext(); 378 MakeBytecodeBody(); 379 } else { 380 MakeBytecodeBody(); 381 } 382 383 set_scope(nullptr); 384 set_info(nullptr); 385 return builder_.ToBytecodeArray(); 386 } 387 388 389 void BytecodeGenerator::MakeBytecodeBody() { 390 // Build the arguments object if it is used. 391 VisitArgumentsObject(scope()->arguments()); 392 393 // TODO(mythria): Build rest arguments array if it is used. 394 int rest_index; 395 if (scope()->rest_parameter(&rest_index)) { 396 UNIMPLEMENTED(); 397 } 398 399 // Build assignment to {.this_function} variable if it is used. 400 VisitThisFunctionVariable(scope()->this_function_var()); 401 402 // Build assignment to {new.target} variable if it is used. 403 VisitNewTargetVariable(scope()->new_target_var()); 404 405 // TODO(rmcilroy): Emit tracing call if requested to do so. 406 if (FLAG_trace) { 407 UNIMPLEMENTED(); 408 } 409 410 // Visit illegal re-declaration and bail out if it exists. 411 if (scope()->HasIllegalRedeclaration()) { 412 Visit(scope()->GetIllegalRedeclaration()); 413 return; 414 } 415 416 // Visit declarations within the function scope. 417 VisitDeclarations(scope()->declarations()); 418 419 // Visit statements in the function body. 420 VisitStatements(info()->literal()->body()); 421 } 422 423 424 void BytecodeGenerator::VisitBlock(Block* stmt) { 425 BlockBuilder block_builder(this->builder()); 426 ControlScopeForBreakable execution_control(this, stmt, &block_builder); 427 428 if (stmt->scope() == NULL) { 429 // Visit statements in the same scope, no declarations. 430 VisitStatements(stmt->statements()); 431 } else { 432 // Visit declarations and statements in a block scope. 433 if (stmt->scope()->NeedsContext()) { 434 VisitNewLocalBlockContext(stmt->scope()); 435 ContextScope scope(this, stmt->scope()); 436 VisitDeclarations(stmt->scope()->declarations()); 437 VisitStatements(stmt->statements()); 438 } else { 439 VisitDeclarations(stmt->scope()->declarations()); 440 VisitStatements(stmt->statements()); 441 } 442 } 443 if (stmt->labels() != nullptr) block_builder.EndBlock(); 444 } 445 446 447 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { 448 Variable* variable = decl->proxy()->var(); 449 VariableMode mode = decl->mode(); 450 // Const and let variables are initialized with the hole so that we can 451 // check that they are only assigned once. 452 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; 453 switch (variable->location()) { 454 case VariableLocation::GLOBAL: 455 case VariableLocation::UNALLOCATED: { 456 Handle<Oddball> value = variable->binding_needs_init() 457 ? isolate()->factory()->the_hole_value() 458 : isolate()->factory()->undefined_value(); 459 globals()->push_back(variable->name()); 460 globals()->push_back(value); 461 break; 462 } 463 case VariableLocation::LOCAL: 464 if (hole_init) { 465 Register destination(variable->index()); 466 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); 467 } 468 break; 469 case VariableLocation::PARAMETER: 470 if (hole_init) { 471 // The parameter indices are shifted by 1 (receiver is variable 472 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 473 Register destination(builder()->Parameter(variable->index() + 1)); 474 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); 475 } 476 break; 477 case VariableLocation::CONTEXT: 478 if (hole_init) { 479 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(), 480 variable->index()); 481 } 482 break; 483 case VariableLocation::LOOKUP: 484 UNIMPLEMENTED(); 485 break; 486 } 487 } 488 489 490 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { 491 Variable* variable = decl->proxy()->var(); 492 switch (variable->location()) { 493 case VariableLocation::GLOBAL: 494 case VariableLocation::UNALLOCATED: { 495 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( 496 decl->fun(), info()->script(), info()); 497 // Check for stack-overflow exception. 498 if (function.is_null()) return SetStackOverflow(); 499 globals()->push_back(variable->name()); 500 globals()->push_back(function); 501 break; 502 } 503 case VariableLocation::PARAMETER: 504 case VariableLocation::LOCAL: { 505 VisitForAccumulatorValue(decl->fun()); 506 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 507 break; 508 } 509 case VariableLocation::CONTEXT: { 510 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); 511 VisitForAccumulatorValue(decl->fun()); 512 builder()->StoreContextSlot(execution_context()->reg(), 513 variable->index()); 514 break; 515 } 516 case VariableLocation::LOOKUP: 517 UNIMPLEMENTED(); 518 } 519 } 520 521 522 void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) { 523 UNIMPLEMENTED(); 524 } 525 526 527 void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) { 528 UNIMPLEMENTED(); 529 } 530 531 532 void BytecodeGenerator::VisitDeclarations( 533 ZoneList<Declaration*>* declarations) { 534 RegisterAllocationScope register_scope(this); 535 DCHECK(globals()->empty()); 536 AstVisitor::VisitDeclarations(declarations); 537 if (globals()->empty()) return; 538 int array_index = 0; 539 Handle<FixedArray> data = isolate()->factory()->NewFixedArray( 540 static_cast<int>(globals()->size()), TENURED); 541 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj); 542 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | 543 DeclareGlobalsNativeFlag::encode(info()->is_native()) | 544 DeclareGlobalsLanguageMode::encode(language_mode()); 545 546 Register pairs = register_allocator()->NewRegister(); 547 builder()->LoadLiteral(data); 548 builder()->StoreAccumulatorInRegister(pairs); 549 550 Register flags = register_allocator()->NewRegister(); 551 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); 552 builder()->StoreAccumulatorInRegister(flags); 553 DCHECK(flags.index() == pairs.index() + 1); 554 555 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); 556 globals()->clear(); 557 } 558 559 560 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { 561 for (int i = 0; i < statements->length(); i++) { 562 // Allocate an outer register allocations scope for the statement. 563 RegisterAllocationScope allocation_scope(this); 564 Statement* stmt = statements->at(i); 565 Visit(stmt); 566 if (stmt->IsJump()) break; 567 } 568 } 569 570 571 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 572 VisitForEffect(stmt->expression()); 573 } 574 575 576 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 577 } 578 579 580 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { 581 BytecodeLabel else_label, end_label; 582 if (stmt->condition()->ToBooleanIsTrue()) { 583 // Generate then block unconditionally as always true. 584 Visit(stmt->then_statement()); 585 } else if (stmt->condition()->ToBooleanIsFalse()) { 586 // Generate else block unconditionally if it exists. 587 if (stmt->HasElseStatement()) { 588 Visit(stmt->else_statement()); 589 } 590 } else { 591 // TODO(oth): If then statement is BreakStatement or 592 // ContinueStatement we can reduce number of generated 593 // jump/jump_ifs here. See BasicLoops test. 594 VisitForAccumulatorValue(stmt->condition()); 595 builder()->JumpIfFalse(&else_label); 596 Visit(stmt->then_statement()); 597 if (stmt->HasElseStatement()) { 598 builder()->Jump(&end_label); 599 builder()->Bind(&else_label); 600 Visit(stmt->else_statement()); 601 } else { 602 builder()->Bind(&else_label); 603 } 604 builder()->Bind(&end_label); 605 } 606 } 607 608 609 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( 610 SloppyBlockFunctionStatement* stmt) { 611 Visit(stmt->statement()); 612 } 613 614 615 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { 616 execution_control()->Continue(stmt->target()); 617 } 618 619 620 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 621 execution_control()->Break(stmt->target()); 622 } 623 624 625 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 626 VisitForAccumulatorValue(stmt->expression()); 627 builder()->Return(); 628 } 629 630 631 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 632 UNIMPLEMENTED(); 633 } 634 635 636 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 637 // We need this scope because we visit for register values. We have to 638 // maintain a execution result scope where registers can be allocated. 639 ZoneList<CaseClause*>* clauses = stmt->cases(); 640 SwitchBuilder switch_builder(builder(), clauses->length()); 641 ControlScopeForBreakable scope(this, stmt, &switch_builder); 642 int default_index = -1; 643 644 // Keep the switch value in a register until a case matches. 645 Register tag = VisitForRegisterValue(stmt->tag()); 646 647 // Iterate over all cases and create nodes for label comparison. 648 BytecodeLabel done_label; 649 for (int i = 0; i < clauses->length(); i++) { 650 CaseClause* clause = clauses->at(i); 651 652 // The default is not a test, remember index. 653 if (clause->is_default()) { 654 default_index = i; 655 continue; 656 } 657 658 // Perform label comparison as if via '===' with tag. 659 VisitForAccumulatorValue(clause->label()); 660 builder()->CompareOperation(Token::Value::EQ_STRICT, tag, 661 language_mode_strength()); 662 switch_builder.Case(i); 663 } 664 665 if (default_index >= 0) { 666 // Emit default jump if there is a default case. 667 switch_builder.DefaultAt(default_index); 668 } else { 669 // Otherwise if we have reached here none of the cases matched, so jump to 670 // done. 671 builder()->Jump(&done_label); 672 } 673 674 // Iterate over all cases and create the case bodies. 675 for (int i = 0; i < clauses->length(); i++) { 676 CaseClause* clause = clauses->at(i); 677 switch_builder.SetCaseTarget(i); 678 VisitStatements(clause->statements()); 679 } 680 builder()->Bind(&done_label); 681 682 switch_builder.SetBreakTarget(done_label); 683 } 684 685 686 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { 687 // Handled entirely in VisitSwitchStatement. 688 UNREACHABLE(); 689 } 690 691 692 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 693 LoopBuilder loop_builder(builder()); 694 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 695 loop_builder.LoopHeader(); 696 if (stmt->cond()->ToBooleanIsFalse()) { 697 Visit(stmt->body()); 698 loop_builder.Condition(); 699 } else if (stmt->cond()->ToBooleanIsTrue()) { 700 loop_builder.Condition(); 701 Visit(stmt->body()); 702 loop_builder.JumpToHeader(); 703 } else { 704 Visit(stmt->body()); 705 loop_builder.Condition(); 706 VisitForAccumulatorValue(stmt->cond()); 707 loop_builder.JumpToHeaderIfTrue(); 708 } 709 loop_builder.EndLoop(); 710 } 711 712 713 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 714 if (stmt->cond()->ToBooleanIsFalse()) { 715 // If the condition is false there is no need to generate the loop. 716 return; 717 } 718 719 LoopBuilder loop_builder(builder()); 720 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 721 loop_builder.LoopHeader(); 722 loop_builder.Condition(); 723 if (!stmt->cond()->ToBooleanIsTrue()) { 724 VisitForAccumulatorValue(stmt->cond()); 725 loop_builder.BreakIfFalse(); 726 } 727 Visit(stmt->body()); 728 loop_builder.JumpToHeader(); 729 loop_builder.EndLoop(); 730 } 731 732 733 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 734 if (stmt->init() != nullptr) { 735 Visit(stmt->init()); 736 } 737 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { 738 // If the condition is known to be false there is no need to generate 739 // body, next or condition blocks. Init block should be generated. 740 return; 741 } 742 743 LoopBuilder loop_builder(builder()); 744 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 745 746 loop_builder.LoopHeader(); 747 loop_builder.Condition(); 748 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { 749 VisitForAccumulatorValue(stmt->cond()); 750 loop_builder.BreakIfFalse(); 751 } 752 Visit(stmt->body()); 753 if (stmt->next() != nullptr) { 754 loop_builder.Next(); 755 Visit(stmt->next()); 756 } 757 loop_builder.JumpToHeader(); 758 loop_builder.EndLoop(); 759 } 760 761 762 void BytecodeGenerator::VisitForInAssignment(Expression* expr, 763 FeedbackVectorSlot slot) { 764 DCHECK(expr->IsValidReferenceExpression()); 765 766 // Evaluate assignment starting with the value to be stored in the 767 // accumulator. 768 Property* property = expr->AsProperty(); 769 LhsKind assign_type = Property::GetAssignType(property); 770 switch (assign_type) { 771 case VARIABLE: { 772 Variable* variable = expr->AsVariableProxy()->var(); 773 VisitVariableAssignment(variable, slot); 774 break; 775 } 776 case NAMED_PROPERTY: { 777 RegisterAllocationScope register_scope(this); 778 Register value = register_allocator()->NewRegister(); 779 builder()->StoreAccumulatorInRegister(value); 780 Register object = VisitForRegisterValue(property->obj()); 781 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); 782 builder()->LoadAccumulatorWithRegister(value); 783 builder()->StoreNamedProperty(object, name, feedback_index(slot), 784 language_mode()); 785 break; 786 } 787 case KEYED_PROPERTY: { 788 RegisterAllocationScope register_scope(this); 789 Register value = register_allocator()->NewRegister(); 790 builder()->StoreAccumulatorInRegister(value); 791 Register object = VisitForRegisterValue(property->obj()); 792 Register key = VisitForRegisterValue(property->key()); 793 builder()->LoadAccumulatorWithRegister(value); 794 builder()->StoreKeyedProperty(object, key, feedback_index(slot), 795 language_mode()); 796 break; 797 } 798 case NAMED_SUPER_PROPERTY: 799 case KEYED_SUPER_PROPERTY: 800 UNIMPLEMENTED(); 801 } 802 } 803 804 805 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { 806 if (stmt->subject()->IsNullLiteral() || 807 stmt->subject()->IsUndefinedLiteral(isolate())) { 808 // ForIn generates lots of code, skip if it wouldn't produce any effects. 809 return; 810 } 811 812 LoopBuilder loop_builder(builder()); 813 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 814 BytecodeLabel subject_null_label, subject_undefined_label, not_object_label; 815 816 // Prepare the state for executing ForIn. 817 VisitForAccumulatorValue(stmt->subject()); 818 builder()->JumpIfUndefined(&subject_undefined_label); 819 builder()->JumpIfNull(&subject_null_label); 820 Register receiver = register_allocator()->NewRegister(); 821 builder()->CastAccumulatorToJSObject(); 822 builder()->JumpIfNull(¬_object_label); 823 builder()->StoreAccumulatorInRegister(receiver); 824 Register cache_type = register_allocator()->NewRegister(); 825 Register cache_array = register_allocator()->NewRegister(); 826 Register cache_length = register_allocator()->NewRegister(); 827 builder()->ForInPrepare(cache_type, cache_array, cache_length); 828 829 // Set up loop counter 830 Register index = register_allocator()->NewRegister(); 831 builder()->LoadLiteral(Smi::FromInt(0)); 832 builder()->StoreAccumulatorInRegister(index); 833 834 // The loop 835 loop_builder.LoopHeader(); 836 loop_builder.Condition(); 837 builder()->ForInDone(index, cache_length); 838 loop_builder.BreakIfTrue(); 839 builder()->ForInNext(receiver, cache_type, cache_array, index); 840 loop_builder.ContinueIfUndefined(); 841 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); 842 Visit(stmt->body()); 843 loop_builder.Next(); 844 builder()->ForInStep(index); 845 builder()->StoreAccumulatorInRegister(index); 846 loop_builder.JumpToHeader(); 847 loop_builder.EndLoop(); 848 builder()->Bind(¬_object_label); 849 builder()->Bind(&subject_null_label); 850 builder()->Bind(&subject_undefined_label); 851 } 852 853 854 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 855 UNIMPLEMENTED(); 856 } 857 858 859 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { 860 if (FLAG_ignition_fake_try_catch) { 861 Visit(stmt->try_block()); 862 return; 863 } 864 UNIMPLEMENTED(); 865 } 866 867 868 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 869 if (FLAG_ignition_fake_try_catch) { 870 Visit(stmt->try_block()); 871 Visit(stmt->finally_block()); 872 return; 873 } 874 UNIMPLEMENTED(); 875 } 876 877 878 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { 879 UNIMPLEMENTED(); 880 } 881 882 883 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 884 // Find or build a shared function info. 885 Handle<SharedFunctionInfo> shared_info = 886 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); 887 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow? 888 builder()->CreateClosure(shared_info, 889 expr->pretenure() ? TENURED : NOT_TENURED); 890 execution_result()->SetResultInAccumulator(); 891 } 892 893 894 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { 895 UNIMPLEMENTED(); 896 } 897 898 899 void BytecodeGenerator::VisitNativeFunctionLiteral( 900 NativeFunctionLiteral* expr) { 901 UNIMPLEMENTED(); 902 } 903 904 905 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { 906 UNIMPLEMENTED(); 907 } 908 909 910 void BytecodeGenerator::VisitConditional(Conditional* expr) { 911 // TODO(rmcilroy): Spot easy cases where there code would not need to 912 // emit the then block or the else block, e.g. condition is 913 // obviously true/1/false/0. 914 915 BytecodeLabel else_label, end_label; 916 917 VisitForAccumulatorValue(expr->condition()); 918 builder()->JumpIfFalse(&else_label); 919 920 VisitForAccumulatorValue(expr->then_expression()); 921 builder()->Jump(&end_label); 922 923 builder()->Bind(&else_label); 924 VisitForAccumulatorValue(expr->else_expression()); 925 builder()->Bind(&end_label); 926 927 execution_result()->SetResultInAccumulator(); 928 } 929 930 931 void BytecodeGenerator::VisitLiteral(Literal* expr) { 932 if (!execution_result()->IsEffect()) { 933 Handle<Object> value = expr->value(); 934 if (value->IsSmi()) { 935 builder()->LoadLiteral(Smi::cast(*value)); 936 } else if (value->IsUndefined()) { 937 builder()->LoadUndefined(); 938 } else if (value->IsTrue()) { 939 builder()->LoadTrue(); 940 } else if (value->IsFalse()) { 941 builder()->LoadFalse(); 942 } else if (value->IsNull()) { 943 builder()->LoadNull(); 944 } else if (value->IsTheHole()) { 945 builder()->LoadTheHole(); 946 } else { 947 builder()->LoadLiteral(value); 948 } 949 execution_result()->SetResultInAccumulator(); 950 } 951 } 952 953 954 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 955 // Materialize a regular expression literal. 956 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(), 957 expr->flags()); 958 execution_result()->SetResultInAccumulator(); 959 } 960 961 962 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 963 // Deep-copy the literal boilerplate. 964 builder()->CreateObjectLiteral(expr->constant_properties(), 965 expr->literal_index(), 966 expr->ComputeFlags(true)); 967 Register literal; 968 969 // Store computed values into the literal. 970 bool literal_in_accumulator = true; 971 int property_index = 0; 972 AccessorTable accessor_table(zone()); 973 for (; property_index < expr->properties()->length(); property_index++) { 974 ObjectLiteral::Property* property = expr->properties()->at(property_index); 975 if (property->is_computed_name()) break; 976 if (property->IsCompileTimeValue()) continue; 977 978 if (literal_in_accumulator) { 979 literal = register_allocator()->NewRegister(); 980 builder()->StoreAccumulatorInRegister(literal); 981 literal_in_accumulator = false; 982 } 983 984 RegisterAllocationScope inner_register_scope(this); 985 Literal* literal_key = property->key()->AsLiteral(); 986 switch (property->kind()) { 987 case ObjectLiteral::Property::CONSTANT: 988 UNREACHABLE(); 989 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 990 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); 991 // Fall through. 992 case ObjectLiteral::Property::COMPUTED: { 993 // It is safe to use [[Put]] here because the boilerplate already 994 // contains computed properties with an uninitialized value. 995 if (literal_key->value()->IsInternalizedString()) { 996 if (property->emit_store()) { 997 VisitForAccumulatorValue(property->value()); 998 builder()->StoreNamedProperty( 999 literal, literal_key->AsPropertyName(), 1000 feedback_index(property->GetSlot(0)), language_mode()); 1001 } else { 1002 VisitForEffect(property->value()); 1003 } 1004 } else { 1005 register_allocator()->PrepareForConsecutiveAllocations(3); 1006 Register key = register_allocator()->NextConsecutiveRegister(); 1007 Register value = register_allocator()->NextConsecutiveRegister(); 1008 Register language = register_allocator()->NextConsecutiveRegister(); 1009 // TODO(oth): This is problematic - can't assume contiguous here. 1010 // literal is allocated in outer register scope, whereas key, value, 1011 // language are in another. 1012 DCHECK(Register::AreContiguous(literal, key, value, language)); 1013 VisitForAccumulatorValue(property->key()); 1014 builder()->StoreAccumulatorInRegister(key); 1015 VisitForAccumulatorValue(property->value()); 1016 builder()->StoreAccumulatorInRegister(value); 1017 if (property->emit_store()) { 1018 builder() 1019 ->LoadLiteral(Smi::FromInt(SLOPPY)) 1020 .StoreAccumulatorInRegister(language) 1021 .CallRuntime(Runtime::kSetProperty, literal, 4); 1022 VisitSetHomeObject(value, literal, property); 1023 } 1024 } 1025 break; 1026 } 1027 case ObjectLiteral::Property::PROTOTYPE: { 1028 register_allocator()->PrepareForConsecutiveAllocations(1); 1029 DCHECK(property->emit_store()); 1030 Register value = register_allocator()->NextConsecutiveRegister(); 1031 DCHECK(Register::AreContiguous(literal, value)); 1032 VisitForAccumulatorValue(property->value()); 1033 builder()->StoreAccumulatorInRegister(value).CallRuntime( 1034 Runtime::kInternalSetPrototype, literal, 2); 1035 break; 1036 } 1037 case ObjectLiteral::Property::GETTER: 1038 if (property->emit_store()) { 1039 accessor_table.lookup(literal_key)->second->getter = property; 1040 } 1041 break; 1042 case ObjectLiteral::Property::SETTER: 1043 if (property->emit_store()) { 1044 accessor_table.lookup(literal_key)->second->setter = property; 1045 } 1046 break; 1047 } 1048 } 1049 1050 // Define accessors, using only a single call to the runtime for each pair of 1051 // corresponding getters and setters. 1052 for (AccessorTable::Iterator it = accessor_table.begin(); 1053 it != accessor_table.end(); ++it) { 1054 RegisterAllocationScope inner_register_scope(this); 1055 register_allocator()->PrepareForConsecutiveAllocations(4); 1056 Register name = register_allocator()->NextConsecutiveRegister(); 1057 Register getter = register_allocator()->NextConsecutiveRegister(); 1058 Register setter = register_allocator()->NextConsecutiveRegister(); 1059 Register attr = register_allocator()->NextConsecutiveRegister(); 1060 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); 1061 VisitForAccumulatorValue(it->first); 1062 builder()->StoreAccumulatorInRegister(name); 1063 VisitObjectLiteralAccessor(literal, it->second->getter, getter); 1064 VisitObjectLiteralAccessor(literal, it->second->setter, setter); 1065 builder() 1066 ->LoadLiteral(Smi::FromInt(NONE)) 1067 .StoreAccumulatorInRegister(attr) 1068 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); 1069 } 1070 1071 // Object literals have two parts. The "static" part on the left contains no 1072 // computed property names, and so we can compute its map ahead of time; see 1073 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts 1074 // with the first computed property name and continues with all properties to 1075 // its right. All the code from above initializes the static component of the 1076 // object literal, and arranges for the map of the result to reflect the 1077 // static order in which the keys appear. For the dynamic properties, we 1078 // compile them into a series of "SetOwnProperty" runtime calls. This will 1079 // preserve insertion order. 1080 for (; property_index < expr->properties()->length(); property_index++) { 1081 if (literal_in_accumulator) { 1082 literal = register_allocator()->NewRegister(); 1083 builder()->StoreAccumulatorInRegister(literal); 1084 literal_in_accumulator = false; 1085 } 1086 1087 ObjectLiteral::Property* property = expr->properties()->at(property_index); 1088 RegisterAllocationScope inner_register_scope(this); 1089 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { 1090 DCHECK(property->emit_store()); 1091 Register value = register_allocator()->NewRegister(); 1092 DCHECK(Register::AreContiguous(literal, value)); 1093 VisitForAccumulatorValue(property->value()); 1094 builder()->StoreAccumulatorInRegister(value).CallRuntime( 1095 Runtime::kInternalSetPrototype, literal, 2); 1096 continue; 1097 } 1098 1099 register_allocator()->PrepareForConsecutiveAllocations(3); 1100 Register key = register_allocator()->NextConsecutiveRegister(); 1101 Register value = register_allocator()->NextConsecutiveRegister(); 1102 Register attr = register_allocator()->NextConsecutiveRegister(); 1103 DCHECK(Register::AreContiguous(literal, key, value, attr)); 1104 1105 VisitForAccumulatorValue(property->key()); 1106 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); 1107 VisitForAccumulatorValue(property->value()); 1108 builder()->StoreAccumulatorInRegister(value); 1109 VisitSetHomeObject(value, literal, property); 1110 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); 1111 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); 1112 switch (property->kind()) { 1113 case ObjectLiteral::Property::CONSTANT: 1114 case ObjectLiteral::Property::COMPUTED: 1115 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1116 function_id = Runtime::kDefineDataPropertyUnchecked; 1117 break; 1118 case ObjectLiteral::Property::PROTOTYPE: 1119 UNREACHABLE(); // Handled specially above. 1120 break; 1121 case ObjectLiteral::Property::GETTER: 1122 function_id = Runtime::kDefineGetterPropertyUnchecked; 1123 break; 1124 case ObjectLiteral::Property::SETTER: 1125 function_id = Runtime::kDefineSetterPropertyUnchecked; 1126 break; 1127 } 1128 builder()->CallRuntime(function_id, literal, 4); 1129 } 1130 1131 // Transform literals that contain functions to fast properties. 1132 if (expr->has_function()) { 1133 DCHECK(!literal_in_accumulator); 1134 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); 1135 } 1136 1137 if (!literal_in_accumulator) { 1138 // Restore literal array into accumulator. 1139 builder()->LoadAccumulatorWithRegister(literal); 1140 } 1141 execution_result()->SetResultInAccumulator(); 1142 } 1143 1144 1145 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1146 // Deep-copy the literal boilerplate. 1147 builder()->CreateArrayLiteral(expr->constant_elements(), 1148 expr->literal_index(), 1149 expr->ComputeFlags(true)); 1150 Register index, literal; 1151 1152 // Evaluate all the non-constant subexpressions and store them into the 1153 // newly cloned array. 1154 bool literal_in_accumulator = true; 1155 for (int array_index = 0; array_index < expr->values()->length(); 1156 array_index++) { 1157 Expression* subexpr = expr->values()->at(array_index); 1158 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 1159 if (subexpr->IsSpread()) { 1160 // TODO(rmcilroy): Deal with spread expressions. 1161 UNIMPLEMENTED(); 1162 } 1163 1164 if (literal_in_accumulator) { 1165 index = register_allocator()->NewRegister(); 1166 literal = register_allocator()->NewRegister(); 1167 builder()->StoreAccumulatorInRegister(literal); 1168 literal_in_accumulator = false; 1169 } 1170 1171 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot(); 1172 builder() 1173 ->LoadLiteral(Smi::FromInt(array_index)) 1174 .StoreAccumulatorInRegister(index); 1175 VisitForAccumulatorValue(subexpr); 1176 builder()->StoreKeyedProperty(literal, index, feedback_index(slot), 1177 language_mode()); 1178 } 1179 1180 if (!literal_in_accumulator) { 1181 // Restore literal array into accumulator. 1182 builder()->LoadAccumulatorWithRegister(literal); 1183 } 1184 execution_result()->SetResultInAccumulator(); 1185 } 1186 1187 1188 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 1189 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 1190 } 1191 1192 1193 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 1194 FeedbackVectorSlot slot, 1195 TypeofMode typeof_mode) { 1196 switch (variable->location()) { 1197 case VariableLocation::LOCAL: { 1198 Register source(Register(variable->index())); 1199 builder()->LoadAccumulatorWithRegister(source); 1200 execution_result()->SetResultInAccumulator(); 1201 break; 1202 } 1203 case VariableLocation::PARAMETER: { 1204 // The parameter indices are shifted by 1 (receiver is variable 1205 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1206 Register source = builder()->Parameter(variable->index() + 1); 1207 builder()->LoadAccumulatorWithRegister(source); 1208 execution_result()->SetResultInAccumulator(); 1209 break; 1210 } 1211 case VariableLocation::GLOBAL: 1212 case VariableLocation::UNALLOCATED: { 1213 builder()->LoadGlobal(variable->name(), feedback_index(slot), 1214 language_mode(), typeof_mode); 1215 execution_result()->SetResultInAccumulator(); 1216 break; 1217 } 1218 case VariableLocation::CONTEXT: { 1219 int depth = execution_context()->ContextChainDepth(variable->scope()); 1220 ContextScope* context = execution_context()->Previous(depth); 1221 Register context_reg; 1222 if (context) { 1223 context_reg = context->reg(); 1224 } else { 1225 context_reg = register_allocator()->NewRegister(); 1226 // Walk the context chain to find the context at the given depth. 1227 // TODO(rmcilroy): Perform this work in a bytecode handler once we have 1228 // a generic mechanism for performing jumps in interpreter.cc. 1229 // TODO(mythria): Also update bytecode graph builder with correct depth 1230 // when this changes. 1231 builder() 1232 ->LoadAccumulatorWithRegister(execution_context()->reg()) 1233 .StoreAccumulatorInRegister(context_reg); 1234 for (int i = 0; i < depth; ++i) { 1235 builder() 1236 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1237 .StoreAccumulatorInRegister(context_reg); 1238 } 1239 } 1240 builder()->LoadContextSlot(context_reg, variable->index()); 1241 execution_result()->SetResultInAccumulator(); 1242 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and 1243 // let variables. 1244 break; 1245 } 1246 case VariableLocation::LOOKUP: { 1247 builder()->LoadLookupSlot(variable->name(), typeof_mode); 1248 execution_result()->SetResultInAccumulator(); 1249 break; 1250 } 1251 } 1252 } 1253 1254 1255 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( 1256 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1257 AccumulatorResultScope accumulator_result(this); 1258 VisitVariableLoad(variable, slot, typeof_mode); 1259 } 1260 1261 1262 Register BytecodeGenerator::VisitVariableLoadForRegisterValue( 1263 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { 1264 RegisterResultScope register_scope(this); 1265 VisitVariableLoad(variable, slot, typeof_mode); 1266 return register_scope.ResultRegister(); 1267 } 1268 1269 1270 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 1271 FeedbackVectorSlot slot) { 1272 switch (variable->location()) { 1273 case VariableLocation::LOCAL: { 1274 // TODO(rmcilroy): support const mode initialization. 1275 Register destination(variable->index()); 1276 builder()->StoreAccumulatorInRegister(destination); 1277 break; 1278 } 1279 case VariableLocation::PARAMETER: { 1280 // The parameter indices are shifted by 1 (receiver is variable 1281 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1282 Register destination(builder()->Parameter(variable->index() + 1)); 1283 builder()->StoreAccumulatorInRegister(destination); 1284 break; 1285 } 1286 case VariableLocation::GLOBAL: 1287 case VariableLocation::UNALLOCATED: { 1288 builder()->StoreGlobal(variable->name(), feedback_index(slot), 1289 language_mode()); 1290 break; 1291 } 1292 case VariableLocation::CONTEXT: { 1293 // TODO(rmcilroy): support const mode initialization. 1294 int depth = execution_context()->ContextChainDepth(variable->scope()); 1295 ContextScope* context = execution_context()->Previous(depth); 1296 Register context_reg; 1297 if (context) { 1298 context_reg = context->reg(); 1299 } else { 1300 Register value_temp = register_allocator()->NewRegister(); 1301 context_reg = register_allocator()->NewRegister(); 1302 // Walk the context chain to find the context at the given depth. 1303 // TODO(rmcilroy): Perform this work in a bytecode handler once we have 1304 // a generic mechanism for performing jumps in interpreter.cc. 1305 // TODO(mythria): Also update bytecode graph builder with correct depth 1306 // when this changes. 1307 builder() 1308 ->StoreAccumulatorInRegister(value_temp) 1309 .LoadAccumulatorWithRegister(execution_context()->reg()) 1310 .StoreAccumulatorInRegister(context_reg); 1311 for (int i = 0; i < depth; ++i) { 1312 builder() 1313 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) 1314 .StoreAccumulatorInRegister(context_reg); 1315 } 1316 builder()->LoadAccumulatorWithRegister(value_temp); 1317 } 1318 builder()->StoreContextSlot(context_reg, variable->index()); 1319 break; 1320 } 1321 case VariableLocation::LOOKUP: { 1322 builder()->StoreLookupSlot(variable->name(), language_mode()); 1323 break; 1324 } 1325 } 1326 } 1327 1328 1329 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 1330 DCHECK(expr->target()->IsValidReferenceExpression()); 1331 Register object, key; 1332 Handle<String> name; 1333 1334 // Left-hand side can only be a property, a global or a variable slot. 1335 Property* property = expr->target()->AsProperty(); 1336 LhsKind assign_type = Property::GetAssignType(property); 1337 1338 // Evaluate LHS expression. 1339 switch (assign_type) { 1340 case VARIABLE: 1341 // Nothing to do to evaluate variable assignment LHS. 1342 break; 1343 case NAMED_PROPERTY: { 1344 object = VisitForRegisterValue(property->obj()); 1345 name = property->key()->AsLiteral()->AsPropertyName(); 1346 break; 1347 } 1348 case KEYED_PROPERTY: { 1349 object = VisitForRegisterValue(property->obj()); 1350 if (expr->is_compound()) { 1351 // Use VisitForAccumulator and store to register so that the key is 1352 // still in the accumulator for loading the old value below. 1353 key = register_allocator()->NewRegister(); 1354 VisitForAccumulatorValue(property->key()); 1355 builder()->StoreAccumulatorInRegister(key); 1356 } else { 1357 key = VisitForRegisterValue(property->key()); 1358 } 1359 break; 1360 } 1361 case NAMED_SUPER_PROPERTY: 1362 case KEYED_SUPER_PROPERTY: 1363 UNIMPLEMENTED(); 1364 } 1365 1366 // Evaluate the value and potentially handle compound assignments by loading 1367 // the left-hand side value and performing a binary operation. 1368 if (expr->is_compound()) { 1369 Register old_value; 1370 switch (assign_type) { 1371 case VARIABLE: { 1372 VariableProxy* proxy = expr->target()->AsVariableProxy(); 1373 old_value = VisitVariableLoadForRegisterValue( 1374 proxy->var(), proxy->VariableFeedbackSlot()); 1375 break; 1376 } 1377 case NAMED_PROPERTY: { 1378 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); 1379 old_value = register_allocator()->NewRegister(); 1380 builder() 1381 ->LoadNamedProperty(object, name, feedback_index(slot), 1382 language_mode()) 1383 .StoreAccumulatorInRegister(old_value); 1384 break; 1385 } 1386 case KEYED_PROPERTY: { 1387 // Key is already in accumulator at this point due to evaluating the 1388 // LHS above. 1389 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); 1390 old_value = register_allocator()->NewRegister(); 1391 builder() 1392 ->LoadKeyedProperty(object, feedback_index(slot), language_mode()) 1393 .StoreAccumulatorInRegister(old_value); 1394 break; 1395 } 1396 case NAMED_SUPER_PROPERTY: 1397 case KEYED_SUPER_PROPERTY: 1398 UNIMPLEMENTED(); 1399 break; 1400 } 1401 VisitForAccumulatorValue(expr->value()); 1402 builder()->BinaryOperation(expr->binary_op(), old_value, 1403 language_mode_strength()); 1404 } else { 1405 VisitForAccumulatorValue(expr->value()); 1406 } 1407 1408 // Store the value. 1409 FeedbackVectorSlot slot = expr->AssignmentSlot(); 1410 switch (assign_type) { 1411 case VARIABLE: { 1412 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. 1413 // Is the value in the accumulator safe? Yes, but scary. 1414 Variable* variable = expr->target()->AsVariableProxy()->var(); 1415 VisitVariableAssignment(variable, slot); 1416 break; 1417 } 1418 case NAMED_PROPERTY: 1419 builder()->StoreNamedProperty(object, name, feedback_index(slot), 1420 language_mode()); 1421 break; 1422 case KEYED_PROPERTY: 1423 builder()->StoreKeyedProperty(object, key, feedback_index(slot), 1424 language_mode()); 1425 break; 1426 case NAMED_SUPER_PROPERTY: 1427 case KEYED_SUPER_PROPERTY: 1428 UNIMPLEMENTED(); 1429 } 1430 execution_result()->SetResultInAccumulator(); 1431 } 1432 1433 1434 void BytecodeGenerator::VisitYield(Yield* expr) { UNIMPLEMENTED(); } 1435 1436 1437 void BytecodeGenerator::VisitThrow(Throw* expr) { 1438 VisitForAccumulatorValue(expr->exception()); 1439 builder()->Throw(); 1440 } 1441 1442 1443 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { 1444 LhsKind property_kind = Property::GetAssignType(expr); 1445 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); 1446 switch (property_kind) { 1447 case VARIABLE: 1448 UNREACHABLE(); 1449 case NAMED_PROPERTY: { 1450 builder()->LoadNamedProperty(obj, 1451 expr->key()->AsLiteral()->AsPropertyName(), 1452 feedback_index(slot), language_mode()); 1453 break; 1454 } 1455 case KEYED_PROPERTY: { 1456 VisitForAccumulatorValue(expr->key()); 1457 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); 1458 break; 1459 } 1460 case NAMED_SUPER_PROPERTY: 1461 case KEYED_SUPER_PROPERTY: 1462 UNIMPLEMENTED(); 1463 } 1464 execution_result()->SetResultInAccumulator(); 1465 } 1466 1467 1468 void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj, 1469 Property* expr) { 1470 AccumulatorResultScope result_scope(this); 1471 VisitPropertyLoad(obj, expr); 1472 } 1473 1474 1475 void BytecodeGenerator::VisitProperty(Property* expr) { 1476 Register obj = VisitForRegisterValue(expr->obj()); 1477 VisitPropertyLoad(obj, expr); 1478 } 1479 1480 1481 Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) { 1482 if (args->length() == 0) { 1483 return Register(); 1484 } 1485 1486 // Visit arguments and place in a contiguous block of temporary 1487 // registers. Return the first temporary register corresponding to 1488 // the first argument. 1489 // 1490 // NB the caller may have already called 1491 // PrepareForConsecutiveAllocations() with args->length() + N. The 1492 // second call here will be a no-op provided there have been N or 1493 // less calls to NextConsecutiveRegister(). Otherwise, the arguments 1494 // here will be consecutive, but they will not be consecutive with 1495 // earlier consecutive allocations made by the caller. 1496 register_allocator()->PrepareForConsecutiveAllocations(args->length()); 1497 1498 // Visit for first argument that goes into returned register 1499 Register first_arg = register_allocator()->NextConsecutiveRegister(); 1500 VisitForAccumulatorValue(args->at(0)); 1501 builder()->StoreAccumulatorInRegister(first_arg); 1502 1503 // Visit remaining arguments 1504 for (int i = 1; i < static_cast<int>(args->length()); i++) { 1505 Register ith_arg = register_allocator()->NextConsecutiveRegister(); 1506 VisitForAccumulatorValue(args->at(i)); 1507 builder()->StoreAccumulatorInRegister(ith_arg); 1508 DCHECK(ith_arg.index() - i == first_arg.index()); 1509 } 1510 return first_arg; 1511 } 1512 1513 1514 void BytecodeGenerator::VisitCall(Call* expr) { 1515 Expression* callee_expr = expr->expression(); 1516 Call::CallType call_type = expr->GetCallType(isolate()); 1517 1518 // Prepare the callee and the receiver to the function call. This depends on 1519 // the semantics of the underlying call type. 1520 1521 // The receiver and arguments need to be allocated consecutively for 1522 // Call(). We allocate the callee and receiver consecutively for calls to 1523 // kLoadLookupSlot. Future optimizations could avoid this there are no 1524 // arguments or the receiver and arguments are already consecutive. 1525 ZoneList<Expression*>* args = expr->arguments(); 1526 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2); 1527 Register callee = register_allocator()->NextConsecutiveRegister(); 1528 Register receiver = register_allocator()->NextConsecutiveRegister(); 1529 1530 switch (call_type) { 1531 case Call::NAMED_PROPERTY_CALL: 1532 case Call::KEYED_PROPERTY_CALL: { 1533 Property* property = callee_expr->AsProperty(); 1534 VisitForAccumulatorValue(property->obj()); 1535 builder()->StoreAccumulatorInRegister(receiver); 1536 VisitPropertyLoadForAccumulator(receiver, property); 1537 builder()->StoreAccumulatorInRegister(callee); 1538 break; 1539 } 1540 case Call::GLOBAL_CALL: { 1541 // Receiver is undefined for global calls. 1542 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 1543 // Load callee as a global variable. 1544 VariableProxy* proxy = callee_expr->AsVariableProxy(); 1545 VisitVariableLoadForAccumulatorValue(proxy->var(), 1546 proxy->VariableFeedbackSlot()); 1547 builder()->StoreAccumulatorInRegister(callee); 1548 break; 1549 } 1550 case Call::LOOKUP_SLOT_CALL: 1551 case Call::POSSIBLY_EVAL_CALL: { 1552 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { 1553 RegisterAllocationScope inner_register_scope(this); 1554 register_allocator()->PrepareForConsecutiveAllocations(2); 1555 Register context = register_allocator()->NextConsecutiveRegister(); 1556 Register name = register_allocator()->NextConsecutiveRegister(); 1557 1558 // Call LoadLookupSlot to get the callee and receiver. 1559 DCHECK(Register::AreContiguous(callee, receiver)); 1560 Variable* variable = callee_expr->AsVariableProxy()->var(); 1561 builder() 1562 ->MoveRegister(Register::function_context(), context) 1563 .LoadLiteral(variable->name()) 1564 .StoreAccumulatorInRegister(name) 1565 .CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee); 1566 break; 1567 } 1568 // Fall through. 1569 DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL); 1570 } 1571 case Call::OTHER_CALL: { 1572 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 1573 VisitForAccumulatorValue(callee_expr); 1574 builder()->StoreAccumulatorInRegister(callee); 1575 break; 1576 } 1577 case Call::NAMED_SUPER_PROPERTY_CALL: 1578 case Call::KEYED_SUPER_PROPERTY_CALL: 1579 case Call::SUPER_CALL: 1580 UNIMPLEMENTED(); 1581 } 1582 1583 // Evaluate all arguments to the function call and store in sequential 1584 // registers. 1585 Register arg = VisitArguments(args); 1586 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1); 1587 1588 // Resolve callee for a potential direct eval call. This block will mutate the 1589 // callee value. 1590 if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) { 1591 RegisterAllocationScope inner_register_scope(this); 1592 register_allocator()->PrepareForConsecutiveAllocations(5); 1593 Register callee_for_eval = register_allocator()->NextConsecutiveRegister(); 1594 Register source = register_allocator()->NextConsecutiveRegister(); 1595 Register function = register_allocator()->NextConsecutiveRegister(); 1596 Register language = register_allocator()->NextConsecutiveRegister(); 1597 Register position = register_allocator()->NextConsecutiveRegister(); 1598 1599 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source 1600 // strings and function closure, and loading language and 1601 // position. 1602 builder() 1603 ->MoveRegister(callee, callee_for_eval) 1604 .MoveRegister(arg, source) 1605 .MoveRegister(Register::function_closure(), function) 1606 .LoadLiteral(Smi::FromInt(language_mode())) 1607 .StoreAccumulatorInRegister(language) 1608 .LoadLiteral( 1609 Smi::FromInt(execution_context()->scope()->start_position())) 1610 .StoreAccumulatorInRegister(position); 1611 1612 // Call ResolvePossiblyDirectEval and modify the callee. 1613 builder() 1614 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 5) 1615 .StoreAccumulatorInRegister(callee); 1616 } 1617 1618 // TODO(rmcilroy): Use CallIC to allow call type feedback. 1619 builder()->Call(callee, receiver, args->length(), 1620 feedback_index(expr->CallFeedbackICSlot())); 1621 execution_result()->SetResultInAccumulator(); 1622 } 1623 1624 1625 void BytecodeGenerator::VisitCallNew(CallNew* expr) { 1626 Register constructor = register_allocator()->NewRegister(); 1627 VisitForAccumulatorValue(expr->expression()); 1628 builder()->StoreAccumulatorInRegister(constructor); 1629 1630 ZoneList<Expression*>* args = expr->arguments(); 1631 Register first_arg = VisitArguments(args); 1632 builder()->New(constructor, first_arg, args->length()); 1633 execution_result()->SetResultInAccumulator(); 1634 } 1635 1636 1637 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { 1638 ZoneList<Expression*>* args = expr->arguments(); 1639 Register receiver; 1640 if (expr->is_jsruntime()) { 1641 // Allocate a register for the receiver and load it with undefined. 1642 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 1); 1643 receiver = register_allocator()->NextConsecutiveRegister(); 1644 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 1645 } 1646 // Evaluate all arguments to the runtime call. 1647 Register first_arg = VisitArguments(args); 1648 1649 if (expr->is_jsruntime()) { 1650 DCHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1); 1651 builder()->CallJSRuntime(expr->context_index(), receiver, args->length()); 1652 } else { 1653 Runtime::FunctionId function_id = expr->function()->function_id; 1654 builder()->CallRuntime(function_id, first_arg, args->length()); 1655 } 1656 execution_result()->SetResultInAccumulator(); 1657 } 1658 1659 1660 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { 1661 VisitForEffect(expr->expression()); 1662 builder()->LoadUndefined(); 1663 execution_result()->SetResultInAccumulator(); 1664 } 1665 1666 1667 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { 1668 if (expr->expression()->IsVariableProxy()) { 1669 // Typeof does not throw a reference error on global variables, hence we 1670 // perform a non-contextual load in case the operand is a variable proxy. 1671 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 1672 VisitVariableLoadForAccumulatorValue( 1673 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); 1674 } else { 1675 VisitForAccumulatorValue(expr->expression()); 1676 } 1677 builder()->TypeOf(); 1678 execution_result()->SetResultInAccumulator(); 1679 } 1680 1681 1682 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { 1683 VisitForAccumulatorValue(expr->expression()); 1684 builder()->LogicalNot(); 1685 execution_result()->SetResultInAccumulator(); 1686 } 1687 1688 1689 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 1690 switch (expr->op()) { 1691 case Token::Value::NOT: 1692 VisitNot(expr); 1693 break; 1694 case Token::Value::TYPEOF: 1695 VisitTypeOf(expr); 1696 break; 1697 case Token::Value::VOID: 1698 VisitVoid(expr); 1699 break; 1700 case Token::Value::DELETE: 1701 VisitDelete(expr); 1702 break; 1703 case Token::Value::BIT_NOT: 1704 case Token::Value::ADD: 1705 case Token::Value::SUB: 1706 // These operators are converted to an equivalent binary operators in 1707 // the parser. These operators are not expected to be visited here. 1708 UNREACHABLE(); 1709 default: 1710 UNREACHABLE(); 1711 } 1712 } 1713 1714 1715 void BytecodeGenerator::VisitDelete(UnaryOperation* expr) { 1716 if (expr->expression()->IsProperty()) { 1717 // Delete of an object property is allowed both in sloppy 1718 // and strict modes. 1719 Property* property = expr->expression()->AsProperty(); 1720 Register object = VisitForRegisterValue(property->obj()); 1721 VisitForAccumulatorValue(property->key()); 1722 builder()->Delete(object, language_mode()); 1723 } else if (expr->expression()->IsVariableProxy()) { 1724 // Delete of an unqualified identifier is allowed in sloppy mode but is 1725 // not allowed in strict mode. Deleting 'this' is allowed in both modes. 1726 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 1727 Variable* variable = proxy->var(); 1728 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate())); 1729 switch (variable->location()) { 1730 case VariableLocation::GLOBAL: 1731 case VariableLocation::UNALLOCATED: { 1732 // Global var, let, const or variables not explicitly declared. 1733 Register native_context = register_allocator()->NewRegister(); 1734 Register global_object = register_allocator()->NewRegister(); 1735 builder() 1736 ->LoadContextSlot(execution_context()->reg(), 1737 Context::NATIVE_CONTEXT_INDEX) 1738 .StoreAccumulatorInRegister(native_context) 1739 .LoadContextSlot(native_context, Context::EXTENSION_INDEX) 1740 .StoreAccumulatorInRegister(global_object) 1741 .LoadLiteral(variable->name()) 1742 .Delete(global_object, language_mode()); 1743 break; 1744 } 1745 case VariableLocation::PARAMETER: 1746 case VariableLocation::LOCAL: 1747 case VariableLocation::CONTEXT: { 1748 // Deleting local var/let/const, context variables, and arguments 1749 // does not have any effect. 1750 if (variable->HasThisName(isolate())) { 1751 builder()->LoadTrue(); 1752 } else { 1753 builder()->LoadFalse(); 1754 } 1755 break; 1756 } 1757 case VariableLocation::LOOKUP: { 1758 builder()->LoadLiteral(variable->name()).DeleteLookupSlot(); 1759 break; 1760 } 1761 default: 1762 UNREACHABLE(); 1763 } 1764 } else { 1765 // Delete of an unresolvable reference returns true. 1766 VisitForEffect(expr->expression()); 1767 builder()->LoadTrue(); 1768 } 1769 execution_result()->SetResultInAccumulator(); 1770 } 1771 1772 1773 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { 1774 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); 1775 1776 // Left-hand side can only be a property, a global or a variable slot. 1777 Property* property = expr->expression()->AsProperty(); 1778 LhsKind assign_type = Property::GetAssignType(property); 1779 1780 // TODO(rmcilroy): Set is_postfix to false if visiting for effect. 1781 bool is_postfix = expr->is_postfix(); 1782 1783 // Evaluate LHS expression and get old value. 1784 Register obj, key, old_value; 1785 Handle<String> name; 1786 switch (assign_type) { 1787 case VARIABLE: { 1788 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 1789 VisitVariableLoadForAccumulatorValue(proxy->var(), 1790 proxy->VariableFeedbackSlot()); 1791 break; 1792 } 1793 case NAMED_PROPERTY: { 1794 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); 1795 obj = VisitForRegisterValue(property->obj()); 1796 name = property->key()->AsLiteral()->AsPropertyName(); 1797 builder()->LoadNamedProperty(obj, name, feedback_index(slot), 1798 language_mode()); 1799 break; 1800 } 1801 case KEYED_PROPERTY: { 1802 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); 1803 obj = VisitForRegisterValue(property->obj()); 1804 // Use visit for accumulator here since we need the key in the accumulator 1805 // for the LoadKeyedProperty. 1806 key = register_allocator()->NewRegister(); 1807 VisitForAccumulatorValue(property->key()); 1808 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty( 1809 obj, feedback_index(slot), language_mode()); 1810 break; 1811 } 1812 case NAMED_SUPER_PROPERTY: 1813 case KEYED_SUPER_PROPERTY: 1814 UNIMPLEMENTED(); 1815 } 1816 1817 // Convert old value into a number. 1818 if (!is_strong(language_mode())) { 1819 builder()->CastAccumulatorToNumber(); 1820 } 1821 1822 // Save result for postfix expressions. 1823 if (is_postfix) { 1824 old_value = register_allocator()->outer()->NewRegister(); 1825 builder()->StoreAccumulatorInRegister(old_value); 1826 } 1827 1828 // Perform +1/-1 operation. 1829 builder()->CountOperation(expr->binary_op(), language_mode_strength()); 1830 1831 // Store the value. 1832 FeedbackVectorSlot feedback_slot = expr->CountSlot(); 1833 switch (assign_type) { 1834 case VARIABLE: { 1835 Variable* variable = expr->expression()->AsVariableProxy()->var(); 1836 VisitVariableAssignment(variable, feedback_slot); 1837 break; 1838 } 1839 case NAMED_PROPERTY: { 1840 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot), 1841 language_mode()); 1842 break; 1843 } 1844 case KEYED_PROPERTY: { 1845 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), 1846 language_mode()); 1847 break; 1848 } 1849 case NAMED_SUPER_PROPERTY: 1850 case KEYED_SUPER_PROPERTY: 1851 UNIMPLEMENTED(); 1852 } 1853 1854 // Restore old value for postfix expressions. 1855 if (is_postfix) { 1856 execution_result()->SetResultInRegister(old_value); 1857 } else { 1858 execution_result()->SetResultInAccumulator(); 1859 } 1860 } 1861 1862 1863 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) { 1864 switch (binop->op()) { 1865 case Token::COMMA: 1866 VisitCommaExpression(binop); 1867 break; 1868 case Token::OR: 1869 VisitLogicalOrExpression(binop); 1870 break; 1871 case Token::AND: 1872 VisitLogicalAndExpression(binop); 1873 break; 1874 default: 1875 VisitArithmeticExpression(binop); 1876 break; 1877 } 1878 } 1879 1880 1881 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1882 Register lhs = VisitForRegisterValue(expr->left()); 1883 VisitForAccumulatorValue(expr->right()); 1884 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); 1885 execution_result()->SetResultInAccumulator(); 1886 } 1887 1888 1889 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { 1890 Register lhs = VisitForRegisterValue(expr->left()); 1891 VisitForAccumulatorValue(expr->right()); 1892 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength()); 1893 execution_result()->SetResultInAccumulator(); 1894 } 1895 1896 1897 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } 1898 1899 1900 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { 1901 UNREACHABLE(); 1902 } 1903 1904 1905 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { 1906 execution_result()->SetResultInRegister(Register::function_closure()); 1907 } 1908 1909 1910 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { 1911 UNIMPLEMENTED(); 1912 } 1913 1914 1915 void BytecodeGenerator::VisitSuperPropertyReference( 1916 SuperPropertyReference* expr) { 1917 UNIMPLEMENTED(); 1918 } 1919 1920 1921 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { 1922 VisitForEffect(binop->left()); 1923 Visit(binop->right()); 1924 } 1925 1926 1927 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { 1928 Expression* left = binop->left(); 1929 Expression* right = binop->right(); 1930 1931 // Short-circuit evaluation- If it is known that left is always true, 1932 // no need to visit right 1933 if (left->ToBooleanIsTrue()) { 1934 VisitForAccumulatorValue(left); 1935 } else { 1936 BytecodeLabel end_label; 1937 VisitForAccumulatorValue(left); 1938 builder()->JumpIfTrue(&end_label); 1939 VisitForAccumulatorValue(right); 1940 builder()->Bind(&end_label); 1941 } 1942 execution_result()->SetResultInAccumulator(); 1943 } 1944 1945 1946 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { 1947 Expression* left = binop->left(); 1948 Expression* right = binop->right(); 1949 1950 // Short-circuit evaluation- If it is known that left is always false, 1951 // no need to visit right 1952 if (left->ToBooleanIsFalse()) { 1953 VisitForAccumulatorValue(left); 1954 } else { 1955 BytecodeLabel end_label; 1956 VisitForAccumulatorValue(left); 1957 builder()->JumpIfFalse(&end_label); 1958 VisitForAccumulatorValue(right); 1959 builder()->Bind(&end_label); 1960 } 1961 execution_result()->SetResultInAccumulator(); 1962 } 1963 1964 1965 void BytecodeGenerator::VisitRewritableAssignmentExpression( 1966 RewritableAssignmentExpression* expr) { 1967 Visit(expr->expression()); 1968 } 1969 1970 1971 void BytecodeGenerator::VisitNewLocalFunctionContext() { 1972 AccumulatorResultScope accumulator_execution_result(this); 1973 Scope* scope = this->scope(); 1974 1975 // Allocate a new local context. 1976 if (scope->is_script_scope()) { 1977 RegisterAllocationScope register_scope(this); 1978 Register closure = register_allocator()->NewRegister(); 1979 Register scope_info = register_allocator()->NewRegister(); 1980 DCHECK(Register::AreContiguous(closure, scope_info)); 1981 builder() 1982 ->LoadAccumulatorWithRegister(Register::function_closure()) 1983 .StoreAccumulatorInRegister(closure) 1984 .LoadLiteral(scope->GetScopeInfo(isolate())) 1985 .StoreAccumulatorInRegister(scope_info) 1986 .CallRuntime(Runtime::kNewScriptContext, closure, 2); 1987 } else { 1988 builder()->CallRuntime(Runtime::kNewFunctionContext, 1989 Register::function_closure(), 1); 1990 } 1991 execution_result()->SetResultInAccumulator(); 1992 } 1993 1994 1995 void BytecodeGenerator::VisitBuildLocalActivationContext() { 1996 Scope* scope = this->scope(); 1997 1998 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { 1999 Variable* variable = scope->receiver(); 2000 Register receiver(builder()->Parameter(0)); 2001 // Context variable (at bottom of the context chain). 2002 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); 2003 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( 2004 execution_context()->reg(), variable->index()); 2005 } 2006 2007 // Copy parameters into context if necessary. 2008 int num_parameters = scope->num_parameters(); 2009 for (int i = 0; i < num_parameters; i++) { 2010 Variable* variable = scope->parameter(i); 2011 if (!variable->IsContextSlot()) continue; 2012 2013 // The parameter indices are shifted by 1 (receiver is variable 2014 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 2015 Register parameter(builder()->Parameter(i + 1)); 2016 // Context variable (at bottom of the context chain). 2017 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); 2018 builder()->LoadAccumulatorWithRegister(parameter) 2019 .StoreContextSlot(execution_context()->reg(), variable->index()); 2020 } 2021 } 2022 2023 2024 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) { 2025 AccumulatorResultScope accumulator_execution_result(this); 2026 DCHECK(scope->is_block_scope()); 2027 2028 // Allocate a new local block context. 2029 register_allocator()->PrepareForConsecutiveAllocations(2); 2030 Register scope_info = register_allocator()->NextConsecutiveRegister(); 2031 Register closure = register_allocator()->NextConsecutiveRegister(); 2032 2033 builder() 2034 ->LoadLiteral(scope->GetScopeInfo(isolate())) 2035 .StoreAccumulatorInRegister(scope_info); 2036 VisitFunctionClosureForContext(); 2037 builder() 2038 ->StoreAccumulatorInRegister(closure) 2039 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2); 2040 execution_result()->SetResultInAccumulator(); 2041 } 2042 2043 2044 void BytecodeGenerator::VisitObjectLiteralAccessor( 2045 Register home_object, ObjectLiteralProperty* property, Register value_out) { 2046 // TODO(rmcilroy): Replace value_out with VisitForRegister(); 2047 if (property == nullptr) { 2048 builder()->LoadNull().StoreAccumulatorInRegister(value_out); 2049 } else { 2050 VisitForAccumulatorValue(property->value()); 2051 builder()->StoreAccumulatorInRegister(value_out); 2052 VisitSetHomeObject(value_out, home_object, property); 2053 } 2054 } 2055 2056 2057 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, 2058 ObjectLiteralProperty* property, 2059 int slot_number) { 2060 Expression* expr = property->value(); 2061 if (!FunctionLiteral::NeedsHomeObject(expr)) return; 2062 2063 UNIMPLEMENTED(); 2064 } 2065 2066 2067 void BytecodeGenerator::VisitArgumentsObject(Variable* variable) { 2068 if (variable == nullptr) return; 2069 2070 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); 2071 2072 // Allocate and initialize a new arguments object and assign to the 2073 // {arguments} variable. 2074 CreateArgumentsType type = 2075 is_strict(language_mode()) || !info()->has_simple_parameters() 2076 ? CreateArgumentsType::kUnmappedArguments 2077 : CreateArgumentsType::kMappedArguments; 2078 builder()->CreateArguments(type); 2079 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2080 } 2081 2082 2083 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { 2084 if (variable == nullptr) return; 2085 2086 // TODO(rmcilroy): Remove once we have tests which exercise this code path. 2087 UNIMPLEMENTED(); 2088 2089 // Store the closure we were called with in the given variable. 2090 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 2091 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2092 } 2093 2094 2095 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { 2096 if (variable == nullptr) return; 2097 2098 // Store the new target we were called with in the given variable. 2099 builder()->LoadAccumulatorWithRegister(Register::new_target()); 2100 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); 2101 } 2102 2103 2104 void BytecodeGenerator::VisitFunctionClosureForContext() { 2105 AccumulatorResultScope accumulator_execution_result(this); 2106 Scope* closure_scope = execution_context()->scope()->ClosureScope(); 2107 if (closure_scope->is_script_scope() || 2108 closure_scope->is_module_scope()) { 2109 // Contexts nested in the native context have a canonical empty function as 2110 // their closure, not the anonymous closure containing the global code. 2111 Register native_context = register_allocator()->NewRegister(); 2112 builder() 2113 ->LoadContextSlot(execution_context()->reg(), 2114 Context::NATIVE_CONTEXT_INDEX) 2115 .StoreAccumulatorInRegister(native_context) 2116 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); 2117 } else { 2118 DCHECK(closure_scope->is_function_scope()); 2119 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 2120 } 2121 execution_result()->SetResultInAccumulator(); 2122 } 2123 2124 2125 // Visits the expression |expr| and places the result in the accumulator. 2126 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { 2127 AccumulatorResultScope accumulator_scope(this); 2128 Visit(expr); 2129 } 2130 2131 2132 // Visits the expression |expr| and discards the result. 2133 void BytecodeGenerator::VisitForEffect(Expression* expr) { 2134 EffectResultScope effect_scope(this); 2135 Visit(expr); 2136 } 2137 2138 2139 // Visits the expression |expr| and returns the register containing 2140 // the expression result. 2141 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { 2142 RegisterResultScope register_scope(this); 2143 Visit(expr); 2144 return register_scope.ResultRegister(); 2145 } 2146 2147 2148 Register BytecodeGenerator::NextContextRegister() const { 2149 if (execution_context() == nullptr) { 2150 // Return the incoming function context for the outermost execution context. 2151 return Register::function_context(); 2152 } 2153 Register previous = execution_context()->reg(); 2154 if (previous == Register::function_context()) { 2155 // If the previous context was the incoming function context, then the next 2156 // context register is the first local context register. 2157 return builder_.first_context_register(); 2158 } else { 2159 // Otherwise use the next local context register. 2160 DCHECK_LT(previous.index(), builder_.last_context_register().index()); 2161 return Register(previous.index() + 1); 2162 } 2163 } 2164 2165 2166 LanguageMode BytecodeGenerator::language_mode() const { 2167 return info()->language_mode(); 2168 } 2169 2170 2171 Strength BytecodeGenerator::language_mode_strength() const { 2172 return strength(language_mode()); 2173 } 2174 2175 2176 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2177 return info()->feedback_vector()->GetIndex(slot); 2178 } 2179 2180 } // namespace interpreter 2181 } // namespace internal 2182 } // namespace v8 2183