Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1386313005: [Interpreter] Adds Object literal support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@int_literal_2
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
rmcilroy 2015/10/13 09:13:14 This is only included for AccessorTable (it is als
Michael Starzinger 2015/10/13 11:06:44 Acknowledged. Works for me. As for moving it, if w
rmcilroy 2015/10/13 17:04:53 Sounds good, ast.h was what I was thinking too. I'
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698