| 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 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 | 904 |
| 905 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 905 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
| 906 HInstruction* old_current = current_instruction_; | 906 HInstruction* old_current = current_instruction_; |
| 907 current_instruction_ = current; | 907 current_instruction_ = current; |
| 908 | 908 |
| 909 LInstruction* instr = NULL; | 909 LInstruction* instr = NULL; |
| 910 if (current->CanReplaceWithDummyUses()) { | 910 if (current->CanReplaceWithDummyUses()) { |
| 911 if (current->OperandCount() == 0) { | 911 if (current->OperandCount() == 0) { |
| 912 instr = DefineAsRegister(new(zone()) LDummy()); | 912 instr = DefineAsRegister(new(zone()) LDummy()); |
| 913 } else { | 913 } else { |
| 914 ASSERT(!current->OperandAt(0)->IsControlInstruction()); |
| 914 instr = DefineAsRegister(new(zone()) | 915 instr = DefineAsRegister(new(zone()) |
| 915 LDummyUse(UseAny(current->OperandAt(0)))); | 916 LDummyUse(UseAny(current->OperandAt(0)))); |
| 916 } | 917 } |
| 917 for (int i = 1; i < current->OperandCount(); ++i) { | 918 for (int i = 1; i < current->OperandCount(); ++i) { |
| 919 if (current->OperandAt(i)->IsControlInstruction()) continue; |
| 918 LInstruction* dummy = | 920 LInstruction* dummy = |
| 919 new(zone()) LDummyUse(UseAny(current->OperandAt(i))); | 921 new(zone()) LDummyUse(UseAny(current->OperandAt(i))); |
| 920 dummy->set_hydrogen_value(current); | 922 dummy->set_hydrogen_value(current); |
| 921 chunk_->AddInstruction(dummy, current_block_); | 923 chunk_->AddInstruction(dummy, current_block_); |
| 922 } | 924 } |
| 923 } else { | 925 } else { |
| 924 instr = current->CompileToLithium(this); | 926 instr = current->CompileToLithium(this); |
| 925 } | 927 } |
| 926 | 928 |
| 927 argument_count_ += current->argument_delta(); | 929 argument_count_ += current->argument_delta(); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp)); | 1020 return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp)); |
| 1019 } | 1021 } |
| 1020 | 1022 |
| 1021 | 1023 |
| 1022 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { | 1024 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { |
| 1023 return new(zone()) LDebugBreak(); | 1025 return new(zone()) LDebugBreak(); |
| 1024 } | 1026 } |
| 1025 | 1027 |
| 1026 | 1028 |
| 1027 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 1029 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| 1030 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
| 1031 if (goto_instr != NULL) return goto_instr; |
| 1032 |
| 1028 ASSERT(instr->value()->representation().IsTagged()); | 1033 ASSERT(instr->value()->representation().IsTagged()); |
| 1029 LOperand* value = UseRegisterAtStart(instr->value()); | 1034 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1030 return new(zone()) LCmpMapAndBranch(value); | 1035 return new(zone()) LCmpMapAndBranch(value); |
| 1031 } | 1036 } |
| 1032 | 1037 |
| 1033 | 1038 |
| 1034 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { | 1039 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { |
| 1035 info()->MarkAsRequiresFrame(); | 1040 info()->MarkAsRequiresFrame(); |
| 1036 return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value()))); | 1041 return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value()))); |
| 1037 } | 1042 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1120 if (instr->HasNoUses()) return NULL; | 1125 if (instr->HasNoUses()) return NULL; |
| 1121 | 1126 |
| 1122 if (info()->IsStub()) { | 1127 if (info()->IsStub()) { |
| 1123 return DefineFixed(new(zone()) LContext, esi); | 1128 return DefineFixed(new(zone()) LContext, esi); |
| 1124 } | 1129 } |
| 1125 | 1130 |
| 1126 return DefineAsRegister(new(zone()) LContext); | 1131 return DefineAsRegister(new(zone()) LContext); |
| 1127 } | 1132 } |
| 1128 | 1133 |
| 1129 | 1134 |
| 1130 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { | |
| 1131 LOperand* context = UseRegisterAtStart(instr->value()); | |
| 1132 return DefineAsRegister(new(zone()) LOuterContext(context)); | |
| 1133 } | |
| 1134 | |
| 1135 | |
| 1136 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { | 1135 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { |
| 1137 LOperand* context = UseFixed(instr->context(), esi); | 1136 LOperand* context = UseFixed(instr->context(), esi); |
| 1138 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr); | 1137 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr); |
| 1139 } | 1138 } |
| 1140 | 1139 |
| 1141 | 1140 |
| 1142 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { | |
| 1143 LOperand* context = UseRegisterAtStart(instr->value()); | |
| 1144 return DefineAsRegister(new(zone()) LGlobalObject(context)); | |
| 1145 } | |
| 1146 | |
| 1147 | |
| 1148 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { | |
| 1149 LOperand* global_object = UseRegisterAtStart(instr->value()); | |
| 1150 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object)); | |
| 1151 } | |
| 1152 | |
| 1153 | |
| 1154 LInstruction* LChunkBuilder::DoCallJSFunction( | 1141 LInstruction* LChunkBuilder::DoCallJSFunction( |
| 1155 HCallJSFunction* instr) { | 1142 HCallJSFunction* instr) { |
| 1156 LOperand* function = UseFixed(instr->function(), edi); | 1143 LOperand* function = UseFixed(instr->function(), edi); |
| 1157 | 1144 |
| 1158 LCallJSFunction* result = new(zone()) LCallJSFunction(function); | 1145 LCallJSFunction* result = new(zone()) LCallJSFunction(function); |
| 1159 | 1146 |
| 1160 return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY); | 1147 return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY); |
| 1161 } | 1148 } |
| 1162 | 1149 |
| 1163 | 1150 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1190 | 1177 |
| 1191 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 1178 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1192 switch (instr->op()) { | 1179 switch (instr->op()) { |
| 1193 case kMathFloor: return DoMathFloor(instr); | 1180 case kMathFloor: return DoMathFloor(instr); |
| 1194 case kMathRound: return DoMathRound(instr); | 1181 case kMathRound: return DoMathRound(instr); |
| 1195 case kMathAbs: return DoMathAbs(instr); | 1182 case kMathAbs: return DoMathAbs(instr); |
| 1196 case kMathLog: return DoMathLog(instr); | 1183 case kMathLog: return DoMathLog(instr); |
| 1197 case kMathExp: return DoMathExp(instr); | 1184 case kMathExp: return DoMathExp(instr); |
| 1198 case kMathSqrt: return DoMathSqrt(instr); | 1185 case kMathSqrt: return DoMathSqrt(instr); |
| 1199 case kMathPowHalf: return DoMathPowHalf(instr); | 1186 case kMathPowHalf: return DoMathPowHalf(instr); |
| 1187 case kMathClz32: return DoMathClz32(instr); |
| 1200 default: | 1188 default: |
| 1201 UNREACHABLE(); | 1189 UNREACHABLE(); |
| 1202 return NULL; | 1190 return NULL; |
| 1203 } | 1191 } |
| 1204 } | 1192 } |
| 1205 | 1193 |
| 1206 | 1194 |
| 1207 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { | 1195 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { |
| 1208 LOperand* input = UseRegisterAtStart(instr->value()); | 1196 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1209 LMathFloor* result = new(zone()) LMathFloor(input); | 1197 LMathFloor* result = new(zone()) LMathFloor(input); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1228 | 1216 |
| 1229 | 1217 |
| 1230 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { | 1218 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { |
| 1231 ASSERT(instr->representation().IsDouble()); | 1219 ASSERT(instr->representation().IsDouble()); |
| 1232 ASSERT(instr->value()->representation().IsDouble()); | 1220 ASSERT(instr->value()->representation().IsDouble()); |
| 1233 LOperand* input = UseRegisterAtStart(instr->value()); | 1221 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1234 return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr); | 1222 return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr); |
| 1235 } | 1223 } |
| 1236 | 1224 |
| 1237 | 1225 |
| 1226 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) { |
| 1227 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1228 LMathClz32* result = new(zone()) LMathClz32(input); |
| 1229 return DefineAsRegister(result); |
| 1230 } |
| 1231 |
| 1232 |
| 1238 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { | 1233 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { |
| 1239 ASSERT(instr->representation().IsDouble()); | 1234 ASSERT(instr->representation().IsDouble()); |
| 1240 ASSERT(instr->value()->representation().IsDouble()); | 1235 ASSERT(instr->value()->representation().IsDouble()); |
| 1241 LOperand* value = UseTempRegister(instr->value()); | 1236 LOperand* value = UseTempRegister(instr->value()); |
| 1242 LOperand* temp1 = TempRegister(); | 1237 LOperand* temp1 = TempRegister(); |
| 1243 LOperand* temp2 = TempRegister(); | 1238 LOperand* temp2 = TempRegister(); |
| 1244 LMathExp* result = new(zone()) LMathExp(value, temp1, temp2); | 1239 LMathExp* result = new(zone()) LMathExp(value, temp1, temp2); |
| 1245 return DefineAsRegister(result); | 1240 return DefineAsRegister(result); |
| 1246 } | 1241 } |
| 1247 | 1242 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1274 LOperand* constructor = UseFixed(instr->constructor(), edi); | 1269 LOperand* constructor = UseFixed(instr->constructor(), edi); |
| 1275 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); | 1270 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor); |
| 1276 return MarkAsCall(DefineFixed(result, eax), instr); | 1271 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1277 } | 1272 } |
| 1278 | 1273 |
| 1279 | 1274 |
| 1280 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { | 1275 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
| 1281 LOperand* context = UseFixed(instr->context(), esi); | 1276 LOperand* context = UseFixed(instr->context(), esi); |
| 1282 LOperand* function = UseFixed(instr->function(), edi); | 1277 LOperand* function = UseFixed(instr->function(), edi); |
| 1283 LCallFunction* call = new(zone()) LCallFunction(context, function); | 1278 LCallFunction* call = new(zone()) LCallFunction(context, function); |
| 1284 LInstruction* result = DefineFixed(call, eax); | 1279 return MarkAsCall(DefineFixed(call, eax), instr); |
| 1285 if (instr->IsTailCall()) return result; | |
| 1286 return MarkAsCall(result, instr); | |
| 1287 } | 1280 } |
| 1288 | 1281 |
| 1289 | 1282 |
| 1290 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { | 1283 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
| 1291 LOperand* context = UseFixed(instr->context(), esi); | 1284 LOperand* context = UseFixed(instr->context(), esi); |
| 1292 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr); | 1285 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr); |
| 1293 } | 1286 } |
| 1294 | 1287 |
| 1295 | 1288 |
| 1296 LInstruction* LChunkBuilder::DoRor(HRor* instr) { | 1289 LInstruction* LChunkBuilder::DoRor(HRor* instr) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1325 } else { | 1318 } else { |
| 1326 return DoArithmeticT(instr->op(), instr); | 1319 return DoArithmeticT(instr->op(), instr); |
| 1327 } | 1320 } |
| 1328 } | 1321 } |
| 1329 | 1322 |
| 1330 | 1323 |
| 1331 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1324 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1332 if (instr->representation().IsSmiOrInteger32()) { | 1325 if (instr->representation().IsSmiOrInteger32()) { |
| 1333 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1326 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1334 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1327 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1335 if (instr->HasPowerOf2Divisor()) { | 1328 if (instr->RightIsPowerOf2()) { |
| 1336 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1329 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
| 1337 LOperand* value = UseRegisterAtStart(instr->left()); | 1330 LOperand* value = UseRegister(instr->left()); |
| 1338 LDivI* div = | 1331 LDivI* div = |
| 1339 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); | 1332 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); |
| 1340 return AssignEnvironment(DefineSameAsFirst(div)); | 1333 return AssignEnvironment(DefineAsRegister(div)); |
| 1341 } | 1334 } |
| 1342 // The temporary operand is necessary to ensure that right is not allocated | 1335 // The temporary operand is necessary to ensure that right is not allocated |
| 1343 // into edx. | 1336 // into edx. |
| 1344 LOperand* temp = FixedTemp(edx); | 1337 LOperand* temp = FixedTemp(edx); |
| 1345 LOperand* dividend = UseFixed(instr->left(), eax); | 1338 LOperand* dividend = UseFixed(instr->left(), eax); |
| 1346 LOperand* divisor = UseRegister(instr->right()); | 1339 LOperand* divisor = UseRegister(instr->right()); |
| 1347 LDivI* result = new(zone()) LDivI(dividend, divisor, temp); | 1340 LDivI* result = new(zone()) LDivI(dividend, divisor, temp); |
| 1348 return AssignEnvironment(DefineFixed(result, eax)); | 1341 return AssignEnvironment(DefineFixed(result, eax)); |
| 1349 } else if (instr->representation().IsDouble()) { | 1342 } else if (instr->representation().IsDouble()) { |
| 1350 return DoArithmeticD(Token::DIV, instr); | 1343 return DoArithmeticD(Token::DIV, instr); |
| 1351 } else { | 1344 } else { |
| 1352 return DoArithmeticT(Token::DIV, instr); | 1345 return DoArithmeticT(Token::DIV, instr); |
| 1353 } | 1346 } |
| 1354 } | 1347 } |
| 1355 | 1348 |
| 1356 | 1349 |
| 1357 HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) { | |
| 1358 if (divisor->IsConstant() && | |
| 1359 HConstant::cast(divisor)->HasInteger32Value()) { | |
| 1360 HConstant* constant_val = HConstant::cast(divisor); | |
| 1361 return constant_val->CopyToRepresentation(Representation::Integer32(), | |
| 1362 divisor->block()->zone()); | |
| 1363 } | |
| 1364 // A value with an integer representation does not need to be transformed. | |
| 1365 if (divisor->representation().IsInteger32()) { | |
| 1366 return divisor; | |
| 1367 // A change from an integer32 can be replaced by the integer32 value. | |
| 1368 } else if (divisor->IsChange() && | |
| 1369 HChange::cast(divisor)->from().IsInteger32()) { | |
| 1370 return HChange::cast(divisor)->value(); | |
| 1371 } | |
| 1372 return NULL; | |
| 1373 } | |
| 1374 | |
| 1375 | |
| 1376 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { | 1350 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
| 1377 HValue* right = instr->right(); | 1351 HValue* right = instr->right(); |
| 1378 if (!right->IsConstant()) { | 1352 if (!right->IsConstant()) { |
| 1379 ASSERT(right->representation().IsInteger32()); | 1353 ASSERT(right->representation().IsInteger32()); |
| 1380 // The temporary operand is necessary to ensure that right is not allocated | 1354 // The temporary operand is necessary to ensure that right is not allocated |
| 1381 // into edx. | 1355 // into edx. |
| 1382 LOperand* temp = FixedTemp(edx); | 1356 LOperand* temp = FixedTemp(edx); |
| 1383 LOperand* dividend = UseFixed(instr->left(), eax); | 1357 LOperand* dividend = UseFixed(instr->left(), eax); |
| 1384 LOperand* divisor = UseRegister(instr->right()); | 1358 LOperand* divisor = UseRegister(instr->right()); |
| 1385 LDivI* flooring_div = new(zone()) LDivI(dividend, divisor, temp); | 1359 LDivI* flooring_div = new(zone()) LDivI(dividend, divisor, temp); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1411 } | 1385 } |
| 1412 | 1386 |
| 1413 | 1387 |
| 1414 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1388 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1415 HValue* left = instr->left(); | 1389 HValue* left = instr->left(); |
| 1416 HValue* right = instr->right(); | 1390 HValue* right = instr->right(); |
| 1417 if (instr->representation().IsSmiOrInteger32()) { | 1391 if (instr->representation().IsSmiOrInteger32()) { |
| 1418 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1392 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1419 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1393 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1420 | 1394 |
| 1421 if (instr->HasPowerOf2Divisor()) { | 1395 if (instr->RightIsPowerOf2()) { |
| 1422 ASSERT(!right->CanBeZero()); | 1396 ASSERT(!right->CanBeZero()); |
| 1423 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | 1397 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), |
| 1424 UseOrConstant(right), | 1398 UseOrConstant(right), |
| 1425 NULL); | 1399 NULL); |
| 1426 LInstruction* result = DefineSameAsFirst(mod); | 1400 LInstruction* result = DefineSameAsFirst(mod); |
| 1427 return (left->CanBeNegative() && | 1401 return (left->CanBeNegative() && |
| 1428 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | 1402 instr->CheckFlag(HValue::kBailoutOnMinusZero)) |
| 1429 ? AssignEnvironment(result) | 1403 ? AssignEnvironment(result) |
| 1430 : result; | 1404 : result; |
| 1431 return AssignEnvironment(DefineSameAsFirst(mod)); | 1405 return AssignEnvironment(DefineSameAsFirst(mod)); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1725 TempRegister()); | 1699 TempRegister()); |
| 1726 } | 1700 } |
| 1727 | 1701 |
| 1728 | 1702 |
| 1729 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) { | 1703 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) { |
| 1730 LOperand* map = UseRegisterAtStart(instr->value()); | 1704 LOperand* map = UseRegisterAtStart(instr->value()); |
| 1731 return DefineAsRegister(new(zone()) LMapEnumLength(map)); | 1705 return DefineAsRegister(new(zone()) LMapEnumLength(map)); |
| 1732 } | 1706 } |
| 1733 | 1707 |
| 1734 | 1708 |
| 1735 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { | |
| 1736 LOperand* object = UseRegisterAtStart(instr->value()); | |
| 1737 return DefineAsRegister(new(zone()) LElementsKind(object)); | |
| 1738 } | |
| 1739 | |
| 1740 | |
| 1741 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | |
| 1742 LOperand* object = UseRegister(instr->value()); | |
| 1743 LValueOf* result = new(zone()) LValueOf(object, TempRegister()); | |
| 1744 return DefineSameAsFirst(result); | |
| 1745 } | |
| 1746 | |
| 1747 | |
| 1748 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { | 1709 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { |
| 1749 LOperand* date = UseFixed(instr->value(), eax); | 1710 LOperand* date = UseFixed(instr->value(), eax); |
| 1750 LDateField* result = | 1711 LDateField* result = |
| 1751 new(zone()) LDateField(date, FixedTemp(ecx), instr->index()); | 1712 new(zone()) LDateField(date, FixedTemp(ecx), instr->index()); |
| 1752 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY); | 1713 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1753 } | 1714 } |
| 1754 | 1715 |
| 1755 | 1716 |
| 1756 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { | 1717 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { |
| 1757 LOperand* string = UseRegisterAtStart(instr->string()); | 1718 LOperand* string = UseRegisterAtStart(instr->string()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1807 } | 1768 } |
| 1808 | 1769 |
| 1809 | 1770 |
| 1810 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { | 1771 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
| 1811 // The control instruction marking the end of a block that completed | 1772 // The control instruction marking the end of a block that completed |
| 1812 // abruptly (e.g., threw an exception). There is nothing specific to do. | 1773 // abruptly (e.g., threw an exception). There is nothing specific to do. |
| 1813 return NULL; | 1774 return NULL; |
| 1814 } | 1775 } |
| 1815 | 1776 |
| 1816 | 1777 |
| 1817 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { | |
| 1818 LOperand* context = UseFixed(instr->context(), esi); | |
| 1819 LOperand* value = UseFixed(instr->value(), eax); | |
| 1820 return MarkAsCall(new(zone()) LThrow(context, value), instr); | |
| 1821 } | |
| 1822 | |
| 1823 | |
| 1824 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { | 1778 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { |
| 1825 return NULL; | 1779 return NULL; |
| 1826 } | 1780 } |
| 1827 | 1781 |
| 1828 | 1782 |
| 1829 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { | 1783 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { |
| 1830 // All HForceRepresentation instructions should be eliminated in the | 1784 // All HForceRepresentation instructions should be eliminated in the |
| 1831 // representation change phase of Hydrogen. | 1785 // representation change phase of Hydrogen. |
| 1832 UNREACHABLE(); | 1786 UNREACHABLE(); |
| 1833 return NULL; | 1787 return NULL; |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2119 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()), | 2073 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()), |
| 2120 TempRegister()))); | 2074 TempRegister()))); |
| 2121 } | 2075 } |
| 2122 | 2076 |
| 2123 | 2077 |
| 2124 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { | 2078 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
| 2125 return DefineAsRegister(new(zone()) LLoadRoot); | 2079 return DefineAsRegister(new(zone()) LLoadRoot); |
| 2126 } | 2080 } |
| 2127 | 2081 |
| 2128 | 2082 |
| 2129 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( | |
| 2130 HLoadExternalArrayPointer* instr) { | |
| 2131 LOperand* input = UseRegisterAtStart(instr->value()); | |
| 2132 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); | |
| 2133 } | |
| 2134 | |
| 2135 | |
| 2136 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 2083 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
| 2137 ASSERT(instr->key()->representation().IsSmiOrInteger32()); | 2084 ASSERT(instr->key()->representation().IsSmiOrInteger32()); |
| 2138 ElementsKind elements_kind = instr->elements_kind(); | 2085 ElementsKind elements_kind = instr->elements_kind(); |
| 2139 bool clobbers_key = ExternalArrayOpRequiresTemp( | 2086 bool clobbers_key = ExternalArrayOpRequiresTemp( |
| 2140 instr->key()->representation(), elements_kind); | 2087 instr->key()->representation(), elements_kind); |
| 2141 LOperand* key = clobbers_key | 2088 LOperand* key = clobbers_key |
| 2142 ? UseTempRegister(instr->key()) | 2089 ? UseTempRegister(instr->key()) |
| 2143 : UseRegisterOrConstantAtStart(instr->key()); | 2090 : UseRegisterOrConstantAtStart(instr->key()); |
| 2144 LLoadKeyed* result = NULL; | 2091 LLoadKeyed* result = NULL; |
| 2145 | 2092 |
| 2146 if (!instr->is_typed_elements()) { | 2093 if (!instr->is_typed_elements()) { |
| 2147 LOperand* obj = UseRegisterAtStart(instr->elements()); | 2094 LOperand* obj = UseRegisterAtStart(instr->elements()); |
| 2148 result = new(zone()) LLoadKeyed(obj, key); | 2095 result = new(zone()) LLoadKeyed(obj, key); |
| 2149 } else { | 2096 } else { |
| 2150 ASSERT( | 2097 ASSERT( |
| 2151 (instr->representation().IsInteger32() && | 2098 (instr->representation().IsInteger32() && |
| 2152 !(IsDoubleOrFloatElementsKind(instr->elements_kind()))) || | 2099 !(IsDoubleOrFloatElementsKind(instr->elements_kind()))) || |
| 2153 (instr->representation().IsDouble() && | 2100 (instr->representation().IsDouble() && |
| 2154 (IsDoubleOrFloatElementsKind(instr->elements_kind())))); | 2101 (IsDoubleOrFloatElementsKind(instr->elements_kind())))); |
| 2155 LOperand* backing_store = UseRegister(instr->elements()); | 2102 LOperand* backing_store = UseRegister(instr->elements()); |
| 2156 result = new(zone()) LLoadKeyed(backing_store, key); | 2103 result = new(zone()) LLoadKeyed(backing_store, key); |
| 2157 } | 2104 } |
| 2158 | 2105 |
| 2159 DefineAsRegister(result); | 2106 DefineAsRegister(result); |
| 2160 bool can_deoptimize = instr->RequiresHoleCheck() || | 2107 bool can_deoptimize = instr->RequiresHoleCheck() || |
| 2161 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS); | 2108 (elements_kind == EXTERNAL_UINT32_ELEMENTS); |
| 2162 // An unsigned int array load might overflow and cause a deopt, make sure it | 2109 // An unsigned int array load might overflow and cause a deopt, make sure it |
| 2163 // has an environment. | 2110 // has an environment. |
| 2164 return can_deoptimize ? AssignEnvironment(result) : result; | 2111 return can_deoptimize ? AssignEnvironment(result) : result; |
| 2165 } | 2112 } |
| 2166 | 2113 |
| 2167 | 2114 |
| 2168 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 2115 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 2169 LOperand* context = UseFixed(instr->context(), esi); | 2116 LOperand* context = UseFixed(instr->context(), esi); |
| 2170 LOperand* object = UseFixed(instr->object(), edx); | 2117 LOperand* object = UseFixed(instr->object(), edx); |
| 2171 LOperand* key = UseFixed(instr->key(), ecx); | 2118 LOperand* key = UseFixed(instr->key(), ecx); |
| 2172 | 2119 |
| 2173 LLoadKeyedGeneric* result = | 2120 LLoadKeyedGeneric* result = |
| 2174 new(zone()) LLoadKeyedGeneric(context, object, key); | 2121 new(zone()) LLoadKeyedGeneric(context, object, key); |
| 2175 return MarkAsCall(DefineFixed(result, eax), instr); | 2122 return MarkAsCall(DefineFixed(result, eax), instr); |
| 2176 } | 2123 } |
| 2177 | 2124 |
| 2178 | 2125 |
| 2179 LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) { | 2126 LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) { |
| 2180 ElementsKind elements_kind = instr->elements_kind(); | 2127 ElementsKind elements_kind = instr->elements_kind(); |
| 2181 | 2128 |
| 2182 // Determine if we need a byte register in this case for the value. | 2129 // Determine if we need a byte register in this case for the value. |
| 2183 bool val_is_fixed_register = | 2130 bool val_is_fixed_register = |
| 2184 elements_kind == EXTERNAL_BYTE_ELEMENTS || | 2131 elements_kind == EXTERNAL_INT8_ELEMENTS || |
| 2185 elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS || | 2132 elements_kind == EXTERNAL_UINT8_ELEMENTS || |
| 2186 elements_kind == EXTERNAL_PIXEL_ELEMENTS || | 2133 elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || |
| 2187 elements_kind == UINT8_ELEMENTS || | 2134 elements_kind == UINT8_ELEMENTS || |
| 2188 elements_kind == INT8_ELEMENTS || | 2135 elements_kind == INT8_ELEMENTS || |
| 2189 elements_kind == UINT8_CLAMPED_ELEMENTS; | 2136 elements_kind == UINT8_CLAMPED_ELEMENTS; |
| 2190 if (val_is_fixed_register) { | 2137 if (val_is_fixed_register) { |
| 2191 return UseFixed(instr->value(), eax); | 2138 return UseFixed(instr->value(), eax); |
| 2192 } | 2139 } |
| 2193 | 2140 |
| 2194 if (!CpuFeatures::IsSafeForSnapshot(SSE2) && | 2141 if (!CpuFeatures::IsSafeForSnapshot(SSE2) && |
| 2195 IsDoubleOrFloatElementsKind(elements_kind)) { | 2142 IsDoubleOrFloatElementsKind(elements_kind)) { |
| 2196 return UseRegisterAtStart(instr->value()); | 2143 return UseRegisterAtStart(instr->value()); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2371 LOperand* value = UseFixed(instr->value(), eax); | 2318 LOperand* value = UseFixed(instr->value(), eax); |
| 2372 | 2319 |
| 2373 LStoreNamedGeneric* result = | 2320 LStoreNamedGeneric* result = |
| 2374 new(zone()) LStoreNamedGeneric(context, object, value); | 2321 new(zone()) LStoreNamedGeneric(context, object, value); |
| 2375 return MarkAsCall(result, instr); | 2322 return MarkAsCall(result, instr); |
| 2376 } | 2323 } |
| 2377 | 2324 |
| 2378 | 2325 |
| 2379 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { | 2326 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { |
| 2380 LOperand* context = UseFixed(instr->context(), esi); | 2327 LOperand* context = UseFixed(instr->context(), esi); |
| 2381 LOperand* left = FLAG_new_string_add | 2328 LOperand* left = UseFixed(instr->left(), edx); |
| 2382 ? UseFixed(instr->left(), edx) | 2329 LOperand* right = UseFixed(instr->right(), eax); |
| 2383 : UseOrConstantAtStart(instr->left()); | |
| 2384 LOperand* right = FLAG_new_string_add | |
| 2385 ? UseFixed(instr->right(), eax) | |
| 2386 : UseOrConstantAtStart(instr->right()); | |
| 2387 LStringAdd* string_add = new(zone()) LStringAdd(context, left, right); | 2330 LStringAdd* string_add = new(zone()) LStringAdd(context, left, right); |
| 2388 return MarkAsCall(DefineFixed(string_add, eax), instr); | 2331 return MarkAsCall(DefineFixed(string_add, eax), instr); |
| 2389 } | 2332 } |
| 2390 | 2333 |
| 2391 | 2334 |
| 2392 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { | 2335 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
| 2393 LOperand* string = UseTempRegister(instr->string()); | 2336 LOperand* string = UseTempRegister(instr->string()); |
| 2394 LOperand* index = UseTempRegister(instr->index()); | 2337 LOperand* index = UseTempRegister(instr->index()); |
| 2395 LOperand* context = UseAny(instr->context()); | 2338 LOperand* context = UseAny(instr->context()); |
| 2396 LStringCharCodeAt* result = | 2339 LStringCharCodeAt* result = |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2647 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2590 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2648 LOperand* object = UseRegister(instr->object()); | 2591 LOperand* object = UseRegister(instr->object()); |
| 2649 LOperand* index = UseTempRegister(instr->index()); | 2592 LOperand* index = UseTempRegister(instr->index()); |
| 2650 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); | 2593 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); |
| 2651 } | 2594 } |
| 2652 | 2595 |
| 2653 | 2596 |
| 2654 } } // namespace v8::internal | 2597 } } // namespace v8::internal |
| 2655 | 2598 |
| 2656 #endif // V8_TARGET_ARCH_IA32 | 2599 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |