| 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/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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |