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 |