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 |