Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1350 } | 1350 } |
| 1351 case ObjectLiteral::Property::SETTER: { | 1351 case ObjectLiteral::Property::SETTER: { |
| 1352 Node* attr = jsgraph()->Constant(DONT_ENUM); | 1352 Node* attr = jsgraph()->Constant(DONT_ENUM); |
| 1353 const Operator* op = javascript()->CallRuntime( | 1353 const Operator* op = javascript()->CallRuntime( |
| 1354 Runtime::kDefineSetterPropertyUnchecked, 4); | 1354 Runtime::kDefineSetterPropertyUnchecked, 4); |
| 1355 NewNode(op, receiver, key, value, attr); | 1355 NewNode(op, receiver, key, value, attr); |
| 1356 break; | 1356 break; |
| 1357 } | 1357 } |
| 1358 } | 1358 } |
| 1359 | 1359 |
| 1360 // TODO(mstarzinger): This is temporary to make "super" work and replicates | 1360 AddHomeObjectIfNeeded(property->value(), value, receiver); |
| 1361 // the existing FullCodeGenerator::NeedsHomeObject predicate. | |
| 1362 if (FunctionLiteral::NeedsHomeObject(property->value())) { | |
| 1363 Unique<Name> name = | |
| 1364 MakeUnique(isolate()->factory()->home_object_symbol()); | |
| 1365 Node* store = NewNode(javascript()->StoreNamed(language_mode(), name), | |
| 1366 value, receiver); | |
| 1367 PrepareFrameState(store, BailoutId::None()); | |
| 1368 } | |
| 1369 } | 1361 } |
| 1370 | 1362 |
| 1371 // Transform both the class literal and the prototype to fast properties. | 1363 // Transform both the class literal and the prototype to fast properties. |
| 1372 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1); | 1364 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1); |
| 1373 NewNode(op, environment()->Pop()); // prototype | 1365 NewNode(op, environment()->Pop()); // prototype |
| 1374 NewNode(op, environment()->Pop()); // literal | 1366 NewNode(op, environment()->Pop()); // literal |
| 1375 | 1367 |
| 1376 // Assign to class variable. | 1368 // Assign to class variable. |
| 1377 if (expr->scope() != NULL) { | 1369 if (expr->scope() != NULL) { |
| 1378 DCHECK_NOT_NULL(expr->class_variable_proxy()); | 1370 DCHECK_NOT_NULL(expr->class_variable_proxy()); |
| 1379 Variable* var = expr->class_variable_proxy()->var(); | 1371 Variable* var = expr->class_variable_proxy()->var(); |
| 1380 BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None()); | 1372 BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None()); |
| 1381 } | 1373 } |
| 1382 | 1374 |
| 1383 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine()); | 1375 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine()); |
| 1384 ast_context()->ProduceValue(literal); | 1376 ast_context()->ProduceValue(literal); |
| 1385 } | 1377 } |
| 1386 | 1378 |
| 1387 | 1379 |
| 1380 void AstGraphBuilder::AddHomeObjectIfNeeded(Expression* expr, Node* function, | |
| 1381 Node* home_object) { | |
| 1382 if (FunctionLiteral::NeedsHomeObject(expr)) { | |
| 1383 Unique<Name> name = MakeUnique(isolate()->factory()->home_object_symbol()); | |
| 1384 Node* store = NewNode(javascript()->StoreNamed(language_mode(), name), | |
| 1385 function, home_object); | |
| 1386 PrepareFrameState(store, BailoutId::None()); | |
| 1387 } | |
| 1388 } | |
| 1389 | |
| 1390 | |
| 1388 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 1391 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 1389 UNREACHABLE(); | 1392 UNREACHABLE(); |
| 1390 } | 1393 } |
| 1391 | 1394 |
| 1392 | 1395 |
| 1393 void AstGraphBuilder::VisitConditional(Conditional* expr) { | 1396 void AstGraphBuilder::VisitConditional(Conditional* expr) { |
| 1394 IfBuilder compare_if(this); | 1397 IfBuilder compare_if(this); |
| 1395 VisitForTest(expr->condition()); | 1398 VisitForTest(expr->condition()); |
| 1396 Node* condition = environment()->Pop(); | 1399 Node* condition = environment()->Pop(); |
| 1397 compare_if.If(condition); | 1400 compare_if.If(condition); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1479 // contains computed properties with an uninitialized value. | 1482 // contains computed properties with an uninitialized value. |
| 1480 if (key->value()->IsInternalizedString()) { | 1483 if (key->value()->IsInternalizedString()) { |
| 1481 if (property->emit_store()) { | 1484 if (property->emit_store()) { |
| 1482 VisitForValue(property->value()); | 1485 VisitForValue(property->value()); |
| 1483 Node* value = environment()->Pop(); | 1486 Node* value = environment()->Pop(); |
| 1484 Unique<Name> name = MakeUnique(key->AsPropertyName()); | 1487 Unique<Name> name = MakeUnique(key->AsPropertyName()); |
| 1485 Node* store = | 1488 Node* store = |
| 1486 NewNode(javascript()->StoreNamed(language_mode(), name), | 1489 NewNode(javascript()->StoreNamed(language_mode(), name), |
| 1487 literal, value); | 1490 literal, value); |
| 1488 PrepareFrameState(store, key->id()); | 1491 PrepareFrameState(store, key->id()); |
| 1492 | |
| 1493 AddHomeObjectIfNeeded(property->value(), value, literal); | |
| 1489 } else { | 1494 } else { |
| 1490 VisitForEffect(property->value()); | 1495 VisitForEffect(property->value()); |
| 1491 } | 1496 } |
| 1492 break; | 1497 break; |
| 1493 } | 1498 } |
| 1494 environment()->Push(literal); // Duplicate receiver. | 1499 environment()->Push(literal); // Duplicate receiver. |
| 1495 VisitForValue(property->key()); | 1500 VisitForValue(property->key()); |
| 1496 VisitForValue(property->value()); | 1501 VisitForValue(property->value()); |
| 1497 Node* value = environment()->Pop(); | 1502 Node* value = environment()->Pop(); |
| 1498 Node* key = environment()->Pop(); | 1503 Node* key = environment()->Pop(); |
| 1499 Node* receiver = environment()->Pop(); | 1504 Node* receiver = environment()->Pop(); |
| 1500 if (property->emit_store()) { | 1505 if (property->emit_store()) { |
| 1501 Node* language = jsgraph()->Constant(SLOPPY); | 1506 Node* language = jsgraph()->Constant(SLOPPY); |
| 1502 const Operator* op = | 1507 const Operator* op = |
| 1503 javascript()->CallRuntime(Runtime::kSetProperty, 4); | 1508 javascript()->CallRuntime(Runtime::kSetProperty, 4); |
| 1504 NewNode(op, receiver, key, value, language); | 1509 NewNode(op, receiver, key, value, language); |
| 1510 | |
| 1511 AddHomeObjectIfNeeded(property->value(), value, receiver); | |
| 1505 } | 1512 } |
| 1506 break; | 1513 break; |
| 1507 } | 1514 } |
| 1508 case ObjectLiteral::Property::PROTOTYPE: { | 1515 case ObjectLiteral::Property::PROTOTYPE: { |
| 1509 environment()->Push(literal); // Duplicate receiver. | 1516 environment()->Push(literal); // Duplicate receiver. |
| 1510 VisitForValue(property->value()); | 1517 VisitForValue(property->value()); |
| 1511 Node* value = environment()->Pop(); | 1518 Node* value = environment()->Pop(); |
| 1512 Node* receiver = environment()->Pop(); | 1519 Node* receiver = environment()->Pop(); |
| 1513 DCHECK(property->emit_store()); | 1520 DCHECK(property->emit_store()); |
| 1514 const Operator* op = | 1521 const Operator* op = |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1530 break; | 1537 break; |
| 1531 } | 1538 } |
| 1532 } | 1539 } |
| 1533 | 1540 |
| 1534 // Create nodes to define accessors, using only a single call to the runtime | 1541 // Create nodes to define accessors, using only a single call to the runtime |
| 1535 // for each pair of corresponding getters and setters. | 1542 // for each pair of corresponding getters and setters. |
| 1536 for (AccessorTable::Iterator it = accessor_table.begin(); | 1543 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1537 it != accessor_table.end(); ++it) { | 1544 it != accessor_table.end(); ++it) { |
| 1538 VisitForValue(it->first); | 1545 VisitForValue(it->first); |
| 1539 VisitForValueOrNull(it->second->getter); | 1546 VisitForValueOrNull(it->second->getter); |
| 1540 VisitForValueOrNull(it->second->setter); | 1547 VisitForValueOrNull(it->second->setter); |
|
Michael Starzinger
2015/02/16 18:36:01
If we ever deoptimize while evaluating the setter
| |
| 1541 Node* setter = environment()->Pop(); | 1548 Node* setter = environment()->Pop(); |
| 1542 Node* getter = environment()->Pop(); | 1549 Node* getter = environment()->Pop(); |
| 1543 Node* name = environment()->Pop(); | 1550 Node* name = environment()->Pop(); |
| 1551 AddHomeObjectIfNeeded(it->second->getter, getter, literal); | |
| 1552 AddHomeObjectIfNeeded(it->second->setter, setter, literal); | |
| 1544 Node* attr = jsgraph()->Constant(NONE); | 1553 Node* attr = jsgraph()->Constant(NONE); |
| 1545 const Operator* op = | 1554 const Operator* op = |
| 1546 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1555 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
| 1547 Node* call = NewNode(op, literal, name, getter, setter, attr); | 1556 Node* call = NewNode(op, literal, name, getter, setter, attr); |
| 1548 // This should not lazy deopt on a new literal. | 1557 // This should not lazy deopt on a new literal. |
| 1549 PrepareFrameState(call, BailoutId::None()); | 1558 PrepareFrameState(call, BailoutId::None()); |
| 1550 } | 1559 } |
| 1551 | 1560 |
| 1552 // Object literals have two parts. The "static" part on the left contains no | 1561 // Object literals have two parts. The "static" part on the left contains no |
| 1553 // computed property names, and so we can compute its map ahead of time; see | 1562 // computed property names, and so we can compute its map ahead of time; see |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1566 environment()->Push(BuildToName(environment()->Pop(), | 1575 environment()->Push(BuildToName(environment()->Pop(), |
| 1567 expr->GetIdForProperty(property_index))); | 1576 expr->GetIdForProperty(property_index))); |
| 1568 // TODO(mstarzinger): For ObjectLiteral::Property::PROTOTYPE the key should | 1577 // TODO(mstarzinger): For ObjectLiteral::Property::PROTOTYPE the key should |
| 1569 // not be on the operand stack while the value is being evaluated. Come up | 1578 // not be on the operand stack while the value is being evaluated. Come up |
| 1570 // with a repro for this and fix it. Also find a nice way to do so. :) | 1579 // with a repro for this and fix it. Also find a nice way to do so. :) |
| 1571 VisitForValue(property->value()); | 1580 VisitForValue(property->value()); |
| 1572 Node* value = environment()->Pop(); | 1581 Node* value = environment()->Pop(); |
| 1573 Node* key = environment()->Pop(); | 1582 Node* key = environment()->Pop(); |
| 1574 Node* receiver = environment()->Pop(); | 1583 Node* receiver = environment()->Pop(); |
| 1575 | 1584 |
| 1585 AddHomeObjectIfNeeded(property->value(), value, receiver); | |
| 1586 | |
| 1576 switch (property->kind()) { | 1587 switch (property->kind()) { |
| 1577 case ObjectLiteral::Property::CONSTANT: | 1588 case ObjectLiteral::Property::CONSTANT: |
| 1578 case ObjectLiteral::Property::COMPUTED: | 1589 case ObjectLiteral::Property::COMPUTED: |
| 1579 case ObjectLiteral::Property::MATERIALIZED_LITERAL: { | 1590 case ObjectLiteral::Property::MATERIALIZED_LITERAL: { |
| 1580 Node* attr = jsgraph()->Constant(NONE); | 1591 Node* attr = jsgraph()->Constant(NONE); |
| 1581 const Operator* op = | 1592 const Operator* op = |
| 1582 javascript()->CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); | 1593 javascript()->CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); |
| 1583 Node* call = NewNode(op, receiver, key, value, attr); | 1594 Node* call = NewNode(op, receiver, key, value, attr); |
| 1584 PrepareFrameState(call, BailoutId::None()); | 1595 PrepareFrameState(call, BailoutId::None()); |
| 1585 break; | 1596 break; |
| (...skipping 1545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3131 Node* dead_node = graph()->NewNode(common()->Dead()); | 3142 Node* dead_node = graph()->NewNode(common()->Dead()); |
| 3132 dead_control_.set(dead_node); | 3143 dead_control_.set(dead_node); |
| 3133 return dead_node; | 3144 return dead_node; |
| 3134 } | 3145 } |
| 3135 return dead_control_.get(); | 3146 return dead_control_.get(); |
| 3136 } | 3147 } |
| 3137 | 3148 |
| 3138 } // namespace compiler | 3149 } // namespace compiler |
| 3139 } // namespace internal | 3150 } // namespace internal |
| 3140 } // namespace v8 | 3151 } // namespace v8 |
| OLD | NEW |