Line data Source code
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/base/platform/platform.h"
33 : #include "src/code-stubs.h"
34 : #include "src/factory.h"
35 : #include "src/macro-assembler.h"
36 : #include "src/objects-inl.h"
37 : #include "src/register-configuration.h"
38 : #include "test/cctest/cctest.h"
39 : #include "test/cctest/test-code-stubs.h"
40 :
41 : namespace v8 {
42 : namespace internal {
43 : namespace test_code_stubs_x64 {
44 :
45 : #define __ assm.
46 :
47 48 : ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
48 : Register destination_reg) {
49 : // Allocate an executable page of memory.
50 : size_t actual_size;
51 : byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
52 48 : Assembler::kMinimalBufferSize, &actual_size, true));
53 48 : CHECK(buffer);
54 : HandleScope handles(isolate);
55 : MacroAssembler assm(isolate, buffer, static_cast<int>(actual_size),
56 48 : v8::internal::CodeObjectRequired::kYes);
57 : DoubleToIStub stub(isolate, destination_reg);
58 96 : byte* start = stub.GetCode()->instruction_start();
59 :
60 48 : __ pushq(rbx);
61 48 : __ pushq(rcx);
62 48 : __ pushq(rdx);
63 48 : __ pushq(rsi);
64 48 : __ pushq(rdi);
65 :
66 1824 : const RegisterConfiguration* config = RegisterConfiguration::Default();
67 :
68 : // Save registers make sure they don't get clobbered.
69 : int reg_num = 0;
70 1248 : for (; reg_num < config->num_allocatable_general_registers(); ++reg_num) {
71 : Register reg =
72 : Register::from_code(config->GetAllocatableGeneralCode(reg_num));
73 576 : if (reg != rsp && reg != rbp && reg != destination_reg) {
74 528 : __ pushq(reg);
75 : }
76 : }
77 :
78 : // Put the double argument into the designated double argument slot.
79 48 : __ subq(rsp, Immediate(kDoubleSize));
80 48 : __ Movsd(MemOperand(rsp, 0), xmm0);
81 :
82 : // Call through to the actual stub
83 48 : __ Call(start, RelocInfo::EXTERNAL_REFERENCE);
84 :
85 48 : __ addq(rsp, Immediate(kDoubleSize));
86 :
87 : // Make sure no registers have been unexpectedly clobbered
88 624 : for (--reg_num; reg_num >= 0; --reg_num) {
89 : Register reg =
90 : Register::from_code(config->GetAllocatableGeneralCode(reg_num));
91 576 : if (reg != rsp && reg != rbp && reg != destination_reg) {
92 1056 : __ cmpq(reg, MemOperand(rsp, 0));
93 528 : __ Assert(equal, kRegisterWasClobbered);
94 528 : __ addq(rsp, Immediate(kPointerSize));
95 : }
96 : }
97 :
98 : __ movq(rax, destination_reg);
99 :
100 48 : __ popq(rdi);
101 48 : __ popq(rsi);
102 48 : __ popq(rdx);
103 48 : __ popq(rcx);
104 48 : __ popq(rbx);
105 :
106 48 : __ ret(0);
107 :
108 : CodeDesc desc;
109 48 : assm.GetCode(isolate, &desc);
110 : return reinterpret_cast<ConvertDToIFunc>(
111 96 : reinterpret_cast<intptr_t>(buffer));
112 : }
113 :
114 : #undef __
115 :
116 :
117 : static Isolate* GetIsolateFrom(LocalContext* context) {
118 6 : return reinterpret_cast<Isolate*>((*context)->GetIsolate());
119 : }
120 :
121 :
122 23724 : TEST(ConvertDToI) {
123 6 : CcTest::InitializeVM();
124 6 : LocalContext context;
125 : Isolate* isolate = GetIsolateFrom(&context);
126 : HandleScope scope(isolate);
127 :
128 : #if DEBUG
129 : // Verify that the tests actually work with the C version. In the release
130 : // code, the compiler optimizes it away because it's all constant, but does it
131 : // wrong, triggering an assert on gcc.
132 : RunAllTruncationTests(&ConvertDToICVersion);
133 : #endif
134 :
135 6 : Register dest_registers[] = {rax, rbx, rcx, rdx, rsi, rdi, r8, r9};
136 :
137 54 : for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) {
138 : RunAllTruncationTests(
139 48 : MakeConvertDToIFuncTrampoline(isolate, dest_registers[d]));
140 6 : }
141 6 : }
142 :
143 : } // namespace test_code_stubs_x64
144 : } // namespace internal
145 71154 : } // namespace v8
|