| 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 |