OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1173 // tos_register_: Heap number to write the answer into. | 1173 // tos_register_: Heap number to write the answer into. |
1174 WriteNonSmiAnswer(int32, tos_register_, r3); | 1174 WriteNonSmiAnswer(int32, tos_register_, r3); |
1175 | 1175 |
1176 Exit(); | 1176 Exit(); |
1177 } | 1177 } |
1178 } | 1178 } |
1179 | 1179 |
1180 | 1180 |
1181 void DeferredInlineSmiOperation::GenerateAnswerOutOfRange() { | 1181 void DeferredInlineSmiOperation::GenerateAnswerOutOfRange() { |
1182 // The input from a bitwise operation were Smis but the result cannot fit | 1182 // The input from a bitwise operation were Smis but the result cannot fit |
1183 // into a Smi, so we store it into a heap number. tos_resgiter_ holds the | 1183 // into a Smi, so we store it into a heap number. VirtualFrame::scratch0() |
1184 // result to be converted. | 1184 // holds the untagged result to be converted. tos_register_ contains the |
1185 // input. See the calls to JumpToAnswerOutOfRange to see how we got here. | |
1185 ASSERT(Token::IsBitOp(op_)); | 1186 ASSERT(Token::IsBitOp(op_)); |
1186 ASSERT(!reversed_); | 1187 ASSERT(!reversed_); |
1187 | 1188 |
1189 Register untagged_result = VirtualFrame::scratch0(); | |
1190 | |
1188 if (FLAG_debug_code) { | 1191 if (FLAG_debug_code) { |
1189 __ Abort("Should not fall through!"); | 1192 __ Abort("Should not fall through!"); |
1190 } | 1193 } |
1191 | 1194 |
1192 __ bind(&answer_out_of_range_); | 1195 __ bind(&answer_out_of_range_); |
1193 if (((value_ & 0x1f) == 0) && (op_ == Token::SHR)) { | 1196 if (((value_ & 0x1f) == 0) && (op_ == Token::SHR)) { |
1194 // >>> 0 is a special case where the result is already tagged but wrong | 1197 // >>> 0 is a special case where the untagged_result register is not set up |
1195 // because the Smi is negative. We untag it. | 1198 // yet. We untag the input to get it. |
1196 __ mov(tos_register_, Operand(tos_register_, ASR, kSmiTagSize)); | 1199 __ mov(untagged_result, Operand(tos_register_, ASR, kSmiTagSize)); |
1197 } | 1200 } |
1198 | 1201 |
1199 // This routine uses the registers from r2 to r6. At the moment they are | 1202 // This routine uses the registers from r2 to r6. At the moment they are |
1200 // not used by the register allocator, but when they are it should use | 1203 // not used by the register allocator, but when they are it should use |
1201 // SpillAll and MergeTo like DeferredInlineSmiOperation::Generate() above. | 1204 // SpillAll and MergeTo like DeferredInlineSmiOperation::Generate() above. |
1202 | 1205 |
1203 // Allocate the result heap number. | 1206 // Allocate the result heap number. |
1204 Register heap_number_map = r7; | 1207 Register heap_number_map = VirtualFrame::scratch1(); |
1205 Register heap_number = r4; | 1208 Register heap_number = r4; |
1206 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 1209 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
1207 // If the allocation fails, fall back to the GenericBinaryOpStub. | 1210 // If the allocation fails, fall back to the GenericBinaryOpStub. |
1208 __ AllocateHeapNumber(heap_number, r5, r6, heap_number_map, entry_label()); | 1211 __ AllocateHeapNumber(heap_number, r5, r6, heap_number_map, entry_label()); |
1209 WriteNonSmiAnswer(tos_register_, heap_number, r3); | 1212 WriteNonSmiAnswer(untagged_result, heap_number, r3); |
1210 __ mov(tos_register_, Operand(heap_number)); | 1213 __ mov(tos_register_, Operand(heap_number)); |
1211 | 1214 |
1212 Exit(); | 1215 Exit(); |
1213 } | 1216 } |
1214 | 1217 |
1215 | 1218 |
1216 static bool PopCountLessThanEqual2(unsigned int x) { | 1219 static bool PopCountLessThanEqual2(unsigned int x) { |
1217 x &= x - 1; | 1220 x &= x - 1; |
1218 return (x & (x - 1)) == 0; | 1221 return (x & (x - 1)) == 0; |
1219 } | 1222 } |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1467 | 1470 |
1468 DeferredInlineSmiOperation* deferred = | 1471 DeferredInlineSmiOperation* deferred = |
1469 new DeferredInlineSmiOperation(op, shift_value, false, mode, tos); | 1472 new DeferredInlineSmiOperation(op, shift_value, false, mode, tos); |
1470 if (!both_sides_are_smi) { | 1473 if (!both_sides_are_smi) { |
1471 __ tst(tos, Operand(kSmiTagMask)); | 1474 __ tst(tos, Operand(kSmiTagMask)); |
1472 deferred->JumpToNonSmiInput(ne); | 1475 deferred->JumpToNonSmiInput(ne); |
1473 } | 1476 } |
1474 switch (op) { | 1477 switch (op) { |
1475 case Token::SHL: { | 1478 case Token::SHL: { |
1476 if (shift_value != 0) { | 1479 if (shift_value != 0) { |
1477 Register scratch = VirtualFrame::scratch0(); | 1480 Register untagged_result = VirtualFrame::scratch0(); |
1481 Register scratch2 = VirtualFrame::scratch1(); | |
Søren Thygesen Gjesse
2010/10/20 11:43:53
scratch2 -> scratch?
| |
1478 int adjusted_shift = shift_value - kSmiTagSize; | 1482 int adjusted_shift = shift_value - kSmiTagSize; |
1479 ASSERT(adjusted_shift >= 0); | 1483 ASSERT(adjusted_shift >= 0); |
1480 | 1484 |
1481 if (adjusted_shift != 0) { | 1485 if (adjusted_shift != 0) { |
1482 __ mov(tos, Operand(tos, LSL, adjusted_shift)); | 1486 __ mov(untagged_result, Operand(tos, LSL, adjusted_shift)); |
1487 } else { | |
1488 __ mov(untagged_result, Operand(tos)); | |
1483 } | 1489 } |
1484 // Check that the *signed* result fits in a smi. | 1490 // Check that the *signed* result fits in a smi. |
1485 __ add(scratch, tos, Operand(0x40000000), SetCC); | 1491 __ add(scratch2, untagged_result, Operand(0x40000000), SetCC); |
1486 deferred->JumpToAnswerOutOfRange(mi); | 1492 deferred->JumpToAnswerOutOfRange(mi); |
1487 __ mov(tos, Operand(tos, LSL, kSmiTagSize)); | 1493 __ mov(tos, Operand(untagged_result, LSL, kSmiTagSize)); |
1488 } | 1494 } |
1489 break; | 1495 break; |
1490 } | 1496 } |
1491 case Token::SHR: { | 1497 case Token::SHR: { |
1492 if (shift_value != 0) { | 1498 if (shift_value != 0) { |
1493 Register scratch = VirtualFrame::scratch0(); | 1499 Register untagged_result = VirtualFrame::scratch0(); |
1494 __ mov(scratch, Operand(tos, ASR, kSmiTagSize)); // Remove tag. | 1500 // Remove tag. |
1495 __ mov(tos, Operand(scratch, LSR, shift_value)); | 1501 __ mov(untagged_result, Operand(tos, ASR, kSmiTagSize)); |
1502 __ mov(untagged_result, Operand(untagged_result, LSR, shift_value)); | |
1496 if (shift_value == 1) { | 1503 if (shift_value == 1) { |
1497 // Check that the *unsigned* result fits in a smi. | 1504 // Check that the *unsigned* result fits in a smi. |
1498 // Neither of the two high-order bits can be set: | 1505 // Neither of the two high-order bits can be set: |
1499 // - 0x80000000: high bit would be lost when smi tagging | 1506 // - 0x80000000: high bit would be lost when smi tagging |
1500 // - 0x40000000: this number would convert to negative when Smi | 1507 // - 0x40000000: this number would convert to negative when Smi |
1501 // tagging. | 1508 // tagging. |
1502 // These two cases can only happen with shifts by 0 or 1 when | 1509 // These two cases can only happen with shifts by 0 or 1 when |
1503 // handed a valid smi. | 1510 // handed a valid smi. |
1504 __ tst(tos, Operand(0xc0000000)); | 1511 __ tst(untagged_result, Operand(0xc0000000)); |
1505 if (!CpuFeatures::IsSupported(VFP3)) { | |
1506 // If the unsigned result does not fit in a Smi, we require an | |
1507 // unsigned to double conversion. Without VFP V8 has to fall | |
1508 // back to the runtime. The deferred code will expect tos | |
1509 // to hold the original Smi to be shifted. | |
1510 __ mov(tos, Operand(scratch, LSL, kSmiTagSize), LeaveCC, ne); | |
1511 } | |
1512 deferred->JumpToAnswerOutOfRange(ne); | 1512 deferred->JumpToAnswerOutOfRange(ne); |
1513 } | 1513 } |
1514 __ mov(tos, Operand(tos, LSL, kSmiTagSize)); | 1514 __ mov(tos, Operand(untagged_result, LSL, kSmiTagSize)); |
1515 } else { | 1515 } else { |
1516 __ cmp(tos, Operand(0, RelocInfo::NONE)); | 1516 __ cmp(tos, Operand(0, RelocInfo::NONE)); |
1517 deferred->JumpToAnswerOutOfRange(mi); | 1517 deferred->JumpToAnswerOutOfRange(mi); |
1518 } | 1518 } |
1519 break; | 1519 break; |
1520 } | 1520 } |
1521 case Token::SAR: { | 1521 case Token::SAR: { |
1522 if (shift_value != 0) { | 1522 if (shift_value != 0) { |
1523 // Do the shift and the tag removal in one operation. If the shift | 1523 // Do the shift and the tag removal in one operation. If the shift |
1524 // is 31 bits (the highest possible value) then we emit the | 1524 // is 31 bits (the highest possible value) then we emit the |
(...skipping 3201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4726 | 4726 |
4727 // Get the value from the frame. | 4727 // Get the value from the frame. |
4728 Register tos = frame_->PopToRegister(); | 4728 Register tos = frame_->PopToRegister(); |
4729 | 4729 |
4730 // Set the frame for the runtime jump target. The code below jumps to the | 4730 // Set the frame for the runtime jump target. The code below jumps to the |
4731 // jump target label so the frame needs to be established before that. | 4731 // jump target label so the frame needs to be established before that. |
4732 ASSERT(runtime.entry_frame() == NULL); | 4732 ASSERT(runtime.entry_frame() == NULL); |
4733 runtime.set_entry_frame(frame_); | 4733 runtime.set_entry_frame(frame_); |
4734 | 4734 |
4735 Register heap_number_map = r6; | 4735 Register heap_number_map = r6; |
4736 Register new_heap_number = r5; | |
4736 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 4737 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
4737 | 4738 |
4738 // Get the double value from the heap number into vfp register d0. | 4739 // Get the double value from the heap number into vfp register d0. |
4739 __ ObjectToDoubleVFPRegister(tos, d0, | 4740 __ ObjectToDoubleVFPRegister(tos, d0, |
4740 scratch1, scratch2, heap_number_map, s0, | 4741 scratch1, scratch2, heap_number_map, s0, |
4741 runtime.entry_label()); | 4742 runtime.entry_label()); |
4742 | 4743 |
4743 // Calculate the square root of d0 and place result in a heap number object. | 4744 // Calculate the square root of d0 and place result in a heap number object. |
4744 __ vsqrt(d0, d0); | 4745 __ vsqrt(d0, d0); |
4745 __ AllocateHeapNumberWithValue( | 4746 __ AllocateHeapNumberWithValue(new_heap_number, |
4746 tos, d0, scratch1, scratch2, heap_number_map, runtime.entry_label()); | 4747 d0, |
4748 scratch1, scratch2, | |
4749 heap_number_map, | |
4750 runtime.entry_label()); | |
4751 __ mov(tos, Operand(new_heap_number)); | |
4747 done.Jump(); | 4752 done.Jump(); |
4748 | 4753 |
4749 runtime.Bind(); | 4754 runtime.Bind(); |
4750 // Push back the argument again for the runtime call. | 4755 // Push back the argument again for the runtime call. |
4751 frame_->EmitPush(tos); | 4756 frame_->EmitPush(tos); |
4752 frame_->CallRuntime(Runtime::kMath_sqrt, 1); | 4757 frame_->CallRuntime(Runtime::kMath_sqrt, 1); |
4753 __ Move(tos, r0); | 4758 __ Move(tos, r0); |
4754 | 4759 |
4755 done.Bind(); | 4760 done.Bind(); |
4756 frame_->EmitPush(tos); | 4761 frame_->EmitPush(tos); |
(...skipping 2547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7304 BinaryOpIC::GetName(runtime_operands_type_)); | 7309 BinaryOpIC::GetName(runtime_operands_type_)); |
7305 return name_; | 7310 return name_; |
7306 } | 7311 } |
7307 | 7312 |
7308 | 7313 |
7309 #undef __ | 7314 #undef __ |
7310 | 7315 |
7311 } } // namespace v8::internal | 7316 } } // namespace v8::internal |
7312 | 7317 |
7313 #endif // V8_TARGET_ARCH_ARM | 7318 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |