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 1210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1221 Handle<SharedFunctionInfo> shared_info = | 1221 Handle<SharedFunctionInfo> shared_info = |
1222 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); | 1222 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); |
1223 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow? | 1223 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow? |
1224 builder()->CreateClosure(shared_info, | 1224 builder()->CreateClosure(shared_info, |
1225 expr->pretenure() ? TENURED : NOT_TENURED); | 1225 expr->pretenure() ? TENURED : NOT_TENURED); |
1226 execution_result()->SetResultInAccumulator(); | 1226 execution_result()->SetResultInAccumulator(); |
1227 } | 1227 } |
1228 | 1228 |
1229 | 1229 |
1230 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { | 1230 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { |
1231 UNIMPLEMENTED(); | 1231 if (expr->scope()->ContextLocalCount() > 0) { |
| 1232 VisitNewLocalBlockContext(expr->scope()); |
| 1233 ContextScope scope(this, expr->scope()); |
| 1234 VisitDeclarations(expr->scope()->declarations()); |
| 1235 VisitClassLiteralContents(expr); |
| 1236 } else { |
| 1237 VisitDeclarations(expr->scope()->declarations()); |
| 1238 VisitClassLiteralContents(expr); |
| 1239 } |
1232 } | 1240 } |
1233 | 1241 |
| 1242 void BytecodeGenerator::VisitClassLiteralContents(ClassLiteral* expr) { |
| 1243 VisitClassLiteralForRuntimeDefinition(expr); |
| 1244 // The prototype is ensured to exist by Runtime_DefineClass in |
| 1245 // VisitClassForRuntimeDefinition. No access check is needed here |
| 1246 // since the constructor is created by the class literal. |
| 1247 register_allocator()->PrepareForConsecutiveAllocations(2); |
| 1248 Register literal = register_allocator()->NextConsecutiveRegister(); |
| 1249 Register prototype = register_allocator()->NextConsecutiveRegister(); |
| 1250 builder() |
| 1251 ->StoreAccumulatorInRegister(literal) |
| 1252 .LoadPrototypeOrInitialMap() |
| 1253 .StoreAccumulatorInRegister(prototype); |
| 1254 |
| 1255 VisitClassLiteralProperties(expr, literal, prototype); |
| 1256 builder()->CallRuntime(Runtime::kFinalizeClassDefinition, literal, 2); |
| 1257 // Assign to class variable. |
| 1258 if (expr->class_variable_proxy() != nullptr) { |
| 1259 Variable* var = expr->class_variable_proxy()->var(); |
| 1260 FeedbackVectorSlot slot = expr->NeedsProxySlot() |
| 1261 ? expr->ProxySlot() |
| 1262 : FeedbackVectorSlot::Invalid(); |
| 1263 VisitVariableAssignment(var, slot); |
| 1264 } |
| 1265 execution_result()->SetResultInAccumulator(); |
| 1266 } |
| 1267 |
| 1268 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( |
| 1269 ClassLiteral* expr) { |
| 1270 AccumulatorResultScope result_scope(this); |
| 1271 register_allocator()->PrepareForConsecutiveAllocations(4); |
| 1272 Register extends = register_allocator()->NextConsecutiveRegister(); |
| 1273 Register constructor = register_allocator()->NextConsecutiveRegister(); |
| 1274 Register start_position = register_allocator()->NextConsecutiveRegister(); |
| 1275 Register end_position = register_allocator()->NextConsecutiveRegister(); |
| 1276 |
| 1277 VisitForAccumulatorValueOrTheHole(expr->extends()); |
| 1278 builder()->StoreAccumulatorInRegister(extends); |
| 1279 |
| 1280 VisitForAccumulatorValue(expr->constructor()); |
| 1281 builder() |
| 1282 ->StoreAccumulatorInRegister(constructor) |
| 1283 .LoadLiteral(Smi::FromInt(expr->start_position())) |
| 1284 .StoreAccumulatorInRegister(start_position) |
| 1285 .LoadLiteral(Smi::FromInt(expr->end_position())) |
| 1286 .StoreAccumulatorInRegister(end_position) |
| 1287 .CallRuntime(Runtime::kDefineClass, extends, 4); |
| 1288 result_scope.SetResultInAccumulator(); |
| 1289 } |
| 1290 |
| 1291 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, |
| 1292 Register literal, |
| 1293 Register prototype) { |
| 1294 RegisterAllocationScope register_scope(this); |
| 1295 register_allocator()->PrepareForConsecutiveAllocations(4); |
| 1296 Register receiver = register_allocator()->NextConsecutiveRegister(); |
| 1297 Register key = register_allocator()->NextConsecutiveRegister(); |
| 1298 Register value = register_allocator()->NextConsecutiveRegister(); |
| 1299 Register attr = register_allocator()->NextConsecutiveRegister(); |
| 1300 |
| 1301 bool attr_assigned = false; |
| 1302 Register old_receiver = Register::invalid_value(); |
| 1303 |
| 1304 // Create nodes to store method values into the literal. |
| 1305 for (int i = 0; i < expr->properties()->length(); i++) { |
| 1306 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 1307 |
| 1308 // Set-up receiver. |
| 1309 Register new_receiver = property->is_static() ? literal : prototype; |
| 1310 if (new_receiver != old_receiver) { |
| 1311 builder()->MoveRegister(new_receiver, receiver); |
| 1312 old_receiver = new_receiver; |
| 1313 } |
| 1314 |
| 1315 VisitForAccumulatorValue(property->key()); |
| 1316 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); |
| 1317 // The static prototype property is read only. We handle the non computed |
| 1318 // property name case in the parser. Since this is the only case where we |
| 1319 // need to check for an own read only property we special case this so we do |
| 1320 // not need to do this for every property. |
| 1321 if (property->is_static() && property->is_computed_name()) { |
| 1322 VisitClassLiteralStaticPrototypeWithComputedName(key); |
| 1323 } |
| 1324 VisitForAccumulatorValue(property->value()); |
| 1325 builder()->StoreAccumulatorInRegister(value); |
| 1326 |
| 1327 VisitSetHomeObject(value, receiver, property); |
| 1328 |
| 1329 if ((property->kind() == ObjectLiteral::Property::GETTER || |
| 1330 property->kind() == ObjectLiteral::Property::SETTER) && |
| 1331 !attr_assigned) { |
| 1332 builder() |
| 1333 ->LoadLiteral(Smi::FromInt(DONT_ENUM)) |
| 1334 .StoreAccumulatorInRegister(attr); |
| 1335 attr_assigned = true; |
| 1336 } |
| 1337 |
| 1338 switch (property->kind()) { |
| 1339 case ObjectLiteral::Property::CONSTANT: |
| 1340 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1341 case ObjectLiteral::Property::PROTOTYPE: |
| 1342 // Invalid properties for ES6 classes. |
| 1343 UNREACHABLE(); |
| 1344 break; |
| 1345 case ObjectLiteral::Property::COMPUTED: { |
| 1346 builder()->CallRuntime(Runtime::kDefineClassMethod, receiver, 3); |
| 1347 break; |
| 1348 } |
| 1349 case ObjectLiteral::Property::GETTER: { |
| 1350 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked, |
| 1351 receiver, 4); |
| 1352 break; |
| 1353 } |
| 1354 case ObjectLiteral::Property::SETTER: { |
| 1355 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, |
| 1356 receiver, 4); |
| 1357 break; |
| 1358 } |
| 1359 } |
| 1360 } |
| 1361 } |
| 1362 |
| 1363 void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName( |
| 1364 Register key) { |
| 1365 BytecodeLabel done; |
| 1366 builder() |
| 1367 ->LoadLiteral(isolate()->factory()->prototype_string()) |
| 1368 .CompareOperation(Token::Value::EQ_STRICT, key, Strength::WEAK) |
| 1369 .JumpIfFalse(&done) |
| 1370 .CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0) |
| 1371 .Bind(&done); |
| 1372 } |
1234 | 1373 |
1235 void BytecodeGenerator::VisitNativeFunctionLiteral( | 1374 void BytecodeGenerator::VisitNativeFunctionLiteral( |
1236 NativeFunctionLiteral* expr) { | 1375 NativeFunctionLiteral* expr) { |
1237 // Find or build a shared function info for the native function template. | 1376 // Find or build a shared function info for the native function template. |
1238 Handle<SharedFunctionInfo> shared_info = | 1377 Handle<SharedFunctionInfo> shared_info = |
1239 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name()); | 1378 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name()); |
1240 builder()->CreateClosure(shared_info, NOT_TENURED); | 1379 builder()->CreateClosure(shared_info, NOT_TENURED); |
1241 execution_result()->SetResultInAccumulator(); | 1380 execution_result()->SetResultInAccumulator(); |
1242 } | 1381 } |
1243 | 1382 |
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2513 execution_result()->SetResultInAccumulator(); | 2652 execution_result()->SetResultInAccumulator(); |
2514 } | 2653 } |
2515 | 2654 |
2516 | 2655 |
2517 // Visits the expression |expr| and places the result in the accumulator. | 2656 // Visits the expression |expr| and places the result in the accumulator. |
2518 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 2657 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
2519 AccumulatorResultScope accumulator_scope(this); | 2658 AccumulatorResultScope accumulator_scope(this); |
2520 Visit(expr); | 2659 Visit(expr); |
2521 } | 2660 } |
2522 | 2661 |
| 2662 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { |
| 2663 if (expr == nullptr) { |
| 2664 builder()->LoadTheHole(); |
| 2665 } else { |
| 2666 VisitForAccumulatorValue(expr); |
| 2667 } |
| 2668 } |
2523 | 2669 |
2524 // Visits the expression |expr| and discards the result. | 2670 // Visits the expression |expr| and discards the result. |
2525 void BytecodeGenerator::VisitForEffect(Expression* expr) { | 2671 void BytecodeGenerator::VisitForEffect(Expression* expr) { |
2526 EffectResultScope effect_scope(this); | 2672 EffectResultScope effect_scope(this); |
2527 Visit(expr); | 2673 Visit(expr); |
2528 } | 2674 } |
2529 | 2675 |
2530 | 2676 |
2531 // Visits the expression |expr| and returns the register containing | 2677 // Visits the expression |expr| and returns the register containing |
2532 // the expression result. | 2678 // the expression result. |
(...skipping 21 matching lines...) Expand all Loading... |
2554 } | 2700 } |
2555 | 2701 |
2556 | 2702 |
2557 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2703 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2558 return TypeFeedbackVector::GetIndex(slot); | 2704 return TypeFeedbackVector::GetIndex(slot); |
2559 } | 2705 } |
2560 | 2706 |
2561 } // namespace interpreter | 2707 } // namespace interpreter |
2562 } // namespace internal | 2708 } // namespace internal |
2563 } // namespace v8 | 2709 } // namespace v8 |
OLD | NEW |