| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
| 10 #include "src/interpreter/bytecode-flags.h" | 10 #include "src/interpreter/bytecode-flags.h" |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 | 530 |
| 531 private: | 531 private: |
| 532 Register result_register_; | 532 Register result_register_; |
| 533 }; | 533 }; |
| 534 | 534 |
| 535 // Used to build a list of global declaration initial value pairs. | 535 // Used to build a list of global declaration initial value pairs. |
| 536 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject { | 536 class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject { |
| 537 public: | 537 public: |
| 538 GlobalDeclarationsBuilder(Isolate* isolate, Zone* zone) | 538 GlobalDeclarationsBuilder(Isolate* isolate, Zone* zone) |
| 539 : isolate_(isolate), | 539 : isolate_(isolate), |
| 540 declaration_pairs_(0, zone), | 540 declarations_(0, zone), |
| 541 constant_pool_entry_(0), | 541 constant_pool_entry_(0), |
| 542 has_constant_pool_entry_(false) {} | 542 has_constant_pool_entry_(false) {} |
| 543 | 543 |
| 544 void AddDeclaration(FeedbackVectorSlot slot, Handle<Object> initial_value) { | 544 void AddFunctionDeclaration(FeedbackVectorSlot slot, FunctionLiteral* func) { |
| 545 DCHECK(!slot.IsInvalid()); | 545 DCHECK(!slot.IsInvalid()); |
| 546 declaration_pairs_.push_back(handle(Smi::FromInt(slot.ToInt()), isolate_)); | 546 declarations_.push_back(std::make_pair(slot, func)); |
| 547 declaration_pairs_.push_back(initial_value); | |
| 548 } | 547 } |
| 549 | 548 |
| 550 Handle<FixedArray> AllocateDeclarationPairs() { | 549 void AddUndefinedDeclaration(FeedbackVectorSlot slot) { |
| 550 DCHECK(!slot.IsInvalid()); |
| 551 declarations_.push_back(std::make_pair(slot, nullptr)); |
| 552 } |
| 553 |
| 554 Handle<FixedArray> AllocateDeclarationPairs(CompilationInfo* info) { |
| 551 DCHECK(has_constant_pool_entry_); | 555 DCHECK(has_constant_pool_entry_); |
| 552 int array_index = 0; | 556 int array_index = 0; |
| 553 Handle<FixedArray> data = isolate_->factory()->NewFixedArray( | 557 Handle<FixedArray> pairs = isolate_->factory()->NewFixedArray( |
| 554 static_cast<int>(declaration_pairs_.size()), TENURED); | 558 static_cast<int>(declarations_.size() * 2), TENURED); |
| 555 for (Handle<Object> obj : declaration_pairs_) { | 559 for (std::pair<FeedbackVectorSlot, FunctionLiteral*> declaration : |
| 556 data->set(array_index++, *obj); | 560 declarations_) { |
| 561 FunctionLiteral* func = declaration.second; |
| 562 Handle<Object> initial_value; |
| 563 if (func == nullptr) { |
| 564 initial_value = isolate_->factory()->undefined_value(); |
| 565 } else { |
| 566 initial_value = |
| 567 Compiler::GetSharedFunctionInfo(func, info->script(), info); |
| 568 } |
| 569 |
| 570 // Return a null handle if any initial values can't be created. Caller |
| 571 // will set stack overflow. |
| 572 if (initial_value.is_null()) return Handle<FixedArray>(); |
| 573 |
| 574 pairs->set(array_index++, Smi::FromInt(declaration.first.ToInt())); |
| 575 pairs->set(array_index++, *initial_value); |
| 557 } | 576 } |
| 558 return data; | 577 return pairs; |
| 559 } | 578 } |
| 560 | 579 |
| 561 size_t constant_pool_entry() { | 580 size_t constant_pool_entry() { |
| 562 DCHECK(has_constant_pool_entry_); | 581 DCHECK(has_constant_pool_entry_); |
| 563 return constant_pool_entry_; | 582 return constant_pool_entry_; |
| 564 } | 583 } |
| 565 | 584 |
| 566 void set_constant_pool_entry(size_t constant_pool_entry) { | 585 void set_constant_pool_entry(size_t constant_pool_entry) { |
| 567 DCHECK(!empty()); | 586 DCHECK(!empty()); |
| 568 DCHECK(!has_constant_pool_entry_); | 587 DCHECK(!has_constant_pool_entry_); |
| 569 constant_pool_entry_ = constant_pool_entry; | 588 constant_pool_entry_ = constant_pool_entry; |
| 570 has_constant_pool_entry_ = true; | 589 has_constant_pool_entry_ = true; |
| 571 } | 590 } |
| 572 | 591 |
| 573 bool empty() { return declaration_pairs_.empty(); } | 592 bool empty() { return declarations_.empty(); } |
| 574 | 593 |
| 575 private: | 594 private: |
| 576 Isolate* isolate_; | 595 Isolate* isolate_; |
| 577 ZoneVector<Handle<Object>> declaration_pairs_; | 596 ZoneVector<std::pair<FeedbackVectorSlot, FunctionLiteral*>> declarations_; |
| 578 size_t constant_pool_entry_; | 597 size_t constant_pool_entry_; |
| 579 bool has_constant_pool_entry_; | 598 bool has_constant_pool_entry_; |
| 580 }; | 599 }; |
| 581 | 600 |
| 582 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) | 601 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) |
| 583 : isolate_(info->isolate()), | 602 : isolate_(info->isolate()), |
| 584 zone_(info->zone()), | 603 zone_(info->zone()), |
| 585 builder_(new (zone()) BytecodeArrayBuilder( | 604 builder_(new (zone()) BytecodeArrayBuilder( |
| 586 info->isolate(), info->zone(), info->num_parameters_including_this(), | 605 info->isolate(), info->zone(), info->num_parameters_including_this(), |
| 587 info->scope()->MaxNestedContextChainLength(), | 606 info->scope()->MaxNestedContextChainLength(), |
| 588 info->scope()->num_stack_slots(), info->literal(), | 607 info->scope()->num_stack_slots(), info->literal(), |
| 589 info->SourcePositionRecordingMode())), | 608 info->SourcePositionRecordingMode())), |
| 590 info_(info), | 609 info_(info), |
| 591 scope_(info->scope()), | 610 scope_(info->scope()), |
| 592 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->isolate(), | 611 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->isolate(), |
| 593 info->zone())), | 612 info->zone())), |
| 594 global_declarations_(0, info->zone()), | 613 global_declarations_(0, info->zone()), |
| 614 function_literals_(0, info->zone()), |
| 615 native_function_literals_(0, info->zone()), |
| 595 execution_control_(nullptr), | 616 execution_control_(nullptr), |
| 596 execution_context_(nullptr), | 617 execution_context_(nullptr), |
| 597 execution_result_(nullptr), | 618 execution_result_(nullptr), |
| 598 register_allocator_(nullptr), | 619 register_allocator_(nullptr), |
| 599 generator_resume_points_(info->literal()->yield_count(), info->zone()), | 620 generator_resume_points_(info->literal()->yield_count(), info->zone()), |
| 600 generator_state_() { | 621 generator_state_() { |
| 601 InitializeAstVisitor(isolate()->stack_guard()->real_climit()); | 622 InitializeAstVisitor(isolate()->stack_guard()->real_climit()); |
| 602 } | 623 } |
| 603 | 624 |
| 604 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() { | 625 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() { |
| 605 GenerateBytecode(); | 626 GenerateBytecode(); |
| 627 FinalizeBytecode(); |
| 628 return builder()->ToBytecodeArray(); |
| 629 } |
| 606 | 630 |
| 631 void BytecodeGenerator::FinalizeBytecode() { |
| 607 // Build global declaration pair arrays. | 632 // Build global declaration pair arrays. |
| 608 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { | 633 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { |
| 609 Handle<FixedArray> declarations = | 634 Handle<FixedArray> declarations = |
| 610 globals_builder->AllocateDeclarationPairs(); | 635 globals_builder->AllocateDeclarationPairs(info()); |
| 636 if (declarations.is_null()) return SetStackOverflow(); |
| 611 builder()->InsertConstantPoolEntryAt(globals_builder->constant_pool_entry(), | 637 builder()->InsertConstantPoolEntryAt(globals_builder->constant_pool_entry(), |
| 612 declarations); | 638 declarations); |
| 613 } | 639 } |
| 614 | 640 |
| 615 return builder()->ToBytecodeArray(); | 641 // Find or build shared function infos. |
| 642 for (std::pair<FunctionLiteral*, size_t> literal : function_literals_) { |
| 643 FunctionLiteral* expr = literal.first; |
| 644 Handle<SharedFunctionInfo> shared_info = |
| 645 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); |
| 646 if (shared_info.is_null()) return SetStackOverflow(); |
| 647 builder()->InsertConstantPoolEntryAt(literal.second, shared_info); |
| 648 } |
| 649 |
| 650 // Find or build shared function infos for the native function templates. |
| 651 for (std::pair<NativeFunctionLiteral*, size_t> literal : |
| 652 native_function_literals_) { |
| 653 NativeFunctionLiteral* expr = literal.first; |
| 654 Handle<SharedFunctionInfo> shared_info = |
| 655 Compiler::GetSharedFunctionInfoForNative(expr->extension(), |
| 656 expr->name()); |
| 657 if (shared_info.is_null()) return SetStackOverflow(); |
| 658 builder()->InsertConstantPoolEntryAt(literal.second, shared_info); |
| 659 } |
| 616 } | 660 } |
| 617 | 661 |
| 618 void BytecodeGenerator::GenerateBytecode() { | 662 void BytecodeGenerator::GenerateBytecode() { |
| 619 // Initialize the incoming context. | 663 // Initialize the incoming context. |
| 620 ContextScope incoming_context(this, scope(), false); | 664 ContextScope incoming_context(this, scope(), false); |
| 621 | 665 |
| 622 // Initialize control scope. | 666 // Initialize control scope. |
| 623 ControlScopeForTopLevel control(this); | 667 ControlScopeForTopLevel control(this); |
| 624 | 668 |
| 625 RegisterAllocationScope register_scope(this); | 669 RegisterAllocationScope register_scope(this); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 Variable* variable = decl->proxy()->var(); | 822 Variable* variable = decl->proxy()->var(); |
| 779 VariableMode mode = decl->mode(); | 823 VariableMode mode = decl->mode(); |
| 780 // Const and let variables are initialized with the hole so that we can | 824 // Const and let variables are initialized with the hole so that we can |
| 781 // check that they are only assigned once. | 825 // check that they are only assigned once. |
| 782 bool hole_init = mode == CONST || mode == LET; | 826 bool hole_init = mode == CONST || mode == LET; |
| 783 switch (variable->location()) { | 827 switch (variable->location()) { |
| 784 case VariableLocation::GLOBAL: | 828 case VariableLocation::GLOBAL: |
| 785 case VariableLocation::UNALLOCATED: { | 829 case VariableLocation::UNALLOCATED: { |
| 786 DCHECK(!variable->binding_needs_init()); | 830 DCHECK(!variable->binding_needs_init()); |
| 787 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); | 831 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); |
| 788 globals_builder()->AddDeclaration( | 832 globals_builder()->AddUndefinedDeclaration(slot); |
| 789 slot, isolate()->factory()->undefined_value()); | |
| 790 break; | 833 break; |
| 791 } | 834 } |
| 792 case VariableLocation::LOCAL: | 835 case VariableLocation::LOCAL: |
| 793 if (hole_init) { | 836 if (hole_init) { |
| 794 Register destination(variable->index()); | 837 Register destination(variable->index()); |
| 795 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); | 838 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); |
| 796 } | 839 } |
| 797 break; | 840 break; |
| 798 case VariableLocation::PARAMETER: | 841 case VariableLocation::PARAMETER: |
| 799 if (hole_init) { | 842 if (hole_init) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 822 break; | 865 break; |
| 823 } | 866 } |
| 824 } | 867 } |
| 825 } | 868 } |
| 826 | 869 |
| 827 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 870 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 828 Variable* variable = decl->proxy()->var(); | 871 Variable* variable = decl->proxy()->var(); |
| 829 switch (variable->location()) { | 872 switch (variable->location()) { |
| 830 case VariableLocation::GLOBAL: | 873 case VariableLocation::GLOBAL: |
| 831 case VariableLocation::UNALLOCATED: { | 874 case VariableLocation::UNALLOCATED: { |
| 832 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( | |
| 833 decl->fun(), info()->script(), info()); | |
| 834 // Check for stack-overflow exception. | |
| 835 if (function.is_null()) return SetStackOverflow(); | |
| 836 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); | 875 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); |
| 837 globals_builder()->AddDeclaration(slot, function); | 876 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); |
| 838 break; | 877 break; |
| 839 } | 878 } |
| 840 case VariableLocation::PARAMETER: | 879 case VariableLocation::PARAMETER: |
| 841 case VariableLocation::LOCAL: { | 880 case VariableLocation::LOCAL: { |
| 842 VisitForAccumulatorValue(decl->fun()); | 881 VisitForAccumulatorValue(decl->fun()); |
| 843 DCHECK(variable->mode() == LET || variable->mode() == VAR || | 882 DCHECK(variable->mode() == LET || variable->mode() == VAR || |
| 844 variable->mode() == CONST); | 883 variable->mode() == CONST); |
| 845 VisitVariableAssignment(variable, Token::INIT, | 884 VisitVariableAssignment(variable, Token::INIT, |
| 846 FeedbackVectorSlot::Invalid()); | 885 FeedbackVectorSlot::Invalid()); |
| 847 break; | 886 break; |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1341 // Dynamic dispatch after the finally-block. | 1380 // Dynamic dispatch after the finally-block. |
| 1342 commands.ApplyDeferredCommands(); | 1381 commands.ApplyDeferredCommands(); |
| 1343 } | 1382 } |
| 1344 | 1383 |
| 1345 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1384 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 1346 builder()->SetStatementPosition(stmt); | 1385 builder()->SetStatementPosition(stmt); |
| 1347 builder()->Debugger(); | 1386 builder()->Debugger(); |
| 1348 } | 1387 } |
| 1349 | 1388 |
| 1350 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 1389 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 1351 // Find or build a shared function info. | |
| 1352 Handle<SharedFunctionInfo> shared_info = | |
| 1353 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); | |
| 1354 if (shared_info.is_null()) { | |
| 1355 return SetStackOverflow(); | |
| 1356 } | |
| 1357 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(), | 1390 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(), |
| 1358 scope()->is_function_scope()); | 1391 scope()->is_function_scope()); |
| 1359 builder()->CreateClosure(shared_info, flags); | 1392 size_t entry = builder()->AllocateConstantPoolEntry(); |
| 1393 builder()->CreateClosure(entry, flags); |
| 1394 function_literals_.push_back(std::make_pair(expr, entry)); |
| 1360 execution_result()->SetResultInAccumulator(); | 1395 execution_result()->SetResultInAccumulator(); |
| 1361 } | 1396 } |
| 1362 | 1397 |
| 1363 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { | 1398 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { |
| 1364 VisitClassLiteralForRuntimeDefinition(expr); | 1399 VisitClassLiteralForRuntimeDefinition(expr); |
| 1365 | 1400 |
| 1366 // Load the "prototype" from the constructor. | 1401 // Load the "prototype" from the constructor. |
| 1367 register_allocator()->PrepareForConsecutiveAllocations(2); | 1402 register_allocator()->PrepareForConsecutiveAllocations(2); |
| 1368 Register literal = register_allocator()->NextConsecutiveRegister(); | 1403 Register literal = register_allocator()->NextConsecutiveRegister(); |
| 1369 Register prototype = register_allocator()->NextConsecutiveRegister(); | 1404 Register prototype = register_allocator()->NextConsecutiveRegister(); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1491 builder() | 1526 builder() |
| 1492 ->LoadLiteral(isolate()->factory()->prototype_string()) | 1527 ->LoadLiteral(isolate()->factory()->prototype_string()) |
| 1493 .CompareOperation(Token::Value::EQ_STRICT, key) | 1528 .CompareOperation(Token::Value::EQ_STRICT, key) |
| 1494 .JumpIfFalse(&done) | 1529 .JumpIfFalse(&done) |
| 1495 .CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0) | 1530 .CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0) |
| 1496 .Bind(&done); | 1531 .Bind(&done); |
| 1497 } | 1532 } |
| 1498 | 1533 |
| 1499 void BytecodeGenerator::VisitNativeFunctionLiteral( | 1534 void BytecodeGenerator::VisitNativeFunctionLiteral( |
| 1500 NativeFunctionLiteral* expr) { | 1535 NativeFunctionLiteral* expr) { |
| 1501 // Find or build a shared function info for the native function template. | 1536 size_t entry = builder()->AllocateConstantPoolEntry(); |
| 1502 Handle<SharedFunctionInfo> shared_info = | 1537 builder()->CreateClosure(entry, NOT_TENURED); |
| 1503 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name()); | 1538 native_function_literals_.push_back(std::make_pair(expr, entry)); |
| 1504 builder()->CreateClosure(shared_info, NOT_TENURED); | |
| 1505 execution_result()->SetResultInAccumulator(); | 1539 execution_result()->SetResultInAccumulator(); |
| 1506 } | 1540 } |
| 1507 | 1541 |
| 1508 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { | 1542 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { |
| 1509 VisitBlock(expr->block()); | 1543 VisitBlock(expr->block()); |
| 1510 VisitVariableProxy(expr->result()); | 1544 VisitVariableProxy(expr->result()); |
| 1511 } | 1545 } |
| 1512 | 1546 |
| 1513 void BytecodeGenerator::VisitConditional(Conditional* expr) { | 1547 void BytecodeGenerator::VisitConditional(Conditional* expr) { |
| 1514 // TODO(rmcilroy): Spot easy cases where there code would not need to | 1548 // TODO(rmcilroy): Spot easy cases where there code would not need to |
| (...skipping 1712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3227 return execution_context()->scope()->language_mode(); | 3261 return execution_context()->scope()->language_mode(); |
| 3228 } | 3262 } |
| 3229 | 3263 |
| 3230 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3264 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3231 return TypeFeedbackVector::GetIndex(slot); | 3265 return TypeFeedbackVector::GetIndex(slot); |
| 3232 } | 3266 } |
| 3233 | 3267 |
| 3234 } // namespace interpreter | 3268 } // namespace interpreter |
| 3235 } // namespace internal | 3269 } // namespace internal |
| 3236 } // namespace v8 | 3270 } // namespace v8 |
| OLD | NEW |