| 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/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/compilation-info.h" | 9 #include "src/compilation-info.h" |
| 10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
| (...skipping 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1369 | 1369 |
| 1370 // The object is expected on the operand stack during computation of the | 1370 // The object is expected on the operand stack during computation of the |
| 1371 // property values and is the value of the entire expression. | 1371 // property values and is the value of the entire expression. |
| 1372 environment()->Push(literal); | 1372 environment()->Push(literal); |
| 1373 | 1373 |
| 1374 // Create nodes to store computed values into the literal. | 1374 // Create nodes to store computed values into the literal. |
| 1375 int property_index = 0; | 1375 int property_index = 0; |
| 1376 AccessorTable accessor_table(local_zone()); | 1376 AccessorTable accessor_table(local_zone()); |
| 1377 for (; property_index < expr->properties()->length(); property_index++) { | 1377 for (; property_index < expr->properties()->length(); property_index++) { |
| 1378 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1378 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1379 if (property->is_computed_name()) break; | 1379 DCHECK(!property->is_computed_name()); |
| 1380 if (property->IsCompileTimeValue()) continue; | 1380 if (property->IsCompileTimeValue()) continue; |
| 1381 | 1381 |
| 1382 Literal* key = property->key()->AsLiteral(); | 1382 Literal* key = property->key()->AsLiteral(); |
| 1383 switch (property->kind()) { | 1383 switch (property->kind()) { |
| 1384 case ObjectLiteral::Property::CONSTANT: | 1384 case ObjectLiteral::Property::CONSTANT: |
| 1385 UNREACHABLE(); | 1385 UNREACHABLE(); |
| 1386 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1386 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1387 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1387 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 1388 // Fall through. | 1388 // Fall through. |
| 1389 case ObjectLiteral::Property::COMPUTED: { | 1389 case ObjectLiteral::Property::COMPUTED: { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 VisitObjectLiteralAccessor(literal, it->second->setter); | 1464 VisitObjectLiteralAccessor(literal, it->second->setter); |
| 1465 Node* setter = environment()->Pop(); | 1465 Node* setter = environment()->Pop(); |
| 1466 Node* getter = environment()->Pop(); | 1466 Node* getter = environment()->Pop(); |
| 1467 Node* name = environment()->Pop(); | 1467 Node* name = environment()->Pop(); |
| 1468 Node* attr = jsgraph()->Constant(NONE); | 1468 Node* attr = jsgraph()->Constant(NONE); |
| 1469 const Operator* op = | 1469 const Operator* op = |
| 1470 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); | 1470 javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
| 1471 Node* call = NewNode(op, literal, name, getter, setter, attr); | 1471 Node* call = NewNode(op, literal, name, getter, setter, attr); |
| 1472 PrepareFrameState(call, it->second->bailout_id); | 1472 PrepareFrameState(call, it->second->bailout_id); |
| 1473 } | 1473 } |
| 1474 | |
| 1475 // Object literals have two parts. The "static" part on the left contains no | |
| 1476 // computed property names, and so we can compute its map ahead of time; see | |
| 1477 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts | |
| 1478 // with the first computed property name and continues with all properties to | |
| 1479 // its right. All the code from above initializes the static component of the | |
| 1480 // object literal, and arranges for the map of the result to reflect the | |
| 1481 // static order in which the keys appear. For the dynamic properties, we | |
| 1482 // compile them into a series of "SetOwnProperty" runtime calls. This will | |
| 1483 // preserve insertion order. | |
| 1484 for (; property_index < expr->properties()->length(); property_index++) { | |
| 1485 ObjectLiteral::Property* property = expr->properties()->at(property_index); | |
| 1486 | |
| 1487 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | |
| 1488 environment()->Push(environment()->Top()); // Duplicate receiver. | |
| 1489 VisitForValue(property->value()); | |
| 1490 Node* value = environment()->Pop(); | |
| 1491 Node* receiver = environment()->Pop(); | |
| 1492 const Operator* op = | |
| 1493 javascript()->CallRuntime(Runtime::kInternalSetPrototype); | |
| 1494 Node* call = NewNode(op, receiver, value); | |
| 1495 PrepareFrameState(call, expr->GetIdForPropertySet(property_index)); | |
| 1496 continue; | |
| 1497 } | |
| 1498 | |
| 1499 environment()->Push(environment()->Top()); // Duplicate receiver. | |
| 1500 VisitForValue(property->key()); | |
| 1501 Node* name = BuildToName(environment()->Pop(), | |
| 1502 expr->GetIdForPropertyName(property_index)); | |
| 1503 environment()->Push(name); | |
| 1504 VisitForValue(property->value()); | |
| 1505 Node* value = environment()->Pop(); | |
| 1506 Node* key = environment()->Pop(); | |
| 1507 Node* receiver = environment()->Pop(); | |
| 1508 BuildSetHomeObject(value, receiver, property); | |
| 1509 switch (property->kind()) { | |
| 1510 case ObjectLiteral::Property::CONSTANT: | |
| 1511 case ObjectLiteral::Property::COMPUTED: | |
| 1512 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | |
| 1513 case ObjectLiteral::Property::PROTOTYPE: | |
| 1514 UNREACHABLE(); // Handled specially above. | |
| 1515 break; | |
| 1516 case ObjectLiteral::Property::GETTER: { | |
| 1517 Node* attr = jsgraph()->Constant(NONE); | |
| 1518 const Operator* op = javascript()->CallRuntime( | |
| 1519 Runtime::kDefineGetterPropertyUnchecked, 4); | |
| 1520 Node* call = NewNode(op, receiver, key, value, attr); | |
| 1521 PrepareFrameState(call, BailoutId::None()); | |
| 1522 break; | |
| 1523 } | |
| 1524 case ObjectLiteral::Property::SETTER: { | |
| 1525 Node* attr = jsgraph()->Constant(NONE); | |
| 1526 const Operator* op = javascript()->CallRuntime( | |
| 1527 Runtime::kDefineSetterPropertyUnchecked, 4); | |
| 1528 Node* call = NewNode(op, receiver, key, value, attr); | |
| 1529 PrepareFrameState(call, BailoutId::None()); | |
| 1530 break; | |
| 1531 } | |
| 1532 } | |
| 1533 } | |
| 1534 | |
| 1535 ast_context()->ProduceValue(expr, environment()->Pop()); | 1474 ast_context()->ProduceValue(expr, environment()->Pop()); |
| 1536 } | 1475 } |
| 1537 | 1476 |
| 1538 | 1477 |
| 1539 void AstGraphBuilder::VisitObjectLiteralAccessor( | 1478 void AstGraphBuilder::VisitObjectLiteralAccessor( |
| 1540 Node* home_object, ObjectLiteralProperty* property) { | 1479 Node* home_object, ObjectLiteralProperty* property) { |
| 1541 if (property == nullptr) { | 1480 if (property == nullptr) { |
| 1542 VisitForValueOrNull(nullptr); | 1481 VisitForValueOrNull(nullptr); |
| 1543 } else { | 1482 } else { |
| 1544 VisitForValue(property->value()); | 1483 VisitForValue(property->value()); |
| (...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3062 } | 3001 } |
| 3063 | 3002 |
| 3064 | 3003 |
| 3065 Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) { | 3004 Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) { |
| 3066 if (Node* node = TryFastToBoolean(input)) return node; | 3005 if (Node* node = TryFastToBoolean(input)) return node; |
| 3067 ToBooleanHints hints = ToBooleanHint::kAny; | 3006 ToBooleanHints hints = ToBooleanHint::kAny; |
| 3068 return NewNode(javascript()->ToBoolean(hints), input); | 3007 return NewNode(javascript()->ToBoolean(hints), input); |
| 3069 } | 3008 } |
| 3070 | 3009 |
| 3071 | 3010 |
| 3072 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) { | |
| 3073 if (Node* node = TryFastToName(input)) return node; | |
| 3074 Node* name = NewNode(javascript()->ToName(), input); | |
| 3075 PrepareFrameState(name, bailout_id, OutputFrameStateCombine::Push()); | |
| 3076 return name; | |
| 3077 } | |
| 3078 | |
| 3079 | |
| 3080 Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) { | 3011 Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) { |
| 3081 Node* object = NewNode(javascript()->ToObject(), input); | 3012 Node* object = NewNode(javascript()->ToObject(), input); |
| 3082 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push()); | 3013 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push()); |
| 3083 return object; | 3014 return object; |
| 3084 } | 3015 } |
| 3085 | 3016 |
| 3086 Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object, | 3017 Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object, |
| 3087 LiteralProperty* property, | 3018 LiteralProperty* property, |
| 3088 int slot_number) { | 3019 int slot_number) { |
| 3089 Expression* expr = property->value(); | 3020 Expression* expr = property->value(); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3238 case IrOpcode::kJSHasProperty: | 3169 case IrOpcode::kJSHasProperty: |
| 3239 case IrOpcode::kJSInstanceOf: | 3170 case IrOpcode::kJSInstanceOf: |
| 3240 return input; | 3171 return input; |
| 3241 default: | 3172 default: |
| 3242 break; | 3173 break; |
| 3243 } | 3174 } |
| 3244 return nullptr; | 3175 return nullptr; |
| 3245 } | 3176 } |
| 3246 | 3177 |
| 3247 | 3178 |
| 3248 Node* AstGraphBuilder::TryFastToName(Node* input) { | |
| 3249 switch (input->opcode()) { | |
| 3250 case IrOpcode::kHeapConstant: { | |
| 3251 Handle<HeapObject> object = HeapObjectMatcher(input).Value(); | |
| 3252 if (object->IsName()) return input; | |
| 3253 break; | |
| 3254 } | |
| 3255 case IrOpcode::kJSToString: | |
| 3256 case IrOpcode::kJSToName: | |
| 3257 case IrOpcode::kJSTypeOf: | |
| 3258 return input; | |
| 3259 default: | |
| 3260 break; | |
| 3261 } | |
| 3262 return nullptr; | |
| 3263 } | |
| 3264 | |
| 3265 | |
| 3266 bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) { | 3179 bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) { |
| 3267 if (info()->osr_ast_id() == stmt->OsrEntryId()) { | 3180 if (info()->osr_ast_id() == stmt->OsrEntryId()) { |
| 3268 DCHECK_EQ(-1, info()->osr_expr_stack_height()); | 3181 DCHECK_EQ(-1, info()->osr_expr_stack_height()); |
| 3269 info()->set_osr_expr_stack_height(environment()->stack_height()); | 3182 info()->set_osr_expr_stack_height(environment()->stack_height()); |
| 3270 return true; | 3183 return true; |
| 3271 } | 3184 } |
| 3272 return false; | 3185 return false; |
| 3273 } | 3186 } |
| 3274 | 3187 |
| 3275 | 3188 |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3614 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment, | 3527 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment, |
| 3615 SourcePositionTable* source_positions, int inlining_id) | 3528 SourcePositionTable* source_positions, int inlining_id) |
| 3616 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, | 3529 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, |
| 3617 loop_assignment), | 3530 loop_assignment), |
| 3618 source_positions_(source_positions), | 3531 source_positions_(source_positions), |
| 3619 start_position_(info->shared_info()->start_position(), inlining_id) {} | 3532 start_position_(info->shared_info()->start_position(), inlining_id) {} |
| 3620 | 3533 |
| 3621 } // namespace compiler | 3534 } // namespace compiler |
| 3622 } // namespace internal | 3535 } // namespace internal |
| 3623 } // namespace v8 | 3536 } // namespace v8 |
| OLD | NEW |