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

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
« no previous file with comments | « no previous file | test/cctest/interpreter/test-bytecode-generator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 988 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 expr->flags()); 999 expr->flags());
1000 execution_result()->SetResultInAccumulator(); 1000 execution_result()->SetResultInAccumulator();
1001 } 1001 }
1002 1002
1003 1003
1004 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1004 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1005 // Deep-copy the literal boilerplate. 1005 // Deep-copy the literal boilerplate.
1006 builder()->CreateObjectLiteral(expr->constant_properties(), 1006 builder()->CreateObjectLiteral(expr->constant_properties(),
1007 expr->literal_index(), 1007 expr->literal_index(),
1008 expr->ComputeFlags(true)); 1008 expr->ComputeFlags(true));
1009 Register literal; 1009
1010 // Allocate in the outer scope since this register is used to return the
1011 // expression's results to the caller.
1012 Register literal = register_allocator()->outer()->NewRegister();
1013 builder()->StoreAccumulatorInRegister(literal);
1010 1014
1011 // Store computed values into the literal. 1015 // Store computed values into the literal.
1012 bool literal_in_accumulator = true;
1013 int property_index = 0; 1016 int property_index = 0;
1014 AccessorTable accessor_table(zone()); 1017 AccessorTable accessor_table(zone());
1015 for (; property_index < expr->properties()->length(); property_index++) { 1018 for (; property_index < expr->properties()->length(); property_index++) {
1016 ObjectLiteral::Property* property = expr->properties()->at(property_index); 1019 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1017 if (property->is_computed_name()) break; 1020 if (property->is_computed_name()) break;
1018 if (property->IsCompileTimeValue()) continue; 1021 if (property->IsCompileTimeValue()) continue;
1019 1022
1020 if (literal_in_accumulator) {
1021 literal = register_allocator()->NewRegister();
1022 builder()->StoreAccumulatorInRegister(literal);
1023 literal_in_accumulator = false;
1024 }
1025
1026 RegisterAllocationScope inner_register_scope(this); 1023 RegisterAllocationScope inner_register_scope(this);
1027 Literal* literal_key = property->key()->AsLiteral(); 1024 Literal* literal_key = property->key()->AsLiteral();
1028 switch (property->kind()) { 1025 switch (property->kind()) {
1029 case ObjectLiteral::Property::CONSTANT: 1026 case ObjectLiteral::Property::CONSTANT:
1030 UNREACHABLE(); 1027 UNREACHABLE();
1031 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1028 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1032 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); 1029 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1033 // Fall through. 1030 // Fall through.
1034 case ObjectLiteral::Property::COMPUTED: { 1031 case ObjectLiteral::Property::COMPUTED: {
1035 // It is safe to use [[Put]] here because the boilerplate already 1032 // It is safe to use [[Put]] here because the boilerplate already
1036 // contains computed properties with an uninitialized value. 1033 // contains computed properties with an uninitialized value.
1037 if (literal_key->value()->IsInternalizedString()) { 1034 if (literal_key->value()->IsInternalizedString()) {
1038 if (property->emit_store()) { 1035 if (property->emit_store()) {
1039 VisitForAccumulatorValue(property->value()); 1036 VisitForAccumulatorValue(property->value());
1040 builder()->StoreNamedProperty( 1037 builder()->StoreNamedProperty(
1041 literal, literal_key->AsPropertyName(), 1038 literal, literal_key->AsPropertyName(),
1042 feedback_index(property->GetSlot(0)), language_mode()); 1039 feedback_index(property->GetSlot(0)), language_mode());
1043 } else { 1040 } else {
1044 VisitForEffect(property->value()); 1041 VisitForEffect(property->value());
1045 } 1042 }
1046 } else { 1043 } else {
1047 register_allocator()->PrepareForConsecutiveAllocations(3); 1044 register_allocator()->PrepareForConsecutiveAllocations(4);
1045 Register literal_argument =
1046 register_allocator()->NextConsecutiveRegister();
1048 Register key = register_allocator()->NextConsecutiveRegister(); 1047 Register key = register_allocator()->NextConsecutiveRegister();
1049 Register value = register_allocator()->NextConsecutiveRegister(); 1048 Register value = register_allocator()->NextConsecutiveRegister();
1050 Register language = register_allocator()->NextConsecutiveRegister(); 1049 Register language = register_allocator()->NextConsecutiveRegister();
1051 // TODO(oth): This is problematic - can't assume contiguous here. 1050
1052 // literal is allocated in outer register scope, whereas key, value, 1051 builder()->MoveRegister(literal, literal_argument);
1053 // language are in another.
1054 DCHECK(Register::AreContiguous(literal, key, value, language));
1055 VisitForAccumulatorValue(property->key()); 1052 VisitForAccumulatorValue(property->key());
1056 builder()->StoreAccumulatorInRegister(key); 1053 builder()->StoreAccumulatorInRegister(key);
1057 VisitForAccumulatorValue(property->value()); 1054 VisitForAccumulatorValue(property->value());
1058 builder()->StoreAccumulatorInRegister(value); 1055 builder()->StoreAccumulatorInRegister(value);
1059 if (property->emit_store()) { 1056 if (property->emit_store()) {
1060 builder() 1057 builder()
1061 ->LoadLiteral(Smi::FromInt(SLOPPY)) 1058 ->LoadLiteral(Smi::FromInt(SLOPPY))
1062 .StoreAccumulatorInRegister(language) 1059 .StoreAccumulatorInRegister(language)
1063 .CallRuntime(Runtime::kSetProperty, literal, 4); 1060 .CallRuntime(Runtime::kSetProperty, literal_argument, 4);
1064 VisitSetHomeObject(value, literal, property); 1061 VisitSetHomeObject(value, literal, property);
1065 } 1062 }
1066 } 1063 }
1067 break; 1064 break;
1068 } 1065 }
1069 case ObjectLiteral::Property::PROTOTYPE: { 1066 case ObjectLiteral::Property::PROTOTYPE: {
1070 register_allocator()->PrepareForConsecutiveAllocations(1);
1071 DCHECK(property->emit_store()); 1067 DCHECK(property->emit_store());
1068 register_allocator()->PrepareForConsecutiveAllocations(2);
1069 Register literal_argument =
1070 register_allocator()->NextConsecutiveRegister();
1072 Register value = register_allocator()->NextConsecutiveRegister(); 1071 Register value = register_allocator()->NextConsecutiveRegister();
1073 DCHECK(Register::AreContiguous(literal, value)); 1072
1073 builder()->MoveRegister(literal, literal_argument);
1074 VisitForAccumulatorValue(property->value()); 1074 VisitForAccumulatorValue(property->value());
1075 builder()->StoreAccumulatorInRegister(value).CallRuntime( 1075 builder()->StoreAccumulatorInRegister(value).CallRuntime(
1076 Runtime::kInternalSetPrototype, literal, 2); 1076 Runtime::kInternalSetPrototype, literal_argument, 2);
1077 break; 1077 break;
1078 } 1078 }
1079 case ObjectLiteral::Property::GETTER: 1079 case ObjectLiteral::Property::GETTER:
1080 if (property->emit_store()) { 1080 if (property->emit_store()) {
1081 accessor_table.lookup(literal_key)->second->getter = property; 1081 accessor_table.lookup(literal_key)->second->getter = property;
1082 } 1082 }
1083 break; 1083 break;
1084 case ObjectLiteral::Property::SETTER: 1084 case ObjectLiteral::Property::SETTER:
1085 if (property->emit_store()) { 1085 if (property->emit_store()) {
1086 accessor_table.lookup(literal_key)->second->setter = property; 1086 accessor_table.lookup(literal_key)->second->setter = property;
1087 } 1087 }
1088 break; 1088 break;
1089 } 1089 }
1090 } 1090 }
1091 1091
1092 // Define accessors, using only a single call to the runtime for each pair of 1092 // Define accessors, using only a single call to the runtime for each pair of
1093 // corresponding getters and setters. 1093 // corresponding getters and setters.
1094 for (AccessorTable::Iterator it = accessor_table.begin(); 1094 for (AccessorTable::Iterator it = accessor_table.begin();
1095 it != accessor_table.end(); ++it) { 1095 it != accessor_table.end(); ++it) {
1096 RegisterAllocationScope inner_register_scope(this); 1096 RegisterAllocationScope inner_register_scope(this);
1097 register_allocator()->PrepareForConsecutiveAllocations(4); 1097 register_allocator()->PrepareForConsecutiveAllocations(5);
1098 Register literal_argument = register_allocator()->NextConsecutiveRegister();
1098 Register name = register_allocator()->NextConsecutiveRegister(); 1099 Register name = register_allocator()->NextConsecutiveRegister();
1099 Register getter = register_allocator()->NextConsecutiveRegister(); 1100 Register getter = register_allocator()->NextConsecutiveRegister();
1100 Register setter = register_allocator()->NextConsecutiveRegister(); 1101 Register setter = register_allocator()->NextConsecutiveRegister();
1101 Register attr = register_allocator()->NextConsecutiveRegister(); 1102 Register attr = register_allocator()->NextConsecutiveRegister();
1102 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); 1103
1104 builder()->MoveRegister(literal, literal_argument);
1103 VisitForAccumulatorValue(it->first); 1105 VisitForAccumulatorValue(it->first);
1104 builder()->StoreAccumulatorInRegister(name); 1106 builder()->StoreAccumulatorInRegister(name);
1105 VisitObjectLiteralAccessor(literal, it->second->getter, getter); 1107 VisitObjectLiteralAccessor(literal, it->second->getter, getter);
1106 VisitObjectLiteralAccessor(literal, it->second->setter, setter); 1108 VisitObjectLiteralAccessor(literal, it->second->setter, setter);
1107 builder() 1109 builder()
1108 ->LoadLiteral(Smi::FromInt(NONE)) 1110 ->LoadLiteral(Smi::FromInt(NONE))
1109 .StoreAccumulatorInRegister(attr) 1111 .StoreAccumulatorInRegister(attr)
1110 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); 1112 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked,
1113 literal_argument, 5);
1111 } 1114 }
1112 1115
1113 // Object literals have two parts. The "static" part on the left contains no 1116 // Object literals have two parts. The "static" part on the left contains no
1114 // computed property names, and so we can compute its map ahead of time; see 1117 // computed property names, and so we can compute its map ahead of time; see
1115 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts 1118 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1116 // with the first computed property name and continues with all properties to 1119 // with the first computed property name and continues with all properties to
1117 // its right. All the code from above initializes the static component of the 1120 // its right. All the code from above initializes the static component of the
1118 // object literal, and arranges for the map of the result to reflect the 1121 // object literal, and arranges for the map of the result to reflect the
1119 // static order in which the keys appear. For the dynamic properties, we 1122 // static order in which the keys appear. For the dynamic properties, we
1120 // compile them into a series of "SetOwnProperty" runtime calls. This will 1123 // compile them into a series of "SetOwnProperty" runtime calls. This will
1121 // preserve insertion order. 1124 // preserve insertion order.
1122 for (; property_index < expr->properties()->length(); property_index++) { 1125 for (; property_index < expr->properties()->length(); property_index++) {
1123 if (literal_in_accumulator) {
1124 literal = register_allocator()->NewRegister();
1125 builder()->StoreAccumulatorInRegister(literal);
1126 literal_in_accumulator = false;
1127 }
1128
1129 ObjectLiteral::Property* property = expr->properties()->at(property_index); 1126 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1130 RegisterAllocationScope inner_register_scope(this); 1127 RegisterAllocationScope inner_register_scope(this);
1128
1131 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { 1129 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1132 DCHECK(property->emit_store()); 1130 DCHECK(property->emit_store());
1133 Register value = register_allocator()->NewRegister(); 1131 register_allocator()->PrepareForConsecutiveAllocations(2);
1134 DCHECK(Register::AreContiguous(literal, value)); 1132 Register literal_argument =
1133 register_allocator()->NextConsecutiveRegister();
1134 Register value = register_allocator()->NextConsecutiveRegister();
1135
1136 builder()->MoveRegister(literal, literal_argument);
1135 VisitForAccumulatorValue(property->value()); 1137 VisitForAccumulatorValue(property->value());
1136 builder()->StoreAccumulatorInRegister(value).CallRuntime( 1138 builder()->StoreAccumulatorInRegister(value).CallRuntime(
1137 Runtime::kInternalSetPrototype, literal, 2); 1139 Runtime::kInternalSetPrototype, literal_argument, 2);
1138 continue; 1140 continue;
1139 } 1141 }
1140 1142
1141 register_allocator()->PrepareForConsecutiveAllocations(3); 1143 register_allocator()->PrepareForConsecutiveAllocations(4);
1144 Register literal_argument = register_allocator()->NextConsecutiveRegister();
1142 Register key = register_allocator()->NextConsecutiveRegister(); 1145 Register key = register_allocator()->NextConsecutiveRegister();
1143 Register value = register_allocator()->NextConsecutiveRegister(); 1146 Register value = register_allocator()->NextConsecutiveRegister();
1144 Register attr = register_allocator()->NextConsecutiveRegister(); 1147 Register attr = register_allocator()->NextConsecutiveRegister();
1145 DCHECK(Register::AreContiguous(literal, key, value, attr)); 1148 DCHECK(Register::AreContiguous(literal_argument, key, value, attr));
1146 1149
1150 builder()->MoveRegister(literal, literal_argument);
1147 VisitForAccumulatorValue(property->key()); 1151 VisitForAccumulatorValue(property->key());
1148 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); 1152 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1149 VisitForAccumulatorValue(property->value()); 1153 VisitForAccumulatorValue(property->value());
1150 builder()->StoreAccumulatorInRegister(value); 1154 builder()->StoreAccumulatorInRegister(value);
1151 VisitSetHomeObject(value, literal, property); 1155 VisitSetHomeObject(value, literal, property);
1152 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); 1156 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
1153 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); 1157 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1);
1154 switch (property->kind()) { 1158 switch (property->kind()) {
1155 case ObjectLiteral::Property::CONSTANT: 1159 case ObjectLiteral::Property::CONSTANT:
1156 case ObjectLiteral::Property::COMPUTED: 1160 case ObjectLiteral::Property::COMPUTED:
1157 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1161 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1158 function_id = Runtime::kDefineDataPropertyUnchecked; 1162 function_id = Runtime::kDefineDataPropertyUnchecked;
1159 break; 1163 break;
1160 case ObjectLiteral::Property::PROTOTYPE: 1164 case ObjectLiteral::Property::PROTOTYPE:
1161 UNREACHABLE(); // Handled specially above. 1165 UNREACHABLE(); // Handled specially above.
1162 break; 1166 break;
1163 case ObjectLiteral::Property::GETTER: 1167 case ObjectLiteral::Property::GETTER:
1164 function_id = Runtime::kDefineGetterPropertyUnchecked; 1168 function_id = Runtime::kDefineGetterPropertyUnchecked;
1165 break; 1169 break;
1166 case ObjectLiteral::Property::SETTER: 1170 case ObjectLiteral::Property::SETTER:
1167 function_id = Runtime::kDefineSetterPropertyUnchecked; 1171 function_id = Runtime::kDefineSetterPropertyUnchecked;
1168 break; 1172 break;
1169 } 1173 }
1170 builder()->CallRuntime(function_id, literal, 4); 1174 builder()->CallRuntime(function_id, literal_argument, 4);
1171 } 1175 }
1172 1176
1173 // Transform literals that contain functions to fast properties. 1177 // Transform literals that contain functions to fast properties.
1174 if (expr->has_function()) { 1178 if (expr->has_function()) {
1175 DCHECK(!literal_in_accumulator);
1176 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); 1179 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1);
1177 } 1180 }
1178 1181
1179 if (!literal_in_accumulator) { 1182 execution_result()->SetResultInRegister(literal);
1180 // Restore literal array into accumulator.
1181 builder()->LoadAccumulatorWithRegister(literal);
1182 }
1183 execution_result()->SetResultInAccumulator();
1184 } 1183 }
1185 1184
1186 1185
1187 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1186 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1188 // Deep-copy the literal boilerplate. 1187 // Deep-copy the literal boilerplate.
1189 builder()->CreateArrayLiteral(expr->constant_elements(), 1188 builder()->CreateArrayLiteral(expr->constant_elements(),
1190 expr->literal_index(), 1189 expr->literal_index(),
1191 expr->ComputeFlags(true)); 1190 expr->ComputeFlags(true));
1192 Register index, literal; 1191 Register index, literal;
1193 1192
(...skipping 1023 matching lines...) Expand 10 before | Expand all | Expand 10 after
2217 } 2216 }
2218 2217
2219 2218
2220 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2219 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2221 return info()->feedback_vector()->GetIndex(slot); 2220 return info()->feedback_vector()->GetIndex(slot);
2222 } 2221 }
2223 2222
2224 } // namespace interpreter 2223 } // namespace interpreter
2225 } // namespace internal 2224 } // namespace internal
2226 } // namespace v8 2225 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/cctest/interpreter/test-bytecode-generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698