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 1327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1338 ObjectLiteral::Property* property = expr->properties()->at(i); | 1338 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 1339 environment()->Push(property->is_static() ? literal : proto); | 1339 environment()->Push(property->is_static() ? literal : proto); |
| 1340 | 1340 |
| 1341 VisitForValue(property->key()); | 1341 VisitForValue(property->key()); |
| 1342 environment()->Push( | 1342 environment()->Push( |
| 1343 BuildToName(environment()->Pop(), expr->GetIdForProperty(i))); | 1343 BuildToName(environment()->Pop(), expr->GetIdForProperty(i))); |
| 1344 VisitForValue(property->value()); | 1344 VisitForValue(property->value()); |
| 1345 Node* value = environment()->Pop(); | 1345 Node* value = environment()->Pop(); |
| 1346 Node* key = environment()->Pop(); | 1346 Node* key = environment()->Pop(); |
| 1347 Node* receiver = environment()->Pop(); | 1347 Node* receiver = environment()->Pop(); |
| 1348 BuildSetHomeObject(value, receiver, property->value()); | |
| 1349 | |
| 1348 switch (property->kind()) { | 1350 switch (property->kind()) { |
| 1349 case ObjectLiteral::Property::CONSTANT: | 1351 case ObjectLiteral::Property::CONSTANT: |
| 1350 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1352 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1351 case ObjectLiteral::Property::PROTOTYPE: | 1353 case ObjectLiteral::Property::PROTOTYPE: |
| 1352 UNREACHABLE(); | 1354 UNREACHABLE(); |
| 1353 case ObjectLiteral::Property::COMPUTED: { | 1355 case ObjectLiteral::Property::COMPUTED: { |
| 1354 const Operator* op = | 1356 const Operator* op = |
| 1355 javascript()->CallRuntime(Runtime::kDefineClassMethod, 3); | 1357 javascript()->CallRuntime(Runtime::kDefineClassMethod, 3); |
| 1356 NewNode(op, receiver, key, value); | 1358 NewNode(op, receiver, key, value); |
| 1357 break; | 1359 break; |
| 1358 } | 1360 } |
| 1359 case ObjectLiteral::Property::GETTER: { | 1361 case ObjectLiteral::Property::GETTER: { |
| 1360 Node* attr = jsgraph()->Constant(DONT_ENUM); | 1362 Node* attr = jsgraph()->Constant(DONT_ENUM); |
| 1361 const Operator* op = javascript()->CallRuntime( | 1363 const Operator* op = javascript()->CallRuntime( |
| 1362 Runtime::kDefineGetterPropertyUnchecked, 4); | 1364 Runtime::kDefineGetterPropertyUnchecked, 4); |
| 1363 NewNode(op, receiver, key, value, attr); | 1365 NewNode(op, receiver, key, value, attr); |
| 1364 break; | 1366 break; |
| 1365 } | 1367 } |
| 1366 case ObjectLiteral::Property::SETTER: { | 1368 case ObjectLiteral::Property::SETTER: { |
| 1367 Node* attr = jsgraph()->Constant(DONT_ENUM); | 1369 Node* attr = jsgraph()->Constant(DONT_ENUM); |
| 1368 const Operator* op = javascript()->CallRuntime( | 1370 const Operator* op = javascript()->CallRuntime( |
| 1369 Runtime::kDefineSetterPropertyUnchecked, 4); | 1371 Runtime::kDefineSetterPropertyUnchecked, 4); |
| 1370 NewNode(op, receiver, key, value, attr); | 1372 NewNode(op, receiver, key, value, attr); |
| 1371 break; | 1373 break; |
| 1372 } | 1374 } |
| 1373 } | 1375 } |
| 1374 | |
| 1375 AddHomeObjectIfNeeded(property->value(), value, receiver); | |
| 1376 } | 1376 } |
| 1377 | 1377 |
| 1378 // Transform both the class literal and the prototype to fast properties. | 1378 // Transform both the class literal and the prototype to fast properties. |
| 1379 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1); | 1379 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1); |
| 1380 NewNode(op, environment()->Pop()); // prototype | 1380 NewNode(op, environment()->Pop()); // prototype |
| 1381 NewNode(op, environment()->Pop()); // literal | 1381 NewNode(op, environment()->Pop()); // literal |
| 1382 | 1382 |
| 1383 // Assign to class variable. | 1383 // Assign to class variable. |
| 1384 if (expr->scope() != NULL) { | 1384 if (expr->scope() != NULL) { |
| 1385 DCHECK_NOT_NULL(expr->class_variable_proxy()); | 1385 DCHECK_NOT_NULL(expr->class_variable_proxy()); |
| 1386 Variable* var = expr->class_variable_proxy()->var(); | 1386 Variable* var = expr->class_variable_proxy()->var(); |
| 1387 BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None()); | 1387 BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None()); |
| 1388 } | 1388 } |
| 1389 | 1389 |
| 1390 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine()); | 1390 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine()); |
| 1391 ast_context()->ProduceValue(literal); | 1391 ast_context()->ProduceValue(literal); |
| 1392 } | 1392 } |
| 1393 | 1393 |
| 1394 | 1394 |
| 1395 void AstGraphBuilder::AddHomeObjectIfNeeded(Expression* expr, Node* function, | |
| 1396 Node* home_object) { | |
| 1397 if (FunctionLiteral::NeedsHomeObject(expr)) { | |
| 1398 Unique<Name> name = MakeUnique(isolate()->factory()->home_object_symbol()); | |
| 1399 Node* store = NewNode(javascript()->StoreNamed(language_mode(), name), | |
| 1400 function, home_object); | |
| 1401 PrepareFrameState(store, BailoutId::None()); | |
| 1402 } | |
| 1403 } | |
| 1404 | |
| 1405 | |
| 1406 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 1395 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 1407 UNREACHABLE(); | 1396 UNREACHABLE(); |
| 1408 } | 1397 } |
| 1409 | 1398 |
| 1410 | 1399 |
| 1411 void AstGraphBuilder::VisitConditional(Conditional* expr) { | 1400 void AstGraphBuilder::VisitConditional(Conditional* expr) { |
| 1412 IfBuilder compare_if(this); | 1401 IfBuilder compare_if(this); |
| 1413 VisitForTest(expr->condition()); | 1402 VisitForTest(expr->condition()); |
| 1414 Node* condition = environment()->Pop(); | 1403 Node* condition = environment()->Pop(); |
| 1415 compare_if.If(condition); | 1404 compare_if.If(condition); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1497 // contains computed properties with an uninitialized value. | 1486 // contains computed properties with an uninitialized value. |
| 1498 if (key->value()->IsInternalizedString()) { | 1487 if (key->value()->IsInternalizedString()) { |
| 1499 if (property->emit_store()) { | 1488 if (property->emit_store()) { |
| 1500 VisitForValue(property->value()); | 1489 VisitForValue(property->value()); |
| 1501 Node* value = environment()->Pop(); | 1490 Node* value = environment()->Pop(); |
| 1502 Unique<Name> name = MakeUnique(key->AsPropertyName()); | 1491 Unique<Name> name = MakeUnique(key->AsPropertyName()); |
| 1503 Node* store = | 1492 Node* store = |
| 1504 NewNode(javascript()->StoreNamed(language_mode(), name), | 1493 NewNode(javascript()->StoreNamed(language_mode(), name), |
| 1505 literal, value); | 1494 literal, value); |
| 1506 PrepareFrameState(store, key->id()); | 1495 PrepareFrameState(store, key->id()); |
| 1507 | 1496 BuildSetHomeObject(value, literal, property->value()); |
| 1508 AddHomeObjectIfNeeded(property->value(), value, literal); | |
| 1509 } else { | 1497 } else { |
| 1510 VisitForEffect(property->value()); | 1498 VisitForEffect(property->value()); |
| 1511 } | 1499 } |
| 1512 break; | 1500 break; |
| 1513 } | 1501 } |
| 1514 environment()->Push(literal); // Duplicate receiver. | 1502 environment()->Push(literal); // Duplicate receiver. |
| 1515 VisitForValue(property->key()); | 1503 VisitForValue(property->key()); |
| 1516 VisitForValue(property->value()); | 1504 VisitForValue(property->value()); |
| 1517 Node* value = environment()->Pop(); | 1505 Node* value = environment()->Pop(); |
| 1518 Node* key = environment()->Pop(); | 1506 Node* key = environment()->Pop(); |
| 1519 Node* receiver = environment()->Pop(); | 1507 Node* receiver = environment()->Pop(); |
| 1520 if (property->emit_store()) { | 1508 if (property->emit_store()) { |
| 1521 Node* language = jsgraph()->Constant(SLOPPY); | 1509 Node* language = jsgraph()->Constant(SLOPPY); |
| 1522 const Operator* op = | 1510 const Operator* op = |
| 1523 javascript()->CallRuntime(Runtime::kSetProperty, 4); | 1511 javascript()->CallRuntime(Runtime::kSetProperty, 4); |
| 1524 NewNode(op, receiver, key, value, language); | 1512 NewNode(op, receiver, key, value, language); |
| 1525 | 1513 BuildSetHomeObject(value, receiver, property->value()); |
| 1526 AddHomeObjectIfNeeded(property->value(), value, receiver); | |
| 1527 } | 1514 } |
| 1528 break; | 1515 break; |
| 1529 } | 1516 } |
| 1530 case ObjectLiteral::Property::PROTOTYPE: { | 1517 case ObjectLiteral::Property::PROTOTYPE: { |
| 1531 environment()->Push(literal); // Duplicate receiver. | 1518 environment()->Push(literal); // Duplicate receiver. |
| 1532 VisitForValue(property->value()); | 1519 VisitForValue(property->value()); |
| 1533 Node* value = environment()->Pop(); | 1520 Node* value = environment()->Pop(); |
| 1534 Node* receiver = environment()->Pop(); | 1521 Node* receiver = environment()->Pop(); |
| 1535 DCHECK(property->emit_store()); | 1522 DCHECK(property->emit_store()); |
| 1536 const Operator* op = | 1523 const Operator* op = |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1552 break; | 1539 break; |
| 1553 } | 1540 } |
| 1554 } | 1541 } |
| 1555 | 1542 |
| 1556 // Create nodes to define accessors, using only a single call to the runtime | 1543 // Create nodes to define accessors, using only a single call to the runtime |
| 1557 // for each pair of corresponding getters and setters. | 1544 // for each pair of corresponding getters and setters. |
| 1558 for (AccessorTable::Iterator it = accessor_table.begin(); | 1545 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1559 it != accessor_table.end(); ++it) { | 1546 it != accessor_table.end(); ++it) { |
| 1560 VisitForValue(it->first); | 1547 VisitForValue(it->first); |
| 1561 VisitForValueOrNull(it->second->getter); | 1548 VisitForValueOrNull(it->second->getter); |
| 1549 BuildSetHomeObject(environment()->Top(), literal, it->second->getter); | |
| 1562 VisitForValueOrNull(it->second->setter); | 1550 VisitForValueOrNull(it->second->setter); |
| 1551 BuildSetHomeObject(environment()->Top(), literal, it->second->setter); | |
| 1563 Node* setter = environment()->Pop(); | 1552 Node* setter = environment()->Pop(); |
| 1564 Node* getter = environment()->Pop(); | 1553 Node* getter = environment()->Pop(); |
| 1565 Node* name = environment()->Pop(); | 1554 Node* name = environment()->Pop(); |
| 1566 AddHomeObjectIfNeeded(it->second->getter, getter, literal); | |
| 1567 AddHomeObjectIfNeeded(it->second->setter, setter, literal); | |
| 1568 Node* attr = jsgraph()->Constant(NONE); | 1555 Node* attr = jsgraph()->Constant(NONE); |
| 1569 const Operator* op = | 1556 const Operator* op = |
| 1570 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1557 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
| 1571 Node* call = NewNode(op, literal, name, getter, setter, attr); | 1558 Node* call = NewNode(op, literal, name, getter, setter, attr); |
| 1572 // This should not lazy deopt on a new literal. | 1559 // This should not lazy deopt on a new literal. |
| 1573 PrepareFrameState(call, BailoutId::None()); | 1560 PrepareFrameState(call, BailoutId::None()); |
| 1574 } | 1561 } |
| 1575 | 1562 |
| 1576 // Object literals have two parts. The "static" part on the left contains no | 1563 // Object literals have two parts. The "static" part on the left contains no |
| 1577 // computed property names, and so we can compute its map ahead of time; see | 1564 // computed property names, and so we can compute its map ahead of time; see |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1589 VisitForValue(property->key()); | 1576 VisitForValue(property->key()); |
| 1590 environment()->Push(BuildToName(environment()->Pop(), | 1577 environment()->Push(BuildToName(environment()->Pop(), |
| 1591 expr->GetIdForProperty(property_index))); | 1578 expr->GetIdForProperty(property_index))); |
| 1592 // TODO(mstarzinger): For ObjectLiteral::Property::PROTOTYPE the key should | 1579 // TODO(mstarzinger): For ObjectLiteral::Property::PROTOTYPE the key should |
| 1593 // not be on the operand stack while the value is being evaluated. Come up | 1580 // not be on the operand stack while the value is being evaluated. Come up |
| 1594 // with a repro for this and fix it. Also find a nice way to do so. :) | 1581 // with a repro for this and fix it. Also find a nice way to do so. :) |
| 1595 VisitForValue(property->value()); | 1582 VisitForValue(property->value()); |
| 1596 Node* value = environment()->Pop(); | 1583 Node* value = environment()->Pop(); |
| 1597 Node* key = environment()->Pop(); | 1584 Node* key = environment()->Pop(); |
| 1598 Node* receiver = environment()->Pop(); | 1585 Node* receiver = environment()->Pop(); |
| 1599 | 1586 BuildSetHomeObject(value, receiver, property->value()); |
| 1600 AddHomeObjectIfNeeded(property->value(), value, receiver); | |
| 1601 | 1587 |
| 1602 switch (property->kind()) { | 1588 switch (property->kind()) { |
| 1603 case ObjectLiteral::Property::CONSTANT: | 1589 case ObjectLiteral::Property::CONSTANT: |
| 1604 case ObjectLiteral::Property::COMPUTED: | 1590 case ObjectLiteral::Property::COMPUTED: |
| 1605 case ObjectLiteral::Property::MATERIALIZED_LITERAL: { | 1591 case ObjectLiteral::Property::MATERIALIZED_LITERAL: { |
| 1606 Node* attr = jsgraph()->Constant(NONE); | 1592 Node* attr = jsgraph()->Constant(NONE); |
| 1607 const Operator* op = | 1593 const Operator* op = |
| 1608 javascript()->CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); | 1594 javascript()->CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); |
| 1609 Node* call = NewNode(op, receiver, key, value, attr); | 1595 Node* call = NewNode(op, receiver, key, value, attr); |
| 1610 PrepareFrameState(call, BailoutId::None()); | 1596 PrepareFrameState(call, BailoutId::None()); |
| (...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2807 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) { | 2793 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) { |
| 2808 // TODO(turbofan): Possible optimization is to NOP on name constants. But the | 2794 // TODO(turbofan): Possible optimization is to NOP on name constants. But the |
| 2809 // same caveat as with BuildToBoolean applies, and it should be factored out | 2795 // same caveat as with BuildToBoolean applies, and it should be factored out |
| 2810 // into a JSOperatorReducer. | 2796 // into a JSOperatorReducer. |
| 2811 Node* name = NewNode(javascript()->ToName(), input); | 2797 Node* name = NewNode(javascript()->ToName(), input); |
| 2812 PrepareFrameState(name, bailout_id); | 2798 PrepareFrameState(name, bailout_id); |
| 2813 return name; | 2799 return name; |
| 2814 } | 2800 } |
| 2815 | 2801 |
| 2816 | 2802 |
| 2803 Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object, | |
| 2804 Expression* expr) { | |
| 2805 if (!FunctionLiteral::NeedsHomeObject(expr)) return value; | |
| 2806 Unique<Name> name = MakeUnique(isolate()->factory()->home_object_symbol()); | |
| 2807 const Operator* op = javascript()->StoreNamed(language_mode(), name); | |
| 2808 Node* store = NewNode(op, value, home_object); | |
| 2809 PrepareFrameState(store, BailoutId::None()); | |
| 2810 return store; | |
|
arv (Not doing code reviews)
2015/02/16 20:09:56
What is the return value used for here?
Michael Starzinger
2015/02/16 20:30:35
It's not used, but for symmetry all builder method
| |
| 2811 } | |
| 2812 | |
| 2813 | |
| 2817 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable, | 2814 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable, |
| 2818 BailoutId bailout_id) { | 2815 BailoutId bailout_id) { |
| 2819 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. | 2816 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. |
| 2820 Node* variable_name = jsgraph()->Constant(variable->name()); | 2817 Node* variable_name = jsgraph()->Constant(variable->name()); |
| 2821 const Operator* op = | 2818 const Operator* op = |
| 2822 javascript()->CallRuntime(Runtime::kThrowReferenceError, 1); | 2819 javascript()->CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2823 Node* call = NewNode(op, variable_name); | 2820 Node* call = NewNode(op, variable_name); |
| 2824 PrepareFrameState(call, bailout_id); | 2821 PrepareFrameState(call, bailout_id); |
| 2825 return call; | 2822 return call; |
| 2826 } | 2823 } |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3189 Node* dead_node = graph()->NewNode(common()->Dead()); | 3186 Node* dead_node = graph()->NewNode(common()->Dead()); |
| 3190 dead_control_.set(dead_node); | 3187 dead_control_.set(dead_node); |
| 3191 return dead_node; | 3188 return dead_node; |
| 3192 } | 3189 } |
| 3193 return dead_control_.get(); | 3190 return dead_control_.get(); |
| 3194 } | 3191 } |
| 3195 | 3192 |
| 3196 } // namespace compiler | 3193 } // namespace compiler |
| 3197 } // namespace internal | 3194 } // namespace internal |
| 3198 } // namespace v8 | 3195 } // namespace v8 |
| OLD | NEW |