| 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 2788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2799 const ParameterCount& actual, | 2799 const ParameterCount& actual, |
| 2800 InvokeFlag flag, | 2800 InvokeFlag flag, |
| 2801 const CallWrapper& call_wrapper) { | 2801 const CallWrapper& call_wrapper) { |
| 2802 // Contract with called JS functions requires that function is passed in x1. | 2802 // Contract with called JS functions requires that function is passed in x1. |
| 2803 // (See FullCodeGenerator::Generate().) | 2803 // (See FullCodeGenerator::Generate().) |
| 2804 __ LoadObject(x1, function); | 2804 __ LoadObject(x1, function); |
| 2805 InvokeFunction(x1, expected, actual, flag, call_wrapper); | 2805 InvokeFunction(x1, expected, actual, flag, call_wrapper); |
| 2806 } | 2806 } |
| 2807 | 2807 |
| 2808 | 2808 |
| 2809 void MacroAssembler::TryInlineTruncateDoubleToI(Register result, | 2809 void MacroAssembler::TryConvertDoubleToInt64(Register result, |
| 2810 DoubleRegister double_input, | 2810 DoubleRegister double_input, |
| 2811 Label* done) { | 2811 Label* done) { |
| 2812 STATIC_ASSERT(kSmiTag == 0); | 2812 // Try to convert with an FPU convert instruction. It's trivial to compute |
| 2813 STATIC_ASSERT(kSmiValueSize == 32); | |
| 2814 | |
| 2815 // Try to convert with a FPU convert instruction. It's trivial to compute | |
| 2816 // the modulo operation on an integer register so we convert to a 64-bit | 2813 // the modulo operation on an integer register so we convert to a 64-bit |
| 2817 // integer, then find the 32-bit result from that. | 2814 // integer. |
| 2818 // | 2815 // |
| 2819 // Fcvtzs will saturate to INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff) | 2816 // Fcvtzs will saturate to INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff) |
| 2820 // when the double is out of range. NaNs and infinities will be converted to 0 | 2817 // when the double is out of range. NaNs and infinities will be converted to 0 |
| 2821 // (as ECMA-262 requires). | 2818 // (as ECMA-262 requires). |
| 2822 Fcvtzs(result, double_input); | 2819 Fcvtzs(result.X(), double_input); |
| 2823 | 2820 |
| 2824 // The values INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff) are not | 2821 // The values INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff) are not |
| 2825 // representable using a double, so if the result is one of those then we know | 2822 // representable using a double, so if the result is one of those then we know |
| 2826 // that saturation occured, and we need to manually handle the conversion. | 2823 // that saturation occured, and we need to manually handle the conversion. |
| 2827 // | 2824 // |
| 2828 // It is easy to detect INT64_MIN and INT64_MAX because adding or subtracting | 2825 // It is easy to detect INT64_MIN and INT64_MAX because adding or subtracting |
| 2829 // 1 will cause signed overflow. | 2826 // 1 will cause signed overflow. |
| 2830 Cmp(result, 1); | 2827 Cmp(result.X(), 1); |
| 2831 Ccmp(result, -1, VFlag, vc); | 2828 Ccmp(result.X(), -1, VFlag, vc); |
| 2832 | 2829 |
| 2833 B(vc, done); | 2830 B(vc, done); |
| 2834 } | 2831 } |
| 2835 | 2832 |
| 2836 | 2833 |
| 2837 void MacroAssembler::TruncateDoubleToI(Register result, | 2834 void MacroAssembler::TruncateDoubleToI(Register result, |
| 2838 DoubleRegister double_input) { | 2835 DoubleRegister double_input) { |
| 2839 Label done; | 2836 Label done; |
| 2840 ASSERT(jssp.Is(StackPointer())); | 2837 ASSERT(jssp.Is(StackPointer())); |
| 2841 | 2838 |
| 2842 TryInlineTruncateDoubleToI(result, double_input, &done); | 2839 // Try to convert the double to an int64. If successful, the bottom 32 bits |
| 2840 // contain our truncated int32 result. |
| 2841 TryConvertDoubleToInt64(result, double_input, &done); |
| 2843 | 2842 |
| 2844 // If we fell through then inline version didn't succeed - call stub instead. | 2843 // If we fell through then inline version didn't succeed - call stub instead. |
| 2845 Push(lr); | 2844 Push(lr); |
| 2846 Push(double_input); // Put input on stack. | 2845 Push(double_input); // Put input on stack. |
| 2847 | 2846 |
| 2848 DoubleToIStub stub(jssp, | 2847 DoubleToIStub stub(jssp, |
| 2849 result, | 2848 result, |
| 2850 0, | 2849 0, |
| 2851 true, // is_truncating | 2850 true, // is_truncating |
| 2852 true); // skip_fastpath | 2851 true); // skip_fastpath |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2863 } | 2862 } |
| 2864 | 2863 |
| 2865 | 2864 |
| 2866 void MacroAssembler::TruncateHeapNumberToI(Register result, | 2865 void MacroAssembler::TruncateHeapNumberToI(Register result, |
| 2867 Register object) { | 2866 Register object) { |
| 2868 Label done; | 2867 Label done; |
| 2869 ASSERT(!result.is(object)); | 2868 ASSERT(!result.is(object)); |
| 2870 ASSERT(jssp.Is(StackPointer())); | 2869 ASSERT(jssp.Is(StackPointer())); |
| 2871 | 2870 |
| 2872 Ldr(fp_scratch, FieldMemOperand(object, HeapNumber::kValueOffset)); | 2871 Ldr(fp_scratch, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 2873 TryInlineTruncateDoubleToI(result, fp_scratch, &done); | 2872 |
| 2873 // Try to convert the double to an int64. If successful, the bottom 32 bits |
| 2874 // contain our truncated int32 result. |
| 2875 TryConvertDoubleToInt64(result, fp_scratch, &done); |
| 2874 | 2876 |
| 2875 // If we fell through then inline version didn't succeed - call stub instead. | 2877 // If we fell through then inline version didn't succeed - call stub instead. |
| 2876 Push(lr); | 2878 Push(lr); |
| 2877 DoubleToIStub stub(object, | 2879 DoubleToIStub stub(object, |
| 2878 result, | 2880 result, |
| 2879 HeapNumber::kValueOffset - kHeapObjectTag, | 2881 HeapNumber::kValueOffset - kHeapObjectTag, |
| 2880 true, // is_truncating | 2882 true, // is_truncating |
| 2881 true); // skip_fastpath | 2883 true); // skip_fastpath |
| 2882 CallStub(&stub); // DoubleToIStub preserves any registers it needs to clobber | 2884 CallStub(&stub); // DoubleToIStub preserves any registers it needs to clobber |
| 2883 Pop(lr); | 2885 Pop(lr); |
| (...skipping 2212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5096 } | 5098 } |
| 5097 } | 5099 } |
| 5098 | 5100 |
| 5099 | 5101 |
| 5100 #undef __ | 5102 #undef __ |
| 5101 | 5103 |
| 5102 | 5104 |
| 5103 } } // namespace v8::internal | 5105 } } // namespace v8::internal |
| 5104 | 5106 |
| 5105 #endif // V8_TARGET_ARCH_A64 | 5107 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |