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

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

Issue 1588903002: [Interpreter] Fixes VisitObjectLiteral to reserve consecutive registers in innerscope. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased the patch. Created 4 years, 11 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 "src/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/compiler.h" 8 #include "src/compiler.h"
9 #include "src/interpreter/bytecode-register-allocator.h" 9 #include "src/interpreter/bytecode-register-allocator.h"
10 #include "src/interpreter/control-flow-builders.h" 10 #include "src/interpreter/control-flow-builders.h"
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after
957 expr->flags()); 957 expr->flags());
958 execution_result()->SetResultInAccumulator(); 958 execution_result()->SetResultInAccumulator();
959 } 959 }
960 960
961 961
962 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 962 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
963 // Deep-copy the literal boilerplate. 963 // Deep-copy the literal boilerplate.
964 builder()->CreateObjectLiteral(expr->constant_properties(), 964 builder()->CreateObjectLiteral(expr->constant_properties(),
965 expr->literal_index(), 965 expr->literal_index(),
966 expr->ComputeFlags(true)); 966 expr->ComputeFlags(true));
967 Register literal; 967
968 // Allocate in the outer scope since this register is returned.
rmcilroy 2016/01/15 17:15:09 /s/since.../since this register is used to return
mythria 2016/01/18 11:34:05 Thanks, Done.
969 Register literal = register_allocator()->outer()->NewRegister();
970 builder()->StoreAccumulatorInRegister(literal);
968 971
969 // Store computed values into the literal. 972 // Store computed values into the literal.
970 bool literal_in_accumulator = true;
971 int property_index = 0; 973 int property_index = 0;
972 AccessorTable accessor_table(zone()); 974 AccessorTable accessor_table(zone());
973 for (; property_index < expr->properties()->length(); property_index++) { 975 for (; property_index < expr->properties()->length(); property_index++) {
974 ObjectLiteral::Property* property = expr->properties()->at(property_index); 976 ObjectLiteral::Property* property = expr->properties()->at(property_index);
975 if (property->is_computed_name()) break; 977 if (property->is_computed_name()) break;
976 if (property->IsCompileTimeValue()) continue; 978 if (property->IsCompileTimeValue()) continue;
977 979
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); 980 RegisterAllocationScope inner_register_scope(this);
985 Literal* literal_key = property->key()->AsLiteral(); 981 Literal* literal_key = property->key()->AsLiteral();
986 switch (property->kind()) { 982 switch (property->kind()) {
987 case ObjectLiteral::Property::CONSTANT: 983 case ObjectLiteral::Property::CONSTANT:
988 UNREACHABLE(); 984 UNREACHABLE();
989 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 985 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
990 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); 986 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
991 // Fall through. 987 // Fall through.
992 case ObjectLiteral::Property::COMPUTED: { 988 case ObjectLiteral::Property::COMPUTED: {
993 // It is safe to use [[Put]] here because the boilerplate already 989 // It is safe to use [[Put]] here because the boilerplate already
994 // contains computed properties with an uninitialized value. 990 // contains computed properties with an uninitialized value.
995 if (literal_key->value()->IsInternalizedString()) { 991 if (literal_key->value()->IsInternalizedString()) {
996 if (property->emit_store()) { 992 if (property->emit_store()) {
997 VisitForAccumulatorValue(property->value()); 993 VisitForAccumulatorValue(property->value());
998 builder()->StoreNamedProperty( 994 builder()->StoreNamedProperty(
999 literal, literal_key->AsPropertyName(), 995 literal, literal_key->AsPropertyName(),
1000 feedback_index(property->GetSlot(0)), language_mode()); 996 feedback_index(property->GetSlot(0)), language_mode());
1001 } else { 997 } else {
1002 VisitForEffect(property->value()); 998 VisitForEffect(property->value());
1003 } 999 }
1004 } else { 1000 } else {
1005 register_allocator()->PrepareForConsecutiveAllocations(3); 1001 register_allocator()->PrepareForConsecutiveAllocations(4);
1002 Register literal_argument =
1003 register_allocator()->NextConsecutiveRegister();
1006 Register key = register_allocator()->NextConsecutiveRegister(); 1004 Register key = register_allocator()->NextConsecutiveRegister();
1007 Register value = register_allocator()->NextConsecutiveRegister(); 1005 Register value = register_allocator()->NextConsecutiveRegister();
1008 Register language = register_allocator()->NextConsecutiveRegister(); 1006 Register language = register_allocator()->NextConsecutiveRegister();
1009 // TODO(oth): This is problematic - can't assume contiguous here. 1007 DCHECK(
1010 // literal is allocated in outer register scope, whereas key, value, 1008 Register::AreContiguous(literal_argument, key, value, language));
rmcilroy 2016/01/15 17:15:09 This DCHECK's probably not necessary anymore.
mythria 2016/01/18 11:34:05 Done.
1011 // language are in another. 1009
1012 DCHECK(Register::AreContiguous(literal, key, value, language)); 1010 builder()->MoveRegister(literal, literal_argument);
1013 VisitForAccumulatorValue(property->key()); 1011 VisitForAccumulatorValue(property->key());
1014 builder()->StoreAccumulatorInRegister(key); 1012 builder()->StoreAccumulatorInRegister(key);
1015 VisitForAccumulatorValue(property->value()); 1013 VisitForAccumulatorValue(property->value());
1016 builder()->StoreAccumulatorInRegister(value); 1014 builder()->StoreAccumulatorInRegister(value);
1017 if (property->emit_store()) { 1015 if (property->emit_store()) {
1018 builder() 1016 builder()
1019 ->LoadLiteral(Smi::FromInt(SLOPPY)) 1017 ->LoadLiteral(Smi::FromInt(SLOPPY))
1020 .StoreAccumulatorInRegister(language) 1018 .StoreAccumulatorInRegister(language)
1021 .CallRuntime(Runtime::kSetProperty, literal, 4); 1019 .CallRuntime(Runtime::kSetProperty, literal_argument, 4);
1022 VisitSetHomeObject(value, literal, property); 1020 VisitSetHomeObject(value, literal, property);
1023 } 1021 }
1024 } 1022 }
1025 break; 1023 break;
1026 } 1024 }
1027 case ObjectLiteral::Property::PROTOTYPE: { 1025 case ObjectLiteral::Property::PROTOTYPE: {
1028 register_allocator()->PrepareForConsecutiveAllocations(1);
1029 DCHECK(property->emit_store()); 1026 DCHECK(property->emit_store());
1027 register_allocator()->PrepareForConsecutiveAllocations(2);
1028 Register literal_argument =
1029 register_allocator()->NextConsecutiveRegister();
1030 Register value = register_allocator()->NextConsecutiveRegister(); 1030 Register value = register_allocator()->NextConsecutiveRegister();
1031 DCHECK(Register::AreContiguous(literal, value)); 1031 DCHECK(Register::AreContiguous(literal_argument, value));
rmcilroy 2016/01/15 17:15:09 ditto
mythria 2016/01/18 11:34:05 Done.
1032
1033 builder()->MoveRegister(literal, literal_argument);
1032 VisitForAccumulatorValue(property->value()); 1034 VisitForAccumulatorValue(property->value());
1033 builder()->StoreAccumulatorInRegister(value).CallRuntime( 1035 builder()->StoreAccumulatorInRegister(value).CallRuntime(
1034 Runtime::kInternalSetPrototype, literal, 2); 1036 Runtime::kInternalSetPrototype, literal_argument, 2);
1035 break; 1037 break;
1036 } 1038 }
1037 case ObjectLiteral::Property::GETTER: 1039 case ObjectLiteral::Property::GETTER:
1038 if (property->emit_store()) { 1040 if (property->emit_store()) {
1039 accessor_table.lookup(literal_key)->second->getter = property; 1041 accessor_table.lookup(literal_key)->second->getter = property;
1040 } 1042 }
1041 break; 1043 break;
1042 case ObjectLiteral::Property::SETTER: 1044 case ObjectLiteral::Property::SETTER:
1043 if (property->emit_store()) { 1045 if (property->emit_store()) {
1044 accessor_table.lookup(literal_key)->second->setter = property; 1046 accessor_table.lookup(literal_key)->second->setter = property;
1045 } 1047 }
1046 break; 1048 break;
1047 } 1049 }
1048 } 1050 }
1049 1051
1050 // Define accessors, using only a single call to the runtime for each pair of 1052 // Define accessors, using only a single call to the runtime for each pair of
1051 // corresponding getters and setters. 1053 // corresponding getters and setters.
1052 for (AccessorTable::Iterator it = accessor_table.begin(); 1054 for (AccessorTable::Iterator it = accessor_table.begin();
1053 it != accessor_table.end(); ++it) { 1055 it != accessor_table.end(); ++it) {
1054 RegisterAllocationScope inner_register_scope(this); 1056 RegisterAllocationScope inner_register_scope(this);
1055 register_allocator()->PrepareForConsecutiveAllocations(4); 1057 register_allocator()->PrepareForConsecutiveAllocations(5);
1058 Register literal_argument = register_allocator()->NextConsecutiveRegister();
1056 Register name = register_allocator()->NextConsecutiveRegister(); 1059 Register name = register_allocator()->NextConsecutiveRegister();
1057 Register getter = register_allocator()->NextConsecutiveRegister(); 1060 Register getter = register_allocator()->NextConsecutiveRegister();
1058 Register setter = register_allocator()->NextConsecutiveRegister(); 1061 Register setter = register_allocator()->NextConsecutiveRegister();
1059 Register attr = register_allocator()->NextConsecutiveRegister(); 1062 Register attr = register_allocator()->NextConsecutiveRegister();
1060 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); 1063 DCHECK(
1064 Register::AreContiguous(literal_argument, name, getter, setter, attr));
rmcilroy 2016/01/15 17:15:09 ditto
mythria 2016/01/18 11:34:05 Done.
1065
1066 builder()->MoveRegister(literal, literal_argument);
1061 VisitForAccumulatorValue(it->first); 1067 VisitForAccumulatorValue(it->first);
1062 builder()->StoreAccumulatorInRegister(name); 1068 builder()->StoreAccumulatorInRegister(name);
1063 VisitObjectLiteralAccessor(literal, it->second->getter, getter); 1069 VisitObjectLiteralAccessor(literal, it->second->getter, getter);
1064 VisitObjectLiteralAccessor(literal, it->second->setter, setter); 1070 VisitObjectLiteralAccessor(literal, it->second->setter, setter);
1065 builder() 1071 builder()
1066 ->LoadLiteral(Smi::FromInt(NONE)) 1072 ->LoadLiteral(Smi::FromInt(NONE))
1067 .StoreAccumulatorInRegister(attr) 1073 .StoreAccumulatorInRegister(attr)
1068 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); 1074 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked,
1075 literal_argument, 5);
1069 } 1076 }
1070 1077
1071 // Object literals have two parts. The "static" part on the left contains no 1078 // 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 1079 // computed property names, and so we can compute its map ahead of time; see
1073 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts 1080 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1074 // with the first computed property name and continues with all properties to 1081 // 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 1082 // 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 1083 // 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 1084 // static order in which the keys appear. For the dynamic properties, we
1078 // compile them into a series of "SetOwnProperty" runtime calls. This will 1085 // compile them into a series of "SetOwnProperty" runtime calls. This will
1079 // preserve insertion order. 1086 // preserve insertion order.
1080 for (; property_index < expr->properties()->length(); property_index++) { 1087 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 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1088 RegisterAllocationScope inner_register_scope(this); 1089 RegisterAllocationScope inner_register_scope(this);
1090
1089 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { 1091 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1090 DCHECK(property->emit_store()); 1092 DCHECK(property->emit_store());
1091 Register value = register_allocator()->NewRegister(); 1093 register_allocator()->PrepareForConsecutiveAllocations(2);
1092 DCHECK(Register::AreContiguous(literal, value)); 1094 Register literal_argument =
1095 register_allocator()->NextConsecutiveRegister();
1096 Register value = register_allocator()->NextConsecutiveRegister();
1097 DCHECK(Register::AreContiguous(literal_argument, value));
rmcilroy 2016/01/15 17:15:09 ditto
mythria 2016/01/18 11:34:05 Done.
1098
1099 builder()->MoveRegister(literal, literal_argument);
1093 VisitForAccumulatorValue(property->value()); 1100 VisitForAccumulatorValue(property->value());
1094 builder()->StoreAccumulatorInRegister(value).CallRuntime( 1101 builder()->StoreAccumulatorInRegister(value).CallRuntime(
1095 Runtime::kInternalSetPrototype, literal, 2); 1102 Runtime::kInternalSetPrototype, literal_argument, 2);
1096 continue; 1103 continue;
1097 } 1104 }
1098 1105
1099 register_allocator()->PrepareForConsecutiveAllocations(3); 1106 register_allocator()->PrepareForConsecutiveAllocations(4);
1107 Register literal_argument = register_allocator()->NextConsecutiveRegister();
1100 Register key = register_allocator()->NextConsecutiveRegister(); 1108 Register key = register_allocator()->NextConsecutiveRegister();
1101 Register value = register_allocator()->NextConsecutiveRegister(); 1109 Register value = register_allocator()->NextConsecutiveRegister();
1102 Register attr = register_allocator()->NextConsecutiveRegister(); 1110 Register attr = register_allocator()->NextConsecutiveRegister();
1103 DCHECK(Register::AreContiguous(literal, key, value, attr)); 1111 DCHECK(Register::AreContiguous(literal_argument, key, value, attr));
1104 1112
1113 builder()->MoveRegister(literal, literal_argument);
1105 VisitForAccumulatorValue(property->key()); 1114 VisitForAccumulatorValue(property->key());
1106 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); 1115 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1107 VisitForAccumulatorValue(property->value()); 1116 VisitForAccumulatorValue(property->value());
1108 builder()->StoreAccumulatorInRegister(value); 1117 builder()->StoreAccumulatorInRegister(value);
1109 VisitSetHomeObject(value, literal, property); 1118 VisitSetHomeObject(value, literal, property);
1110 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); 1119 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
1111 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); 1120 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1);
1112 switch (property->kind()) { 1121 switch (property->kind()) {
1113 case ObjectLiteral::Property::CONSTANT: 1122 case ObjectLiteral::Property::CONSTANT:
1114 case ObjectLiteral::Property::COMPUTED: 1123 case ObjectLiteral::Property::COMPUTED:
1115 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1124 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1116 function_id = Runtime::kDefineDataPropertyUnchecked; 1125 function_id = Runtime::kDefineDataPropertyUnchecked;
1117 break; 1126 break;
1118 case ObjectLiteral::Property::PROTOTYPE: 1127 case ObjectLiteral::Property::PROTOTYPE:
1119 UNREACHABLE(); // Handled specially above. 1128 UNREACHABLE(); // Handled specially above.
1120 break; 1129 break;
1121 case ObjectLiteral::Property::GETTER: 1130 case ObjectLiteral::Property::GETTER:
1122 function_id = Runtime::kDefineGetterPropertyUnchecked; 1131 function_id = Runtime::kDefineGetterPropertyUnchecked;
1123 break; 1132 break;
1124 case ObjectLiteral::Property::SETTER: 1133 case ObjectLiteral::Property::SETTER:
1125 function_id = Runtime::kDefineSetterPropertyUnchecked; 1134 function_id = Runtime::kDefineSetterPropertyUnchecked;
1126 break; 1135 break;
1127 } 1136 }
1128 builder()->CallRuntime(function_id, literal, 4); 1137 builder()->CallRuntime(function_id, literal_argument, 4);
1129 } 1138 }
1130 1139
1131 // Transform literals that contain functions to fast properties. 1140 // Transform literals that contain functions to fast properties.
1132 if (expr->has_function()) { 1141 if (expr->has_function()) {
1133 DCHECK(!literal_in_accumulator);
1134 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); 1142 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1);
1135 } 1143 }
1136 1144
1137 if (!literal_in_accumulator) { 1145 execution_result()->SetResultInRegister(literal);
1138 // Restore literal array into accumulator.
1139 builder()->LoadAccumulatorWithRegister(literal);
1140 }
1141 execution_result()->SetResultInAccumulator();
1142 } 1146 }
1143 1147
1144 1148
1145 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1149 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1146 // Deep-copy the literal boilerplate. 1150 // Deep-copy the literal boilerplate.
1147 builder()->CreateArrayLiteral(expr->constant_elements(), 1151 builder()->CreateArrayLiteral(expr->constant_elements(),
1148 expr->literal_index(), 1152 expr->literal_index(),
1149 expr->ComputeFlags(true)); 1153 expr->ComputeFlags(true));
1150 Register index, literal; 1154 Register index, literal;
1151 1155
(...skipping 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after
2173 } 2177 }
2174 2178
2175 2179
2176 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2180 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2177 return info()->feedback_vector()->GetIndex(slot); 2181 return info()->feedback_vector()->GetIndex(slot);
2178 } 2182 }
2179 2183
2180 } // namespace interpreter 2184 } // namespace interpreter
2181 } // namespace internal 2185 } // namespace internal
2182 } // namespace v8 2186 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/cctest/interpreter/test-bytecode-generator.cc » ('j') | test/mjsunit/mjsunit.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698