| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 } | 833 } |
| 834 block->set_argument_count(argument_count_); | 834 block->set_argument_count(argument_count_); |
| 835 next_block_ = NULL; | 835 next_block_ = NULL; |
| 836 current_block_ = NULL; | 836 current_block_ = NULL; |
| 837 } | 837 } |
| 838 | 838 |
| 839 | 839 |
| 840 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 840 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
| 841 HInstruction* old_current = current_instruction_; | 841 HInstruction* old_current = current_instruction_; |
| 842 current_instruction_ = current; | 842 current_instruction_ = current; |
| 843 if (current->has_position()) position_ = current->position(); | |
| 844 | 843 |
| 845 LInstruction* instr = NULL; | 844 LInstruction* instr = NULL; |
| 846 if (current->CanReplaceWithDummyUses()) { | 845 if (current->CanReplaceWithDummyUses()) { |
| 847 if (current->OperandCount() == 0) { | 846 if (current->OperandCount() == 0) { |
| 848 instr = DefineAsRegister(new(zone()) LDummy()); | 847 instr = DefineAsRegister(new(zone()) LDummy()); |
| 849 } else { | 848 } else { |
| 849 ASSERT(!current->OperandAt(0)->IsControlInstruction()); |
| 850 instr = DefineAsRegister(new(zone()) | 850 instr = DefineAsRegister(new(zone()) |
| 851 LDummyUse(UseAny(current->OperandAt(0)))); | 851 LDummyUse(UseAny(current->OperandAt(0)))); |
| 852 } | 852 } |
| 853 for (int i = 1; i < current->OperandCount(); ++i) { | 853 for (int i = 1; i < current->OperandCount(); ++i) { |
| 854 if (current->OperandAt(i)->IsControlInstruction()) continue; |
| 854 LInstruction* dummy = | 855 LInstruction* dummy = |
| 855 new(zone()) LDummyUse(UseAny(current->OperandAt(i))); | 856 new(zone()) LDummyUse(UseAny(current->OperandAt(i))); |
| 856 dummy->set_hydrogen_value(current); | 857 dummy->set_hydrogen_value(current); |
| 857 chunk_->AddInstruction(dummy, current_block_); | 858 chunk_->AddInstruction(dummy, current_block_); |
| 858 } | 859 } |
| 859 } else { | 860 } else { |
| 860 instr = current->CompileToLithium(this); | 861 instr = current->CompileToLithium(this); |
| 861 } | 862 } |
| 862 | 863 |
| 863 argument_count_ += current->argument_delta(); | 864 argument_count_ += current->argument_delta(); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 933 return result; | 934 return result; |
| 934 } | 935 } |
| 935 | 936 |
| 936 | 937 |
| 937 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { | 938 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { |
| 938 return new(zone()) LDebugBreak(); | 939 return new(zone()) LDebugBreak(); |
| 939 } | 940 } |
| 940 | 941 |
| 941 | 942 |
| 942 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 943 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| 944 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
| 945 if (goto_instr != NULL) return goto_instr; |
| 946 |
| 943 ASSERT(instr->value()->representation().IsTagged()); | 947 ASSERT(instr->value()->representation().IsTagged()); |
| 944 LOperand* value = UseRegisterAtStart(instr->value()); | 948 LOperand* value = UseRegisterAtStart(instr->value()); |
| 945 LOperand* temp = TempRegister(); | 949 LOperand* temp = TempRegister(); |
| 946 return new(zone()) LCmpMapAndBranch(value, temp); | 950 return new(zone()) LCmpMapAndBranch(value, temp); |
| 947 } | 951 } |
| 948 | 952 |
| 949 | 953 |
| 950 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) { | 954 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) { |
| 951 info()->MarkAsRequiresFrame(); | 955 info()->MarkAsRequiresFrame(); |
| 952 LOperand* value = UseRegister(instr->value()); | 956 LOperand* value = UseRegister(instr->value()); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 if (instr->HasNoUses()) return NULL; | 1039 if (instr->HasNoUses()) return NULL; |
| 1036 | 1040 |
| 1037 if (info()->IsStub()) { | 1041 if (info()->IsStub()) { |
| 1038 return DefineFixed(new(zone()) LContext, cp); | 1042 return DefineFixed(new(zone()) LContext, cp); |
| 1039 } | 1043 } |
| 1040 | 1044 |
| 1041 return DefineAsRegister(new(zone()) LContext); | 1045 return DefineAsRegister(new(zone()) LContext); |
| 1042 } | 1046 } |
| 1043 | 1047 |
| 1044 | 1048 |
| 1045 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { | |
| 1046 LOperand* context = UseRegisterAtStart(instr->value()); | |
| 1047 return DefineAsRegister(new(zone()) LOuterContext(context)); | |
| 1048 } | |
| 1049 | |
| 1050 | |
| 1051 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { | 1049 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { |
| 1052 LOperand* context = UseFixed(instr->context(), cp); | 1050 LOperand* context = UseFixed(instr->context(), cp); |
| 1053 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr); | 1051 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr); |
| 1054 } | 1052 } |
| 1055 | 1053 |
| 1056 | 1054 |
| 1057 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { | |
| 1058 LOperand* context = UseRegisterAtStart(instr->value()); | |
| 1059 return DefineAsRegister(new(zone()) LGlobalObject(context)); | |
| 1060 } | |
| 1061 | |
| 1062 | |
| 1063 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { | |
| 1064 LOperand* global_object = UseRegisterAtStart(instr->value()); | |
| 1065 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object)); | |
| 1066 } | |
| 1067 | |
| 1068 | |
| 1069 LInstruction* LChunkBuilder::DoCallJSFunction( | 1055 LInstruction* LChunkBuilder::DoCallJSFunction( |
| 1070 HCallJSFunction* instr) { | 1056 HCallJSFunction* instr) { |
| 1071 LOperand* function = UseFixed(instr->function(), r1); | 1057 LOperand* function = UseFixed(instr->function(), r1); |
| 1072 | 1058 |
| 1073 LCallJSFunction* result = new(zone()) LCallJSFunction(function); | 1059 LCallJSFunction* result = new(zone()) LCallJSFunction(function); |
| 1074 | 1060 |
| 1075 return MarkAsCall(DefineFixed(result, r0), instr); | 1061 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1076 } | 1062 } |
| 1077 | 1063 |
| 1078 | 1064 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1105 | 1091 |
| 1106 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 1092 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1107 switch (instr->op()) { | 1093 switch (instr->op()) { |
| 1108 case kMathFloor: return DoMathFloor(instr); | 1094 case kMathFloor: return DoMathFloor(instr); |
| 1109 case kMathRound: return DoMathRound(instr); | 1095 case kMathRound: return DoMathRound(instr); |
| 1110 case kMathAbs: return DoMathAbs(instr); | 1096 case kMathAbs: return DoMathAbs(instr); |
| 1111 case kMathLog: return DoMathLog(instr); | 1097 case kMathLog: return DoMathLog(instr); |
| 1112 case kMathExp: return DoMathExp(instr); | 1098 case kMathExp: return DoMathExp(instr); |
| 1113 case kMathSqrt: return DoMathSqrt(instr); | 1099 case kMathSqrt: return DoMathSqrt(instr); |
| 1114 case kMathPowHalf: return DoMathPowHalf(instr); | 1100 case kMathPowHalf: return DoMathPowHalf(instr); |
| 1101 case kMathClz32: return DoMathClz32(instr); |
| 1115 default: | 1102 default: |
| 1116 UNREACHABLE(); | 1103 UNREACHABLE(); |
| 1117 return NULL; | 1104 return NULL; |
| 1118 } | 1105 } |
| 1119 } | 1106 } |
| 1120 | 1107 |
| 1121 | 1108 |
| 1122 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { | 1109 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { |
| 1123 LOperand* input = UseRegister(instr->value()); | 1110 LOperand* input = UseRegister(instr->value()); |
| 1124 LMathFloor* result = new(zone()) LMathFloor(input); | 1111 LMathFloor* result = new(zone()) LMathFloor(input); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1146 | 1133 |
| 1147 | 1134 |
| 1148 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { | 1135 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { |
| 1149 ASSERT(instr->representation().IsDouble()); | 1136 ASSERT(instr->representation().IsDouble()); |
| 1150 ASSERT(instr->value()->representation().IsDouble()); | 1137 ASSERT(instr->value()->representation().IsDouble()); |
| 1151 LOperand* input = UseFixedDouble(instr->value(), d0); | 1138 LOperand* input = UseFixedDouble(instr->value(), d0); |
| 1152 return MarkAsCall(DefineFixedDouble(new(zone()) LMathLog(input), d0), instr); | 1139 return MarkAsCall(DefineFixedDouble(new(zone()) LMathLog(input), d0), instr); |
| 1153 } | 1140 } |
| 1154 | 1141 |
| 1155 | 1142 |
| 1143 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) { |
| 1144 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1145 LMathClz32* result = new(zone()) LMathClz32(input); |
| 1146 return DefineAsRegister(result); |
| 1147 } |
| 1148 |
| 1149 |
| 1156 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { | 1150 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { |
| 1157 ASSERT(instr->representation().IsDouble()); | 1151 ASSERT(instr->representation().IsDouble()); |
| 1158 ASSERT(instr->value()->representation().IsDouble()); | 1152 ASSERT(instr->value()->representation().IsDouble()); |
| 1159 LOperand* input = UseRegister(instr->value()); | 1153 LOperand* input = UseRegister(instr->value()); |
| 1160 LOperand* temp1 = TempRegister(); | 1154 LOperand* temp1 = TempRegister(); |
| 1161 LOperand* temp2 = TempRegister(); | 1155 LOperand* temp2 = TempRegister(); |
| 1162 LOperand* double_temp = FixedTemp(d3); // Chosen by fair dice roll. | 1156 LOperand* double_temp = FixedTemp(d3); // Chosen by fair dice roll. |
| 1163 LMathExp* result = new(zone()) LMathExp(input, double_temp, temp1, temp2); | 1157 LMathExp* result = new(zone()) LMathExp(input, double_temp, temp1, temp2); |
| 1164 return DefineAsRegister(result); | 1158 return DefineAsRegister(result); |
| 1165 } | 1159 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1192 LOperand* constructor = UseFixed(instr->constructor(), r1); | 1186 LOperand* constructor = UseFixed(instr->constructor(), r1); |
| 1193 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); | 1187 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); |
| 1194 return MarkAsCall(DefineFixed(result, r0), instr); | 1188 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1195 } | 1189 } |
| 1196 | 1190 |
| 1197 | 1191 |
| 1198 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { | 1192 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
| 1199 LOperand* context = UseFixed(instr->context(), cp); | 1193 LOperand* context = UseFixed(instr->context(), cp); |
| 1200 LOperand* function = UseFixed(instr->function(), r1); | 1194 LOperand* function = UseFixed(instr->function(), r1); |
| 1201 LCallFunction* call = new(zone()) LCallFunction(context, function); | 1195 LCallFunction* call = new(zone()) LCallFunction(context, function); |
| 1202 LInstruction* result = DefineFixed(call, r0); | 1196 return MarkAsCall(DefineFixed(call, r0), instr); |
| 1203 if (instr->IsTailCall()) return result; | |
| 1204 return MarkAsCall(result, instr); | |
| 1205 } | 1197 } |
| 1206 | 1198 |
| 1207 | 1199 |
| 1208 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { | 1200 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
| 1209 LOperand* context = UseFixed(instr->context(), cp); | 1201 LOperand* context = UseFixed(instr->context(), cp); |
| 1210 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), r0), instr); | 1202 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), r0), instr); |
| 1211 } | 1203 } |
| 1212 | 1204 |
| 1213 | 1205 |
| 1214 LInstruction* LChunkBuilder::DoRor(HRor* instr) { | 1206 LInstruction* LChunkBuilder::DoRor(HRor* instr) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1243 } else { | 1235 } else { |
| 1244 return DoArithmeticT(instr->op(), instr); | 1236 return DoArithmeticT(instr->op(), instr); |
| 1245 } | 1237 } |
| 1246 } | 1238 } |
| 1247 | 1239 |
| 1248 | 1240 |
| 1249 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1241 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1250 if (instr->representation().IsSmiOrInteger32()) { | 1242 if (instr->representation().IsSmiOrInteger32()) { |
| 1251 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1243 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1252 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1244 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1253 if (instr->HasPowerOf2Divisor()) { | 1245 if (instr->RightIsPowerOf2()) { |
| 1254 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1246 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
| 1255 LOperand* value = UseRegisterAtStart(instr->left()); | 1247 LOperand* value = UseRegister(instr->left()); |
| 1256 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); | 1248 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); |
| 1257 return AssignEnvironment(DefineAsRegister(div)); | 1249 return AssignEnvironment(DefineAsRegister(div)); |
| 1258 } | 1250 } |
| 1259 LOperand* dividend = UseRegister(instr->left()); | 1251 LOperand* dividend = UseRegister(instr->left()); |
| 1260 LOperand* divisor = UseRegister(instr->right()); | 1252 LOperand* divisor = UseRegister(instr->right()); |
| 1261 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); | 1253 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); |
| 1262 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); | 1254 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); |
| 1263 return AssignEnvironment(DefineAsRegister(div)); | 1255 return AssignEnvironment(DefineAsRegister(div)); |
| 1264 } else if (instr->representation().IsDouble()) { | 1256 } else if (instr->representation().IsDouble()) { |
| 1265 return DoArithmeticD(Token::DIV, instr); | 1257 return DoArithmeticD(Token::DIV, instr); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1289 int32_t power_of_2_factor = | 1281 int32_t power_of_2_factor = |
| 1290 CompilerIntrinsics::CountTrailingZeros(divisor_abs); | 1282 CompilerIntrinsics::CountTrailingZeros(divisor_abs); |
| 1291 DivMagicNumbers magic_numbers = | 1283 DivMagicNumbers magic_numbers = |
| 1292 DivMagicNumberFor(divisor_abs >> power_of_2_factor); | 1284 DivMagicNumberFor(divisor_abs >> power_of_2_factor); |
| 1293 if (magic_numbers.M != InvalidDivMagicNumber.M) return true; | 1285 if (magic_numbers.M != InvalidDivMagicNumber.M) return true; |
| 1294 | 1286 |
| 1295 return false; | 1287 return false; |
| 1296 } | 1288 } |
| 1297 | 1289 |
| 1298 | 1290 |
| 1299 HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) { | |
| 1300 if (CpuFeatures::IsSupported(SUDIV)) { | |
| 1301 // A value with an integer representation does not need to be transformed. | |
| 1302 if (divisor->representation().IsInteger32()) { | |
| 1303 return divisor; | |
| 1304 // A change from an integer32 can be replaced by the integer32 value. | |
| 1305 } else if (divisor->IsChange() && | |
| 1306 HChange::cast(divisor)->from().IsInteger32()) { | |
| 1307 return HChange::cast(divisor)->value(); | |
| 1308 } | |
| 1309 } | |
| 1310 | |
| 1311 if (divisor->IsConstant() && HConstant::cast(divisor)->HasInteger32Value()) { | |
| 1312 HConstant* constant_val = HConstant::cast(divisor); | |
| 1313 int32_t int32_val = constant_val->Integer32Value(); | |
| 1314 if (LChunkBuilder::HasMagicNumberForDivisor(int32_val) || | |
| 1315 CpuFeatures::IsSupported(SUDIV)) { | |
| 1316 return constant_val->CopyToRepresentation(Representation::Integer32(), | |
| 1317 divisor->block()->zone()); | |
| 1318 } | |
| 1319 } | |
| 1320 | |
| 1321 return NULL; | |
| 1322 } | |
| 1323 | |
| 1324 | |
| 1325 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { | 1291 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
| 1292 // LMathFloorOfDiv can only handle a subset of divisors, so fall |
| 1293 // back to a flooring division in all other cases. |
| 1326 HValue* right = instr->right(); | 1294 HValue* right = instr->right(); |
| 1295 if (!right->IsInteger32Constant() || |
| 1296 (!CpuFeatures::IsSupported(SUDIV) && |
| 1297 !HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value()))) { |
| 1298 LOperand* dividend = UseRegister(instr->left()); |
| 1299 LOperand* divisor = UseRegister(right); |
| 1300 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); |
| 1301 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); |
| 1302 return AssignEnvironment(DefineAsRegister(div)); |
| 1303 } |
| 1304 |
| 1327 LOperand* dividend = UseRegister(instr->left()); | 1305 LOperand* dividend = UseRegister(instr->left()); |
| 1328 LOperand* divisor = CpuFeatures::IsSupported(SUDIV) | 1306 LOperand* divisor = CpuFeatures::IsSupported(SUDIV) |
| 1329 ? UseRegister(right) | 1307 ? UseRegister(right) |
| 1330 : UseOrConstant(right); | 1308 : UseOrConstant(right); |
| 1331 LOperand* remainder = TempRegister(); | 1309 LOperand* remainder = TempRegister(); |
| 1332 ASSERT(CpuFeatures::IsSupported(SUDIV) || | |
| 1333 (right->IsConstant() && | |
| 1334 HConstant::cast(right)->HasInteger32Value() && | |
| 1335 HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value()))); | |
| 1336 return AssignEnvironment(DefineAsRegister( | 1310 return AssignEnvironment(DefineAsRegister( |
| 1337 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); | 1311 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); |
| 1338 } | 1312 } |
| 1339 | 1313 |
| 1340 | 1314 |
| 1341 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1315 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1342 HValue* left = instr->left(); | 1316 HValue* left = instr->left(); |
| 1343 HValue* right = instr->right(); | 1317 HValue* right = instr->right(); |
| 1344 if (instr->representation().IsSmiOrInteger32()) { | 1318 if (instr->representation().IsSmiOrInteger32()) { |
| 1345 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1319 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1346 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1320 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1347 if (instr->HasPowerOf2Divisor()) { | 1321 if (instr->RightIsPowerOf2()) { |
| 1348 ASSERT(!right->CanBeZero()); | 1322 ASSERT(!right->CanBeZero()); |
| 1349 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | 1323 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), |
| 1350 UseConstant(right)); | 1324 UseConstant(right)); |
| 1351 LInstruction* result = DefineAsRegister(mod); | 1325 LInstruction* result = DefineAsRegister(mod); |
| 1352 return (left->CanBeNegative() && | 1326 return (left->CanBeNegative() && |
| 1353 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | 1327 instr->CheckFlag(HValue::kBailoutOnMinusZero)) |
| 1354 ? AssignEnvironment(result) | 1328 ? AssignEnvironment(result) |
| 1355 : result; | 1329 : result; |
| 1356 } else if (CpuFeatures::IsSupported(SUDIV)) { | 1330 } else if (CpuFeatures::IsSupported(SUDIV)) { |
| 1357 LModI* mod = new(zone()) LModI(UseRegister(left), | 1331 LModI* mod = new(zone()) LModI(UseRegister(left), |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1732 return new(zone()) LClassOfTestAndBranch(value, TempRegister()); | 1706 return new(zone()) LClassOfTestAndBranch(value, TempRegister()); |
| 1733 } | 1707 } |
| 1734 | 1708 |
| 1735 | 1709 |
| 1736 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) { | 1710 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) { |
| 1737 LOperand* map = UseRegisterAtStart(instr->value()); | 1711 LOperand* map = UseRegisterAtStart(instr->value()); |
| 1738 return DefineAsRegister(new(zone()) LMapEnumLength(map)); | 1712 return DefineAsRegister(new(zone()) LMapEnumLength(map)); |
| 1739 } | 1713 } |
| 1740 | 1714 |
| 1741 | 1715 |
| 1742 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { | |
| 1743 LOperand* object = UseRegisterAtStart(instr->value()); | |
| 1744 return DefineAsRegister(new(zone()) LElementsKind(object)); | |
| 1745 } | |
| 1746 | |
| 1747 | |
| 1748 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | |
| 1749 LOperand* object = UseRegister(instr->value()); | |
| 1750 LValueOf* result = new(zone()) LValueOf(object, TempRegister()); | |
| 1751 return DefineAsRegister(result); | |
| 1752 } | |
| 1753 | |
| 1754 | |
| 1755 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { | 1716 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { |
| 1756 LOperand* object = UseFixed(instr->value(), r0); | 1717 LOperand* object = UseFixed(instr->value(), r0); |
| 1757 LDateField* result = | 1718 LDateField* result = |
| 1758 new(zone()) LDateField(object, FixedTemp(r1), instr->index()); | 1719 new(zone()) LDateField(object, FixedTemp(r1), instr->index()); |
| 1759 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); | 1720 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1760 } | 1721 } |
| 1761 | 1722 |
| 1762 | 1723 |
| 1763 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { | 1724 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { |
| 1764 LOperand* string = UseRegisterAtStart(instr->string()); | 1725 LOperand* string = UseRegisterAtStart(instr->string()); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1792 } | 1753 } |
| 1793 | 1754 |
| 1794 | 1755 |
| 1795 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { | 1756 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
| 1796 // The control instruction marking the end of a block that completed | 1757 // The control instruction marking the end of a block that completed |
| 1797 // abruptly (e.g., threw an exception). There is nothing specific to do. | 1758 // abruptly (e.g., threw an exception). There is nothing specific to do. |
| 1798 return NULL; | 1759 return NULL; |
| 1799 } | 1760 } |
| 1800 | 1761 |
| 1801 | 1762 |
| 1802 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { | |
| 1803 LOperand* context = UseFixed(instr->context(), cp); | |
| 1804 LOperand* value = UseFixed(instr->value(), r0); | |
| 1805 return MarkAsCall(new(zone()) LThrow(context, value), instr); | |
| 1806 } | |
| 1807 | |
| 1808 | |
| 1809 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { | 1763 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { |
| 1810 return NULL; | 1764 return NULL; |
| 1811 } | 1765 } |
| 1812 | 1766 |
| 1813 | 1767 |
| 1814 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { | 1768 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { |
| 1815 // All HForceRepresentation instructions should be eliminated in the | 1769 // All HForceRepresentation instructions should be eliminated in the |
| 1816 // representation change phase of Hydrogen. | 1770 // representation change phase of Hydrogen. |
| 1817 UNREACHABLE(); | 1771 UNREACHABLE(); |
| 1818 return NULL; | 1772 return NULL; |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2080 return AssignEnvironment(DefineAsRegister( | 2034 return AssignEnvironment(DefineAsRegister( |
| 2081 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function())))); | 2035 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function())))); |
| 2082 } | 2036 } |
| 2083 | 2037 |
| 2084 | 2038 |
| 2085 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { | 2039 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
| 2086 return DefineAsRegister(new(zone()) LLoadRoot); | 2040 return DefineAsRegister(new(zone()) LLoadRoot); |
| 2087 } | 2041 } |
| 2088 | 2042 |
| 2089 | 2043 |
| 2090 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( | |
| 2091 HLoadExternalArrayPointer* instr) { | |
| 2092 LOperand* input = UseRegisterAtStart(instr->value()); | |
| 2093 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); | |
| 2094 } | |
| 2095 | |
| 2096 | |
| 2097 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 2044 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
| 2098 ASSERT(instr->key()->representation().IsSmiOrInteger32()); | 2045 ASSERT(instr->key()->representation().IsSmiOrInteger32()); |
| 2099 ElementsKind elements_kind = instr->elements_kind(); | 2046 ElementsKind elements_kind = instr->elements_kind(); |
| 2100 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 2047 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
| 2101 LLoadKeyed* result = NULL; | 2048 LLoadKeyed* result = NULL; |
| 2102 | 2049 |
| 2103 if (!instr->is_typed_elements()) { | 2050 if (!instr->is_typed_elements()) { |
| 2104 LOperand* obj = NULL; | 2051 LOperand* obj = NULL; |
| 2105 if (instr->representation().IsDouble()) { | 2052 if (instr->representation().IsDouble()) { |
| 2106 obj = UseRegister(instr->elements()); | 2053 obj = UseRegister(instr->elements()); |
| 2107 } else { | 2054 } else { |
| 2108 ASSERT(instr->representation().IsSmiOrTagged()); | 2055 ASSERT(instr->representation().IsSmiOrTagged()); |
| 2109 obj = UseRegisterAtStart(instr->elements()); | 2056 obj = UseRegisterAtStart(instr->elements()); |
| 2110 } | 2057 } |
| 2111 result = new(zone()) LLoadKeyed(obj, key); | 2058 result = new(zone()) LLoadKeyed(obj, key); |
| 2112 } else { | 2059 } else { |
| 2113 ASSERT( | 2060 ASSERT( |
| 2114 (instr->representation().IsInteger32() && | 2061 (instr->representation().IsInteger32() && |
| 2115 !IsDoubleOrFloatElementsKind(instr->elements_kind())) || | 2062 !IsDoubleOrFloatElementsKind(instr->elements_kind())) || |
| 2116 (instr->representation().IsDouble() && | 2063 (instr->representation().IsDouble() && |
| 2117 IsDoubleOrFloatElementsKind(instr->elements_kind()))); | 2064 IsDoubleOrFloatElementsKind(instr->elements_kind()))); |
| 2118 LOperand* backing_store = UseRegister(instr->elements()); | 2065 LOperand* backing_store = UseRegister(instr->elements()); |
| 2119 result = new(zone()) LLoadKeyed(backing_store, key); | 2066 result = new(zone()) LLoadKeyed(backing_store, key); |
| 2120 } | 2067 } |
| 2121 | 2068 |
| 2122 DefineAsRegister(result); | 2069 DefineAsRegister(result); |
| 2123 // An unsigned int array load might overflow and cause a deopt, make sure it | 2070 // An unsigned int array load might overflow and cause a deopt, make sure it |
| 2124 // has an environment. | 2071 // has an environment. |
| 2125 bool can_deoptimize = instr->RequiresHoleCheck() || | 2072 bool can_deoptimize = instr->RequiresHoleCheck() || |
| 2126 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS || | 2073 elements_kind == EXTERNAL_UINT32_ELEMENTS || |
| 2127 elements_kind == UINT32_ELEMENTS; | 2074 elements_kind == UINT32_ELEMENTS; |
| 2128 return can_deoptimize ? AssignEnvironment(result) : result; | 2075 return can_deoptimize ? AssignEnvironment(result) : result; |
| 2129 } | 2076 } |
| 2130 | 2077 |
| 2131 | 2078 |
| 2132 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 2079 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 2133 LOperand* context = UseFixed(instr->context(), cp); | 2080 LOperand* context = UseFixed(instr->context(), cp); |
| 2134 LOperand* object = UseFixed(instr->object(), r1); | 2081 LOperand* object = UseFixed(instr->object(), r1); |
| 2135 LOperand* key = UseFixed(instr->key(), r0); | 2082 LOperand* key = UseFixed(instr->key(), r0); |
| 2136 | 2083 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2273 LOperand* obj = UseFixed(instr->object(), r1); | 2220 LOperand* obj = UseFixed(instr->object(), r1); |
| 2274 LOperand* val = UseFixed(instr->value(), r0); | 2221 LOperand* val = UseFixed(instr->value(), r0); |
| 2275 | 2222 |
| 2276 LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val); | 2223 LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val); |
| 2277 return MarkAsCall(result, instr); | 2224 return MarkAsCall(result, instr); |
| 2278 } | 2225 } |
| 2279 | 2226 |
| 2280 | 2227 |
| 2281 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { | 2228 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { |
| 2282 LOperand* context = UseFixed(instr->context(), cp); | 2229 LOperand* context = UseFixed(instr->context(), cp); |
| 2283 LOperand* left = FLAG_new_string_add | 2230 LOperand* left = UseFixed(instr->left(), r1); |
| 2284 ? UseFixed(instr->left(), r1) | 2231 LOperand* right = UseFixed(instr->right(), r0); |
| 2285 : UseRegisterAtStart(instr->left()); | |
| 2286 LOperand* right = FLAG_new_string_add | |
| 2287 ? UseFixed(instr->right(), r0) | |
| 2288 : UseRegisterAtStart(instr->right()); | |
| 2289 return MarkAsCall( | 2232 return MarkAsCall( |
| 2290 DefineFixed(new(zone()) LStringAdd(context, left, right), r0), | 2233 DefineFixed(new(zone()) LStringAdd(context, left, right), r0), |
| 2291 instr); | 2234 instr); |
| 2292 } | 2235 } |
| 2293 | 2236 |
| 2294 | 2237 |
| 2295 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { | 2238 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
| 2296 LOperand* string = UseTempRegister(instr->string()); | 2239 LOperand* string = UseTempRegister(instr->string()); |
| 2297 LOperand* index = UseTempRegister(instr->index()); | 2240 LOperand* index = UseTempRegister(instr->index()); |
| 2298 LOperand* context = UseAny(instr->context()); | 2241 LOperand* context = UseAny(instr->context()); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2533 } | 2476 } |
| 2534 | 2477 |
| 2535 | 2478 |
| 2536 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2479 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2537 LOperand* object = UseRegister(instr->object()); | 2480 LOperand* object = UseRegister(instr->object()); |
| 2538 LOperand* index = UseRegister(instr->index()); | 2481 LOperand* index = UseRegister(instr->index()); |
| 2539 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2482 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
| 2540 } | 2483 } |
| 2541 | 2484 |
| 2542 } } // namespace v8::internal | 2485 } } // namespace v8::internal |
| OLD | NEW |