| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/interpreter/control-flow-builders.h" | 8 #include "src/interpreter/control-flow-builders.h" |
| 9 #include "src/objects.h" | 9 #include "src/objects.h" |
| 10 #include "src/parser.h" | 10 #include "src/parser.h" |
| (...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 case ObjectLiteral::Property::CONSTANT: | 706 case ObjectLiteral::Property::CONSTANT: |
| 707 UNREACHABLE(); | 707 UNREACHABLE(); |
| 708 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 708 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 709 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); | 709 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 710 // Fall through. | 710 // Fall through. |
| 711 case ObjectLiteral::Property::COMPUTED: { | 711 case ObjectLiteral::Property::COMPUTED: { |
| 712 // It is safe to use [[Put]] here because the boilerplate already | 712 // It is safe to use [[Put]] here because the boilerplate already |
| 713 // contains computed properties with an uninitialized value. | 713 // contains computed properties with an uninitialized value. |
| 714 if (literal_key->value()->IsInternalizedString()) { | 714 if (literal_key->value()->IsInternalizedString()) { |
| 715 if (property->emit_store()) { | 715 if (property->emit_store()) { |
| 716 Register name = inner_temporary_register_scope.NewRegister(); | 716 size_t name_index = |
| 717 builder() | 717 builder()->GetConstantPoolEntry(literal_key->AsPropertyName()); |
| 718 ->LoadLiteral(literal_key->AsPropertyName()) | |
| 719 .StoreAccumulatorInRegister(name); | |
| 720 VisitForAccumulatorValue(property->value()); | 718 VisitForAccumulatorValue(property->value()); |
| 721 builder()->StoreNamedProperty(literal, name, | 719 builder()->StoreNamedProperty(literal, name_index, |
| 722 feedback_index(property->GetSlot(0)), | 720 feedback_index(property->GetSlot(0)), |
| 723 language_mode()); | 721 language_mode()); |
| 724 } else { | 722 } else { |
| 725 VisitForEffect(property->value()); | 723 VisitForEffect(property->value()); |
| 726 } | 724 } |
| 727 } else { | 725 } else { |
| 728 inner_temporary_register_scope.PrepareForConsecutiveAllocations(3); | 726 inner_temporary_register_scope.PrepareForConsecutiveAllocations(3); |
| 729 Register key = | 727 Register key = |
| 730 inner_temporary_register_scope.NextConsecutiveRegister(); | 728 inner_temporary_register_scope.NextConsecutiveRegister(); |
| 731 Register value = | 729 Register value = |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 } | 930 } |
| 933 case VariableLocation::PARAMETER: { | 931 case VariableLocation::PARAMETER: { |
| 934 // The parameter indices are shifted by 1 (receiver is variable | 932 // The parameter indices are shifted by 1 (receiver is variable |
| 935 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 933 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 936 Register source = builder()->Parameter(variable->index() + 1); | 934 Register source = builder()->Parameter(variable->index() + 1); |
| 937 execution_result()->SetResultInRegister(source); | 935 execution_result()->SetResultInRegister(source); |
| 938 break; | 936 break; |
| 939 } | 937 } |
| 940 case VariableLocation::GLOBAL: | 938 case VariableLocation::GLOBAL: |
| 941 case VariableLocation::UNALLOCATED: { | 939 case VariableLocation::UNALLOCATED: { |
| 942 TemporaryRegisterScope temporary_register_scope(builder()); | 940 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); |
| 943 Register obj = temporary_register_scope.NewRegister(); | 941 builder()->LoadGlobal(name_index, feedback_index(slot), language_mode()); |
| 944 builder()->LoadContextSlot(execution_context()->reg(), | |
| 945 Context::GLOBAL_OBJECT_INDEX); | |
| 946 builder()->StoreAccumulatorInRegister(obj); | |
| 947 builder()->LoadLiteral(variable->name()); | |
| 948 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | |
| 949 execution_result()->SetResultInAccumulator(); | 942 execution_result()->SetResultInAccumulator(); |
| 950 break; | 943 break; |
| 951 } | 944 } |
| 952 case VariableLocation::CONTEXT: { | 945 case VariableLocation::CONTEXT: { |
| 953 ContextScope* context = execution_context()->Previous(variable->scope()); | 946 ContextScope* context = execution_context()->Previous(variable->scope()); |
| 954 if (context) { | 947 if (context) { |
| 955 builder()->LoadContextSlot(context->reg(), variable->index()); | 948 builder()->LoadContextSlot(context->reg(), variable->index()); |
| 956 execution_result()->SetResultInAccumulator(); | 949 execution_result()->SetResultInAccumulator(); |
| 957 } else { | 950 } else { |
| 958 UNIMPLEMENTED(); | 951 UNIMPLEMENTED(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 980 case VariableLocation::PARAMETER: { | 973 case VariableLocation::PARAMETER: { |
| 981 // The parameter indices are shifted by 1 (receiver is variable | 974 // The parameter indices are shifted by 1 (receiver is variable |
| 982 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 975 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 983 Register destination(builder()->Parameter(variable->index() + 1)); | 976 Register destination(builder()->Parameter(variable->index() + 1)); |
| 984 builder()->StoreAccumulatorInRegister(destination); | 977 builder()->StoreAccumulatorInRegister(destination); |
| 985 RecordStoreToRegister(destination); | 978 RecordStoreToRegister(destination); |
| 986 break; | 979 break; |
| 987 } | 980 } |
| 988 case VariableLocation::GLOBAL: | 981 case VariableLocation::GLOBAL: |
| 989 case VariableLocation::UNALLOCATED: { | 982 case VariableLocation::UNALLOCATED: { |
| 990 Register value = execution_result()->NewRegister(); | 983 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); |
| 991 Register obj = execution_result()->NewRegister(); | 984 builder()->StoreGlobal(name_index, feedback_index(slot), language_mode()); |
| 992 Register name = execution_result()->NewRegister(); | |
| 993 | |
| 994 // TODO(rmcilroy): Investigate whether we can avoid having to stash the | |
| 995 // value in a register. | |
| 996 builder()->StoreAccumulatorInRegister(value); | |
| 997 builder()->LoadContextSlot(execution_context()->reg(), | |
| 998 Context::GLOBAL_OBJECT_INDEX); | |
| 999 builder()->StoreAccumulatorInRegister(obj); | |
| 1000 builder()->LoadLiteral(variable->name()); | |
| 1001 builder()->StoreAccumulatorInRegister(name); | |
| 1002 builder()->LoadAccumulatorWithRegister(value); | |
| 1003 builder()->StoreNamedProperty(obj, name, feedback_index(slot), | |
| 1004 language_mode()); | |
| 1005 break; | 985 break; |
| 1006 } | 986 } |
| 1007 case VariableLocation::CONTEXT: { | 987 case VariableLocation::CONTEXT: { |
| 1008 // TODO(rmcilroy): support const mode initialization. | 988 // TODO(rmcilroy): support const mode initialization. |
| 1009 ContextScope* context = execution_context()->Previous(variable->scope()); | 989 ContextScope* context = execution_context()->Previous(variable->scope()); |
| 1010 if (context) { | 990 if (context) { |
| 1011 builder()->StoreContextSlot(context->reg(), variable->index()); | 991 builder()->StoreContextSlot(context->reg(), variable->index()); |
| 1012 } else { | 992 } else { |
| 1013 UNIMPLEMENTED(); | 993 UNIMPLEMENTED(); |
| 1014 } | 994 } |
| 1015 break; | 995 break; |
| 1016 } | 996 } |
| 1017 case VariableLocation::LOOKUP: | 997 case VariableLocation::LOOKUP: |
| 1018 UNIMPLEMENTED(); | 998 UNIMPLEMENTED(); |
| 1019 } | 999 } |
| 1020 } | 1000 } |
| 1021 | 1001 |
| 1022 | 1002 |
| 1023 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 1003 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 1024 DCHECK(expr->target()->IsValidReferenceExpression()); | 1004 DCHECK(expr->target()->IsValidReferenceExpression()); |
| 1025 Register object, key; | 1005 Register object, key; |
| 1006 size_t name_index = kMaxUInt32; |
| 1026 | 1007 |
| 1027 // Left-hand side can only be a property, a global or a variable slot. | 1008 // Left-hand side can only be a property, a global or a variable slot. |
| 1028 Property* property = expr->target()->AsProperty(); | 1009 Property* property = expr->target()->AsProperty(); |
| 1029 LhsKind assign_type = Property::GetAssignType(property); | 1010 LhsKind assign_type = Property::GetAssignType(property); |
| 1030 | 1011 |
| 1031 // Evaluate LHS expression. | 1012 // Evaluate LHS expression. |
| 1032 switch (assign_type) { | 1013 switch (assign_type) { |
| 1033 case VARIABLE: | 1014 case VARIABLE: |
| 1034 // Nothing to do to evaluate variable assignment LHS. | 1015 // Nothing to do to evaluate variable assignment LHS. |
| 1035 break; | 1016 break; |
| 1036 case NAMED_PROPERTY: { | 1017 case NAMED_PROPERTY: { |
| 1037 object = VisitForRegisterValue(property->obj()); | 1018 object = VisitForRegisterValue(property->obj()); |
| 1038 key = execution_result()->NewRegister(); | 1019 name_index = builder()->GetConstantPoolEntry( |
| 1039 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()); | 1020 property->key()->AsLiteral()->AsPropertyName()); |
| 1040 builder()->StoreAccumulatorInRegister(key); | |
| 1041 break; | 1021 break; |
| 1042 } | 1022 } |
| 1043 case KEYED_PROPERTY: { | 1023 case KEYED_PROPERTY: { |
| 1044 object = VisitForRegisterValue(property->obj()); | 1024 object = VisitForRegisterValue(property->obj()); |
| 1045 key = VisitForRegisterValue(property->key()); | 1025 key = VisitForRegisterValue(property->key()); |
| 1046 break; | 1026 break; |
| 1047 } | 1027 } |
| 1048 case NAMED_SUPER_PROPERTY: | 1028 case NAMED_SUPER_PROPERTY: |
| 1049 case KEYED_SUPER_PROPERTY: | 1029 case KEYED_SUPER_PROPERTY: |
| 1050 UNIMPLEMENTED(); | 1030 UNIMPLEMENTED(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1062 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 1042 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
| 1063 switch (assign_type) { | 1043 switch (assign_type) { |
| 1064 case VARIABLE: { | 1044 case VARIABLE: { |
| 1065 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. | 1045 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. |
| 1066 // Is the value in the accumulator safe? Yes, but scary. | 1046 // Is the value in the accumulator safe? Yes, but scary. |
| 1067 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1047 Variable* variable = expr->target()->AsVariableProxy()->var(); |
| 1068 VisitVariableAssignment(variable, slot); | 1048 VisitVariableAssignment(variable, slot); |
| 1069 break; | 1049 break; |
| 1070 } | 1050 } |
| 1071 case NAMED_PROPERTY: | 1051 case NAMED_PROPERTY: |
| 1072 builder()->StoreNamedProperty(object, key, feedback_index(slot), | 1052 builder()->StoreNamedProperty(object, name_index, feedback_index(slot), |
| 1073 language_mode()); | 1053 language_mode()); |
| 1074 break; | 1054 break; |
| 1075 case KEYED_PROPERTY: | 1055 case KEYED_PROPERTY: |
| 1076 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | 1056 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
| 1077 language_mode()); | 1057 language_mode()); |
| 1078 break; | 1058 break; |
| 1079 case NAMED_SUPER_PROPERTY: | 1059 case NAMED_SUPER_PROPERTY: |
| 1080 case KEYED_SUPER_PROPERTY: | 1060 case KEYED_SUPER_PROPERTY: |
| 1081 UNIMPLEMENTED(); | 1061 UNIMPLEMENTED(); |
| 1082 } | 1062 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1093 } | 1073 } |
| 1094 | 1074 |
| 1095 | 1075 |
| 1096 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { | 1076 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { |
| 1097 LhsKind property_kind = Property::GetAssignType(expr); | 1077 LhsKind property_kind = Property::GetAssignType(expr); |
| 1098 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); | 1078 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); |
| 1099 switch (property_kind) { | 1079 switch (property_kind) { |
| 1100 case VARIABLE: | 1080 case VARIABLE: |
| 1101 UNREACHABLE(); | 1081 UNREACHABLE(); |
| 1102 case NAMED_PROPERTY: { | 1082 case NAMED_PROPERTY: { |
| 1103 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); | 1083 size_t name_index = builder()->GetConstantPoolEntry( |
| 1104 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 1084 expr->key()->AsLiteral()->AsPropertyName()); |
| 1085 builder()->LoadNamedProperty(obj, name_index, feedback_index(slot), |
| 1086 language_mode()); |
| 1105 break; | 1087 break; |
| 1106 } | 1088 } |
| 1107 case KEYED_PROPERTY: { | 1089 case KEYED_PROPERTY: { |
| 1108 VisitForAccumulatorValue(expr->key()); | 1090 VisitForAccumulatorValue(expr->key()); |
| 1109 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); | 1091 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); |
| 1110 break; | 1092 break; |
| 1111 } | 1093 } |
| 1112 case NAMED_SUPER_PROPERTY: | 1094 case NAMED_SUPER_PROPERTY: |
| 1113 case KEYED_SUPER_PROPERTY: | 1095 case KEYED_SUPER_PROPERTY: |
| 1114 UNIMPLEMENTED(); | 1096 UNIMPLEMENTED(); |
| 1115 } | 1097 } |
| 1116 execution_result()->SetResultInAccumulator(); | 1098 execution_result()->SetResultInAccumulator(); |
| 1117 } | 1099 } |
| 1118 | 1100 |
| 1119 | 1101 |
| 1102 void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj, |
| 1103 Property* expr) { |
| 1104 AccumulatorResultScope result_scope(this); |
| 1105 VisitPropertyLoad(obj, expr); |
| 1106 } |
| 1107 |
| 1108 |
| 1120 void BytecodeGenerator::VisitProperty(Property* expr) { | 1109 void BytecodeGenerator::VisitProperty(Property* expr) { |
| 1121 Register obj = VisitForRegisterValue(expr->obj()); | 1110 Register obj = VisitForRegisterValue(expr->obj()); |
| 1122 VisitPropertyLoad(obj, expr); | 1111 VisitPropertyLoad(obj, expr); |
| 1123 } | 1112 } |
| 1124 | 1113 |
| 1125 | 1114 |
| 1126 Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) { | 1115 Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) { |
| 1127 // Visit arguments and place in a contiguous block of temporary | 1116 // Visit arguments and place in a contiguous block of temporary |
| 1128 // registers. Return the first temporary register corresponding to | 1117 // registers. Return the first temporary register corresponding to |
| 1129 // the first argument. | 1118 // the first argument. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1166 ZoneList<Expression*>* args = expr->arguments(); | 1155 ZoneList<Expression*>* args = expr->arguments(); |
| 1167 execution_result()->PrepareForConsecutiveAllocations(args->length() + 1); | 1156 execution_result()->PrepareForConsecutiveAllocations(args->length() + 1); |
| 1168 Register receiver = execution_result()->NextConsecutiveRegister(); | 1157 Register receiver = execution_result()->NextConsecutiveRegister(); |
| 1169 | 1158 |
| 1170 switch (call_type) { | 1159 switch (call_type) { |
| 1171 case Call::PROPERTY_CALL: { | 1160 case Call::PROPERTY_CALL: { |
| 1172 Property* property = callee_expr->AsProperty(); | 1161 Property* property = callee_expr->AsProperty(); |
| 1173 if (property->IsSuperAccess()) { | 1162 if (property->IsSuperAccess()) { |
| 1174 UNIMPLEMENTED(); | 1163 UNIMPLEMENTED(); |
| 1175 } | 1164 } |
| 1165 |
| 1176 VisitForAccumulatorValue(property->obj()); | 1166 VisitForAccumulatorValue(property->obj()); |
| 1177 builder()->StoreAccumulatorInRegister(receiver); | 1167 builder()->StoreAccumulatorInRegister(receiver); |
| 1178 // Need a result scope here to keep our consecutive | 1168 VisitPropertyLoadForAccumulator(receiver, property); |
| 1179 // temporaries. | |
| 1180 AccumulatorResultScope accumulator_execution_result(this); | |
| 1181 // Perform a property load of the callee. | |
| 1182 VisitPropertyLoad(receiver, property); | |
| 1183 builder()->StoreAccumulatorInRegister(callee); | 1169 builder()->StoreAccumulatorInRegister(callee); |
| 1184 break; | 1170 break; |
| 1185 } | 1171 } |
| 1186 case Call::GLOBAL_CALL: { | 1172 case Call::GLOBAL_CALL: { |
| 1187 // Receiver is undefined for global calls. | 1173 // Receiver is undefined for global calls. |
| 1188 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 1174 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
| 1189 // Load callee as a global variable. | 1175 // Load callee as a global variable. |
| 1190 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 1176 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
| 1191 // Result scope for VisitVariableLoad to avoid using our temporaries | 1177 // Result scope for VisitVariableLoad to avoid using our temporaries |
| 1192 // and double setting the result in our result_scope() and. | 1178 // and double setting the result in our result_scope() and. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 | 1252 |
| 1267 | 1253 |
| 1268 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { | 1254 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { |
| 1269 VisitForEffect(expr->expression()); | 1255 VisitForEffect(expr->expression()); |
| 1270 builder()->LoadUndefined(); | 1256 builder()->LoadUndefined(); |
| 1271 execution_result()->SetResultInAccumulator(); | 1257 execution_result()->SetResultInAccumulator(); |
| 1272 } | 1258 } |
| 1273 | 1259 |
| 1274 | 1260 |
| 1275 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { | 1261 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { |
| 1262 // TODO(rmcilroy): Set TypeofMode to INSIDE_TYPEOF for any loadICs performed |
| 1263 // while visiting the expression. |
| 1276 VisitForAccumulatorValue(expr->expression()); | 1264 VisitForAccumulatorValue(expr->expression()); |
| 1277 builder()->TypeOf(); | 1265 builder()->TypeOf(); |
| 1278 execution_result()->SetResultInAccumulator(); | 1266 execution_result()->SetResultInAccumulator(); |
| 1279 } | 1267 } |
| 1280 | 1268 |
| 1281 | 1269 |
| 1282 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { | 1270 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { |
| 1283 VisitForAccumulatorValue(expr->expression()); | 1271 VisitForAccumulatorValue(expr->expression()); |
| 1284 builder()->LogicalNot(); | 1272 builder()->LogicalNot(); |
| 1285 execution_result()->SetResultInAccumulator(); | 1273 execution_result()->SetResultInAccumulator(); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1382 UNIMPLEMENTED(); | 1370 UNIMPLEMENTED(); |
| 1383 } | 1371 } |
| 1384 | 1372 |
| 1385 | 1373 |
| 1386 void BytecodeGenerator::VisitSuperPropertyReference( | 1374 void BytecodeGenerator::VisitSuperPropertyReference( |
| 1387 SuperPropertyReference* expr) { | 1375 SuperPropertyReference* expr) { |
| 1388 UNIMPLEMENTED(); | 1376 UNIMPLEMENTED(); |
| 1389 } | 1377 } |
| 1390 | 1378 |
| 1391 | 1379 |
| 1380 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { |
| 1381 VisitForEffect(binop->left()); |
| 1382 Visit(binop->right()); |
| 1383 } |
| 1384 |
| 1385 |
| 1386 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { |
| 1387 Expression* left = binop->left(); |
| 1388 Expression* right = binop->right(); |
| 1389 |
| 1390 // Short-circuit evaluation- If it is known that left is always true, |
| 1391 // no need to visit right |
| 1392 if (left->ToBooleanIsTrue()) { |
| 1393 VisitForAccumulatorValue(left); |
| 1394 } else { |
| 1395 BytecodeLabel end_label; |
| 1396 VisitForAccumulatorValue(left); |
| 1397 builder()->JumpIfToBooleanTrue(&end_label); |
| 1398 VisitForAccumulatorValue(right); |
| 1399 builder()->Bind(&end_label); |
| 1400 } |
| 1401 execution_result()->SetResultInAccumulator(); |
| 1402 } |
| 1403 |
| 1404 |
| 1405 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { |
| 1406 Expression* left = binop->left(); |
| 1407 Expression* right = binop->right(); |
| 1408 |
| 1409 // Short-circuit evaluation- If it is known that left is always false, |
| 1410 // no need to visit right |
| 1411 if (left->ToBooleanIsFalse()) { |
| 1412 VisitForAccumulatorValue(left); |
| 1413 } else { |
| 1414 BytecodeLabel end_label; |
| 1415 VisitForAccumulatorValue(left); |
| 1416 builder()->JumpIfToBooleanFalse(&end_label); |
| 1417 VisitForAccumulatorValue(right); |
| 1418 builder()->Bind(&end_label); |
| 1419 } |
| 1420 execution_result()->SetResultInAccumulator(); |
| 1421 } |
| 1422 |
| 1423 |
| 1392 void BytecodeGenerator::VisitNewLocalFunctionContext() { | 1424 void BytecodeGenerator::VisitNewLocalFunctionContext() { |
| 1425 AccumulatorResultScope accumulator_execution_result(this); |
| 1393 Scope* scope = this->scope(); | 1426 Scope* scope = this->scope(); |
| 1394 | 1427 |
| 1395 // Allocate a new local context. | 1428 // Allocate a new local context. |
| 1396 if (scope->is_script_scope()) { | 1429 if (scope->is_script_scope()) { |
| 1397 TemporaryRegisterScope temporary_register_scope(builder()); | 1430 TemporaryRegisterScope temporary_register_scope(builder()); |
| 1398 Register closure = temporary_register_scope.NewRegister(); | 1431 Register closure = temporary_register_scope.NewRegister(); |
| 1399 Register scope_info = temporary_register_scope.NewRegister(); | 1432 Register scope_info = temporary_register_scope.NewRegister(); |
| 1400 DCHECK(Register::AreContiguous(closure, scope_info)); | 1433 DCHECK(Register::AreContiguous(closure, scope_info)); |
| 1401 builder() | 1434 builder() |
| 1402 ->LoadAccumulatorWithRegister(Register::function_closure()) | 1435 ->LoadAccumulatorWithRegister(Register::function_closure()) |
| 1403 .StoreAccumulatorInRegister(closure) | 1436 .StoreAccumulatorInRegister(closure) |
| 1404 .LoadLiteral(scope->GetScopeInfo(isolate())) | 1437 .LoadLiteral(scope->GetScopeInfo(isolate())) |
| 1405 .StoreAccumulatorInRegister(scope_info) | 1438 .StoreAccumulatorInRegister(scope_info) |
| 1406 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 1439 .CallRuntime(Runtime::kNewScriptContext, closure, 2); |
| 1407 } else { | 1440 } else { |
| 1408 builder()->CallRuntime(Runtime::kNewFunctionContext, | 1441 builder()->CallRuntime(Runtime::kNewFunctionContext, |
| 1409 Register::function_closure(), 1); | 1442 Register::function_closure(), 1); |
| 1410 } | 1443 } |
| 1444 execution_result()->SetResultInAccumulator(); |
| 1411 } | 1445 } |
| 1412 | 1446 |
| 1413 | 1447 |
| 1414 void BytecodeGenerator::VisitBuildLocalActivationContext() { | 1448 void BytecodeGenerator::VisitBuildLocalActivationContext() { |
| 1415 Scope* scope = this->scope(); | 1449 Scope* scope = this->scope(); |
| 1416 | 1450 |
| 1417 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 1451 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
| 1418 UNIMPLEMENTED(); | 1452 UNIMPLEMENTED(); |
| 1419 } | 1453 } |
| 1420 | 1454 |
| 1421 // Copy parameters into context if necessary. | 1455 // Copy parameters into context if necessary. |
| 1422 int num_parameters = scope->num_parameters(); | 1456 int num_parameters = scope->num_parameters(); |
| 1423 for (int i = 0; i < num_parameters; i++) { | 1457 for (int i = 0; i < num_parameters; i++) { |
| 1424 Variable* variable = scope->parameter(i); | 1458 Variable* variable = scope->parameter(i); |
| 1425 if (!variable->IsContextSlot()) continue; | 1459 if (!variable->IsContextSlot()) continue; |
| 1426 | 1460 |
| 1427 // The parameter indices are shifted by 1 (receiver is variable | 1461 // The parameter indices are shifted by 1 (receiver is variable |
| 1428 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1462 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 1429 Register parameter(builder()->Parameter(i + 1)); | 1463 Register parameter(builder()->Parameter(i + 1)); |
| 1430 // Context variable (at bottom of the context chain). | 1464 // Context variable (at bottom of the context chain). |
| 1431 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 1465 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 1432 builder()->LoadAccumulatorWithRegister(parameter) | 1466 builder()->LoadAccumulatorWithRegister(parameter) |
| 1433 .StoreContextSlot(execution_context()->reg(), variable->index()); | 1467 .StoreContextSlot(execution_context()->reg(), variable->index()); |
| 1434 } | 1468 } |
| 1435 } | 1469 } |
| 1436 | 1470 |
| 1437 | 1471 |
| 1438 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) { | 1472 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) { |
| 1473 AccumulatorResultScope accumulator_execution_result(this); |
| 1439 DCHECK(scope->is_block_scope()); | 1474 DCHECK(scope->is_block_scope()); |
| 1440 | 1475 |
| 1441 // Allocate a new local block context. | 1476 // Allocate a new local block context. |
| 1442 TemporaryRegisterScope temporary_register_scope(builder()); | 1477 TemporaryRegisterScope temporary_register_scope(builder()); |
| 1443 Register scope_info = temporary_register_scope.NewRegister(); | 1478 Register scope_info = temporary_register_scope.NewRegister(); |
| 1444 Register closure = temporary_register_scope.NewRegister(); | 1479 Register closure = temporary_register_scope.NewRegister(); |
| 1445 DCHECK(Register::AreContiguous(scope_info, closure)); | 1480 DCHECK(Register::AreContiguous(scope_info, closure)); |
| 1446 builder() | 1481 builder() |
| 1447 ->LoadLiteral(scope->GetScopeInfo(isolate())) | 1482 ->LoadLiteral(scope->GetScopeInfo(isolate())) |
| 1448 .StoreAccumulatorInRegister(scope_info); | 1483 .StoreAccumulatorInRegister(scope_info); |
| 1449 VisitFunctionClosureForContext(); | 1484 VisitFunctionClosureForContext(); |
| 1450 builder() | 1485 builder() |
| 1451 ->StoreAccumulatorInRegister(closure) | 1486 ->StoreAccumulatorInRegister(closure) |
| 1452 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2); | 1487 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2); |
| 1453 } | |
| 1454 | |
| 1455 | |
| 1456 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { | |
| 1457 VisitForEffect(binop->left()); | |
| 1458 Visit(binop->right()); | |
| 1459 } | |
| 1460 | |
| 1461 | |
| 1462 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { | |
| 1463 Expression* left = binop->left(); | |
| 1464 Expression* right = binop->right(); | |
| 1465 | |
| 1466 // Short-circuit evaluation- If it is known that left is always true, | |
| 1467 // no need to visit right | |
| 1468 if (left->ToBooleanIsTrue()) { | |
| 1469 VisitForAccumulatorValue(left); | |
| 1470 } else { | |
| 1471 BytecodeLabel end_label; | |
| 1472 VisitForAccumulatorValue(left); | |
| 1473 builder()->JumpIfToBooleanTrue(&end_label); | |
| 1474 VisitForAccumulatorValue(right); | |
| 1475 builder()->Bind(&end_label); | |
| 1476 } | |
| 1477 execution_result()->SetResultInAccumulator(); | 1488 execution_result()->SetResultInAccumulator(); |
| 1478 } | 1489 } |
| 1479 | 1490 |
| 1480 | |
| 1481 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { | |
| 1482 Expression* left = binop->left(); | |
| 1483 Expression* right = binop->right(); | |
| 1484 | |
| 1485 // Short-circuit evaluation- If it is known that left is always false, | |
| 1486 // no need to visit right | |
| 1487 if (left->ToBooleanIsFalse()) { | |
| 1488 VisitForAccumulatorValue(left); | |
| 1489 } else { | |
| 1490 BytecodeLabel end_label; | |
| 1491 VisitForAccumulatorValue(left); | |
| 1492 builder()->JumpIfToBooleanFalse(&end_label); | |
| 1493 VisitForAccumulatorValue(right); | |
| 1494 builder()->Bind(&end_label); | |
| 1495 } | |
| 1496 execution_result()->SetResultInAccumulator(); | |
| 1497 } | |
| 1498 | |
| 1499 | 1491 |
| 1500 void BytecodeGenerator::VisitObjectLiteralAccessor( | 1492 void BytecodeGenerator::VisitObjectLiteralAccessor( |
| 1501 Register home_object, ObjectLiteralProperty* property, Register value_out) { | 1493 Register home_object, ObjectLiteralProperty* property, Register value_out) { |
| 1502 // TODO(rmcilroy): Replace value_out with VisitForRegister(); | 1494 // TODO(rmcilroy): Replace value_out with VisitForRegister(); |
| 1503 if (property == nullptr) { | 1495 if (property == nullptr) { |
| 1504 builder()->LoadNull().StoreAccumulatorInRegister(value_out); | 1496 builder()->LoadNull().StoreAccumulatorInRegister(value_out); |
| 1505 } else { | 1497 } else { |
| 1506 VisitForAccumulatorValue(property->value()); | 1498 VisitForAccumulatorValue(property->value()); |
| 1507 builder()->StoreAccumulatorInRegister(value_out); | 1499 builder()->StoreAccumulatorInRegister(value_out); |
| 1508 VisitSetHomeObject(value_out, home_object, property); | 1500 VisitSetHomeObject(value_out, home_object, property); |
| 1509 } | 1501 } |
| 1510 } | 1502 } |
| 1511 | 1503 |
| 1512 | 1504 |
| 1513 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, | 1505 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, |
| 1514 ObjectLiteralProperty* property, | 1506 ObjectLiteralProperty* property, |
| 1515 int slot_number) { | 1507 int slot_number) { |
| 1516 Expression* expr = property->value(); | 1508 Expression* expr = property->value(); |
| 1517 if (!FunctionLiteral::NeedsHomeObject(expr)) return; | 1509 if (!FunctionLiteral::NeedsHomeObject(expr)) return; |
| 1518 | 1510 |
| 1519 // TODO(rmcilroy): Remove UNIMPLEMENTED once we have tests for setting the | |
| 1520 // home object. | |
| 1521 UNIMPLEMENTED(); | 1511 UNIMPLEMENTED(); |
| 1522 | |
| 1523 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 1524 Register name = temporary_register_scope.NewRegister(); | |
| 1525 isolate()->factory()->home_object_symbol(); | |
| 1526 builder() | |
| 1527 ->LoadLiteral(isolate()->factory()->home_object_symbol()) | |
| 1528 .StoreAccumulatorInRegister(name) | |
| 1529 .StoreNamedProperty(home_object, name, | |
| 1530 feedback_index(property->GetSlot(slot_number)), | |
| 1531 language_mode()); | |
| 1532 } | 1512 } |
| 1533 | 1513 |
| 1534 | 1514 |
| 1535 void BytecodeGenerator::VisitFunctionClosureForContext() { | 1515 void BytecodeGenerator::VisitFunctionClosureForContext() { |
| 1516 AccumulatorResultScope accumulator_execution_result(this); |
| 1536 Scope* closure_scope = execution_context()->scope()->ClosureScope(); | 1517 Scope* closure_scope = execution_context()->scope()->ClosureScope(); |
| 1537 if (closure_scope->is_script_scope() || | 1518 if (closure_scope->is_script_scope() || |
| 1538 closure_scope->is_module_scope()) { | 1519 closure_scope->is_module_scope()) { |
| 1539 // Contexts nested in the native context have a canonical empty function as | 1520 // Contexts nested in the native context have a canonical empty function as |
| 1540 // their closure, not the anonymous closure containing the global code. | 1521 // their closure, not the anonymous closure containing the global code. |
| 1541 // Pass a SMI sentinel and let the runtime look up the empty function. | 1522 // Pass a SMI sentinel and let the runtime look up the empty function. |
| 1542 builder()->LoadLiteral(Smi::FromInt(0)); | 1523 builder()->LoadLiteral(Smi::FromInt(0)); |
| 1543 } else { | 1524 } else { |
| 1544 DCHECK(closure_scope->is_function_scope()); | 1525 DCHECK(closure_scope->is_function_scope()); |
| 1545 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 1526 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 1546 } | 1527 } |
| 1528 execution_result()->SetResultInAccumulator(); |
| 1547 } | 1529 } |
| 1548 | 1530 |
| 1549 | 1531 |
| 1550 void BytecodeGenerator::PrepareForBinaryExpression() { | 1532 void BytecodeGenerator::PrepareForBinaryExpression() { |
| 1551 if (binary_expression_depth_++ == 0) { | 1533 if (binary_expression_depth_++ == 0) { |
| 1552 binary_expression_hazard_set_.clear(); | 1534 binary_expression_hazard_set_.clear(); |
| 1553 } | 1535 } |
| 1554 } | 1536 } |
| 1555 | 1537 |
| 1556 | 1538 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1634 } | 1616 } |
| 1635 | 1617 |
| 1636 | 1618 |
| 1637 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 1619 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 1638 return info()->feedback_vector()->GetIndex(slot); | 1620 return info()->feedback_vector()->GetIndex(slot); |
| 1639 } | 1621 } |
| 1640 | 1622 |
| 1641 } // namespace interpreter | 1623 } // namespace interpreter |
| 1642 } // namespace internal | 1624 } // namespace internal |
| 1643 } // namespace v8 | 1625 } // namespace v8 |
| OLD | NEW |