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

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

Issue 2423053002: Install the 'name' property in classes at runtime (Closed)
Patch Set: Check for 'name' properties at parse-time Created 4 years 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/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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698