| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/x64/codegen-x64.h" | 5 #include "src/x64/codegen-x64.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 | 80 |
| 81 CodeDesc desc; | 81 CodeDesc desc; |
| 82 masm.GetCode(&desc); | 82 masm.GetCode(&desc); |
| 83 DCHECK(!RelocInfo::RequiresRelocation(desc)); | 83 DCHECK(!RelocInfo::RequiresRelocation(desc)); |
| 84 | 84 |
| 85 Assembler::FlushICache(isolate, buffer, actual_size); | 85 Assembler::FlushICache(isolate, buffer, actual_size); |
| 86 base::OS::ProtectCode(buffer, actual_size); | 86 base::OS::ProtectCode(buffer, actual_size); |
| 87 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); | 87 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); |
| 88 } | 88 } |
| 89 | 89 |
| 90 | |
| 91 #ifdef _WIN64 | |
| 92 typedef double (*ModuloFunction)(double, double); | |
| 93 // Define custom fmod implementation. | |
| 94 ModuloFunction CreateModuloFunction() { | |
| 95 size_t actual_size; | |
| 96 byte* buffer = static_cast<byte*>( | |
| 97 base::OS::Allocate(Assembler::kMinimalBufferSize, &actual_size, true)); | |
| 98 CHECK(buffer); | |
| 99 MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size), | |
| 100 CodeObjectRequired::kNo); | |
| 101 // Generated code is put into a fixed, unmovable, buffer, and not into | |
| 102 // the V8 heap. We can't, and don't, refer to any relocatable addresses | |
| 103 // (e.g. the JavaScript nan-object). | |
| 104 | |
| 105 // Windows 64 ABI passes double arguments in xmm0, xmm1 and | |
| 106 // returns result in xmm0. | |
| 107 // Argument backing space is allocated on the stack above | |
| 108 // the return address. | |
| 109 | |
| 110 // Compute x mod y. | |
| 111 // Load y and x (use argument backing store as temporary storage). | |
| 112 __ Movsd(Operand(rsp, kRegisterSize * 2), xmm1); | |
| 113 __ Movsd(Operand(rsp, kRegisterSize), xmm0); | |
| 114 __ fld_d(Operand(rsp, kRegisterSize * 2)); | |
| 115 __ fld_d(Operand(rsp, kRegisterSize)); | |
| 116 | |
| 117 // Clear exception flags before operation. | |
| 118 { | |
| 119 Label no_exceptions; | |
| 120 __ fwait(); | |
| 121 __ fnstsw_ax(); | |
| 122 // Clear if Illegal Operand or Zero Division exceptions are set. | |
| 123 __ testb(rax, Immediate(5)); | |
| 124 __ j(zero, &no_exceptions); | |
| 125 __ fnclex(); | |
| 126 __ bind(&no_exceptions); | |
| 127 } | |
| 128 | |
| 129 // Compute st(0) % st(1) | |
| 130 { | |
| 131 Label partial_remainder_loop; | |
| 132 __ bind(&partial_remainder_loop); | |
| 133 __ fprem(); | |
| 134 __ fwait(); | |
| 135 __ fnstsw_ax(); | |
| 136 __ testl(rax, Immediate(0x400 /* C2 */)); | |
| 137 // If C2 is set, computation only has partial result. Loop to | |
| 138 // continue computation. | |
| 139 __ j(not_zero, &partial_remainder_loop); | |
| 140 } | |
| 141 | |
| 142 Label valid_result; | |
| 143 Label return_result; | |
| 144 // If Invalid Operand or Zero Division exceptions are set, | |
| 145 // return NaN. | |
| 146 __ testb(rax, Immediate(5)); | |
| 147 __ j(zero, &valid_result); | |
| 148 __ fstp(0); // Drop result in st(0). | |
| 149 int64_t kNaNValue = V8_INT64_C(0x7ff8000000000000); | |
| 150 __ movq(rcx, kNaNValue); | |
| 151 __ movq(Operand(rsp, kRegisterSize), rcx); | |
| 152 __ Movsd(xmm0, Operand(rsp, kRegisterSize)); | |
| 153 __ jmp(&return_result); | |
| 154 | |
| 155 // If result is valid, return that. | |
| 156 __ bind(&valid_result); | |
| 157 __ fstp_d(Operand(rsp, kRegisterSize)); | |
| 158 __ Movsd(xmm0, Operand(rsp, kRegisterSize)); | |
| 159 | |
| 160 // Clean up FPU stack and exceptions and return xmm0 | |
| 161 __ bind(&return_result); | |
| 162 __ fstp(0); // Unload y. | |
| 163 | |
| 164 Label clear_exceptions; | |
| 165 __ testb(rax, Immediate(0x3f /* Any Exception*/)); | |
| 166 __ j(not_zero, &clear_exceptions); | |
| 167 __ ret(0); | |
| 168 __ bind(&clear_exceptions); | |
| 169 __ fnclex(); | |
| 170 __ ret(0); | |
| 171 | |
| 172 CodeDesc desc; | |
| 173 masm.GetCode(&desc); | |
| 174 base::OS::ProtectCode(buffer, actual_size); | |
| 175 // Call the function from C++ through this pointer. | |
| 176 return FUNCTION_CAST<ModuloFunction>(buffer); | |
| 177 } | |
| 178 | |
| 179 #endif | |
| 180 | |
| 181 #undef __ | 90 #undef __ |
| 182 | 91 |
| 183 // ------------------------------------------------------------------------- | 92 // ------------------------------------------------------------------------- |
| 184 // Code generators | 93 // Code generators |
| 185 | 94 |
| 186 #define __ ACCESS_MASM(masm) | 95 #define __ ACCESS_MASM(masm) |
| 187 | 96 |
| 188 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | 97 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
| 189 MacroAssembler* masm, | 98 MacroAssembler* masm, |
| 190 Register receiver, | 99 Register receiver, |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 return Operand(base_reg_, argument_count_reg_, times_pointer_size, | 632 return Operand(base_reg_, argument_count_reg_, times_pointer_size, |
| 724 displacement_to_last_argument + (receiver - 1 - index) * kPointerSize); | 633 displacement_to_last_argument + (receiver - 1 - index) * kPointerSize); |
| 725 } | 634 } |
| 726 } | 635 } |
| 727 | 636 |
| 728 | 637 |
| 729 } // namespace internal | 638 } // namespace internal |
| 730 } // namespace v8 | 639 } // namespace v8 |
| 731 | 640 |
| 732 #endif // V8_TARGET_ARCH_X64 | 641 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |