OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 // xmm1 : untagged double input argument | 1129 // xmm1 : untagged double input argument |
1130 // Output: | 1130 // Output: |
1131 // xmm1 : untagged double result. | 1131 // xmm1 : untagged double result. |
1132 | 1132 |
1133 Label runtime_call; | 1133 Label runtime_call; |
1134 Label runtime_call_clear_stack; | 1134 Label runtime_call_clear_stack; |
1135 Label skip_cache; | 1135 Label skip_cache; |
1136 const bool tagged = (argument_type_ == TAGGED); | 1136 const bool tagged = (argument_type_ == TAGGED); |
1137 if (tagged) { | 1137 if (tagged) { |
1138 Label input_not_smi, loaded; | 1138 Label input_not_smi, loaded; |
| 1139 |
1139 // Test that rax is a number. | 1140 // Test that rax is a number. |
1140 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 1141 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
1141 __ movq(rax, args.GetArgumentOperand(0)); | 1142 __ movq(rax, args.GetArgumentOperand(0)); |
1142 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); | 1143 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); |
1143 // Input is a smi. Untag and load it onto the FPU stack. | 1144 // Input is a smi. Untag and load it onto the FPU stack. |
1144 // Then load the bits of the double into rbx. | 1145 // Then load the bits of the double into rbx. |
1145 __ SmiToInteger32(rax, rax); | 1146 __ SmiToInteger32(rax, rax); |
1146 __ subq(rsp, Immediate(kDoubleSize)); | 1147 __ subq(rsp, Immediate(kDoubleSize)); |
1147 __ cvtlsi2sd(xmm1, rax); | 1148 __ cvtlsi2sd(xmm1, rax); |
1148 __ movsd(Operand(rsp, 0), xmm1); | 1149 __ movsd(Operand(rsp, 0), xmm1); |
1149 __ movq(rbx, xmm1); | 1150 __ movq(rbx, xmm1); |
1150 __ movq(rdx, xmm1); | 1151 __ movq(rdx, xmm1); |
1151 __ fld_d(Operand(rsp, 0)); | 1152 __ fld_d(Operand(rsp, 0)); |
1152 __ addq(rsp, Immediate(kDoubleSize)); | 1153 __ addq(rsp, Immediate(kDoubleSize)); |
1153 __ jmp(&loaded, Label::kNear); | 1154 __ jmp(&loaded, Label::kNear); |
1154 | 1155 |
1155 __ bind(&input_not_smi); | 1156 __ bind(&input_not_smi); |
1156 // Check if input is a HeapNumber. | 1157 __ TaggedToI(rbx, rax, xmm1, TREAT_MINUS_ZERO_AS_ZERO, &runtime_call); |
1157 __ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex); | |
1158 __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | |
1159 __ j(not_equal, &runtime_call); | |
1160 // Input is a HeapNumber. Push it on the FPU stack and load its | |
1161 // bits into rbx. | |
1162 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset)); | |
1163 __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset)); | |
1164 __ movq(rdx, rbx); | 1158 __ movq(rdx, rbx); |
1165 | 1159 |
1166 __ bind(&loaded); | 1160 __ bind(&loaded); |
1167 } else { // UNTAGGED. | 1161 } else { // UNTAGGED. |
1168 __ movq(rbx, xmm1); | 1162 __ movq(rbx, xmm1); |
1169 __ movq(rdx, xmm1); | 1163 __ movq(rdx, xmm1); |
1170 } | 1164 } |
1171 | 1165 |
1172 // ST[0] == double value, if TAGGED. | 1166 // ST[0] == double value, if TAGGED. |
1173 // rbx = bits of double value. | 1167 // rbx = bits of double value. |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 1433 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
1440 __ bind(&check_undefined_arg1); | 1434 __ bind(&check_undefined_arg1); |
1441 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); | 1435 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); |
1442 __ j(not_equal, conversion_failure); | 1436 __ j(not_equal, conversion_failure); |
1443 __ Set(r8, 0); | 1437 __ Set(r8, 0); |
1444 __ jmp(&load_arg2); | 1438 __ jmp(&load_arg2); |
1445 | 1439 |
1446 __ bind(&arg1_is_object); | 1440 __ bind(&arg1_is_object); |
1447 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map); | 1441 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map); |
1448 __ j(not_equal, &check_undefined_arg1); | 1442 __ j(not_equal, &check_undefined_arg1); |
1449 // Get the untagged integer version of the rdx heap number in rcx. | 1443 // Get the untagged integer version of the rdx heap number in r8. |
1450 DoubleToIStub stub1(rdx, r8, HeapNumber::kValueOffset - kHeapObjectTag, | 1444 __ TruncateHeapNumberToI(r8, rdx); |
1451 true); | |
1452 __ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
1453 | 1445 |
1454 // Here r8 has the untagged integer, rax has a Smi or a heap number. | 1446 // Here r8 has the untagged integer, rax has a Smi or a heap number. |
1455 __ bind(&load_arg2); | 1447 __ bind(&load_arg2); |
1456 // Test if arg2 is a Smi. | 1448 // Test if arg2 is a Smi. |
1457 __ JumpIfNotSmi(rax, &arg2_is_object); | 1449 __ JumpIfNotSmi(rax, &arg2_is_object); |
1458 __ SmiToInteger32(rcx, rax); | 1450 __ SmiToInteger32(rcx, rax); |
1459 __ jmp(&done); | 1451 __ jmp(&done); |
1460 | 1452 |
1461 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 1453 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
1462 __ bind(&check_undefined_arg2); | 1454 __ bind(&check_undefined_arg2); |
1463 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 1455 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
1464 __ j(not_equal, conversion_failure); | 1456 __ j(not_equal, conversion_failure); |
1465 __ Set(rcx, 0); | 1457 __ Set(rcx, 0); |
1466 __ jmp(&done); | 1458 __ jmp(&done); |
1467 | 1459 |
1468 __ bind(&arg2_is_object); | 1460 __ bind(&arg2_is_object); |
1469 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map); | 1461 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map); |
1470 __ j(not_equal, &check_undefined_arg2); | 1462 __ j(not_equal, &check_undefined_arg2); |
1471 // Get the untagged integer version of the rax heap number in rcx. | 1463 // Get the untagged integer version of the rax heap number in rcx. |
1472 DoubleToIStub stub2(rax, rcx, HeapNumber::kValueOffset - kHeapObjectTag, | 1464 __ TruncateHeapNumberToI(rcx, rax); |
1473 true); | |
1474 __ call(stub2.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
1475 | 1465 |
1476 __ bind(&done); | 1466 __ bind(&done); |
1477 __ movl(rax, r8); | 1467 __ movl(rax, r8); |
1478 } | 1468 } |
1479 | 1469 |
1480 | 1470 |
1481 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { | 1471 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { |
1482 __ SmiToInteger32(kScratchRegister, rdx); | 1472 __ SmiToInteger32(kScratchRegister, rdx); |
1483 __ cvtlsi2sd(xmm0, kScratchRegister); | 1473 __ cvtlsi2sd(xmm0, kScratchRegister); |
1484 __ SmiToInteger32(kScratchRegister, rax); | 1474 __ SmiToInteger32(kScratchRegister, rax); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1641 } else if (exponent_type_ == TAGGED) { | 1631 } else if (exponent_type_ == TAGGED) { |
1642 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 1632 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
1643 __ SmiToInteger32(exponent, exponent); | 1633 __ SmiToInteger32(exponent, exponent); |
1644 __ jmp(&int_exponent); | 1634 __ jmp(&int_exponent); |
1645 | 1635 |
1646 __ bind(&exponent_not_smi); | 1636 __ bind(&exponent_not_smi); |
1647 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); | 1637 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); |
1648 } | 1638 } |
1649 | 1639 |
1650 if (exponent_type_ != INTEGER) { | 1640 if (exponent_type_ != INTEGER) { |
1651 Label fast_power; | 1641 Label fast_power, try_arithmetic_simplification; |
1652 // Detect integer exponents stored as double. | 1642 // Detect integer exponents stored as double. |
| 1643 __ DoubleToI(exponent, double_exponent, double_scratch, |
| 1644 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification); |
| 1645 __ jmp(&int_exponent); |
| 1646 |
| 1647 __ bind(&try_arithmetic_simplification); |
1653 __ cvttsd2si(exponent, double_exponent); | 1648 __ cvttsd2si(exponent, double_exponent); |
1654 // Skip to runtime if possibly NaN (indicated by the indefinite integer). | 1649 // Skip to runtime if possibly NaN (indicated by the indefinite integer). |
1655 __ cmpl(exponent, Immediate(0x80000000u)); | 1650 __ cmpl(exponent, Immediate(0x80000000u)); |
1656 __ j(equal, &call_runtime); | 1651 __ j(equal, &call_runtime); |
1657 __ cvtlsi2sd(double_scratch, exponent); | |
1658 // Already ruled out NaNs for exponent. | |
1659 __ ucomisd(double_exponent, double_scratch); | |
1660 __ j(equal, &int_exponent); | |
1661 | 1652 |
1662 if (exponent_type_ == ON_STACK) { | 1653 if (exponent_type_ == ON_STACK) { |
1663 // Detect square root case. Crankshaft detects constant +/-0.5 at | 1654 // Detect square root case. Crankshaft detects constant +/-0.5 at |
1664 // compile time and uses DoMathPowHalf instead. We then skip this check | 1655 // compile time and uses DoMathPowHalf instead. We then skip this check |
1665 // for non-constant cases of +/-0.5 as these hardly occur. | 1656 // for non-constant cases of +/-0.5 as these hardly occur. |
1666 Label continue_sqrt, continue_rsqrt, not_plus_half; | 1657 Label continue_sqrt, continue_rsqrt, not_plus_half; |
1667 // Test for 0.5. | 1658 // Test for 0.5. |
1668 // Load double_scratch with 0.5. | 1659 // Load double_scratch with 0.5. |
1669 __ movq(scratch, V8_UINT64_C(0x3FE0000000000000), RelocInfo::NONE64); | 1660 __ movq(scratch, V8_UINT64_C(0x3FE0000000000000), RelocInfo::NONE64); |
1670 __ movq(double_scratch, scratch); | 1661 __ movq(double_scratch, scratch); |
(...skipping 4952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6623 __ bind(&fast_elements_case); | 6614 __ bind(&fast_elements_case); |
6624 GenerateCase(masm, FAST_ELEMENTS); | 6615 GenerateCase(masm, FAST_ELEMENTS); |
6625 } | 6616 } |
6626 | 6617 |
6627 | 6618 |
6628 #undef __ | 6619 #undef __ |
6629 | 6620 |
6630 } } // namespace v8::internal | 6621 } } // namespace v8::internal |
6631 | 6622 |
6632 #endif // V8_TARGET_ARCH_X64 | 6623 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |