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 |