| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 public: | 1009 public: |
| 1010 DeferredModI(LCodeGen* codegen, LModI* instr) | 1010 DeferredModI(LCodeGen* codegen, LModI* instr) |
| 1011 : LDeferredCode(codegen), instr_(instr) { } | 1011 : LDeferredCode(codegen), instr_(instr) { } |
| 1012 virtual void Generate() { | 1012 virtual void Generate() { |
| 1013 codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD); | 1013 codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD); |
| 1014 } | 1014 } |
| 1015 private: | 1015 private: |
| 1016 LModI* instr_; | 1016 LModI* instr_; |
| 1017 }; | 1017 }; |
| 1018 // These registers hold untagged 32 bit values. | 1018 // These registers hold untagged 32 bit values. |
| 1019 Register left = ToRegister(instr->left()); | 1019 Register left = ToRegister(instr->InputAt(0)); |
| 1020 Register right = ToRegister(instr->right()); | 1020 Register right = ToRegister(instr->InputAt(1)); |
| 1021 Register result = ToRegister(instr->result()); | 1021 Register result = ToRegister(instr->result()); |
| 1022 Register scratch = scratch0(); | 1022 Register scratch = scratch0(); |
| 1023 | 1023 |
| 1024 Label deoptimize, done; | 1024 Label deoptimize, done; |
| 1025 // Check for x % 0. | 1025 // Check for x % 0. |
| 1026 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1026 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1027 __ tst(right, Operand(right)); | 1027 __ tst(right, Operand(right)); |
| 1028 __ b(eq, &deoptimize); | 1028 __ b(eq, &deoptimize); |
| 1029 } | 1029 } |
| 1030 | 1030 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 public: | 1095 public: |
| 1096 DeferredDivI(LCodeGen* codegen, LDivI* instr) | 1096 DeferredDivI(LCodeGen* codegen, LDivI* instr) |
| 1097 : LDeferredCode(codegen), instr_(instr) { } | 1097 : LDeferredCode(codegen), instr_(instr) { } |
| 1098 virtual void Generate() { | 1098 virtual void Generate() { |
| 1099 codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV); | 1099 codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV); |
| 1100 } | 1100 } |
| 1101 private: | 1101 private: |
| 1102 LDivI* instr_; | 1102 LDivI* instr_; |
| 1103 }; | 1103 }; |
| 1104 | 1104 |
| 1105 const Register left = ToRegister(instr->left()); | 1105 const Register left = ToRegister(instr->InputAt(0)); |
| 1106 const Register right = ToRegister(instr->right()); | 1106 const Register right = ToRegister(instr->InputAt(1)); |
| 1107 const Register scratch = scratch0(); | 1107 const Register scratch = scratch0(); |
| 1108 const Register result = ToRegister(instr->result()); | 1108 const Register result = ToRegister(instr->result()); |
| 1109 | 1109 |
| 1110 // Check for x / 0. | 1110 // Check for x / 0. |
| 1111 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1111 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1112 __ tst(right, right); | 1112 __ tst(right, right); |
| 1113 DeoptimizeIf(eq, instr->environment()); | 1113 DeoptimizeIf(eq, instr->environment()); |
| 1114 } | 1114 } |
| 1115 | 1115 |
| 1116 // Check for (0 / -x) that will produce negative zero. | 1116 // Check for (0 / -x) that will produce negative zero. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1163 __ BranchOnNotSmi(result, &deoptimize); | 1163 __ BranchOnNotSmi(result, &deoptimize); |
| 1164 __ SmiUntag(result); | 1164 __ SmiUntag(result); |
| 1165 __ b(&done); | 1165 __ b(&done); |
| 1166 | 1166 |
| 1167 __ bind(&deoptimize); | 1167 __ bind(&deoptimize); |
| 1168 DeoptimizeIf(al, instr->environment()); | 1168 DeoptimizeIf(al, instr->environment()); |
| 1169 __ bind(&done); | 1169 __ bind(&done); |
| 1170 } | 1170 } |
| 1171 | 1171 |
| 1172 | 1172 |
| 1173 void LCodeGen::DoDeferredGenericBinaryStub(LBinaryOperation* instr, | 1173 template<int T> |
| 1174 void LCodeGen::DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr, |
| 1174 Token::Value op) { | 1175 Token::Value op) { |
| 1175 Register left = ToRegister(instr->left()); | 1176 Register left = ToRegister(instr->InputAt(0)); |
| 1176 Register right = ToRegister(instr->right()); | 1177 Register right = ToRegister(instr->InputAt(1)); |
| 1177 | 1178 |
| 1178 __ PushSafepointRegistersAndDoubles(); | 1179 __ PushSafepointRegistersAndDoubles(); |
| 1179 GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right); | 1180 GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right); |
| 1180 __ CallStub(&stub); | 1181 __ CallStub(&stub); |
| 1181 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1182 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
| 1182 0, | 1183 0, |
| 1183 Safepoint::kNoDeoptimizationIndex); | 1184 Safepoint::kNoDeoptimizationIndex); |
| 1184 // Overwrite the stored value of r0 with the result of the stub. | 1185 // Overwrite the stored value of r0 with the result of the stub. |
| 1185 __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters * | 1186 __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters * |
| 1186 kDoubleSize)); | 1187 kDoubleSize)); |
| 1187 __ PopSafepointRegistersAndDoubles(); | 1188 __ PopSafepointRegistersAndDoubles(); |
| 1188 } | 1189 } |
| 1189 | 1190 |
| 1190 | 1191 |
| 1191 void LCodeGen::DoMulI(LMulI* instr) { | 1192 void LCodeGen::DoMulI(LMulI* instr) { |
| 1192 Register scratch = scratch0(); | 1193 Register scratch = scratch0(); |
| 1193 Register left = ToRegister(instr->left()); | 1194 Register left = ToRegister(instr->InputAt(0)); |
| 1194 Register right = EmitLoadRegister(instr->right(), scratch); | 1195 Register right = EmitLoadRegister(instr->InputAt(1), scratch); |
| 1195 | 1196 |
| 1196 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && | 1197 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 1197 !instr->right()->IsConstantOperand()) { | 1198 !instr->InputAt(1)->IsConstantOperand()) { |
| 1198 __ orr(ToRegister(instr->temp()), left, right); | 1199 __ orr(ToRegister(instr->TempAt(0)), left, right); |
| 1199 } | 1200 } |
| 1200 | 1201 |
| 1201 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1202 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1202 // scratch:left = left * right. | 1203 // scratch:left = left * right. |
| 1203 __ smull(scratch, left, left, right); | 1204 __ smull(scratch, left, left, right); |
| 1204 __ mov(ip, Operand(left, ASR, 31)); | 1205 __ mov(ip, Operand(left, ASR, 31)); |
| 1205 __ cmp(ip, Operand(scratch)); | 1206 __ cmp(ip, Operand(scratch)); |
| 1206 DeoptimizeIf(ne, instr->environment()); | 1207 DeoptimizeIf(ne, instr->environment()); |
| 1207 } else { | 1208 } else { |
| 1208 __ mul(left, left, right); | 1209 __ mul(left, left, right); |
| 1209 } | 1210 } |
| 1210 | 1211 |
| 1211 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1212 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1212 // Bail out if the result is supposed to be negative zero. | 1213 // Bail out if the result is supposed to be negative zero. |
| 1213 Label done; | 1214 Label done; |
| 1214 __ tst(left, Operand(left)); | 1215 __ tst(left, Operand(left)); |
| 1215 __ b(ne, &done); | 1216 __ b(ne, &done); |
| 1216 if (instr->right()->IsConstantOperand()) { | 1217 if (instr->InputAt(1)->IsConstantOperand()) { |
| 1217 if (ToInteger32(LConstantOperand::cast(instr->right())) < 0) { | 1218 if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) < 0) { |
| 1218 DeoptimizeIf(no_condition, instr->environment()); | 1219 DeoptimizeIf(no_condition, instr->environment()); |
| 1219 } | 1220 } |
| 1220 } else { | 1221 } else { |
| 1221 // Test the non-zero operand for negative sign. | 1222 // Test the non-zero operand for negative sign. |
| 1222 __ cmp(ToRegister(instr->temp()), Operand(0)); | 1223 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
| 1223 DeoptimizeIf(mi, instr->environment()); | 1224 DeoptimizeIf(mi, instr->environment()); |
| 1224 } | 1225 } |
| 1225 __ bind(&done); | 1226 __ bind(&done); |
| 1226 } | 1227 } |
| 1227 } | 1228 } |
| 1228 | 1229 |
| 1229 | 1230 |
| 1230 void LCodeGen::DoBitI(LBitI* instr) { | 1231 void LCodeGen::DoBitI(LBitI* instr) { |
| 1231 LOperand* left = instr->left(); | 1232 LOperand* left = instr->InputAt(0); |
| 1232 LOperand* right = instr->right(); | 1233 LOperand* right = instr->InputAt(1); |
| 1233 ASSERT(left->Equals(instr->result())); | 1234 ASSERT(left->Equals(instr->result())); |
| 1234 ASSERT(left->IsRegister()); | 1235 ASSERT(left->IsRegister()); |
| 1235 Register result = ToRegister(left); | 1236 Register result = ToRegister(left); |
| 1236 Register right_reg = EmitLoadRegister(right, ip); | 1237 Register right_reg = EmitLoadRegister(right, ip); |
| 1237 switch (instr->op()) { | 1238 switch (instr->op()) { |
| 1238 case Token::BIT_AND: | 1239 case Token::BIT_AND: |
| 1239 __ and_(result, ToRegister(left), Operand(right_reg)); | 1240 __ and_(result, ToRegister(left), Operand(right_reg)); |
| 1240 break; | 1241 break; |
| 1241 case Token::BIT_OR: | 1242 case Token::BIT_OR: |
| 1242 __ orr(result, ToRegister(left), Operand(right_reg)); | 1243 __ orr(result, ToRegister(left), Operand(right_reg)); |
| 1243 break; | 1244 break; |
| 1244 case Token::BIT_XOR: | 1245 case Token::BIT_XOR: |
| 1245 __ eor(result, ToRegister(left), Operand(right_reg)); | 1246 __ eor(result, ToRegister(left), Operand(right_reg)); |
| 1246 break; | 1247 break; |
| 1247 default: | 1248 default: |
| 1248 UNREACHABLE(); | 1249 UNREACHABLE(); |
| 1249 break; | 1250 break; |
| 1250 } | 1251 } |
| 1251 } | 1252 } |
| 1252 | 1253 |
| 1253 | 1254 |
| 1254 void LCodeGen::DoShiftI(LShiftI* instr) { | 1255 void LCodeGen::DoShiftI(LShiftI* instr) { |
| 1255 Register scratch = scratch0(); | 1256 Register scratch = scratch0(); |
| 1256 LOperand* left = instr->left(); | 1257 LOperand* left = instr->InputAt(0); |
| 1257 LOperand* right = instr->right(); | 1258 LOperand* right = instr->InputAt(1); |
| 1258 ASSERT(left->Equals(instr->result())); | 1259 ASSERT(left->Equals(instr->result())); |
| 1259 ASSERT(left->IsRegister()); | 1260 ASSERT(left->IsRegister()); |
| 1260 Register result = ToRegister(left); | 1261 Register result = ToRegister(left); |
| 1261 if (right->IsRegister()) { | 1262 if (right->IsRegister()) { |
| 1262 // Mask the right operand. | 1263 // Mask the right operand. |
| 1263 __ and_(scratch, ToRegister(right), Operand(0x1F)); | 1264 __ and_(scratch, ToRegister(right), Operand(0x1F)); |
| 1264 switch (instr->op()) { | 1265 switch (instr->op()) { |
| 1265 case Token::SAR: | 1266 case Token::SAR: |
| 1266 __ mov(result, Operand(result, ASR, scratch)); | 1267 __ mov(result, Operand(result, ASR, scratch)); |
| 1267 break; | 1268 break; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1304 break; | 1305 break; |
| 1305 default: | 1306 default: |
| 1306 UNREACHABLE(); | 1307 UNREACHABLE(); |
| 1307 break; | 1308 break; |
| 1308 } | 1309 } |
| 1309 } | 1310 } |
| 1310 } | 1311 } |
| 1311 | 1312 |
| 1312 | 1313 |
| 1313 void LCodeGen::DoSubI(LSubI* instr) { | 1314 void LCodeGen::DoSubI(LSubI* instr) { |
| 1314 Register left = ToRegister(instr->left()); | 1315 Register left = ToRegister(instr->InputAt(0)); |
| 1315 Register right = EmitLoadRegister(instr->right(), ip); | 1316 Register right = EmitLoadRegister(instr->InputAt(1), ip); |
| 1316 ASSERT(instr->left()->Equals(instr->result())); | 1317 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 1317 __ sub(left, left, right, SetCC); | 1318 __ sub(left, left, right, SetCC); |
| 1318 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1319 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1319 DeoptimizeIf(vs, instr->environment()); | 1320 DeoptimizeIf(vs, instr->environment()); |
| 1320 } | 1321 } |
| 1321 } | 1322 } |
| 1322 | 1323 |
| 1323 | 1324 |
| 1324 void LCodeGen::DoConstantI(LConstantI* instr) { | 1325 void LCodeGen::DoConstantI(LConstantI* instr) { |
| 1325 ASSERT(instr->result()->IsRegister()); | 1326 ASSERT(instr->result()->IsRegister()); |
| 1326 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1327 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 1327 } | 1328 } |
| 1328 | 1329 |
| 1329 | 1330 |
| 1330 void LCodeGen::DoConstantD(LConstantD* instr) { | 1331 void LCodeGen::DoConstantD(LConstantD* instr) { |
| 1331 ASSERT(instr->result()->IsDoubleRegister()); | 1332 ASSERT(instr->result()->IsDoubleRegister()); |
| 1332 DwVfpRegister result = ToDoubleRegister(instr->result()); | 1333 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 1333 double v = instr->value(); | 1334 double v = instr->value(); |
| 1334 __ vmov(result, v); | 1335 __ vmov(result, v); |
| 1335 } | 1336 } |
| 1336 | 1337 |
| 1337 | 1338 |
| 1338 void LCodeGen::DoConstantT(LConstantT* instr) { | 1339 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1339 ASSERT(instr->result()->IsRegister()); | 1340 ASSERT(instr->result()->IsRegister()); |
| 1340 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1341 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 1341 } | 1342 } |
| 1342 | 1343 |
| 1343 | 1344 |
| 1344 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1345 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 1345 Register result = ToRegister(instr->result()); | 1346 Register result = ToRegister(instr->result()); |
| 1346 Register array = ToRegister(instr->input()); | 1347 Register array = ToRegister(instr->InputAt(0)); |
| 1347 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); | 1348 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); |
| 1348 } | 1349 } |
| 1349 | 1350 |
| 1350 | 1351 |
| 1351 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | 1352 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { |
| 1352 Register result = ToRegister(instr->result()); | 1353 Register result = ToRegister(instr->result()); |
| 1353 Register array = ToRegister(instr->input()); | 1354 Register array = ToRegister(instr->InputAt(0)); |
| 1354 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); | 1355 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); |
| 1355 } | 1356 } |
| 1356 | 1357 |
| 1357 | 1358 |
| 1358 void LCodeGen::DoValueOf(LValueOf* instr) { | 1359 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 1359 Register input = ToRegister(instr->input()); | 1360 Register input = ToRegister(instr->InputAt(0)); |
| 1360 Register result = ToRegister(instr->result()); | 1361 Register result = ToRegister(instr->result()); |
| 1361 Register map = ToRegister(instr->temporary()); | 1362 Register map = ToRegister(instr->TempAt(0)); |
| 1362 ASSERT(input.is(result)); | 1363 ASSERT(input.is(result)); |
| 1363 Label done; | 1364 Label done; |
| 1364 | 1365 |
| 1365 // If the object is a smi return the object. | 1366 // If the object is a smi return the object. |
| 1366 __ tst(input, Operand(kSmiTagMask)); | 1367 __ tst(input, Operand(kSmiTagMask)); |
| 1367 __ b(eq, &done); | 1368 __ b(eq, &done); |
| 1368 | 1369 |
| 1369 // If the object is not a value type, return the object. | 1370 // If the object is not a value type, return the object. |
| 1370 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | 1371 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); |
| 1371 __ b(ne, &done); | 1372 __ b(ne, &done); |
| 1372 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); | 1373 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); |
| 1373 | 1374 |
| 1374 __ bind(&done); | 1375 __ bind(&done); |
| 1375 } | 1376 } |
| 1376 | 1377 |
| 1377 | 1378 |
| 1378 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1379 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1379 LOperand* input = instr->input(); | 1380 LOperand* input = instr->InputAt(0); |
| 1380 ASSERT(input->Equals(instr->result())); | 1381 ASSERT(input->Equals(instr->result())); |
| 1381 __ mvn(ToRegister(input), Operand(ToRegister(input))); | 1382 __ mvn(ToRegister(input), Operand(ToRegister(input))); |
| 1382 } | 1383 } |
| 1383 | 1384 |
| 1384 | 1385 |
| 1385 void LCodeGen::DoThrow(LThrow* instr) { | 1386 void LCodeGen::DoThrow(LThrow* instr) { |
| 1386 Register input_reg = EmitLoadRegister(instr->input(), ip); | 1387 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
| 1387 __ push(input_reg); | 1388 __ push(input_reg); |
| 1388 CallRuntime(Runtime::kThrow, 1, instr); | 1389 CallRuntime(Runtime::kThrow, 1, instr); |
| 1389 | 1390 |
| 1390 if (FLAG_debug_code) { | 1391 if (FLAG_debug_code) { |
| 1391 __ stop("Unreachable code."); | 1392 __ stop("Unreachable code."); |
| 1392 } | 1393 } |
| 1393 } | 1394 } |
| 1394 | 1395 |
| 1395 | 1396 |
| 1396 void LCodeGen::DoAddI(LAddI* instr) { | 1397 void LCodeGen::DoAddI(LAddI* instr) { |
| 1397 LOperand* left = instr->left(); | 1398 LOperand* left = instr->InputAt(0); |
| 1398 LOperand* right = instr->right(); | 1399 LOperand* right = instr->InputAt(1); |
| 1399 ASSERT(left->Equals(instr->result())); | 1400 ASSERT(left->Equals(instr->result())); |
| 1400 | 1401 |
| 1401 Register right_reg = EmitLoadRegister(right, ip); | 1402 Register right_reg = EmitLoadRegister(right, ip); |
| 1402 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), SetCC); | 1403 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), SetCC); |
| 1403 | 1404 |
| 1404 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1405 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1405 DeoptimizeIf(vs, instr->environment()); | 1406 DeoptimizeIf(vs, instr->environment()); |
| 1406 } | 1407 } |
| 1407 } | 1408 } |
| 1408 | 1409 |
| 1409 | 1410 |
| 1410 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1411 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 1411 DoubleRegister left = ToDoubleRegister(instr->left()); | 1412 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); |
| 1412 DoubleRegister right = ToDoubleRegister(instr->right()); | 1413 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); |
| 1413 switch (instr->op()) { | 1414 switch (instr->op()) { |
| 1414 case Token::ADD: | 1415 case Token::ADD: |
| 1415 __ vadd(left, left, right); | 1416 __ vadd(left, left, right); |
| 1416 break; | 1417 break; |
| 1417 case Token::SUB: | 1418 case Token::SUB: |
| 1418 __ vsub(left, left, right); | 1419 __ vsub(left, left, right); |
| 1419 break; | 1420 break; |
| 1420 case Token::MUL: | 1421 case Token::MUL: |
| 1421 __ vmul(left, left, right); | 1422 __ vmul(left, left, right); |
| 1422 break; | 1423 break; |
| 1423 case Token::DIV: | 1424 case Token::DIV: |
| 1424 __ vdiv(left, left, right); | 1425 __ vdiv(left, left, right); |
| 1425 break; | 1426 break; |
| 1426 case Token::MOD: { | 1427 case Token::MOD: { |
| 1427 Abort("DoArithmeticD unimplemented for MOD."); | 1428 Abort("DoArithmeticD unimplemented for MOD."); |
| 1428 break; | 1429 break; |
| 1429 } | 1430 } |
| 1430 default: | 1431 default: |
| 1431 UNREACHABLE(); | 1432 UNREACHABLE(); |
| 1432 break; | 1433 break; |
| 1433 } | 1434 } |
| 1434 } | 1435 } |
| 1435 | 1436 |
| 1436 | 1437 |
| 1437 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1438 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1438 ASSERT(ToRegister(instr->left()).is(r1)); | 1439 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); |
| 1439 ASSERT(ToRegister(instr->right()).is(r0)); | 1440 ASSERT(ToRegister(instr->InputAt(1)).is(r0)); |
| 1440 ASSERT(ToRegister(instr->result()).is(r0)); | 1441 ASSERT(ToRegister(instr->result()).is(r0)); |
| 1441 | 1442 |
| 1442 // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current | 1443 // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current |
| 1443 // GenericBinaryOpStub: | 1444 // GenericBinaryOpStub: |
| 1444 // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1445 // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1445 GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0); | 1446 GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0); |
| 1446 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1447 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1447 } | 1448 } |
| 1448 | 1449 |
| 1449 | 1450 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1473 } | 1474 } |
| 1474 } | 1475 } |
| 1475 | 1476 |
| 1476 | 1477 |
| 1477 void LCodeGen::DoBranch(LBranch* instr) { | 1478 void LCodeGen::DoBranch(LBranch* instr) { |
| 1478 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1479 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1479 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1480 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1480 | 1481 |
| 1481 Representation r = instr->hydrogen()->representation(); | 1482 Representation r = instr->hydrogen()->representation(); |
| 1482 if (r.IsInteger32()) { | 1483 if (r.IsInteger32()) { |
| 1483 Register reg = ToRegister(instr->input()); | 1484 Register reg = ToRegister(instr->InputAt(0)); |
| 1484 __ cmp(reg, Operand(0)); | 1485 __ cmp(reg, Operand(0)); |
| 1485 EmitBranch(true_block, false_block, nz); | 1486 EmitBranch(true_block, false_block, nz); |
| 1486 } else if (r.IsDouble()) { | 1487 } else if (r.IsDouble()) { |
| 1487 DoubleRegister reg = ToDoubleRegister(instr->input()); | 1488 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0)); |
| 1488 Register scratch = scratch0(); | 1489 Register scratch = scratch0(); |
| 1489 | 1490 |
| 1490 // Test the double value. Zero and NaN are false. | 1491 // Test the double value. Zero and NaN are false. |
| 1491 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 1492 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); |
| 1492 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1493 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
| 1493 EmitBranch(true_block, false_block, ne); | 1494 EmitBranch(true_block, false_block, ne); |
| 1494 } else { | 1495 } else { |
| 1495 ASSERT(r.IsTagged()); | 1496 ASSERT(r.IsTagged()); |
| 1496 Register reg = ToRegister(instr->input()); | 1497 Register reg = ToRegister(instr->InputAt(0)); |
| 1497 if (instr->hydrogen()->type().IsBoolean()) { | 1498 if (instr->hydrogen()->type().IsBoolean()) { |
| 1498 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 1499 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 1499 __ cmp(reg, ip); | 1500 __ cmp(reg, ip); |
| 1500 EmitBranch(true_block, false_block, eq); | 1501 EmitBranch(true_block, false_block, eq); |
| 1501 } else { | 1502 } else { |
| 1502 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1503 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1503 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1504 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1504 | 1505 |
| 1505 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1506 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 1506 __ cmp(reg, ip); | 1507 __ cmp(reg, ip); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1629 Abort("DoCmpID unimplemented."); | 1630 Abort("DoCmpID unimplemented."); |
| 1630 } | 1631 } |
| 1631 | 1632 |
| 1632 | 1633 |
| 1633 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1634 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
| 1634 Abort("DoCmpIDAndBranch unimplemented."); | 1635 Abort("DoCmpIDAndBranch unimplemented."); |
| 1635 } | 1636 } |
| 1636 | 1637 |
| 1637 | 1638 |
| 1638 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1639 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
| 1639 Register left = ToRegister(instr->left()); | 1640 Register left = ToRegister(instr->InputAt(0)); |
| 1640 Register right = ToRegister(instr->right()); | 1641 Register right = ToRegister(instr->InputAt(1)); |
| 1641 Register result = ToRegister(instr->result()); | 1642 Register result = ToRegister(instr->result()); |
| 1642 | 1643 |
| 1643 __ cmp(left, Operand(right)); | 1644 __ cmp(left, Operand(right)); |
| 1644 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); | 1645 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); |
| 1645 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); | 1646 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); |
| 1646 } | 1647 } |
| 1647 | 1648 |
| 1648 | 1649 |
| 1649 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1650 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
| 1650 Register left = ToRegister(instr->left()); | 1651 Register left = ToRegister(instr->InputAt(0)); |
| 1651 Register right = ToRegister(instr->right()); | 1652 Register right = ToRegister(instr->InputAt(1)); |
| 1652 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1653 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1653 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1654 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1654 | 1655 |
| 1655 __ cmp(left, Operand(right)); | 1656 __ cmp(left, Operand(right)); |
| 1656 EmitBranch(true_block, false_block, eq); | 1657 EmitBranch(true_block, false_block, eq); |
| 1657 } | 1658 } |
| 1658 | 1659 |
| 1659 | 1660 |
| 1660 void LCodeGen::DoIsNull(LIsNull* instr) { | 1661 void LCodeGen::DoIsNull(LIsNull* instr) { |
| 1661 Register reg = ToRegister(instr->input()); | 1662 Register reg = ToRegister(instr->InputAt(0)); |
| 1662 Register result = ToRegister(instr->result()); | 1663 Register result = ToRegister(instr->result()); |
| 1663 | 1664 |
| 1664 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1665 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 1665 __ cmp(reg, ip); | 1666 __ cmp(reg, ip); |
| 1666 if (instr->is_strict()) { | 1667 if (instr->is_strict()) { |
| 1667 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); | 1668 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); |
| 1668 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); | 1669 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); |
| 1669 } else { | 1670 } else { |
| 1670 Label true_value, false_value, done; | 1671 Label true_value, false_value, done; |
| 1671 __ b(eq, &true_value); | 1672 __ b(eq, &true_value); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1686 __ jmp(&done); | 1687 __ jmp(&done); |
| 1687 __ bind(&true_value); | 1688 __ bind(&true_value); |
| 1688 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1689 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1689 __ bind(&done); | 1690 __ bind(&done); |
| 1690 } | 1691 } |
| 1691 } | 1692 } |
| 1692 | 1693 |
| 1693 | 1694 |
| 1694 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1695 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
| 1695 Register scratch = scratch0(); | 1696 Register scratch = scratch0(); |
| 1696 Register reg = ToRegister(instr->input()); | 1697 Register reg = ToRegister(instr->InputAt(0)); |
| 1697 | 1698 |
| 1698 // TODO(fsc): If the expression is known to be a smi, then it's | 1699 // TODO(fsc): If the expression is known to be a smi, then it's |
| 1699 // definitely not null. Jump to the false block. | 1700 // definitely not null. Jump to the false block. |
| 1700 | 1701 |
| 1701 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1702 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1702 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1703 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1703 | 1704 |
| 1704 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1705 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 1705 __ cmp(reg, ip); | 1706 __ cmp(reg, ip); |
| 1706 if (instr->is_strict()) { | 1707 if (instr->is_strict()) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1740 | 1741 |
| 1741 | 1742 |
| 1742 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1743 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 1743 Abort("DoIsObjectAndBranch unimplemented."); | 1744 Abort("DoIsObjectAndBranch unimplemented."); |
| 1744 } | 1745 } |
| 1745 | 1746 |
| 1746 | 1747 |
| 1747 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1748 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
| 1748 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1749 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1749 Register result = ToRegister(instr->result()); | 1750 Register result = ToRegister(instr->result()); |
| 1750 Register input_reg = EmitLoadRegister(instr->input(), ip); | 1751 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
| 1751 __ tst(input_reg, Operand(kSmiTagMask)); | 1752 __ tst(input_reg, Operand(kSmiTagMask)); |
| 1752 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1753 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1753 Label done; | 1754 Label done; |
| 1754 __ b(eq, &done); | 1755 __ b(eq, &done); |
| 1755 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1756 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1756 __ bind(&done); | 1757 __ bind(&done); |
| 1757 } | 1758 } |
| 1758 | 1759 |
| 1759 | 1760 |
| 1760 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1761 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 1761 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1762 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1762 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1763 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1763 | 1764 |
| 1764 Register input_reg = EmitLoadRegister(instr->input(), ip); | 1765 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
| 1765 __ tst(input_reg, Operand(kSmiTagMask)); | 1766 __ tst(input_reg, Operand(kSmiTagMask)); |
| 1766 EmitBranch(true_block, false_block, eq); | 1767 EmitBranch(true_block, false_block, eq); |
| 1767 } | 1768 } |
| 1768 | 1769 |
| 1769 | 1770 |
| 1770 InstanceType LHasInstanceType::TestType() { | |
| 1771 InstanceType from = hydrogen()->from(); | |
| 1772 InstanceType to = hydrogen()->to(); | |
| 1773 if (from == FIRST_TYPE) return to; | |
| 1774 ASSERT(from == to || to == LAST_TYPE); | |
| 1775 return from; | |
| 1776 } | |
| 1777 | |
| 1778 | |
| 1779 Condition LHasInstanceType::BranchCondition() { | |
| 1780 InstanceType from = hydrogen()->from(); | |
| 1781 InstanceType to = hydrogen()->to(); | |
| 1782 if (from == to) return eq; | |
| 1783 if (to == LAST_TYPE) return hs; | |
| 1784 if (from == FIRST_TYPE) return ls; | |
| 1785 UNREACHABLE(); | |
| 1786 return eq; | |
| 1787 } | |
| 1788 | |
| 1789 | |
| 1790 static InstanceType TestType(HHasInstanceType* instr) { | 1771 static InstanceType TestType(HHasInstanceType* instr) { |
| 1791 InstanceType from = instr->from(); | 1772 InstanceType from = instr->from(); |
| 1792 InstanceType to = instr->to(); | 1773 InstanceType to = instr->to(); |
| 1793 if (from == FIRST_TYPE) return to; | 1774 if (from == FIRST_TYPE) return to; |
| 1794 ASSERT(from == to || to == LAST_TYPE); | 1775 ASSERT(from == to || to == LAST_TYPE); |
| 1795 return from; | 1776 return from; |
| 1796 } | 1777 } |
| 1797 | 1778 |
| 1798 | 1779 |
| 1799 static Condition BranchCondition(HHasInstanceType* instr) { | 1780 static Condition BranchCondition(HHasInstanceType* instr) { |
| 1800 InstanceType from = instr->from(); | 1781 InstanceType from = instr->from(); |
| 1801 InstanceType to = instr->to(); | 1782 InstanceType to = instr->to(); |
| 1802 if (from == to) return eq; | 1783 if (from == to) return eq; |
| 1803 if (to == LAST_TYPE) return hs; | 1784 if (to == LAST_TYPE) return hs; |
| 1804 if (from == FIRST_TYPE) return ls; | 1785 if (from == FIRST_TYPE) return ls; |
| 1805 UNREACHABLE(); | 1786 UNREACHABLE(); |
| 1806 return eq; | 1787 return eq; |
| 1807 } | 1788 } |
| 1808 | 1789 |
| 1809 | 1790 |
| 1810 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1791 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
| 1811 Register input = ToRegister(instr->input()); | 1792 Register input = ToRegister(instr->InputAt(0)); |
| 1812 Register result = ToRegister(instr->result()); | 1793 Register result = ToRegister(instr->result()); |
| 1813 | 1794 |
| 1814 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1795 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1815 Label done; | 1796 Label done; |
| 1816 __ tst(input, Operand(kSmiTagMask)); | 1797 __ tst(input, Operand(kSmiTagMask)); |
| 1817 __ LoadRoot(result, Heap::kFalseValueRootIndex, eq); | 1798 __ LoadRoot(result, Heap::kFalseValueRootIndex, eq); |
| 1818 __ b(eq, &done); | 1799 __ b(eq, &done); |
| 1819 __ CompareObjectType(input, result, result, TestType(instr->hydrogen())); | 1800 __ CompareObjectType(input, result, result, TestType(instr->hydrogen())); |
| 1820 Condition cond = BranchCondition(instr->hydrogen()); | 1801 Condition cond = BranchCondition(instr->hydrogen()); |
| 1821 __ LoadRoot(result, Heap::kTrueValueRootIndex, cond); | 1802 __ LoadRoot(result, Heap::kTrueValueRootIndex, cond); |
| 1822 __ LoadRoot(result, Heap::kFalseValueRootIndex, NegateCondition(cond)); | 1803 __ LoadRoot(result, Heap::kFalseValueRootIndex, NegateCondition(cond)); |
| 1823 __ bind(&done); | 1804 __ bind(&done); |
| 1824 } | 1805 } |
| 1825 | 1806 |
| 1826 | 1807 |
| 1827 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1808 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 1828 Register scratch = scratch0(); | 1809 Register scratch = scratch0(); |
| 1829 Register input = ToRegister(instr->input()); | 1810 Register input = ToRegister(instr->InputAt(0)); |
| 1830 | 1811 |
| 1831 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1812 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1832 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1813 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1833 | 1814 |
| 1834 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1815 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1835 | 1816 |
| 1836 __ tst(input, Operand(kSmiTagMask)); | 1817 __ tst(input, Operand(kSmiTagMask)); |
| 1837 __ b(eq, false_label); | 1818 __ b(eq, false_label); |
| 1838 | 1819 |
| 1839 __ CompareObjectType(input, scratch, scratch, instr->TestType()); | 1820 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); |
| 1840 EmitBranch(true_block, false_block, instr->BranchCondition()); | 1821 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
| 1841 } | 1822 } |
| 1842 | 1823 |
| 1843 | 1824 |
| 1844 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1825 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
| 1845 Abort("DoHasCachedArrayIndex unimplemented."); | 1826 Abort("DoHasCachedArrayIndex unimplemented."); |
| 1846 } | 1827 } |
| 1847 | 1828 |
| 1848 | 1829 |
| 1849 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1830 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 1850 LHasCachedArrayIndexAndBranch* instr) { | 1831 LHasCachedArrayIndexAndBranch* instr) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1903 // booted. This routine isn't expected to work for random API-created | 1884 // booted. This routine isn't expected to work for random API-created |
| 1904 // classes and it doesn't have to because you can't access it with natives | 1885 // classes and it doesn't have to because you can't access it with natives |
| 1905 // syntax. Since both sides are symbols it is sufficient to use an identity | 1886 // syntax. Since both sides are symbols it is sufficient to use an identity |
| 1906 // comparison. | 1887 // comparison. |
| 1907 __ cmp(temp, Operand(class_name)); | 1888 __ cmp(temp, Operand(class_name)); |
| 1908 // End with the answer in flags. | 1889 // End with the answer in flags. |
| 1909 } | 1890 } |
| 1910 | 1891 |
| 1911 | 1892 |
| 1912 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1893 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
| 1913 Register input = ToRegister(instr->input()); | 1894 Register input = ToRegister(instr->InputAt(0)); |
| 1914 Register result = ToRegister(instr->result()); | 1895 Register result = ToRegister(instr->result()); |
| 1915 ASSERT(input.is(result)); | 1896 ASSERT(input.is(result)); |
| 1916 Handle<String> class_name = instr->hydrogen()->class_name(); | 1897 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1917 | 1898 |
| 1918 Label done, is_true, is_false; | 1899 Label done, is_true, is_false; |
| 1919 | 1900 |
| 1920 EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input); | 1901 EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input); |
| 1921 __ b(ne, &is_false); | 1902 __ b(ne, &is_false); |
| 1922 | 1903 |
| 1923 __ bind(&is_true); | 1904 __ bind(&is_true); |
| 1924 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 1905 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 1925 __ jmp(&done); | 1906 __ jmp(&done); |
| 1926 | 1907 |
| 1927 __ bind(&is_false); | 1908 __ bind(&is_false); |
| 1928 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 1909 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 1929 __ bind(&done); | 1910 __ bind(&done); |
| 1930 } | 1911 } |
| 1931 | 1912 |
| 1932 | 1913 |
| 1933 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1914 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 1934 Register input = ToRegister(instr->input()); | 1915 Register input = ToRegister(instr->InputAt(0)); |
| 1935 Register temp = scratch0(); | 1916 Register temp = scratch0(); |
| 1936 Register temp2 = ToRegister(instr->temporary()); | 1917 Register temp2 = ToRegister(instr->TempAt(0)); |
| 1937 Handle<String> class_name = instr->hydrogen()->class_name(); | 1918 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1938 | 1919 |
| 1939 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1920 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1940 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1921 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1941 | 1922 |
| 1942 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1923 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1943 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1924 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1944 | 1925 |
| 1945 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 1926 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
| 1946 | 1927 |
| 1947 EmitBranch(true_block, false_block, eq); | 1928 EmitBranch(true_block, false_block, eq); |
| 1948 } | 1929 } |
| 1949 | 1930 |
| 1950 | 1931 |
| 1951 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1932 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 1952 Register reg = ToRegister(instr->input()); | 1933 Register reg = ToRegister(instr->InputAt(0)); |
| 1953 Register temp = ToRegister(instr->temp()); | 1934 Register temp = ToRegister(instr->TempAt(0)); |
| 1954 int true_block = instr->true_block_id(); | 1935 int true_block = instr->true_block_id(); |
| 1955 int false_block = instr->false_block_id(); | 1936 int false_block = instr->false_block_id(); |
| 1956 | 1937 |
| 1957 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1938 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1958 __ cmp(temp, Operand(instr->map())); | 1939 __ cmp(temp, Operand(instr->map())); |
| 1959 EmitBranch(true_block, false_block, eq); | 1940 EmitBranch(true_block, false_block, eq); |
| 1960 } | 1941 } |
| 1961 | 1942 |
| 1962 | 1943 |
| 1963 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1944 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1964 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. | 1945 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); // Object is in r0. |
| 1965 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. | 1946 ASSERT(ToRegister(instr->InputAt(1)).is(r1)); // Function is in r1. |
| 1966 | 1947 |
| 1967 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1948 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 1968 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1949 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1969 | 1950 |
| 1970 Label true_value, done; | 1951 Label true_value, done; |
| 1971 __ tst(r0, r0); | 1952 __ tst(r0, r0); |
| 1972 __ mov(r0, Operand(Factory::false_value()), LeaveCC, ne); | 1953 __ mov(r0, Operand(Factory::false_value()), LeaveCC, ne); |
| 1973 __ mov(r0, Operand(Factory::true_value()), LeaveCC, eq); | 1954 __ mov(r0, Operand(Factory::true_value()), LeaveCC, eq); |
| 1974 } | 1955 } |
| 1975 | 1956 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1993 | 1974 |
| 1994 private: | 1975 private: |
| 1995 LInstanceOfKnownGlobal* instr_; | 1976 LInstanceOfKnownGlobal* instr_; |
| 1996 Label map_check_; | 1977 Label map_check_; |
| 1997 }; | 1978 }; |
| 1998 | 1979 |
| 1999 DeferredInstanceOfKnownGlobal* deferred; | 1980 DeferredInstanceOfKnownGlobal* deferred; |
| 2000 deferred = new DeferredInstanceOfKnownGlobal(this, instr); | 1981 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
| 2001 | 1982 |
| 2002 Label done, false_result; | 1983 Label done, false_result; |
| 2003 Register object = ToRegister(instr->input()); | 1984 Register object = ToRegister(instr->InputAt(0)); |
| 2004 Register temp = ToRegister(instr->temp()); | 1985 Register temp = ToRegister(instr->TempAt(0)); |
| 2005 Register result = ToRegister(instr->result()); | 1986 Register result = ToRegister(instr->result()); |
| 2006 | 1987 |
| 2007 ASSERT(object.is(r0)); | 1988 ASSERT(object.is(r0)); |
| 2008 ASSERT(result.is(r0)); | 1989 ASSERT(result.is(r0)); |
| 2009 | 1990 |
| 2010 // A Smi is not instance of anything. | 1991 // A Smi is not instance of anything. |
| 2011 __ BranchOnSmi(object, &false_result); | 1992 __ BranchOnSmi(object, &false_result); |
| 2012 | 1993 |
| 2013 // This is the inlined call site instanceof cache. The two occurences of the | 1994 // This is the inlined call site instanceof cache. The two occurences of the |
| 2014 // hole value will be patched to the last map/result pair generated by the | 1995 // hole value will be patched to the last map/result pair generated by the |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2066 flags | InstanceofStub::kCallSiteInlineCheck); | 2047 flags | InstanceofStub::kCallSiteInlineCheck); |
| 2067 flags = static_cast<InstanceofStub::Flags>( | 2048 flags = static_cast<InstanceofStub::Flags>( |
| 2068 flags | InstanceofStub::kReturnTrueFalseObject); | 2049 flags | InstanceofStub::kReturnTrueFalseObject); |
| 2069 InstanceofStub stub(flags); | 2050 InstanceofStub stub(flags); |
| 2070 | 2051 |
| 2071 __ PushSafepointRegisters(); | 2052 __ PushSafepointRegisters(); |
| 2072 | 2053 |
| 2073 // Get the temp register reserved by the instruction. This needs to be r4 as | 2054 // Get the temp register reserved by the instruction. This needs to be r4 as |
| 2074 // its slot of the pushing of safepoint registers is used to communicate the | 2055 // its slot of the pushing of safepoint registers is used to communicate the |
| 2075 // offset to the location of the map check. | 2056 // offset to the location of the map check. |
| 2076 Register temp = ToRegister(instr->temp()); | 2057 Register temp = ToRegister(instr->TempAt(0)); |
| 2077 ASSERT(temp.is(r4)); | 2058 ASSERT(temp.is(r4)); |
| 2078 __ mov(InstanceofStub::right(), Operand(instr->function())); | 2059 __ mov(InstanceofStub::right(), Operand(instr->function())); |
| 2079 static const int kAdditionalDelta = 4; | 2060 static const int kAdditionalDelta = 4; |
| 2080 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; | 2061 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
| 2081 Label before_push_delta; | 2062 Label before_push_delta; |
| 2082 __ bind(&before_push_delta); | 2063 __ bind(&before_push_delta); |
| 2083 __ BlockConstPoolFor(kAdditionalDelta); | 2064 __ BlockConstPoolFor(kAdditionalDelta); |
| 2084 __ mov(temp, Operand(delta * kPointerSize)); | 2065 __ mov(temp, Operand(delta * kPointerSize)); |
| 2085 __ StoreToSafepointRegisterSlot(temp); | 2066 __ StoreToSafepointRegisterSlot(temp); |
| 2086 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); | 2067 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2162 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); | 2143 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); |
| 2163 if (instr->hydrogen()->check_hole_value()) { | 2144 if (instr->hydrogen()->check_hole_value()) { |
| 2164 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2145 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 2165 __ cmp(result, ip); | 2146 __ cmp(result, ip); |
| 2166 DeoptimizeIf(eq, instr->environment()); | 2147 DeoptimizeIf(eq, instr->environment()); |
| 2167 } | 2148 } |
| 2168 } | 2149 } |
| 2169 | 2150 |
| 2170 | 2151 |
| 2171 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { | 2152 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { |
| 2172 Register value = ToRegister(instr->input()); | 2153 Register value = ToRegister(instr->InputAt(0)); |
| 2173 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); | 2154 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); |
| 2174 __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); | 2155 __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); |
| 2175 } | 2156 } |
| 2176 | 2157 |
| 2177 | 2158 |
| 2178 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2159 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 2179 // TODO(antonm): load a context with a separate instruction. | 2160 // TODO(antonm): load a context with a separate instruction. |
| 2180 Register result = ToRegister(instr->result()); | 2161 Register result = ToRegister(instr->result()); |
| 2181 __ LoadContext(result, instr->context_chain_length()); | 2162 __ LoadContext(result, instr->context_chain_length()); |
| 2182 __ ldr(result, ContextOperand(result, instr->slot_index())); | 2163 __ ldr(result, ContextOperand(result, instr->slot_index())); |
| 2183 } | 2164 } |
| 2184 | 2165 |
| 2185 | 2166 |
| 2186 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2167 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 2187 Register object = ToRegister(instr->input()); | 2168 Register object = ToRegister(instr->InputAt(0)); |
| 2188 Register result = ToRegister(instr->result()); | 2169 Register result = ToRegister(instr->result()); |
| 2189 if (instr->hydrogen()->is_in_object()) { | 2170 if (instr->hydrogen()->is_in_object()) { |
| 2190 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); | 2171 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); |
| 2191 } else { | 2172 } else { |
| 2192 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2173 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 2193 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); | 2174 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); |
| 2194 } | 2175 } |
| 2195 } | 2176 } |
| 2196 | 2177 |
| 2197 | 2178 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2244 // in initial map. | 2225 // in initial map. |
| 2245 __ bind(&non_instance); | 2226 __ bind(&non_instance); |
| 2246 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); | 2227 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); |
| 2247 | 2228 |
| 2248 // All done. | 2229 // All done. |
| 2249 __ bind(&done); | 2230 __ bind(&done); |
| 2250 } | 2231 } |
| 2251 | 2232 |
| 2252 | 2233 |
| 2253 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2234 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
| 2254 ASSERT(instr->result()->Equals(instr->input())); | 2235 ASSERT(instr->result()->Equals(instr->InputAt(0))); |
| 2255 Register reg = ToRegister(instr->input()); | 2236 Register reg = ToRegister(instr->InputAt(0)); |
| 2256 Register scratch = scratch0(); | 2237 Register scratch = scratch0(); |
| 2257 | 2238 |
| 2258 __ ldr(reg, FieldMemOperand(reg, JSObject::kElementsOffset)); | 2239 __ ldr(reg, FieldMemOperand(reg, JSObject::kElementsOffset)); |
| 2259 if (FLAG_debug_code) { | 2240 if (FLAG_debug_code) { |
| 2260 Label done; | 2241 Label done; |
| 2261 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2242 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2262 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 2243 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
| 2263 __ cmp(scratch, ip); | 2244 __ cmp(scratch, ip); |
| 2264 __ b(eq, &done); | 2245 __ b(eq, &done); |
| 2265 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); | 2246 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2326 __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2307 __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 2327 | 2308 |
| 2328 // Result is the frame pointer for the frame if not adapted and for the real | 2309 // Result is the frame pointer for the frame if not adapted and for the real |
| 2329 // frame below the adaptor frame if adapted. | 2310 // frame below the adaptor frame if adapted. |
| 2330 __ mov(result, fp, LeaveCC, ne); | 2311 __ mov(result, fp, LeaveCC, ne); |
| 2331 __ mov(result, scratch, LeaveCC, eq); | 2312 __ mov(result, scratch, LeaveCC, eq); |
| 2332 } | 2313 } |
| 2333 | 2314 |
| 2334 | 2315 |
| 2335 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2316 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 2336 Register elem = ToRegister(instr->input()); | 2317 Register elem = ToRegister(instr->InputAt(0)); |
| 2337 Register result = ToRegister(instr->result()); | 2318 Register result = ToRegister(instr->result()); |
| 2338 | 2319 |
| 2339 Label done; | 2320 Label done; |
| 2340 | 2321 |
| 2341 // If no arguments adaptor frame the number of arguments is fixed. | 2322 // If no arguments adaptor frame the number of arguments is fixed. |
| 2342 __ cmp(fp, elem); | 2323 __ cmp(fp, elem); |
| 2343 __ mov(result, Operand(scope()->num_parameters())); | 2324 __ mov(result, Operand(scope()->num_parameters())); |
| 2344 __ b(eq, &done); | 2325 __ b(eq, &done); |
| 2345 | 2326 |
| 2346 // Arguments adaptor frame present. Get argument length from there. | 2327 // Arguments adaptor frame present. Get argument length from there. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2411 // which is r0, as expected by InvokeFunction. | 2392 // which is r0, as expected by InvokeFunction. |
| 2412 v8::internal::ParameterCount actual(receiver); | 2393 v8::internal::ParameterCount actual(receiver); |
| 2413 SafepointGenerator safepoint_generator(this, | 2394 SafepointGenerator safepoint_generator(this, |
| 2414 instr->pointer_map(), | 2395 instr->pointer_map(), |
| 2415 Safepoint::kNoDeoptimizationIndex); | 2396 Safepoint::kNoDeoptimizationIndex); |
| 2416 __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator); | 2397 __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator); |
| 2417 } | 2398 } |
| 2418 | 2399 |
| 2419 | 2400 |
| 2420 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2401 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 2421 LOperand* argument = instr->input(); | 2402 LOperand* argument = instr->InputAt(0); |
| 2422 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 2403 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
| 2423 Abort("DoPushArgument not implemented for double type."); | 2404 Abort("DoPushArgument not implemented for double type."); |
| 2424 } else { | 2405 } else { |
| 2425 Register argument_reg = EmitLoadRegister(argument, ip); | 2406 Register argument_reg = EmitLoadRegister(argument, ip); |
| 2426 __ push(argument_reg); | 2407 __ push(argument_reg); |
| 2427 } | 2408 } |
| 2428 } | 2409 } |
| 2429 | 2410 |
| 2430 | 2411 |
| 2431 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 2412 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2475 | 2456 |
| 2476 | 2457 |
| 2477 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2458 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 2478 ASSERT(ToRegister(instr->result()).is(r0)); | 2459 ASSERT(ToRegister(instr->result()).is(r0)); |
| 2479 __ mov(r1, Operand(instr->function())); | 2460 __ mov(r1, Operand(instr->function())); |
| 2480 CallKnownFunction(instr->function(), instr->arity(), instr); | 2461 CallKnownFunction(instr->function(), instr->arity(), instr); |
| 2481 } | 2462 } |
| 2482 | 2463 |
| 2483 | 2464 |
| 2484 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2465 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 2485 Register input = ToRegister(instr->input()); | 2466 Register input = ToRegister(instr->InputAt(0)); |
| 2486 Register scratch = scratch0(); | 2467 Register scratch = scratch0(); |
| 2487 | 2468 |
| 2488 // Deoptimize if not a heap number. | 2469 // Deoptimize if not a heap number. |
| 2489 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 2470 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 2490 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 2471 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 2491 __ cmp(scratch, Operand(ip)); | 2472 __ cmp(scratch, Operand(ip)); |
| 2492 DeoptimizeIf(ne, instr->environment()); | 2473 DeoptimizeIf(ne, instr->environment()); |
| 2493 | 2474 |
| 2494 Label done; | 2475 Label done; |
| 2495 Register tmp = input.is(r0) ? r1 : r0; | 2476 Register tmp = input.is(r0) ? r1 : r0; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2538 __ str(tmp, input_register_slot); | 2519 __ str(tmp, input_register_slot); |
| 2539 __ PopSafepointRegisters(); | 2520 __ PopSafepointRegisters(); |
| 2540 | 2521 |
| 2541 __ bind(&done); | 2522 __ bind(&done); |
| 2542 } | 2523 } |
| 2543 | 2524 |
| 2544 | 2525 |
| 2545 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2526 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 2546 Label is_positive; | 2527 Label is_positive; |
| 2547 uint32_t kSignMask = 0x80000000u; | 2528 uint32_t kSignMask = 0x80000000u; |
| 2548 Register input = ToRegister(instr->input()); | 2529 Register input = ToRegister(instr->InputAt(0)); |
| 2549 __ tst(input, Operand(kSignMask)); | 2530 __ tst(input, Operand(kSignMask)); |
| 2550 __ b(eq, &is_positive); | 2531 __ b(eq, &is_positive); |
| 2551 __ rsb(input, input, Operand(0), SetCC); | 2532 __ rsb(input, input, Operand(0), SetCC); |
| 2552 // Deoptimize on overflow. | 2533 // Deoptimize on overflow. |
| 2553 DeoptimizeIf(vs, instr->environment()); | 2534 DeoptimizeIf(vs, instr->environment()); |
| 2554 __ bind(&is_positive); | 2535 __ bind(&is_positive); |
| 2555 } | 2536 } |
| 2556 | 2537 |
| 2557 | 2538 |
| 2558 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2539 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
| 2559 // Class for deferred case. | 2540 // Class for deferred case. |
| 2560 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 2541 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 2561 public: | 2542 public: |
| 2562 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2543 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
| 2563 LUnaryMathOperation* instr) | 2544 LUnaryMathOperation* instr) |
| 2564 : LDeferredCode(codegen), instr_(instr) { } | 2545 : LDeferredCode(codegen), instr_(instr) { } |
| 2565 virtual void Generate() { | 2546 virtual void Generate() { |
| 2566 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 2547 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 2567 } | 2548 } |
| 2568 private: | 2549 private: |
| 2569 LUnaryMathOperation* instr_; | 2550 LUnaryMathOperation* instr_; |
| 2570 }; | 2551 }; |
| 2571 | 2552 |
| 2572 ASSERT(instr->input()->Equals(instr->result())); | 2553 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 2573 Representation r = instr->hydrogen()->value()->representation(); | 2554 Representation r = instr->hydrogen()->value()->representation(); |
| 2574 if (r.IsDouble()) { | 2555 if (r.IsDouble()) { |
| 2575 DwVfpRegister input = ToDoubleRegister(instr->input()); | 2556 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 2576 // __ vabs(input, input); | 2557 // __ vabs(input, input); |
| 2577 Abort("Double DoMathAbs unimplemented"); | 2558 Abort("Double DoMathAbs unimplemented"); |
| 2578 } else if (r.IsInteger32()) { | 2559 } else if (r.IsInteger32()) { |
| 2579 EmitIntegerMathAbs(instr); | 2560 EmitIntegerMathAbs(instr); |
| 2580 } else { | 2561 } else { |
| 2581 // Representation is tagged. | 2562 // Representation is tagged. |
| 2582 DeferredMathAbsTaggedHeapNumber* deferred = | 2563 DeferredMathAbsTaggedHeapNumber* deferred = |
| 2583 new DeferredMathAbsTaggedHeapNumber(this, instr); | 2564 new DeferredMathAbsTaggedHeapNumber(this, instr); |
| 2584 Register input = ToRegister(instr->input()); | 2565 Register input = ToRegister(instr->InputAt(0)); |
| 2585 // Smi check. | 2566 // Smi check. |
| 2586 __ BranchOnNotSmi(input, deferred->entry()); | 2567 __ BranchOnNotSmi(input, deferred->entry()); |
| 2587 // If smi, handle it directly. | 2568 // If smi, handle it directly. |
| 2588 EmitIntegerMathAbs(instr); | 2569 EmitIntegerMathAbs(instr); |
| 2589 __ bind(deferred->exit()); | 2570 __ bind(deferred->exit()); |
| 2590 } | 2571 } |
| 2591 } | 2572 } |
| 2592 | 2573 |
| 2593 | 2574 |
| 2594 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 2575 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| 2595 DoubleRegister input = ToDoubleRegister(instr->input()); | 2576 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 2596 Register result = ToRegister(instr->result()); | 2577 Register result = ToRegister(instr->result()); |
| 2597 Register prev_fpscr = ToRegister(instr->temp()); | 2578 Register prev_fpscr = ToRegister(instr->TempAt(0)); |
| 2598 SwVfpRegister single_scratch = double_scratch0().low(); | 2579 SwVfpRegister single_scratch = double_scratch0().low(); |
| 2599 Register scratch = scratch0(); | 2580 Register scratch = scratch0(); |
| 2600 | 2581 |
| 2601 // Set custom FPCSR: | 2582 // Set custom FPCSR: |
| 2602 // - Set rounding mode to "Round towards Minus Infinity". | 2583 // - Set rounding mode to "Round towards Minus Infinity". |
| 2603 // - Clear vfp cumulative exception flags. | 2584 // - Clear vfp cumulative exception flags. |
| 2604 // - Make sure Flush-to-zero mode control bit is unset. | 2585 // - Make sure Flush-to-zero mode control bit is unset. |
| 2605 __ vmrs(prev_fpscr); | 2586 __ vmrs(prev_fpscr); |
| 2606 __ bic(scratch, prev_fpscr, | 2587 __ bic(scratch, prev_fpscr, |
| 2607 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); | 2588 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2629 __ cmp(result, Operand(0)); | 2610 __ cmp(result, Operand(0)); |
| 2630 __ b(ne, &done); | 2611 __ b(ne, &done); |
| 2631 __ vmov(scratch, input.high()); | 2612 __ vmov(scratch, input.high()); |
| 2632 __ tst(scratch, Operand(HeapNumber::kSignMask)); | 2613 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
| 2633 DeoptimizeIf(ne, instr->environment()); | 2614 DeoptimizeIf(ne, instr->environment()); |
| 2634 __ bind(&done); | 2615 __ bind(&done); |
| 2635 } | 2616 } |
| 2636 | 2617 |
| 2637 | 2618 |
| 2638 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 2619 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 2639 DoubleRegister input = ToDoubleRegister(instr->input()); | 2620 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 2640 ASSERT(ToDoubleRegister(instr->result()).is(input)); | 2621 ASSERT(ToDoubleRegister(instr->result()).is(input)); |
| 2641 __ vsqrt(input, input); | 2622 __ vsqrt(input, input); |
| 2642 } | 2623 } |
| 2643 | 2624 |
| 2644 | 2625 |
| 2645 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { | 2626 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { |
| 2646 switch (instr->op()) { | 2627 switch (instr->op()) { |
| 2647 case kMathAbs: | 2628 case kMathAbs: |
| 2648 DoMathAbs(instr); | 2629 DoMathAbs(instr); |
| 2649 break; | 2630 break; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2705 | 2686 |
| 2706 | 2687 |
| 2707 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 2688 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 2708 ASSERT(ToRegister(instr->result()).is(r0)); | 2689 ASSERT(ToRegister(instr->result()).is(r0)); |
| 2709 __ mov(r1, Operand(instr->target())); | 2690 __ mov(r1, Operand(instr->target())); |
| 2710 CallKnownFunction(instr->target(), instr->arity(), instr); | 2691 CallKnownFunction(instr->target(), instr->arity(), instr); |
| 2711 } | 2692 } |
| 2712 | 2693 |
| 2713 | 2694 |
| 2714 void LCodeGen::DoCallNew(LCallNew* instr) { | 2695 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 2715 ASSERT(ToRegister(instr->input()).is(r1)); | 2696 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); |
| 2716 ASSERT(ToRegister(instr->result()).is(r0)); | 2697 ASSERT(ToRegister(instr->result()).is(r0)); |
| 2717 | 2698 |
| 2718 Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); | 2699 Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); |
| 2719 __ mov(r0, Operand(instr->arity())); | 2700 __ mov(r0, Operand(instr->arity())); |
| 2720 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); | 2701 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); |
| 2721 } | 2702 } |
| 2722 | 2703 |
| 2723 | 2704 |
| 2724 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 2705 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 2725 CallRuntime(instr->function(), instr->arity(), instr); | 2706 CallRuntime(instr->function(), instr->arity(), instr); |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2947 __ AbortIfNotSmi(r0); | 2928 __ AbortIfNotSmi(r0); |
| 2948 } | 2929 } |
| 2949 __ SmiUntag(r0); | 2930 __ SmiUntag(r0); |
| 2950 MemOperand result_stack_slot = masm()->SafepointRegisterSlot(result); | 2931 MemOperand result_stack_slot = masm()->SafepointRegisterSlot(result); |
| 2951 __ str(r0, result_stack_slot); | 2932 __ str(r0, result_stack_slot); |
| 2952 __ PopSafepointRegisters(); | 2933 __ PopSafepointRegisters(); |
| 2953 } | 2934 } |
| 2954 | 2935 |
| 2955 | 2936 |
| 2956 void LCodeGen::DoStringLength(LStringLength* instr) { | 2937 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 2957 Register string = ToRegister(instr->input()); | 2938 Register string = ToRegister(instr->InputAt(0)); |
| 2958 Register result = ToRegister(instr->result()); | 2939 Register result = ToRegister(instr->result()); |
| 2959 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); | 2940 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); |
| 2960 } | 2941 } |
| 2961 | 2942 |
| 2962 | 2943 |
| 2963 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 2944 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 2964 LOperand* input = instr->input(); | 2945 LOperand* input = instr->InputAt(0); |
| 2965 ASSERT(input->IsRegister() || input->IsStackSlot()); | 2946 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 2966 LOperand* output = instr->result(); | 2947 LOperand* output = instr->result(); |
| 2967 ASSERT(output->IsDoubleRegister()); | 2948 ASSERT(output->IsDoubleRegister()); |
| 2968 SwVfpRegister single_scratch = double_scratch0().low(); | 2949 SwVfpRegister single_scratch = double_scratch0().low(); |
| 2969 if (input->IsStackSlot()) { | 2950 if (input->IsStackSlot()) { |
| 2970 Register scratch = scratch0(); | 2951 Register scratch = scratch0(); |
| 2971 __ ldr(scratch, ToMemOperand(input)); | 2952 __ ldr(scratch, ToMemOperand(input)); |
| 2972 __ vmov(single_scratch, scratch); | 2953 __ vmov(single_scratch, scratch); |
| 2973 } else { | 2954 } else { |
| 2974 __ vmov(single_scratch, ToRegister(input)); | 2955 __ vmov(single_scratch, ToRegister(input)); |
| 2975 } | 2956 } |
| 2976 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); | 2957 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); |
| 2977 } | 2958 } |
| 2978 | 2959 |
| 2979 | 2960 |
| 2980 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 2961 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 2981 class DeferredNumberTagI: public LDeferredCode { | 2962 class DeferredNumberTagI: public LDeferredCode { |
| 2982 public: | 2963 public: |
| 2983 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 2964 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
| 2984 : LDeferredCode(codegen), instr_(instr) { } | 2965 : LDeferredCode(codegen), instr_(instr) { } |
| 2985 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } | 2966 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } |
| 2986 private: | 2967 private: |
| 2987 LNumberTagI* instr_; | 2968 LNumberTagI* instr_; |
| 2988 }; | 2969 }; |
| 2989 | 2970 |
| 2990 LOperand* input = instr->input(); | 2971 LOperand* input = instr->InputAt(0); |
| 2991 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 2972 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 2992 Register reg = ToRegister(input); | 2973 Register reg = ToRegister(input); |
| 2993 | 2974 |
| 2994 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); | 2975 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); |
| 2995 __ SmiTag(reg, SetCC); | 2976 __ SmiTag(reg, SetCC); |
| 2996 __ b(vs, deferred->entry()); | 2977 __ b(vs, deferred->entry()); |
| 2997 __ bind(deferred->exit()); | 2978 __ bind(deferred->exit()); |
| 2998 } | 2979 } |
| 2999 | 2980 |
| 3000 | 2981 |
| 3001 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 2982 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
| 3002 Label slow; | 2983 Label slow; |
| 3003 Register reg = ToRegister(instr->input()); | 2984 Register reg = ToRegister(instr->InputAt(0)); |
| 3004 DoubleRegister dbl_scratch = d0; | 2985 DoubleRegister dbl_scratch = d0; |
| 3005 SwVfpRegister flt_scratch = s0; | 2986 SwVfpRegister flt_scratch = s0; |
| 3006 | 2987 |
| 3007 // Preserve the value of all registers. | 2988 // Preserve the value of all registers. |
| 3008 __ PushSafepointRegisters(); | 2989 __ PushSafepointRegisters(); |
| 3009 | 2990 |
| 3010 // There was overflow, so bits 30 and 31 of the original integer | 2991 // There was overflow, so bits 30 and 31 of the original integer |
| 3011 // disagree. Try to allocate a heap number in new space and store | 2992 // disagree. Try to allocate a heap number in new space and store |
| 3012 // the value in there. If that fails, call the runtime system. | 2993 // the value in there. If that fails, call the runtime system. |
| 3013 Label done; | 2994 Label done; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3050 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 3031 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 3051 class DeferredNumberTagD: public LDeferredCode { | 3032 class DeferredNumberTagD: public LDeferredCode { |
| 3052 public: | 3033 public: |
| 3053 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 3034 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 3054 : LDeferredCode(codegen), instr_(instr) { } | 3035 : LDeferredCode(codegen), instr_(instr) { } |
| 3055 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 3036 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 3056 private: | 3037 private: |
| 3057 LNumberTagD* instr_; | 3038 LNumberTagD* instr_; |
| 3058 }; | 3039 }; |
| 3059 | 3040 |
| 3060 DoubleRegister input_reg = ToDoubleRegister(instr->input()); | 3041 DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 3061 Register scratch = scratch0(); | 3042 Register scratch = scratch0(); |
| 3062 Register reg = ToRegister(instr->result()); | 3043 Register reg = ToRegister(instr->result()); |
| 3063 Register temp1 = ToRegister(instr->temp1()); | 3044 Register temp1 = ToRegister(instr->TempAt(0)); |
| 3064 Register temp2 = ToRegister(instr->temp2()); | 3045 Register temp2 = ToRegister(instr->TempAt(1)); |
| 3065 | 3046 |
| 3066 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); | 3047 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); |
| 3067 if (FLAG_inline_new) { | 3048 if (FLAG_inline_new) { |
| 3068 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 3049 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 3069 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); | 3050 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); |
| 3070 } else { | 3051 } else { |
| 3071 __ jmp(deferred->entry()); | 3052 __ jmp(deferred->entry()); |
| 3072 } | 3053 } |
| 3073 __ bind(deferred->exit()); | 3054 __ bind(deferred->exit()); |
| 3074 __ sub(ip, reg, Operand(kHeapObjectTag)); | 3055 __ sub(ip, reg, Operand(kHeapObjectTag)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3087 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 3068 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 3088 RecordSafepointWithRegisters( | 3069 RecordSafepointWithRegisters( |
| 3089 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | 3070 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 3090 int reg_stack_index = __ SafepointRegisterStackIndex(reg.code()); | 3071 int reg_stack_index = __ SafepointRegisterStackIndex(reg.code()); |
| 3091 __ str(r0, MemOperand(sp, reg_stack_index * kPointerSize)); | 3072 __ str(r0, MemOperand(sp, reg_stack_index * kPointerSize)); |
| 3092 __ PopSafepointRegisters(); | 3073 __ PopSafepointRegisters(); |
| 3093 } | 3074 } |
| 3094 | 3075 |
| 3095 | 3076 |
| 3096 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 3077 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 3097 LOperand* input = instr->input(); | 3078 LOperand* input = instr->InputAt(0); |
| 3098 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3079 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 3099 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 3080 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 3100 __ SmiTag(ToRegister(input)); | 3081 __ SmiTag(ToRegister(input)); |
| 3101 } | 3082 } |
| 3102 | 3083 |
| 3103 | 3084 |
| 3104 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 3085 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 3105 LOperand* input = instr->input(); | 3086 LOperand* input = instr->InputAt(0); |
| 3106 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3087 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 3107 if (instr->needs_check()) { | 3088 if (instr->needs_check()) { |
| 3108 __ tst(ToRegister(input), Operand(kSmiTagMask)); | 3089 __ tst(ToRegister(input), Operand(kSmiTagMask)); |
| 3109 DeoptimizeIf(ne, instr->environment()); | 3090 DeoptimizeIf(ne, instr->environment()); |
| 3110 } | 3091 } |
| 3111 __ SmiUntag(ToRegister(input)); | 3092 __ SmiUntag(ToRegister(input)); |
| 3112 } | 3093 } |
| 3113 | 3094 |
| 3114 | 3095 |
| 3115 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3096 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3162 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 3143 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 3163 : LDeferredCode(codegen), instr_(instr) { } | 3144 : LDeferredCode(codegen), instr_(instr) { } |
| 3164 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 3145 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 3165 private: | 3146 private: |
| 3166 LTaggedToI* instr_; | 3147 LTaggedToI* instr_; |
| 3167 }; | 3148 }; |
| 3168 | 3149 |
| 3169 | 3150 |
| 3170 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3151 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 3171 Label done; | 3152 Label done; |
| 3172 Register input_reg = ToRegister(instr->input()); | 3153 Register input_reg = ToRegister(instr->InputAt(0)); |
| 3173 Register scratch = scratch0(); | 3154 Register scratch = scratch0(); |
| 3174 DoubleRegister dbl_scratch = d0; | 3155 DoubleRegister dbl_scratch = d0; |
| 3175 SwVfpRegister flt_scratch = s0; | 3156 SwVfpRegister flt_scratch = s0; |
| 3176 DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp()); | 3157 DoubleRegister dbl_tmp = ToDoubleRegister(instr->TempAt(0)); |
| 3177 | 3158 |
| 3178 // Heap number map check. | 3159 // Heap number map check. |
| 3179 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 3160 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 3180 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3161 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 3181 __ cmp(scratch, Operand(ip)); | 3162 __ cmp(scratch, Operand(ip)); |
| 3182 | 3163 |
| 3183 if (instr->truncating()) { | 3164 if (instr->truncating()) { |
| 3184 Label heap_number; | 3165 Label heap_number; |
| 3185 __ b(eq, &heap_number); | 3166 __ b(eq, &heap_number); |
| 3186 // Check for undefined. Undefined is converted to zero for truncating | 3167 // Check for undefined. Undefined is converted to zero for truncating |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3223 __ vmov(lr, ip, dbl_tmp); | 3204 __ vmov(lr, ip, dbl_tmp); |
| 3224 __ tst(ip, Operand(1 << 31)); // Test sign bit. | 3205 __ tst(ip, Operand(1 << 31)); // Test sign bit. |
| 3225 DeoptimizeIf(ne, instr->environment()); | 3206 DeoptimizeIf(ne, instr->environment()); |
| 3226 } | 3207 } |
| 3227 } | 3208 } |
| 3228 __ bind(&done); | 3209 __ bind(&done); |
| 3229 } | 3210 } |
| 3230 | 3211 |
| 3231 | 3212 |
| 3232 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 3213 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 3233 LOperand* input = instr->input(); | 3214 LOperand* input = instr->InputAt(0); |
| 3234 ASSERT(input->IsRegister()); | 3215 ASSERT(input->IsRegister()); |
| 3235 ASSERT(input->Equals(instr->result())); | 3216 ASSERT(input->Equals(instr->result())); |
| 3236 | 3217 |
| 3237 Register input_reg = ToRegister(input); | 3218 Register input_reg = ToRegister(input); |
| 3238 | 3219 |
| 3239 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); | 3220 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); |
| 3240 | 3221 |
| 3241 // Smi check. | 3222 // Smi check. |
| 3242 __ tst(input_reg, Operand(kSmiTagMask)); | 3223 __ tst(input_reg, Operand(kSmiTagMask)); |
| 3243 __ b(ne, deferred->entry()); | 3224 __ b(ne, deferred->entry()); |
| 3244 | 3225 |
| 3245 // Smi to int32 conversion | 3226 // Smi to int32 conversion |
| 3246 __ SmiUntag(input_reg); // Untag smi. | 3227 __ SmiUntag(input_reg); // Untag smi. |
| 3247 | 3228 |
| 3248 __ bind(deferred->exit()); | 3229 __ bind(deferred->exit()); |
| 3249 } | 3230 } |
| 3250 | 3231 |
| 3251 | 3232 |
| 3252 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 3233 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 3253 LOperand* input = instr->input(); | 3234 LOperand* input = instr->InputAt(0); |
| 3254 ASSERT(input->IsRegister()); | 3235 ASSERT(input->IsRegister()); |
| 3255 LOperand* result = instr->result(); | 3236 LOperand* result = instr->result(); |
| 3256 ASSERT(result->IsDoubleRegister()); | 3237 ASSERT(result->IsDoubleRegister()); |
| 3257 | 3238 |
| 3258 Register input_reg = ToRegister(input); | 3239 Register input_reg = ToRegister(input); |
| 3259 DoubleRegister result_reg = ToDoubleRegister(result); | 3240 DoubleRegister result_reg = ToDoubleRegister(result); |
| 3260 | 3241 |
| 3261 EmitNumberUntagD(input_reg, result_reg, instr->environment()); | 3242 EmitNumberUntagD(input_reg, result_reg, instr->environment()); |
| 3262 } | 3243 } |
| 3263 | 3244 |
| 3264 | 3245 |
| 3265 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 3246 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 3266 Abort("DoDoubleToI unimplemented."); | 3247 Abort("DoDoubleToI unimplemented."); |
| 3267 } | 3248 } |
| 3268 | 3249 |
| 3269 | 3250 |
| 3270 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 3251 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 3271 LOperand* input = instr->input(); | 3252 LOperand* input = instr->InputAt(0); |
| 3272 ASSERT(input->IsRegister()); | 3253 ASSERT(input->IsRegister()); |
| 3273 __ tst(ToRegister(input), Operand(kSmiTagMask)); | 3254 __ tst(ToRegister(input), Operand(kSmiTagMask)); |
| 3274 DeoptimizeIf(instr->condition(), instr->environment()); | 3255 DeoptimizeIf(instr->condition(), instr->environment()); |
| 3275 } | 3256 } |
| 3276 | 3257 |
| 3277 | 3258 |
| 3278 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 3259 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 3279 Register input = ToRegister(instr->input()); | 3260 Register input = ToRegister(instr->InputAt(0)); |
| 3280 Register scratch = scratch0(); | 3261 Register scratch = scratch0(); |
| 3281 InstanceType first = instr->hydrogen()->first(); | 3262 InstanceType first = instr->hydrogen()->first(); |
| 3282 InstanceType last = instr->hydrogen()->last(); | 3263 InstanceType last = instr->hydrogen()->last(); |
| 3283 | 3264 |
| 3284 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3265 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 3285 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 3266 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 3286 __ cmp(scratch, Operand(first)); | 3267 __ cmp(scratch, Operand(first)); |
| 3287 | 3268 |
| 3288 // If there is only one type in the interval check for equality. | 3269 // If there is only one type in the interval check for equality. |
| 3289 if (first == last) { | 3270 if (first == last) { |
| 3290 DeoptimizeIf(ne, instr->environment()); | 3271 DeoptimizeIf(ne, instr->environment()); |
| 3291 } else { | 3272 } else { |
| 3292 DeoptimizeIf(lo, instr->environment()); | 3273 DeoptimizeIf(lo, instr->environment()); |
| 3293 // Omit check for the last type. | 3274 // Omit check for the last type. |
| 3294 if (last != LAST_TYPE) { | 3275 if (last != LAST_TYPE) { |
| 3295 __ cmp(scratch, Operand(last)); | 3276 __ cmp(scratch, Operand(last)); |
| 3296 DeoptimizeIf(hi, instr->environment()); | 3277 DeoptimizeIf(hi, instr->environment()); |
| 3297 } | 3278 } |
| 3298 } | 3279 } |
| 3299 } | 3280 } |
| 3300 | 3281 |
| 3301 | 3282 |
| 3302 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 3283 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
| 3303 ASSERT(instr->input()->IsRegister()); | 3284 ASSERT(instr->InputAt(0)->IsRegister()); |
| 3304 Register reg = ToRegister(instr->input()); | 3285 Register reg = ToRegister(instr->InputAt(0)); |
| 3305 __ cmp(reg, Operand(instr->hydrogen()->target())); | 3286 __ cmp(reg, Operand(instr->hydrogen()->target())); |
| 3306 DeoptimizeIf(ne, instr->environment()); | 3287 DeoptimizeIf(ne, instr->environment()); |
| 3307 } | 3288 } |
| 3308 | 3289 |
| 3309 | 3290 |
| 3310 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 3291 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
| 3311 Register scratch = scratch0(); | 3292 Register scratch = scratch0(); |
| 3312 LOperand* input = instr->input(); | 3293 LOperand* input = instr->InputAt(0); |
| 3313 ASSERT(input->IsRegister()); | 3294 ASSERT(input->IsRegister()); |
| 3314 Register reg = ToRegister(input); | 3295 Register reg = ToRegister(input); |
| 3315 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 3296 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 3316 __ cmp(scratch, Operand(instr->hydrogen()->map())); | 3297 __ cmp(scratch, Operand(instr->hydrogen()->map())); |
| 3317 DeoptimizeIf(ne, instr->environment()); | 3298 DeoptimizeIf(ne, instr->environment()); |
| 3318 } | 3299 } |
| 3319 | 3300 |
| 3320 | 3301 |
| 3321 void LCodeGen::LoadHeapObject(Register result, | 3302 void LCodeGen::LoadHeapObject(Register result, |
| 3322 Handle<HeapObject> object) { | 3303 Handle<HeapObject> object) { |
| 3323 if (Heap::InNewSpace(*object)) { | 3304 if (Heap::InNewSpace(*object)) { |
| 3324 Handle<JSGlobalPropertyCell> cell = | 3305 Handle<JSGlobalPropertyCell> cell = |
| 3325 Factory::NewJSGlobalPropertyCell(object); | 3306 Factory::NewJSGlobalPropertyCell(object); |
| 3326 __ mov(result, Operand(cell)); | 3307 __ mov(result, Operand(cell)); |
| 3327 __ ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset)); | 3308 __ ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset)); |
| 3328 } else { | 3309 } else { |
| 3329 __ mov(result, Operand(object)); | 3310 __ mov(result, Operand(object)); |
| 3330 } | 3311 } |
| 3331 } | 3312 } |
| 3332 | 3313 |
| 3333 | 3314 |
| 3334 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 3315 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 3335 Register temp1 = ToRegister(instr->temp1()); | 3316 Register temp1 = ToRegister(instr->TempAt(0)); |
| 3336 Register temp2 = ToRegister(instr->temp2()); | 3317 Register temp2 = ToRegister(instr->TempAt(1)); |
| 3337 | 3318 |
| 3338 Handle<JSObject> holder = instr->holder(); | 3319 Handle<JSObject> holder = instr->holder(); |
| 3339 Handle<JSObject> current_prototype = instr->prototype(); | 3320 Handle<JSObject> current_prototype = instr->prototype(); |
| 3340 | 3321 |
| 3341 // Load prototype object. | 3322 // Load prototype object. |
| 3342 LoadHeapObject(temp1, current_prototype); | 3323 LoadHeapObject(temp1, current_prototype); |
| 3343 | 3324 |
| 3344 // Check prototype maps up to the holder. | 3325 // Check prototype maps up to the holder. |
| 3345 while (!current_prototype.is_identical_to(holder)) { | 3326 while (!current_prototype.is_identical_to(holder)) { |
| 3346 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); | 3327 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3474 __ mov(r1, Operand(pretenure | 3455 __ mov(r1, Operand(pretenure |
| 3475 ? Factory::true_value() | 3456 ? Factory::true_value() |
| 3476 : Factory::false_value())); | 3457 : Factory::false_value())); |
| 3477 __ Push(cp, r2, r1); | 3458 __ Push(cp, r2, r1); |
| 3478 CallRuntime(Runtime::kNewClosure, 3, instr); | 3459 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 3479 } | 3460 } |
| 3480 } | 3461 } |
| 3481 | 3462 |
| 3482 | 3463 |
| 3483 void LCodeGen::DoTypeof(LTypeof* instr) { | 3464 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 3484 Register input = ToRegister(instr->input()); | 3465 Register input = ToRegister(instr->InputAt(0)); |
| 3485 __ push(input); | 3466 __ push(input); |
| 3486 CallRuntime(Runtime::kTypeof, 1, instr); | 3467 CallRuntime(Runtime::kTypeof, 1, instr); |
| 3487 } | 3468 } |
| 3488 | 3469 |
| 3489 | 3470 |
| 3490 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 3471 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
| 3491 Register input = ToRegister(instr->input()); | 3472 Register input = ToRegister(instr->InputAt(0)); |
| 3492 Register result = ToRegister(instr->result()); | 3473 Register result = ToRegister(instr->result()); |
| 3493 Label true_label; | 3474 Label true_label; |
| 3494 Label false_label; | 3475 Label false_label; |
| 3495 Label done; | 3476 Label done; |
| 3496 | 3477 |
| 3497 Condition final_branch_condition = EmitTypeofIs(&true_label, | 3478 Condition final_branch_condition = EmitTypeofIs(&true_label, |
| 3498 &false_label, | 3479 &false_label, |
| 3499 input, | 3480 input, |
| 3500 instr->type_literal()); | 3481 instr->type_literal()); |
| 3501 __ b(final_branch_condition, &true_label); | 3482 __ b(final_branch_condition, &true_label); |
| 3502 __ bind(&false_label); | 3483 __ bind(&false_label); |
| 3503 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 3484 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 3504 __ b(&done); | 3485 __ b(&done); |
| 3505 | 3486 |
| 3506 __ bind(&true_label); | 3487 __ bind(&true_label); |
| 3507 __ LoadRoot(result, Heap::kTrueValueRootIndex); | 3488 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 3508 | 3489 |
| 3509 __ bind(&done); | 3490 __ bind(&done); |
| 3510 } | 3491 } |
| 3511 | 3492 |
| 3512 | 3493 |
| 3513 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 3494 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 3514 Register input = ToRegister(instr->input()); | 3495 Register input = ToRegister(instr->InputAt(0)); |
| 3515 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 3496 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 3516 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 3497 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 3517 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 3498 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 3518 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 3499 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 3519 | 3500 |
| 3520 Condition final_branch_condition = EmitTypeofIs(true_label, | 3501 Condition final_branch_condition = EmitTypeofIs(true_label, |
| 3521 false_label, | 3502 false_label, |
| 3522 input, | 3503 input, |
| 3523 instr->type_literal()); | 3504 instr->type_literal()); |
| 3524 | 3505 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3644 | 3625 |
| 3645 | 3626 |
| 3646 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 3627 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
| 3647 Abort("DoOsrEntry unimplemented."); | 3628 Abort("DoOsrEntry unimplemented."); |
| 3648 } | 3629 } |
| 3649 | 3630 |
| 3650 | 3631 |
| 3651 #undef __ | 3632 #undef __ |
| 3652 | 3633 |
| 3653 } } // namespace v8::internal | 3634 } } // namespace v8::internal |
| OLD | NEW |