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/control-builders.h" | 8 #include "src/compiler/control-builders.h" |
9 #include "src/compiler/machine-operator.h" | 9 #include "src/compiler/machine-operator.h" |
10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
(...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 | 854 |
855 // Create node to materialize a regular expression literal. | 855 // Create node to materialize a regular expression literal. |
856 Node* literals_array = | 856 Node* literals_array = |
857 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); | 857 BuildLoadObjectField(closure, JSFunction::kLiteralsOffset); |
858 Node* literal_index = jsgraph()->Constant(expr->literal_index()); | 858 Node* literal_index = jsgraph()->Constant(expr->literal_index()); |
859 Node* pattern = jsgraph()->Constant(expr->pattern()); | 859 Node* pattern = jsgraph()->Constant(expr->pattern()); |
860 Node* flags = jsgraph()->Constant(expr->flags()); | 860 Node* flags = jsgraph()->Constant(expr->flags()); |
861 const Operator* op = | 861 const Operator* op = |
862 javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4); | 862 javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4); |
863 Node* literal = NewNode(op, literals_array, literal_index, pattern, flags); | 863 Node* literal = NewNode(op, literals_array, literal_index, pattern, flags); |
| 864 PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine()); |
864 ast_context()->ProduceValue(literal); | 865 ast_context()->ProduceValue(literal); |
865 } | 866 } |
866 | 867 |
867 | 868 |
868 void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 869 void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
869 Node* closure = GetFunctionClosure(); | 870 Node* closure = GetFunctionClosure(); |
870 | 871 |
871 // Create node to deep-copy the literal boilerplate. | 872 // Create node to deep-copy the literal boilerplate. |
872 expr->BuildConstantProperties(isolate()); | 873 expr->BuildConstantProperties(isolate()); |
873 Node* literals_array = | 874 Node* literals_array = |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1088 case VARIABLE: { | 1089 case VARIABLE: { |
1089 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1090 Variable* variable = expr->target()->AsVariableProxy()->var(); |
1090 old_value = BuildVariableLoad(variable, expr->target()->id()); | 1091 old_value = BuildVariableLoad(variable, expr->target()->id()); |
1091 break; | 1092 break; |
1092 } | 1093 } |
1093 case NAMED_PROPERTY: { | 1094 case NAMED_PROPERTY: { |
1094 Node* object = environment()->Top(); | 1095 Node* object = environment()->Top(); |
1095 Unique<Name> name = | 1096 Unique<Name> name = |
1096 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1097 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
1097 old_value = NewNode(javascript()->LoadNamed(name), object); | 1098 old_value = NewNode(javascript()->LoadNamed(name), object); |
1098 PrepareFrameState(old_value, property->LoadId(), kPushOutput); | 1099 PrepareFrameState(old_value, property->LoadId(), |
| 1100 OutputFrameStateCombine::Push()); |
1099 break; | 1101 break; |
1100 } | 1102 } |
1101 case KEYED_PROPERTY: { | 1103 case KEYED_PROPERTY: { |
1102 Node* key = environment()->Top(); | 1104 Node* key = environment()->Top(); |
1103 Node* object = environment()->Peek(1); | 1105 Node* object = environment()->Peek(1); |
1104 old_value = NewNode(javascript()->LoadProperty(), object, key); | 1106 old_value = NewNode(javascript()->LoadProperty(), object, key); |
1105 PrepareFrameState(old_value, property->LoadId(), kPushOutput); | 1107 PrepareFrameState(old_value, property->LoadId(), |
| 1108 OutputFrameStateCombine::Push()); |
1106 break; | 1109 break; |
1107 } | 1110 } |
1108 } | 1111 } |
1109 environment()->Push(old_value); | 1112 environment()->Push(old_value); |
1110 VisitForValue(expr->value()); | 1113 VisitForValue(expr->value()); |
1111 Node* right = environment()->Pop(); | 1114 Node* right = environment()->Pop(); |
1112 Node* left = environment()->Pop(); | 1115 Node* left = environment()->Pop(); |
1113 Node* value = BuildBinaryOp(left, right, expr->binary_op()); | 1116 Node* value = BuildBinaryOp(left, right, expr->binary_op()); |
1114 PrepareFrameState(value, expr->binary_operation()->id(), kPushOutput); | 1117 PrepareFrameState(value, expr->binary_operation()->id(), |
| 1118 OutputFrameStateCombine::Push()); |
1115 environment()->Push(value); | 1119 environment()->Push(value); |
1116 } else { | 1120 } else { |
1117 VisitForValue(expr->value()); | 1121 VisitForValue(expr->value()); |
1118 } | 1122 } |
1119 | 1123 |
1120 // Store the value. | 1124 // Store the value. |
1121 Node* value = environment()->Pop(); | 1125 Node* value = environment()->Pop(); |
1122 switch (assign_type) { | 1126 switch (assign_type) { |
1123 case VARIABLE: { | 1127 case VARIABLE: { |
1124 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1128 Variable* variable = expr->target()->AsVariableProxy()->var(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 // TODO(turbofan): VisitYield | 1161 // TODO(turbofan): VisitYield |
1158 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); | 1162 ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); |
1159 } | 1163 } |
1160 | 1164 |
1161 | 1165 |
1162 void AstGraphBuilder::VisitThrow(Throw* expr) { | 1166 void AstGraphBuilder::VisitThrow(Throw* expr) { |
1163 VisitForValue(expr->exception()); | 1167 VisitForValue(expr->exception()); |
1164 Node* exception = environment()->Pop(); | 1168 Node* exception = environment()->Pop(); |
1165 const Operator* op = javascript()->Runtime(Runtime::kThrow, 1); | 1169 const Operator* op = javascript()->Runtime(Runtime::kThrow, 1); |
1166 Node* value = NewNode(op, exception); | 1170 Node* value = NewNode(op, exception); |
| 1171 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
1167 ast_context()->ProduceValue(value); | 1172 ast_context()->ProduceValue(value); |
1168 } | 1173 } |
1169 | 1174 |
1170 | 1175 |
1171 void AstGraphBuilder::VisitProperty(Property* expr) { | 1176 void AstGraphBuilder::VisitProperty(Property* expr) { |
1172 Node* value; | 1177 Node* value; |
1173 if (expr->key()->IsPropertyName()) { | 1178 if (expr->key()->IsPropertyName()) { |
1174 VisitForValue(expr->obj()); | 1179 VisitForValue(expr->obj()); |
1175 Node* object = environment()->Pop(); | 1180 Node* object = environment()->Pop(); |
1176 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); | 1181 Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); |
(...skipping 28 matching lines...) Expand all Loading... |
1205 break; | 1210 break; |
1206 } | 1211 } |
1207 case Call::LOOKUP_SLOT_CALL: { | 1212 case Call::LOOKUP_SLOT_CALL: { |
1208 Variable* variable = callee->AsVariableProxy()->var(); | 1213 Variable* variable = callee->AsVariableProxy()->var(); |
1209 DCHECK(variable->location() == Variable::LOOKUP); | 1214 DCHECK(variable->location() == Variable::LOOKUP); |
1210 Node* name = jsgraph()->Constant(variable->name()); | 1215 Node* name = jsgraph()->Constant(variable->name()); |
1211 const Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); | 1216 const Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); |
1212 Node* pair = NewNode(op, current_context(), name); | 1217 Node* pair = NewNode(op, current_context(), name); |
1213 callee_value = NewNode(common()->Projection(0), pair); | 1218 callee_value = NewNode(common()->Projection(0), pair); |
1214 receiver_value = NewNode(common()->Projection(1), pair); | 1219 receiver_value = NewNode(common()->Projection(1), pair); |
| 1220 |
| 1221 PrepareFrameState(pair, expr->EvalOrLookupId(), |
| 1222 OutputFrameStateCombine::Push()); |
1215 break; | 1223 break; |
1216 } | 1224 } |
1217 case Call::PROPERTY_CALL: { | 1225 case Call::PROPERTY_CALL: { |
1218 Property* property = callee->AsProperty(); | 1226 Property* property = callee->AsProperty(); |
1219 VisitForValue(property->obj()); | 1227 VisitForValue(property->obj()); |
1220 Node* object = environment()->Top(); | 1228 Node* object = environment()->Top(); |
1221 if (property->key()->IsPropertyName()) { | 1229 if (property->key()->IsPropertyName()) { |
1222 Unique<Name> name = | 1230 Unique<Name> name = |
1223 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1231 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
1224 callee_value = NewNode(javascript()->LoadNamed(name), object); | 1232 callee_value = NewNode(javascript()->LoadNamed(name), object); |
1225 } else { | 1233 } else { |
1226 VisitForValue(property->key()); | 1234 VisitForValue(property->key()); |
1227 Node* key = environment()->Pop(); | 1235 Node* key = environment()->Pop(); |
1228 callee_value = NewNode(javascript()->LoadProperty(), object, key); | 1236 callee_value = NewNode(javascript()->LoadProperty(), object, key); |
1229 } | 1237 } |
1230 PrepareFrameState(callee_value, property->LoadId(), kPushOutput); | 1238 PrepareFrameState(callee_value, property->LoadId(), |
| 1239 OutputFrameStateCombine::Push()); |
1231 receiver_value = environment()->Pop(); | 1240 receiver_value = environment()->Pop(); |
1232 // Note that a PROPERTY_CALL requires the receiver to be wrapped into an | 1241 // Note that a PROPERTY_CALL requires the receiver to be wrapped into an |
1233 // object for sloppy callees. This could also be modeled explicitly here, | 1242 // object for sloppy callees. This could also be modeled explicitly here, |
1234 // thereby obsoleting the need for a flag to the call operator. | 1243 // thereby obsoleting the need for a flag to the call operator. |
1235 flags = CALL_AS_METHOD; | 1244 flags = CALL_AS_METHOD; |
1236 break; | 1245 break; |
1237 } | 1246 } |
1238 case Call::POSSIBLY_EVAL_CALL: | 1247 case Call::POSSIBLY_EVAL_CALL: |
1239 possibly_eval = true; | 1248 possibly_eval = true; |
1240 // Fall through. | 1249 // Fall through. |
(...skipping 23 matching lines...) Expand all Loading... |
1264 Node* source = environment()->Peek(arg_count - 1); | 1273 Node* source = environment()->Peek(arg_count - 1); |
1265 | 1274 |
1266 // Create node to ask for help resolving potential eval call. This will | 1275 // Create node to ask for help resolving potential eval call. This will |
1267 // provide a fully resolved callee and the corresponding receiver. | 1276 // provide a fully resolved callee and the corresponding receiver. |
1268 Node* receiver = environment()->Lookup(info()->scope()->receiver()); | 1277 Node* receiver = environment()->Lookup(info()->scope()->receiver()); |
1269 Node* strict = jsgraph()->Constant(strict_mode()); | 1278 Node* strict = jsgraph()->Constant(strict_mode()); |
1270 Node* position = jsgraph()->Constant(info()->scope()->start_position()); | 1279 Node* position = jsgraph()->Constant(info()->scope()->start_position()); |
1271 const Operator* op = | 1280 const Operator* op = |
1272 javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 5); | 1281 javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 5); |
1273 Node* pair = NewNode(op, callee, source, receiver, strict, position); | 1282 Node* pair = NewNode(op, callee, source, receiver, strict, position); |
| 1283 PrepareFrameState(pair, expr->EvalOrLookupId(), |
| 1284 OutputFrameStateCombine::PokeAt(arg_count + 1)); |
1274 Node* new_callee = NewNode(common()->Projection(0), pair); | 1285 Node* new_callee = NewNode(common()->Projection(0), pair); |
1275 Node* new_receiver = NewNode(common()->Projection(1), pair); | 1286 Node* new_receiver = NewNode(common()->Projection(1), pair); |
1276 | 1287 |
1277 // Patch callee and receiver on the environment. | 1288 // Patch callee and receiver on the environment. |
1278 environment()->Poke(arg_count + 1, new_callee); | 1289 environment()->Poke(arg_count + 1, new_callee); |
1279 environment()->Poke(arg_count + 0, new_receiver); | 1290 environment()->Poke(arg_count + 0, new_receiver); |
1280 } | 1291 } |
1281 | 1292 |
1282 // Create node to perform the function call. | 1293 // Create node to perform the function call. |
1283 const Operator* call = javascript()->Call(args->length() + 2, flags); | 1294 const Operator* call = javascript()->Call(args->length() + 2, flags); |
(...skipping 22 matching lines...) Expand all Loading... |
1306 Handle<String> name = expr->name(); | 1317 Handle<String> name = expr->name(); |
1307 | 1318 |
1308 // The callee and the receiver both have to be pushed onto the operand stack | 1319 // The callee and the receiver both have to be pushed onto the operand stack |
1309 // before arguments are being evaluated. | 1320 // before arguments are being evaluated. |
1310 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; | 1321 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; |
1311 Node* receiver_value = BuildLoadBuiltinsObject(); | 1322 Node* receiver_value = BuildLoadBuiltinsObject(); |
1312 Unique<String> unique = MakeUnique(name); | 1323 Unique<String> unique = MakeUnique(name); |
1313 Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); | 1324 Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); |
1314 // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft | 1325 // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft |
1315 // refuses to optimize functions with jsruntime calls). | 1326 // refuses to optimize functions with jsruntime calls). |
1316 PrepareFrameState(callee_value, BailoutId::None(), kPushOutput); | 1327 PrepareFrameState(callee_value, BailoutId::None(), |
| 1328 OutputFrameStateCombine::Push()); |
1317 environment()->Push(callee_value); | 1329 environment()->Push(callee_value); |
1318 environment()->Push(receiver_value); | 1330 environment()->Push(receiver_value); |
1319 | 1331 |
1320 // Evaluate all arguments to the JS runtime call. | 1332 // Evaluate all arguments to the JS runtime call. |
1321 ZoneList<Expression*>* args = expr->arguments(); | 1333 ZoneList<Expression*>* args = expr->arguments(); |
1322 VisitForValues(args); | 1334 VisitForValues(args); |
1323 | 1335 |
1324 // Create node to perform the JS runtime call. | 1336 // Create node to perform the JS runtime call. |
1325 const Operator* call = javascript()->Call(args->length() + 2, flags); | 1337 const Operator* call = javascript()->Call(args->length() + 2, flags); |
1326 Node* value = ProcessArguments(call, args->length() + 2); | 1338 Node* value = ProcessArguments(call, args->length() + 2); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1388 old_value = BuildVariableLoad(variable, expr->expression()->id()); | 1400 old_value = BuildVariableLoad(variable, expr->expression()->id()); |
1389 stack_depth = 0; | 1401 stack_depth = 0; |
1390 break; | 1402 break; |
1391 } | 1403 } |
1392 case NAMED_PROPERTY: { | 1404 case NAMED_PROPERTY: { |
1393 VisitForValue(property->obj()); | 1405 VisitForValue(property->obj()); |
1394 Node* object = environment()->Top(); | 1406 Node* object = environment()->Top(); |
1395 Unique<Name> name = | 1407 Unique<Name> name = |
1396 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1408 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
1397 old_value = NewNode(javascript()->LoadNamed(name), object); | 1409 old_value = NewNode(javascript()->LoadNamed(name), object); |
1398 PrepareFrameState(old_value, property->LoadId(), kPushOutput); | 1410 PrepareFrameState(old_value, property->LoadId(), |
| 1411 OutputFrameStateCombine::Push()); |
1399 stack_depth = 1; | 1412 stack_depth = 1; |
1400 break; | 1413 break; |
1401 } | 1414 } |
1402 case KEYED_PROPERTY: { | 1415 case KEYED_PROPERTY: { |
1403 VisitForValue(property->obj()); | 1416 VisitForValue(property->obj()); |
1404 VisitForValue(property->key()); | 1417 VisitForValue(property->key()); |
1405 Node* key = environment()->Top(); | 1418 Node* key = environment()->Top(); |
1406 Node* object = environment()->Peek(1); | 1419 Node* object = environment()->Peek(1); |
1407 old_value = NewNode(javascript()->LoadProperty(), object, key); | 1420 old_value = NewNode(javascript()->LoadProperty(), object, key); |
1408 PrepareFrameState(old_value, property->LoadId(), kPushOutput); | 1421 PrepareFrameState(old_value, property->LoadId(), |
| 1422 OutputFrameStateCombine::Push()); |
1409 stack_depth = 2; | 1423 stack_depth = 2; |
1410 break; | 1424 break; |
1411 } | 1425 } |
1412 } | 1426 } |
1413 | 1427 |
1414 // Convert old value into a number. | 1428 // Convert old value into a number. |
1415 old_value = NewNode(javascript()->ToNumber(), old_value); | 1429 old_value = NewNode(javascript()->ToNumber(), old_value); |
1416 | 1430 |
1417 // Save result for postfix expressions at correct stack depth. | 1431 // Save result for postfix expressions at correct stack depth. |
1418 if (is_postfix) environment()->Poke(stack_depth, old_value); | 1432 if (is_postfix) environment()->Poke(stack_depth, old_value); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1576 } | 1590 } |
1577 | 1591 |
1578 | 1592 |
1579 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { | 1593 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { |
1580 Node* value; | 1594 Node* value; |
1581 if (expr->expression()->IsVariableProxy()) { | 1595 if (expr->expression()->IsVariableProxy()) { |
1582 // Delete of an unqualified identifier is only allowed in classic mode but | 1596 // Delete of an unqualified identifier is only allowed in classic mode but |
1583 // deleting "this" is allowed in all language modes. | 1597 // deleting "this" is allowed in all language modes. |
1584 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 1598 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
1585 DCHECK(strict_mode() == SLOPPY || variable->is_this()); | 1599 DCHECK(strict_mode() == SLOPPY || variable->is_this()); |
1586 value = BuildVariableDelete(variable); | 1600 value = BuildVariableDelete(variable, expr->id(), |
| 1601 ast_context()->GetStateCombine()); |
1587 } else if (expr->expression()->IsProperty()) { | 1602 } else if (expr->expression()->IsProperty()) { |
1588 Property* property = expr->expression()->AsProperty(); | 1603 Property* property = expr->expression()->AsProperty(); |
1589 VisitForValue(property->obj()); | 1604 VisitForValue(property->obj()); |
1590 VisitForValue(property->key()); | 1605 VisitForValue(property->key()); |
1591 Node* key = environment()->Pop(); | 1606 Node* key = environment()->Pop(); |
1592 Node* object = environment()->Pop(); | 1607 Node* object = environment()->Pop(); |
1593 value = NewNode(javascript()->DeleteProperty(strict_mode()), object, key); | 1608 value = NewNode(javascript()->DeleteProperty(strict_mode()), object, key); |
| 1609 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
1594 } else { | 1610 } else { |
1595 VisitForEffect(expr->expression()); | 1611 VisitForEffect(expr->expression()); |
1596 value = jsgraph()->TrueConstant(); | 1612 value = jsgraph()->TrueConstant(); |
1597 } | 1613 } |
1598 ast_context()->ProduceValue(value); | 1614 ast_context()->ProduceValue(value); |
1599 } | 1615 } |
1600 | 1616 |
1601 | 1617 |
1602 void AstGraphBuilder::VisitVoid(UnaryOperation* expr) { | 1618 void AstGraphBuilder::VisitVoid(UnaryOperation* expr) { |
1603 VisitForEffect(expr->expression()); | 1619 VisitForEffect(expr->expression()); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1729 hole_check.Then(); | 1745 hole_check.Then(); |
1730 environment()->Push(for_hole); | 1746 environment()->Push(for_hole); |
1731 hole_check.Else(); | 1747 hole_check.Else(); |
1732 environment()->Push(not_hole); | 1748 environment()->Push(not_hole); |
1733 hole_check.End(); | 1749 hole_check.End(); |
1734 return environment()->Pop(); | 1750 return environment()->Pop(); |
1735 } | 1751 } |
1736 | 1752 |
1737 | 1753 |
1738 Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable, | 1754 Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable, |
1739 Node* not_hole) { | 1755 Node* not_hole, |
| 1756 BailoutId bailout_id) { |
1740 IfBuilder hole_check(this); | 1757 IfBuilder hole_check(this); |
1741 Node* the_hole = jsgraph()->TheHoleConstant(); | 1758 Node* the_hole = jsgraph()->TheHoleConstant(); |
1742 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); | 1759 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); |
1743 hole_check.If(check); | 1760 hole_check.If(check); |
1744 hole_check.Then(); | 1761 hole_check.Then(); |
1745 environment()->Push(BuildThrowReferenceError(variable)); | 1762 environment()->Push(BuildThrowReferenceError(variable, bailout_id)); |
1746 hole_check.Else(); | 1763 hole_check.Else(); |
1747 environment()->Push(not_hole); | 1764 environment()->Push(not_hole); |
1748 hole_check.End(); | 1765 hole_check.End(); |
1749 return environment()->Pop(); | 1766 return environment()->Pop(); |
1750 } | 1767 } |
1751 | 1768 |
1752 | 1769 |
1753 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, | 1770 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, |
1754 BailoutId bailout_id, | 1771 BailoutId bailout_id, |
1755 ContextualMode contextual_mode) { | 1772 ContextualMode contextual_mode) { |
1756 Node* the_hole = jsgraph()->TheHoleConstant(); | 1773 Node* the_hole = jsgraph()->TheHoleConstant(); |
1757 VariableMode mode = variable->mode(); | 1774 VariableMode mode = variable->mode(); |
1758 switch (variable->location()) { | 1775 switch (variable->location()) { |
1759 case Variable::UNALLOCATED: { | 1776 case Variable::UNALLOCATED: { |
1760 // Global var, const, or let variable. | 1777 // Global var, const, or let variable. |
1761 Node* global = BuildLoadGlobalObject(); | 1778 Node* global = BuildLoadGlobalObject(); |
1762 Unique<Name> name = MakeUnique(variable->name()); | 1779 Unique<Name> name = MakeUnique(variable->name()); |
1763 const Operator* op = javascript()->LoadNamed(name, contextual_mode); | 1780 const Operator* op = javascript()->LoadNamed(name, contextual_mode); |
1764 Node* node = NewNode(op, global); | 1781 Node* node = NewNode(op, global); |
1765 PrepareFrameState(node, bailout_id, kPushOutput); | 1782 PrepareFrameState(node, bailout_id, OutputFrameStateCombine::Push()); |
1766 return node; | 1783 return node; |
1767 } | 1784 } |
1768 case Variable::PARAMETER: | 1785 case Variable::PARAMETER: |
1769 case Variable::LOCAL: { | 1786 case Variable::LOCAL: { |
1770 // Local var, const, or let variable. | 1787 // Local var, const, or let variable. |
1771 Node* value = environment()->Lookup(variable); | 1788 Node* value = environment()->Lookup(variable); |
1772 if (mode == CONST_LEGACY) { | 1789 if (mode == CONST_LEGACY) { |
1773 // Perform check for uninitialized legacy const variables. | 1790 // Perform check for uninitialized legacy const variables. |
1774 if (value->op() == the_hole->op()) { | 1791 if (value->op() == the_hole->op()) { |
1775 value = jsgraph()->UndefinedConstant(); | 1792 value = jsgraph()->UndefinedConstant(); |
1776 } else if (value->opcode() == IrOpcode::kPhi) { | 1793 } else if (value->opcode() == IrOpcode::kPhi) { |
1777 Node* undefined = jsgraph()->UndefinedConstant(); | 1794 Node* undefined = jsgraph()->UndefinedConstant(); |
1778 value = BuildHoleCheckSilent(value, undefined, value); | 1795 value = BuildHoleCheckSilent(value, undefined, value); |
1779 } | 1796 } |
1780 } else if (mode == LET || mode == CONST) { | 1797 } else if (mode == LET || mode == CONST) { |
1781 // Perform check for uninitialized let/const variables. | 1798 // Perform check for uninitialized let/const variables. |
1782 if (value->op() == the_hole->op()) { | 1799 if (value->op() == the_hole->op()) { |
1783 value = BuildThrowReferenceError(variable); | 1800 value = BuildThrowReferenceError(variable, bailout_id); |
1784 } else if (value->opcode() == IrOpcode::kPhi) { | 1801 } else if (value->opcode() == IrOpcode::kPhi) { |
1785 value = BuildHoleCheckThrow(value, variable, value); | 1802 value = BuildHoleCheckThrow(value, variable, value, bailout_id); |
1786 } | 1803 } |
1787 } | 1804 } |
1788 return value; | 1805 return value; |
1789 } | 1806 } |
1790 case Variable::CONTEXT: { | 1807 case Variable::CONTEXT: { |
1791 // Context variable (potentially up the context chain). | 1808 // Context variable (potentially up the context chain). |
1792 int depth = current_scope()->ContextChainLength(variable->scope()); | 1809 int depth = current_scope()->ContextChainLength(variable->scope()); |
1793 bool immutable = variable->maybe_assigned() == kNotAssigned; | 1810 bool immutable = variable->maybe_assigned() == kNotAssigned; |
1794 const Operator* op = | 1811 const Operator* op = |
1795 javascript()->LoadContext(depth, variable->index(), immutable); | 1812 javascript()->LoadContext(depth, variable->index(), immutable); |
1796 Node* value = NewNode(op, current_context()); | 1813 Node* value = NewNode(op, current_context()); |
1797 // TODO(titzer): initialization checks are redundant for already | 1814 // TODO(titzer): initialization checks are redundant for already |
1798 // initialized immutable context loads, but only specialization knows. | 1815 // initialized immutable context loads, but only specialization knows. |
1799 // Maybe specializer should be a parameter to the graph builder? | 1816 // Maybe specializer should be a parameter to the graph builder? |
1800 if (mode == CONST_LEGACY) { | 1817 if (mode == CONST_LEGACY) { |
1801 // Perform check for uninitialized legacy const variables. | 1818 // Perform check for uninitialized legacy const variables. |
1802 Node* undefined = jsgraph()->UndefinedConstant(); | 1819 Node* undefined = jsgraph()->UndefinedConstant(); |
1803 value = BuildHoleCheckSilent(value, undefined, value); | 1820 value = BuildHoleCheckSilent(value, undefined, value); |
1804 } else if (mode == LET || mode == CONST) { | 1821 } else if (mode == LET || mode == CONST) { |
1805 // Perform check for uninitialized let/const variables. | 1822 // Perform check for uninitialized let/const variables. |
1806 value = BuildHoleCheckThrow(value, variable, value); | 1823 value = BuildHoleCheckThrow(value, variable, value, bailout_id); |
1807 } | 1824 } |
1808 return value; | 1825 return value; |
1809 } | 1826 } |
1810 case Variable::LOOKUP: { | 1827 case Variable::LOOKUP: { |
1811 // Dynamic lookup of context variable (anywhere in the chain). | 1828 // Dynamic lookup of context variable (anywhere in the chain). |
1812 Node* name = jsgraph()->Constant(variable->name()); | 1829 Node* name = jsgraph()->Constant(variable->name()); |
1813 Runtime::FunctionId function_id = | 1830 Runtime::FunctionId function_id = |
1814 (contextual_mode == CONTEXTUAL) | 1831 (contextual_mode == CONTEXTUAL) |
1815 ? Runtime::kLoadLookupSlot | 1832 ? Runtime::kLoadLookupSlot |
1816 : Runtime::kLoadLookupSlotNoReferenceError; | 1833 : Runtime::kLoadLookupSlotNoReferenceError; |
1817 const Operator* op = javascript()->Runtime(function_id, 2); | 1834 const Operator* op = javascript()->Runtime(function_id, 2); |
1818 Node* pair = NewNode(op, current_context(), name); | 1835 Node* pair = NewNode(op, current_context(), name); |
| 1836 PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1)); |
1819 return NewNode(common()->Projection(0), pair); | 1837 return NewNode(common()->Projection(0), pair); |
1820 } | 1838 } |
1821 } | 1839 } |
1822 UNREACHABLE(); | 1840 UNREACHABLE(); |
1823 return NULL; | 1841 return NULL; |
1824 } | 1842 } |
1825 | 1843 |
1826 | 1844 |
1827 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) { | 1845 Node* AstGraphBuilder::BuildVariableDelete( |
| 1846 Variable* variable, BailoutId bailout_id, |
| 1847 OutputFrameStateCombine state_combine) { |
1828 switch (variable->location()) { | 1848 switch (variable->location()) { |
1829 case Variable::UNALLOCATED: { | 1849 case Variable::UNALLOCATED: { |
1830 // Global var, const, or let variable. | 1850 // Global var, const, or let variable. |
1831 Node* global = BuildLoadGlobalObject(); | 1851 Node* global = BuildLoadGlobalObject(); |
1832 Node* name = jsgraph()->Constant(variable->name()); | 1852 Node* name = jsgraph()->Constant(variable->name()); |
1833 const Operator* op = javascript()->DeleteProperty(strict_mode()); | 1853 const Operator* op = javascript()->DeleteProperty(strict_mode()); |
1834 return NewNode(op, global, name); | 1854 Node* result = NewNode(op, global, name); |
| 1855 PrepareFrameState(result, bailout_id, state_combine); |
| 1856 return result; |
1835 } | 1857 } |
1836 case Variable::PARAMETER: | 1858 case Variable::PARAMETER: |
1837 case Variable::LOCAL: | 1859 case Variable::LOCAL: |
1838 case Variable::CONTEXT: | 1860 case Variable::CONTEXT: |
1839 // Local var, const, or let variable or context variable. | 1861 // Local var, const, or let variable or context variable. |
1840 return variable->is_this() ? jsgraph()->TrueConstant() | 1862 return variable->is_this() ? jsgraph()->TrueConstant() |
1841 : jsgraph()->FalseConstant(); | 1863 : jsgraph()->FalseConstant(); |
1842 case Variable::LOOKUP: { | 1864 case Variable::LOOKUP: { |
1843 // Dynamic lookup of context variable (anywhere in the chain). | 1865 // Dynamic lookup of context variable (anywhere in the chain). |
1844 Node* name = jsgraph()->Constant(variable->name()); | 1866 Node* name = jsgraph()->Constant(variable->name()); |
1845 const Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2); | 1867 const Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2); |
1846 return NewNode(op, current_context(), name); | 1868 Node* result = NewNode(op, current_context(), name); |
| 1869 PrepareFrameState(result, bailout_id, state_combine); |
| 1870 return result; |
1847 } | 1871 } |
1848 } | 1872 } |
1849 UNREACHABLE(); | 1873 UNREACHABLE(); |
1850 return NULL; | 1874 return NULL; |
1851 } | 1875 } |
1852 | 1876 |
1853 | 1877 |
1854 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, | 1878 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, |
1855 Token::Value op, | 1879 Token::Value op, |
1856 BailoutId bailout_id) { | 1880 BailoutId bailout_id) { |
(...skipping 21 matching lines...) Expand all Loading... |
1878 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { | 1902 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { |
1879 // Non-initializing assignments to legacy const is ignored. | 1903 // Non-initializing assignments to legacy const is ignored. |
1880 return value; | 1904 return value; |
1881 } else if (mode == LET && op != Token::INIT_LET) { | 1905 } else if (mode == LET && op != Token::INIT_LET) { |
1882 // Perform an initialization check for let declared variables. | 1906 // Perform an initialization check for let declared variables. |
1883 // Also note that the dynamic hole-check is only done to ensure that | 1907 // Also note that the dynamic hole-check is only done to ensure that |
1884 // this does not break in the presence of do-expressions within the | 1908 // this does not break in the presence of do-expressions within the |
1885 // temporal dead zone of a let declared variable. | 1909 // temporal dead zone of a let declared variable. |
1886 Node* current = environment()->Lookup(variable); | 1910 Node* current = environment()->Lookup(variable); |
1887 if (current->op() == the_hole->op()) { | 1911 if (current->op() == the_hole->op()) { |
1888 value = BuildThrowReferenceError(variable); | 1912 value = BuildThrowReferenceError(variable, bailout_id); |
1889 } else if (value->opcode() == IrOpcode::kPhi) { | 1913 } else if (value->opcode() == IrOpcode::kPhi) { |
1890 value = BuildHoleCheckThrow(current, variable, value); | 1914 value = BuildHoleCheckThrow(current, variable, value, bailout_id); |
1891 } | 1915 } |
1892 } else if (mode == CONST && op != Token::INIT_CONST) { | 1916 } else if (mode == CONST && op != Token::INIT_CONST) { |
1893 // All assignments to const variables are early errors. | 1917 // All assignments to const variables are early errors. |
1894 UNREACHABLE(); | 1918 UNREACHABLE(); |
1895 } | 1919 } |
1896 environment()->Bind(variable, value); | 1920 environment()->Bind(variable, value); |
1897 return value; | 1921 return value; |
1898 case Variable::CONTEXT: { | 1922 case Variable::CONTEXT: { |
1899 // Context variable (potentially up the context chain). | 1923 // Context variable (potentially up the context chain). |
1900 int depth = current_scope()->ContextChainLength(variable->scope()); | 1924 int depth = current_scope()->ContextChainLength(variable->scope()); |
1901 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { | 1925 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { |
1902 // Perform an initialization check for legacy const variables. | 1926 // Perform an initialization check for legacy const variables. |
1903 const Operator* op = | 1927 const Operator* op = |
1904 javascript()->LoadContext(depth, variable->index(), false); | 1928 javascript()->LoadContext(depth, variable->index(), false); |
1905 Node* current = NewNode(op, current_context()); | 1929 Node* current = NewNode(op, current_context()); |
1906 value = BuildHoleCheckSilent(current, value, current); | 1930 value = BuildHoleCheckSilent(current, value, current); |
1907 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { | 1931 } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) { |
1908 // Non-initializing assignments to legacy const is ignored. | 1932 // Non-initializing assignments to legacy const is ignored. |
1909 return value; | 1933 return value; |
1910 } else if (mode == LET && op != Token::INIT_LET) { | 1934 } else if (mode == LET && op != Token::INIT_LET) { |
1911 // Perform an initialization check for let declared variables. | 1935 // Perform an initialization check for let declared variables. |
1912 const Operator* op = | 1936 const Operator* op = |
1913 javascript()->LoadContext(depth, variable->index(), false); | 1937 javascript()->LoadContext(depth, variable->index(), false); |
1914 Node* current = NewNode(op, current_context()); | 1938 Node* current = NewNode(op, current_context()); |
1915 value = BuildHoleCheckThrow(current, variable, value); | 1939 value = BuildHoleCheckThrow(current, variable, value, bailout_id); |
1916 } else if (mode == CONST && op != Token::INIT_CONST) { | 1940 } else if (mode == CONST && op != Token::INIT_CONST) { |
1917 // All assignments to const variables are early errors. | 1941 // All assignments to const variables are early errors. |
1918 UNREACHABLE(); | 1942 UNREACHABLE(); |
1919 } | 1943 } |
1920 const Operator* op = javascript()->StoreContext(depth, variable->index()); | 1944 const Operator* op = javascript()->StoreContext(depth, variable->index()); |
1921 return NewNode(op, current_context(), value); | 1945 return NewNode(op, current_context(), value); |
1922 } | 1946 } |
1923 case Variable::LOOKUP: { | 1947 case Variable::LOOKUP: { |
1924 // Dynamic lookup of context variable (anywhere in the chain). | 1948 // Dynamic lookup of context variable (anywhere in the chain). |
1925 Node* name = jsgraph()->Constant(variable->name()); | 1949 Node* name = jsgraph()->Constant(variable->name()); |
1926 Node* strict = jsgraph()->Constant(strict_mode()); | 1950 Node* strict = jsgraph()->Constant(strict_mode()); |
1927 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for | 1951 // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for |
1928 // initializations of const declarations. | 1952 // initializations of const declarations. |
1929 const Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4); | 1953 const Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4); |
1930 return NewNode(op, value, current_context(), name, strict); | 1954 Node* store = NewNode(op, value, current_context(), name, strict); |
| 1955 PrepareFrameState(store, bailout_id); |
| 1956 return store; |
1931 } | 1957 } |
1932 } | 1958 } |
1933 UNREACHABLE(); | 1959 UNREACHABLE(); |
1934 return NULL; | 1960 return NULL; |
1935 } | 1961 } |
1936 | 1962 |
1937 | 1963 |
1938 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) { | 1964 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) { |
1939 // TODO(sigurds) Use simplified load here once it is ready. | 1965 // TODO(sigurds) Use simplified load here once it is ready. |
1940 Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object, | 1966 Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object, |
(...skipping 17 matching lines...) Expand all Loading... |
1958 return NewNode(load_op, context); | 1984 return NewNode(load_op, context); |
1959 } | 1985 } |
1960 | 1986 |
1961 | 1987 |
1962 Node* AstGraphBuilder::BuildToBoolean(Node* value) { | 1988 Node* AstGraphBuilder::BuildToBoolean(Node* value) { |
1963 // TODO(mstarzinger): Possible optimization is to NOP for boolean values. | 1989 // TODO(mstarzinger): Possible optimization is to NOP for boolean values. |
1964 return NewNode(javascript()->ToBoolean(), value); | 1990 return NewNode(javascript()->ToBoolean(), value); |
1965 } | 1991 } |
1966 | 1992 |
1967 | 1993 |
1968 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) { | 1994 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable, |
| 1995 BailoutId bailout_id) { |
1969 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. | 1996 // TODO(mstarzinger): Should be unified with the VisitThrow implementation. |
1970 Node* variable_name = jsgraph()->Constant(variable->name()); | 1997 Node* variable_name = jsgraph()->Constant(variable->name()); |
1971 const Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1); | 1998 const Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1); |
1972 return NewNode(op, variable_name); | 1999 Node* call = NewNode(op, variable_name); |
| 2000 PrepareFrameState(call, bailout_id); |
| 2001 return call; |
1973 } | 2002 } |
1974 | 2003 |
1975 | 2004 |
1976 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { | 2005 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) { |
1977 const Operator* js_op; | 2006 const Operator* js_op; |
1978 switch (op) { | 2007 switch (op) { |
1979 case Token::BIT_OR: | 2008 case Token::BIT_OR: |
1980 js_op = javascript()->BitwiseOr(); | 2009 js_op = javascript()->BitwiseOr(); |
1981 break; | 2010 break; |
1982 case Token::BIT_AND: | 2011 case Token::BIT_AND: |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2023 DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() == | 2052 DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() == |
2024 IrOpcode::kDead); | 2053 IrOpcode::kDead); |
2025 NodeProperties::ReplaceFrameStateInput( | 2054 NodeProperties::ReplaceFrameStateInput( |
2026 node, environment()->Checkpoint(ast_id, combine)); | 2055 node, environment()->Checkpoint(ast_id, combine)); |
2027 } | 2056 } |
2028 } | 2057 } |
2029 | 2058 |
2030 } | 2059 } |
2031 } | 2060 } |
2032 } // namespace v8::internal::compiler | 2061 } // namespace v8::internal::compiler |
OLD | NEW |