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/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/compilation-info.h" | 10 #include "src/compilation-info.h" |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
564 global_declarations_(0, info->zone()), | 564 global_declarations_(0, info->zone()), |
565 function_literals_(0, info->zone()), | 565 function_literals_(0, info->zone()), |
566 native_function_literals_(0, info->zone()), | 566 native_function_literals_(0, info->zone()), |
567 execution_control_(nullptr), | 567 execution_control_(nullptr), |
568 execution_context_(nullptr), | 568 execution_context_(nullptr), |
569 execution_result_(nullptr), | 569 execution_result_(nullptr), |
570 generator_resume_points_(info->literal()->yield_count(), info->zone()), | 570 generator_resume_points_(info->literal()->yield_count(), info->zone()), |
571 generator_state_(), | 571 generator_state_(), |
572 loop_depth_(0), | 572 loop_depth_(0), |
573 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), | 573 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), |
574 prototype_string_(info->isolate()->factory()->prototype_string()) { | 574 prototype_string_(info->isolate()->factory()->prototype_string()), |
575 } | 575 name_string_(info->isolate()->factory()->name_string()) {} |
576 | 576 |
577 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { | 577 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { |
578 AllocateDeferredConstants(); | 578 AllocateDeferredConstants(); |
579 if (HasStackOverflow()) return Handle<BytecodeArray>(); | 579 if (HasStackOverflow()) return Handle<BytecodeArray>(); |
580 return builder()->ToBytecodeArray(isolate); | 580 return builder()->ToBytecodeArray(isolate); |
581 } | 581 } |
582 | 582 |
583 void BytecodeGenerator::AllocateDeferredConstants() { | 583 void BytecodeGenerator::AllocateDeferredConstants() { |
584 // Build global declaration pair arrays. | 584 // Build global declaration pair arrays. |
585 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { | 585 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { |
(...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1375 scope()->is_function_scope()); | 1375 scope()->is_function_scope()); |
1376 size_t entry = builder()->AllocateConstantPoolEntry(); | 1376 size_t entry = builder()->AllocateConstantPoolEntry(); |
1377 builder()->CreateClosure(entry, flags); | 1377 builder()->CreateClosure(entry, flags); |
1378 function_literals_.push_back(std::make_pair(expr, entry)); | 1378 function_literals_.push_back(std::make_pair(expr, entry)); |
1379 } | 1379 } |
1380 | 1380 |
1381 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { | 1381 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { |
1382 VisitClassLiteralForRuntimeDefinition(expr); | 1382 VisitClassLiteralForRuntimeDefinition(expr); |
1383 | 1383 |
1384 // Load the "prototype" from the constructor. | 1384 // Load the "prototype" from the constructor. |
1385 RegisterList args = register_allocator()->NewRegisterList(2); | 1385 RegisterList args = register_allocator()->NewRegisterList(3); |
1386 Register literal = args[0]; | 1386 Register literal = args[0]; |
1387 Register prototype = args[1]; | 1387 Register prototype = args[1]; |
1388 FeedbackVectorSlot slot = expr->PrototypeSlot(); | 1388 FeedbackVectorSlot slot = expr->PrototypeSlot(); |
1389 builder() | 1389 builder() |
1390 ->StoreAccumulatorInRegister(literal) | 1390 ->StoreAccumulatorInRegister(literal) |
1391 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) | 1391 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) |
1392 .StoreAccumulatorInRegister(prototype); | 1392 .StoreAccumulatorInRegister(prototype); |
1393 | 1393 |
1394 VisitClassLiteralProperties(expr, literal, prototype); | 1394 Register needs_name = args[2]; |
rmcilroy
2016/11/28 10:28:59
This shouldn't be allocated in the same RegisterLi
| |
1395 VisitClassLiteralProperties(expr, literal, prototype, needs_name); | |
1396 BuildClassLiteralNameProperty(expr, literal, needs_name); | |
1395 builder()->CallRuntime(Runtime::kToFastProperties, literal); | 1397 builder()->CallRuntime(Runtime::kToFastProperties, literal); |
1396 // Assign to class variable. | 1398 // Assign to class variable. |
1397 if (expr->class_variable_proxy() != nullptr) { | 1399 if (expr->class_variable_proxy() != nullptr) { |
1398 Variable* var = expr->class_variable_proxy()->var(); | 1400 Variable* var = expr->class_variable_proxy()->var(); |
1399 FeedbackVectorSlot slot = expr->NeedsProxySlot() | 1401 FeedbackVectorSlot slot = expr->NeedsProxySlot() |
1400 ? expr->ProxySlot() | 1402 ? expr->ProxySlot() |
1401 : FeedbackVectorSlot::Invalid(); | 1403 : FeedbackVectorSlot::Invalid(); |
1402 VisitVariableAssignment(var, Token::INIT, slot); | 1404 VisitVariableAssignment(var, Token::INIT, slot); |
1403 } | 1405 } |
1404 } | 1406 } |
1405 | 1407 |
1406 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( | 1408 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( |
1407 ClassLiteral* expr) { | 1409 ClassLiteral* expr) { |
1408 RegisterAllocationScope register_scope(this); | 1410 RegisterAllocationScope register_scope(this); |
1409 RegisterList args = register_allocator()->NewRegisterList(4); | 1411 RegisterList args = register_allocator()->NewRegisterList(4); |
1410 VisitForAccumulatorValueOrTheHole(expr->extends()); | 1412 VisitForAccumulatorValueOrTheHole(expr->extends()); |
1411 builder()->StoreAccumulatorInRegister(args[0]); | 1413 builder()->StoreAccumulatorInRegister(args[0]); |
1412 VisitForRegisterValue(expr->constructor(), args[1]); | 1414 VisitForRegisterValue(expr->constructor(), args[1]); |
1413 builder() | 1415 builder() |
1414 ->LoadLiteral(Smi::FromInt(expr->start_position())) | 1416 ->LoadLiteral(Smi::FromInt(expr->start_position())) |
1415 .StoreAccumulatorInRegister(args[2]) | 1417 .StoreAccumulatorInRegister(args[2]) |
1416 .LoadLiteral(Smi::FromInt(expr->end_position())) | 1418 .LoadLiteral(Smi::FromInt(expr->end_position())) |
1417 .StoreAccumulatorInRegister(args[3]) | 1419 .StoreAccumulatorInRegister(args[3]) |
1418 .CallRuntime(Runtime::kDefineClass, args); | 1420 .CallRuntime(Runtime::kDefineClass, args); |
1419 } | 1421 } |
1420 | 1422 |
1421 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, | 1423 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, |
1422 Register literal, | 1424 Register literal, |
1423 Register prototype) { | 1425 Register prototype, |
1426 Register needs_name) { | |
1424 RegisterAllocationScope register_scope(this); | 1427 RegisterAllocationScope register_scope(this); |
1425 RegisterList args = register_allocator()->NewRegisterList(5); | 1428 RegisterList args = register_allocator()->NewRegisterList(5); |
1426 Register receiver = args[0], key = args[1], value = args[2], attr = args[3], | 1429 Register receiver = args[0], key = args[1], value = args[2], attr = args[3], |
1427 set_function_name = args[4]; | 1430 set_function_name = args[4]; |
1428 | 1431 |
1429 bool attr_assigned = false; | 1432 bool attr_assigned = false; |
1430 Register old_receiver = Register::invalid_value(); | 1433 Register old_receiver = Register::invalid_value(); |
1431 | 1434 |
1435 // Initialize has_name_static_property. | |
1436 bool check_name = !expr->has_name_static_property() && | |
Toon Verwaest
2016/11/28 10:40:58
Isn't the general case that we don't have a static
| |
1437 !expr->constructor()->raw_name()->IsEmpty(); | |
1438 if (check_name) { | |
1439 builder()->LoadTrue().StoreAccumulatorInRegister(needs_name); | |
1440 } | |
1441 | |
1432 // Create nodes to store method values into the literal. | 1442 // Create nodes to store method values into the literal. |
1433 for (int i = 0; i < expr->properties()->length(); i++) { | 1443 for (int i = 0; i < expr->properties()->length(); i++) { |
1434 ClassLiteral::Property* property = expr->properties()->at(i); | 1444 ClassLiteral::Property* property = expr->properties()->at(i); |
1435 | 1445 |
1436 // Set-up receiver. | 1446 // Set-up receiver. |
1437 Register new_receiver = property->is_static() ? literal : prototype; | 1447 Register new_receiver = property->is_static() ? literal : prototype; |
1438 if (new_receiver != old_receiver) { | 1448 if (new_receiver != old_receiver) { |
1439 builder()->MoveRegister(new_receiver, receiver); | 1449 builder()->MoveRegister(new_receiver, receiver); |
1440 old_receiver = new_receiver; | 1450 old_receiver = new_receiver; |
1441 } | 1451 } |
1442 | 1452 |
1443 VisitForAccumulatorValue(property->key()); | 1453 VisitForAccumulatorValue(property->key()); |
1444 builder()->ConvertAccumulatorToName(key); | 1454 builder()->ConvertAccumulatorToName(key); |
1445 | 1455 |
1446 if (property->is_static() && property->is_computed_name()) { | 1456 if (property->is_static() && property->is_computed_name()) { |
1457 // Check for a static property called "name". | |
1458 if (check_name) { | |
1459 BytecodeLabel has_name; | |
1460 builder() | |
1461 ->LoadAccumulatorWithRegister(needs_name) | |
1462 .JumpIfFalse(&has_name) | |
1463 .LoadLiteral(name_string()) | |
1464 .CompareOperation(Token::Value::EQ_STRICT, key) | |
1465 .LogicalNot() | |
1466 .StoreAccumulatorInRegister(needs_name) | |
1467 .Bind(&has_name); | |
1468 } | |
rmcilroy
2016/11/28 10:28:59
I'm not keen on this extra code added to every pro
Toon Verwaest
2016/11/28 10:40:58
I agree, we should just do something more expensiv
| |
1469 | |
1447 // The static prototype property is read only. We handle the non computed | 1470 // The static prototype property is read only. We handle the non computed |
1448 // property name case in the parser. Since this is the only case where we | 1471 // property name case in the parser. Since this is the only case where we |
1449 // need to check for an own read only property we special case this so we | 1472 // need to check for an own read only property we special case this so we |
1450 // do not need to do this for every property. | 1473 // do not need to do this for every property. |
1451 BytecodeLabel done; | 1474 BytecodeLabel done; |
1452 builder() | 1475 builder() |
1453 ->LoadLiteral(prototype_string()) | 1476 ->LoadLiteral(prototype_string()) |
1454 .CompareOperation(Token::Value::EQ_STRICT, key) | 1477 .CompareOperation(Token::Value::EQ_STRICT, key) |
1455 .JumpIfFalse(&done) | 1478 .JumpIfFalse(&done) |
1456 .CallRuntime(Runtime::kThrowStaticPrototypeError) | 1479 .CallRuntime(Runtime::kThrowStaticPrototypeError) |
(...skipping 29 matching lines...) Expand all Loading... | |
1486 break; | 1509 break; |
1487 } | 1510 } |
1488 case ClassLiteral::Property::FIELD: { | 1511 case ClassLiteral::Property::FIELD: { |
1489 UNREACHABLE(); | 1512 UNREACHABLE(); |
1490 break; | 1513 break; |
1491 } | 1514 } |
1492 } | 1515 } |
1493 } | 1516 } |
1494 } | 1517 } |
1495 | 1518 |
1519 void BytecodeGenerator::BuildClassLiteralNameProperty(ClassLiteral* expr, | |
1520 Register literal, | |
1521 Register needs_name) { | |
1522 bool check_name = !expr->has_name_static_property() && | |
1523 !expr->constructor()->raw_name()->IsEmpty(); | |
1524 if (check_name) { | |
1525 BytecodeLabel has_name; | |
1526 builder() | |
1527 ->LoadAccumulatorWithRegister(needs_name) | |
1528 .JumpIfFalse(&has_name) | |
1529 .CallRuntime(Runtime::kInstallClassNameAccessor, literal) | |
1530 .Bind(&has_name); | |
1531 } | |
1532 } | |
1533 | |
1496 void BytecodeGenerator::VisitNativeFunctionLiteral( | 1534 void BytecodeGenerator::VisitNativeFunctionLiteral( |
1497 NativeFunctionLiteral* expr) { | 1535 NativeFunctionLiteral* expr) { |
1498 size_t entry = builder()->AllocateConstantPoolEntry(); | 1536 size_t entry = builder()->AllocateConstantPoolEntry(); |
1499 builder()->CreateClosure(entry, NOT_TENURED); | 1537 builder()->CreateClosure(entry, NOT_TENURED); |
1500 native_function_literals_.push_back(std::make_pair(expr, entry)); | 1538 native_function_literals_.push_back(std::make_pair(expr, entry)); |
1501 } | 1539 } |
1502 | 1540 |
1503 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { | 1541 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { |
1504 VisitBlock(expr->block()); | 1542 VisitBlock(expr->block()); |
1505 VisitVariableProxy(expr->result()); | 1543 VisitVariableProxy(expr->result()); |
(...skipping 1681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3187 } | 3225 } |
3188 | 3226 |
3189 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3227 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
3190 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3228 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
3191 : Runtime::kStoreKeyedToSuper_Sloppy; | 3229 : Runtime::kStoreKeyedToSuper_Sloppy; |
3192 } | 3230 } |
3193 | 3231 |
3194 } // namespace interpreter | 3232 } // namespace interpreter |
3195 } // namespace internal | 3233 } // namespace internal |
3196 } // namespace v8 | 3234 } // namespace v8 |
OLD | NEW |