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 <stack> | 7 #include <stack> |
8 | 8 |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
| 10 #include "src/full-codegen/full-codegen.h" |
10 #include "src/interpreter/control-flow-builders.h" | 11 #include "src/interpreter/control-flow-builders.h" |
11 #include "src/objects.h" | 12 #include "src/objects.h" |
12 #include "src/parser.h" | 13 #include "src/parser.h" |
13 #include "src/scopes.h" | 14 #include "src/scopes.h" |
14 #include "src/token.h" | 15 #include "src/token.h" |
15 | 16 |
16 namespace v8 { | 17 namespace v8 { |
17 namespace internal { | 18 namespace internal { |
18 namespace interpreter { | 19 namespace interpreter { |
19 | 20 |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 } | 491 } |
491 } | 492 } |
492 | 493 |
493 | 494 |
494 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 495 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
495 UNIMPLEMENTED(); | 496 UNIMPLEMENTED(); |
496 } | 497 } |
497 | 498 |
498 | 499 |
499 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 500 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
500 UNIMPLEMENTED(); | 501 // Deep-copy the literal boilerplate. |
| 502 builder() |
| 503 ->LoadLiteral(expr->constant_properties()) |
| 504 .CreateObjectLiteral(expr->literal_index(), expr->ComputeFlags(true)); |
| 505 |
| 506 TemporaryRegisterScope temporary_register_scope(builder()); |
| 507 Register literal; |
| 508 |
| 509 // Store computed values into the literal. |
| 510 bool literal_in_accumulator = true; |
| 511 int property_index = 0; |
| 512 AccessorTable accessor_table(zone()); |
| 513 for (; property_index < expr->properties()->length(); property_index++) { |
| 514 TemporaryRegisterScope inner_temporary_register_scope(builder()); |
| 515 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 516 if (property->is_computed_name()) break; |
| 517 if (property->IsCompileTimeValue()) continue; |
| 518 |
| 519 if (literal_in_accumulator) { |
| 520 literal = temporary_register_scope.NewRegister(); |
| 521 builder()->StoreAccumulatorInRegister(literal); |
| 522 literal_in_accumulator = false; |
| 523 } |
| 524 |
| 525 Literal* literal_key = property->key()->AsLiteral(); |
| 526 switch (property->kind()) { |
| 527 case ObjectLiteral::Property::CONSTANT: |
| 528 UNREACHABLE(); |
| 529 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 530 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 531 // Fall through. |
| 532 case ObjectLiteral::Property::COMPUTED: { |
| 533 // It is safe to use [[Put]] here because the boilerplate already |
| 534 // contains computed properties with an uninitialized value. |
| 535 if (literal_key->value()->IsInternalizedString()) { |
| 536 if (property->emit_store()) { |
| 537 Register name = inner_temporary_register_scope.NewRegister(); |
| 538 builder() |
| 539 ->LoadLiteral(literal_key->AsPropertyName()) |
| 540 .StoreAccumulatorInRegister(name); |
| 541 Visit(property->value()); |
| 542 builder()->StoreNamedProperty(literal, name, |
| 543 feedback_index(property->GetSlot(0)), |
| 544 language_mode()); |
| 545 } else { |
| 546 Visit(property->value()); |
| 547 } |
| 548 } else { |
| 549 Register key = inner_temporary_register_scope.NewRegister(); |
| 550 Register value = inner_temporary_register_scope.NewRegister(); |
| 551 Register language = inner_temporary_register_scope.NewRegister(); |
| 552 DCHECK(Register::AreContiguous(literal, key, value, language)); |
| 553 Visit(property->key()); |
| 554 builder()->StoreAccumulatorInRegister(key); |
| 555 Visit(property->value()); |
| 556 builder()->StoreAccumulatorInRegister(value); |
| 557 if (property->emit_store()) { |
| 558 builder() |
| 559 ->LoadLiteral(Smi::FromInt(SLOPPY)) |
| 560 .StoreAccumulatorInRegister(language) |
| 561 .CallRuntime(Runtime::kSetProperty, literal, 4); |
| 562 VisitSetHomeObject(value, literal, property); |
| 563 } |
| 564 } |
| 565 break; |
| 566 } |
| 567 case ObjectLiteral::Property::PROTOTYPE: { |
| 568 DCHECK(property->emit_store()); |
| 569 Register value = inner_temporary_register_scope.NewRegister(); |
| 570 DCHECK(Register::AreContiguous(literal, value)); |
| 571 Visit(property->value()); |
| 572 builder()->StoreAccumulatorInRegister(value).CallRuntime( |
| 573 Runtime::kInternalSetPrototype, literal, 2); |
| 574 break; |
| 575 } |
| 576 case ObjectLiteral::Property::GETTER: |
| 577 if (property->emit_store()) { |
| 578 accessor_table.lookup(literal_key)->second->getter = property; |
| 579 } |
| 580 break; |
| 581 case ObjectLiteral::Property::SETTER: |
| 582 if (property->emit_store()) { |
| 583 accessor_table.lookup(literal_key)->second->setter = property; |
| 584 } |
| 585 break; |
| 586 } |
| 587 } |
| 588 |
| 589 // Create nodes to define accessors, using only a single call to the runtime |
| 590 // for each pair of corresponding getters and setters. |
| 591 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 592 it != accessor_table.end(); ++it) { |
| 593 TemporaryRegisterScope inner_temporary_register_scope(builder()); |
| 594 Register name = inner_temporary_register_scope.NewRegister(); |
| 595 Register getter = inner_temporary_register_scope.NewRegister(); |
| 596 Register setter = inner_temporary_register_scope.NewRegister(); |
| 597 Register attr = inner_temporary_register_scope.NewRegister(); |
| 598 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); |
| 599 Visit(it->first); |
| 600 builder()->StoreAccumulatorInRegister(name); |
| 601 VisitObjectLiteralAccessor(literal, it->second->getter, getter); |
| 602 VisitObjectLiteralAccessor(literal, it->second->setter, setter); |
| 603 builder() |
| 604 ->LoadLiteral(Smi::FromInt(NONE)) |
| 605 .StoreAccumulatorInRegister(attr) |
| 606 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); |
| 607 } |
| 608 |
| 609 // Object literals have two parts. The "static" part on the left contains no |
| 610 // computed property names, and so we can compute its map ahead of time; see |
| 611 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts |
| 612 // with the first computed property name and continues with all properties to |
| 613 // its right. All the code from above initializes the static component of the |
| 614 // object literal, and arranges for the map of the result to reflect the |
| 615 // static order in which the keys appear. For the dynamic properties, we |
| 616 // compile them into a series of "SetOwnProperty" runtime calls. This will |
| 617 // preserve insertion order. |
| 618 for (; property_index < expr->properties()->length(); property_index++) { |
| 619 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 620 |
| 621 if (literal_in_accumulator) { |
| 622 literal = temporary_register_scope.NewRegister(); |
| 623 builder()->StoreAccumulatorInRegister(literal); |
| 624 literal_in_accumulator = false; |
| 625 } |
| 626 |
| 627 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 628 DCHECK(property->emit_store()); |
| 629 TemporaryRegisterScope inner_temporary_register_scope(builder()); |
| 630 Register value = inner_temporary_register_scope.NewRegister(); |
| 631 DCHECK(Register::AreContiguous(literal, value)); |
| 632 Visit(property->value()); |
| 633 builder()->StoreAccumulatorInRegister(value).CallRuntime( |
| 634 Runtime::kInternalSetPrototype, literal, 2); |
| 635 continue; |
| 636 } |
| 637 |
| 638 TemporaryRegisterScope inner_temporary_register_scope(builder()); |
| 639 Register key = inner_temporary_register_scope.NewRegister(); |
| 640 Register value = inner_temporary_register_scope.NewRegister(); |
| 641 Register attr = inner_temporary_register_scope.NewRegister(); |
| 642 DCHECK(Register::AreContiguous(literal, key, value, attr)); |
| 643 |
| 644 Visit(property->key()); |
| 645 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); |
| 646 Visit(property->value()); |
| 647 builder()->StoreAccumulatorInRegister(value); |
| 648 VisitSetHomeObject(value, literal, property); |
| 649 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); |
| 650 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); |
| 651 switch (property->kind()) { |
| 652 case ObjectLiteral::Property::CONSTANT: |
| 653 case ObjectLiteral::Property::COMPUTED: |
| 654 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 655 function_id = Runtime::kDefineDataPropertyUnchecked; |
| 656 break; |
| 657 case ObjectLiteral::Property::PROTOTYPE: |
| 658 UNREACHABLE(); // Handled specially above. |
| 659 break; |
| 660 case ObjectLiteral::Property::GETTER: |
| 661 function_id = Runtime::kDefineGetterPropertyUnchecked; |
| 662 break; |
| 663 case ObjectLiteral::Property::SETTER: |
| 664 function_id = Runtime::kDefineSetterPropertyUnchecked; |
| 665 break; |
| 666 } |
| 667 builder()->CallRuntime(function_id, literal, 4); |
| 668 } |
| 669 |
| 670 // Transform literals that contain functions to fast properties. |
| 671 if (expr->has_function()) { |
| 672 DCHECK(!literal_in_accumulator); |
| 673 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); |
| 674 } |
| 675 |
| 676 if (!literal_in_accumulator) { |
| 677 // Restore literal array into accumulator. |
| 678 builder()->LoadAccumulatorWithRegister(literal); |
| 679 } |
501 } | 680 } |
502 | 681 |
503 | 682 |
504 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 683 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
505 // Deep-copy the literal boilerplate. | 684 // Deep-copy the literal boilerplate. |
506 expr->BuildConstantElements(isolate()); | 685 expr->BuildConstantElements(isolate()); |
507 builder() | 686 builder() |
508 ->LoadLiteral(expr->constant_elements()) | 687 ->LoadLiteral(expr->constant_elements()) |
509 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true)); | 688 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true)); |
510 | 689 |
511 TemporaryRegisterScope temporary_register_scope(builder()); | 690 TemporaryRegisterScope temporary_register_scope(builder()); |
512 Register index, literal_array; | 691 Register index, literal; |
513 | 692 |
514 // Create nodes to evaluate all the non-constant subexpressions and to store | 693 // Create nodes to evaluate all the non-constant subexpressions and to store |
515 // them into the newly cloned array. | 694 // them into the newly cloned array. |
516 bool literal_array_in_accumulator = true; | 695 bool literal_in_accumulator = true; |
517 for (int array_index = 0; array_index < expr->values()->length(); | 696 for (int array_index = 0; array_index < expr->values()->length(); |
518 array_index++) { | 697 array_index++) { |
519 Expression* subexpr = expr->values()->at(array_index); | 698 Expression* subexpr = expr->values()->at(array_index); |
520 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 699 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
521 if (subexpr->IsSpread()) { | 700 if (subexpr->IsSpread()) { |
522 // TODO(rmcilroy): Deal with spread expressions. | 701 // TODO(rmcilroy): Deal with spread expressions. |
523 UNIMPLEMENTED(); | 702 UNIMPLEMENTED(); |
524 } | 703 } |
525 | 704 |
526 if (literal_array_in_accumulator) { | 705 if (literal_in_accumulator) { |
527 index = temporary_register_scope.NewRegister(); | 706 index = temporary_register_scope.NewRegister(); |
528 literal_array = temporary_register_scope.NewRegister(); | 707 literal = temporary_register_scope.NewRegister(); |
529 builder()->StoreAccumulatorInRegister(literal_array); | 708 builder()->StoreAccumulatorInRegister(literal); |
530 literal_array_in_accumulator = false; | 709 literal_in_accumulator = false; |
531 } | 710 } |
532 | 711 |
533 builder() | 712 builder() |
534 ->LoadLiteral(Smi::FromInt(array_index)) | 713 ->LoadLiteral(Smi::FromInt(array_index)) |
535 .StoreAccumulatorInRegister(index); | 714 .StoreAccumulatorInRegister(index); |
536 Visit(subexpr); | 715 Visit(subexpr); |
537 builder()->GenericStoreKeyedProperty(literal_array, index); | 716 builder()->GenericStoreKeyedProperty(literal, index); |
538 } | 717 } |
539 | 718 |
540 if (!literal_array_in_accumulator) { | 719 if (!literal_in_accumulator) { |
541 // Restore literal array into accumulator. | 720 // Restore literal array into accumulator. |
542 builder()->LoadAccumulatorWithRegister(literal_array); | 721 builder()->LoadAccumulatorWithRegister(literal); |
543 } | 722 } |
544 } | 723 } |
545 | 724 |
546 | 725 |
547 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 726 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
548 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 727 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
549 } | 728 } |
550 | 729 |
551 | 730 |
552 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 731 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
930 | 1109 |
931 | 1110 |
932 void BytecodeGenerator::VisitNewLocalFunctionContext() { | 1111 void BytecodeGenerator::VisitNewLocalFunctionContext() { |
933 Scope* scope = this->scope(); | 1112 Scope* scope = this->scope(); |
934 | 1113 |
935 // Allocate a new local context. | 1114 // Allocate a new local context. |
936 if (scope->is_script_scope()) { | 1115 if (scope->is_script_scope()) { |
937 TemporaryRegisterScope temporary_register_scope(builder()); | 1116 TemporaryRegisterScope temporary_register_scope(builder()); |
938 Register closure = temporary_register_scope.NewRegister(); | 1117 Register closure = temporary_register_scope.NewRegister(); |
939 Register scope_info = temporary_register_scope.NewRegister(); | 1118 Register scope_info = temporary_register_scope.NewRegister(); |
940 DCHECK_EQ(closure.index() + 1, scope_info.index()); | 1119 DCHECK(Register::AreContiguous(closure, scope_info)); |
941 builder() | 1120 builder() |
942 ->LoadAccumulatorWithRegister(Register::function_closure()) | 1121 ->LoadAccumulatorWithRegister(Register::function_closure()) |
943 .StoreAccumulatorInRegister(closure) | 1122 .StoreAccumulatorInRegister(closure) |
944 .LoadLiteral(scope->GetScopeInfo(isolate())) | 1123 .LoadLiteral(scope->GetScopeInfo(isolate())) |
945 .StoreAccumulatorInRegister(scope_info) | 1124 .StoreAccumulatorInRegister(scope_info) |
946 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 1125 .CallRuntime(Runtime::kNewScriptContext, closure, 2); |
947 } else { | 1126 } else { |
948 builder()->CallRuntime(Runtime::kNewFunctionContext, | 1127 builder()->CallRuntime(Runtime::kNewFunctionContext, |
949 Register::function_closure(), 1); | 1128 Register::function_closure(), 1); |
950 } | 1129 } |
(...skipping 21 matching lines...) Expand all Loading... |
972 TemporaryRegisterScope temporary_register_scope(builder()); | 1151 TemporaryRegisterScope temporary_register_scope(builder()); |
973 Register temporary = temporary_register_scope.NewRegister(); | 1152 Register temporary = temporary_register_scope.NewRegister(); |
974 | 1153 |
975 Visit(left); | 1154 Visit(left); |
976 builder()->StoreAccumulatorInRegister(temporary); | 1155 builder()->StoreAccumulatorInRegister(temporary); |
977 Visit(right); | 1156 Visit(right); |
978 builder()->BinaryOperation(op, temporary, language_mode_strength()); | 1157 builder()->BinaryOperation(op, temporary, language_mode_strength()); |
979 } | 1158 } |
980 | 1159 |
981 | 1160 |
| 1161 void BytecodeGenerator::VisitObjectLiteralAccessor( |
| 1162 Register home_object, ObjectLiteralProperty* property, Register value_out) { |
| 1163 // TODO(rmcilroy): Replace value_out with VisitForRegister(); |
| 1164 if (property == nullptr) { |
| 1165 builder()->LoadNull().StoreAccumulatorInRegister(value_out); |
| 1166 } else { |
| 1167 Visit(property->value()); |
| 1168 builder()->StoreAccumulatorInRegister(value_out); |
| 1169 VisitSetHomeObject(value_out, home_object, property); |
| 1170 } |
| 1171 } |
| 1172 |
| 1173 |
| 1174 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, |
| 1175 ObjectLiteralProperty* property, |
| 1176 int slot_number) { |
| 1177 Expression* expr = property->value(); |
| 1178 if (!FunctionLiteral::NeedsHomeObject(expr)) return; |
| 1179 |
| 1180 // TODO(rmcilroy): Remove UNIMPLEMENTED once we have tests for setting the |
| 1181 // home object. |
| 1182 UNIMPLEMENTED(); |
| 1183 |
| 1184 TemporaryRegisterScope temporary_register_scope(builder()); |
| 1185 Register name = temporary_register_scope.NewRegister(); |
| 1186 isolate()->factory()->home_object_symbol(); |
| 1187 builder() |
| 1188 ->LoadLiteral(isolate()->factory()->home_object_symbol()) |
| 1189 .StoreAccumulatorInRegister(name) |
| 1190 .StoreNamedProperty(home_object, name, |
| 1191 feedback_index(property->GetSlot(slot_number)), |
| 1192 language_mode()); |
| 1193 } |
| 1194 |
| 1195 |
982 LanguageMode BytecodeGenerator::language_mode() const { | 1196 LanguageMode BytecodeGenerator::language_mode() const { |
983 return info()->language_mode(); | 1197 return info()->language_mode(); |
984 } | 1198 } |
985 | 1199 |
986 | 1200 |
987 Strength BytecodeGenerator::language_mode_strength() const { | 1201 Strength BytecodeGenerator::language_mode_strength() const { |
988 return strength(language_mode()); | 1202 return strength(language_mode()); |
989 } | 1203 } |
990 | 1204 |
991 | 1205 |
992 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 1206 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
993 return info()->feedback_vector()->GetIndex(slot); | 1207 return info()->feedback_vector()->GetIndex(slot); |
994 } | 1208 } |
995 | 1209 |
996 } // namespace interpreter | 1210 } // namespace interpreter |
997 } // namespace internal | 1211 } // namespace internal |
998 } // namespace v8 | 1212 } // namespace v8 |
OLD | NEW |