1// Copyright 2013 the V8 project authors. All rights reserved. 2// Rrdistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Rrdistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Rrdistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include <stdlib.h> 29 30#include "src/v8.h" 31 32#include "src/code-stubs.h" 33#include "src/factory.h" 34#include "src/macro-assembler.h" 35#include "src/platform.h" 36#include "src/simulator.h" 37#include "test/cctest/cctest.h" 38#include "test/cctest/test-code-stubs.h" 39 40using namespace v8::internal; 41 42#define __ masm. 43 44ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate, 45 Register source_reg, 46 Register destination_reg, 47 bool inline_fastpath) { 48 // Allocate an executable page of memory. 49 size_t actual_size = 4 * Assembler::kMinimalBufferSize; 50 byte* buffer = static_cast<byte*>(OS::Allocate(actual_size, 51 &actual_size, 52 true)); 53 CHECK(buffer); 54 HandleScope handles(isolate); 55 MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size)); 56 DoubleToIStub stub(isolate, source_reg, destination_reg, 0, true, 57 inline_fastpath); 58 59 byte* start = stub.GetCode()->instruction_start(); 60 Label done; 61 62 __ SetStackPointer(csp); 63 __ PushCalleeSavedRegisters(); 64 __ Mov(jssp, csp); 65 __ SetStackPointer(jssp); 66 67 // Push the double argument. 68 __ Push(d0); 69 __ Mov(source_reg, jssp); 70 71 MacroAssembler::PushPopQueue queue(&masm); 72 73 // Save registers make sure they don't get clobbered. 74 int source_reg_offset = kDoubleSize; 75 int reg_num = 0; 76 for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) { 77 Register reg = Register::from_code(reg_num); 78 if (!reg.is(destination_reg)) { 79 queue.Queue(reg); 80 source_reg_offset += kPointerSize; 81 } 82 } 83 // Re-push the double argument. 84 queue.Queue(d0); 85 86 queue.PushQueued(); 87 88 // Call through to the actual stub 89 if (inline_fastpath) { 90 __ Ldr(d0, MemOperand(source_reg)); 91 __ TryConvertDoubleToInt64(destination_reg, d0, &done); 92 if (destination_reg.is(source_reg)) { 93 // Restore clobbered source_reg. 94 __ add(source_reg, jssp, Operand(source_reg_offset)); 95 } 96 } 97 __ Call(start, RelocInfo::EXTERNAL_REFERENCE); 98 __ bind(&done); 99 100 __ Drop(1, kDoubleSize); 101 102 // // Make sure no registers have been unexpectedly clobbered 103 for (--reg_num; reg_num >= 0; --reg_num) { 104 Register reg = Register::from_code(reg_num); 105 if (!reg.is(destination_reg)) { 106 __ Pop(ip0); 107 __ cmp(reg, ip0); 108 __ Assert(eq, kRegisterWasClobbered); 109 } 110 } 111 112 __ Drop(1, kDoubleSize); 113 114 if (!destination_reg.is(x0)) 115 __ Mov(x0, destination_reg); 116 117 // Restore callee save registers. 118 __ Mov(csp, jssp); 119 __ SetStackPointer(csp); 120 __ PopCalleeSavedRegisters(); 121 122 __ Ret(); 123 124 CodeDesc desc; 125 masm.GetCode(&desc); 126 CPU::FlushICache(buffer, actual_size); 127 return (reinterpret_cast<ConvertDToIFunc>( 128 reinterpret_cast<intptr_t>(buffer))); 129} 130 131#undef __ 132 133 134static Isolate* GetIsolateFrom(LocalContext* context) { 135 return reinterpret_cast<Isolate*>((*context)->GetIsolate()); 136} 137 138 139int32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func, 140 double from) { 141#ifdef USE_SIMULATOR 142 Simulator::CallArgument args[] = { 143 Simulator::CallArgument(from), 144 Simulator::CallArgument::End() 145 }; 146 return Simulator::current(Isolate::Current())->CallInt64( 147 FUNCTION_ADDR(func), args); 148#else 149 return (*func)(from); 150#endif 151} 152 153 154TEST(ConvertDToI) { 155 CcTest::InitializeVM(); 156 LocalContext context; 157 Isolate* isolate = GetIsolateFrom(&context); 158 HandleScope scope(isolate); 159 160#if DEBUG 161 // Verify that the tests actually work with the C version. In the release 162 // code, the compiler optimizes it away because it's all constant, but does it 163 // wrong, triggering an assert on gcc. 164 RunAllTruncationTests(&ConvertDToICVersion); 165#endif 166 167 Register source_registers[] = {jssp, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, 168 x10, x11, x12, x13, x14, x15, x18, x19, x20, 169 x21, x22, x23, x24}; 170 Register dest_registers[] = {x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, 171 x12, x13, x14, x15, x18, x19, x20, x21, x22, x23, 172 x24}; 173 174 for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) { 175 for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) { 176 RunAllTruncationTests( 177 RunGeneratedCodeCallWrapper, 178 MakeConvertDToIFuncTrampoline(isolate, 179 source_registers[s], 180 dest_registers[d], 181 false)); 182 RunAllTruncationTests( 183 RunGeneratedCodeCallWrapper, 184 MakeConvertDToIFuncTrampoline(isolate, 185 source_registers[s], 186 dest_registers[d], 187 true)); 188 } 189 } 190} 191