• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions 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 "v8.h"
31 
32 #include "disassembler.h"
33 #include "factory.h"
34 #include "macro-assembler.h"
35 #include "platform.h"
36 #include "serialize.h"
37 #include "cctest.h"
38 
39 using namespace v8::internal;
40 
41 
42 typedef int (*F0)();
43 typedef int (*F1)(int x);
44 typedef int (*F2)(int x, int y);
45 
46 
47 static v8::Persistent<v8::Context> env;
48 
49 
InitializeVM()50 static void InitializeVM() {
51   if (env.IsEmpty()) {
52     env = v8::Context::New();
53   }
54 }
55 
56 
57 #define __ assm.
58 
TEST(AssemblerIa320)59 TEST(AssemblerIa320) {
60   InitializeVM();
61   v8::HandleScope scope;
62 
63   v8::internal::byte buffer[256];
64   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
65 
66   __ mov(eax, Operand(esp, 4));
67   __ add(eax, Operand(esp, 8));
68   __ ret(0);
69 
70   CodeDesc desc;
71   assm.GetCode(&desc);
72   Object* code = HEAP->CreateCode(
73       desc,
74       Code::ComputeFlags(Code::STUB),
75       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
76   CHECK(code->IsCode());
77 #ifdef OBJECT_PRINT
78   Code::cast(code)->Print();
79 #endif
80   F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
81   int res = f(3, 4);
82   ::printf("f() = %d\n", res);
83   CHECK_EQ(7, res);
84 }
85 
86 
TEST(AssemblerIa321)87 TEST(AssemblerIa321) {
88   InitializeVM();
89   v8::HandleScope scope;
90 
91   v8::internal::byte buffer[256];
92   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
93   Label L, C;
94 
95   __ mov(edx, Operand(esp, 4));
96   __ xor_(eax, Operand(eax));  // clear eax
97   __ jmp(&C);
98 
99   __ bind(&L);
100   __ add(eax, Operand(edx));
101   __ sub(Operand(edx), Immediate(1));
102 
103   __ bind(&C);
104   __ test(edx, Operand(edx));
105   __ j(not_zero, &L, taken);
106   __ ret(0);
107 
108   CodeDesc desc;
109   assm.GetCode(&desc);
110   Object* code = HEAP->CreateCode(
111       desc,
112       Code::ComputeFlags(Code::STUB),
113       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
114   CHECK(code->IsCode());
115 #ifdef OBJECT_PRINT
116   Code::cast(code)->Print();
117 #endif
118   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
119   int res = f(100);
120   ::printf("f() = %d\n", res);
121   CHECK_EQ(5050, res);
122 }
123 
124 
TEST(AssemblerIa322)125 TEST(AssemblerIa322) {
126   InitializeVM();
127   v8::HandleScope scope;
128 
129   v8::internal::byte buffer[256];
130   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
131   Label L, C;
132 
133   __ mov(edx, Operand(esp, 4));
134   __ mov(eax, 1);
135   __ jmp(&C);
136 
137   __ bind(&L);
138   __ imul(eax, Operand(edx));
139   __ sub(Operand(edx), Immediate(1));
140 
141   __ bind(&C);
142   __ test(edx, Operand(edx));
143   __ j(not_zero, &L, taken);
144   __ ret(0);
145 
146   // some relocated stuff here, not executed
147   __ mov(eax, FACTORY->true_value());
148   __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
149 
150   CodeDesc desc;
151   assm.GetCode(&desc);
152   Object* code = HEAP->CreateCode(
153       desc,
154       Code::ComputeFlags(Code::STUB),
155       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
156   CHECK(code->IsCode());
157 #ifdef OBJECT_PRINT
158   Code::cast(code)->Print();
159 #endif
160   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
161   int res = f(10);
162   ::printf("f() = %d\n", res);
163   CHECK_EQ(3628800, res);
164 }
165 
166 
167 typedef int (*F3)(float x);
168 
TEST(AssemblerIa323)169 TEST(AssemblerIa323) {
170   InitializeVM();
171   if (!CpuFeatures::IsSupported(SSE2)) return;
172 
173   v8::HandleScope scope;
174 
175   v8::internal::byte buffer[256];
176   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
177 
178   CHECK(CpuFeatures::IsSupported(SSE2));
179   { CpuFeatures::Scope fscope(SSE2);
180     __ cvttss2si(eax, Operand(esp, 4));
181     __ ret(0);
182   }
183 
184   CodeDesc desc;
185   assm.GetCode(&desc);
186   Code* code = Code::cast(HEAP->CreateCode(
187       desc,
188       Code::ComputeFlags(Code::STUB),
189       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
190   // don't print the code - our disassembler can't handle cvttss2si
191   // instead print bytes
192   Disassembler::Dump(stdout,
193                      code->instruction_start(),
194                      code->instruction_start() + code->instruction_size());
195   F3 f = FUNCTION_CAST<F3>(code->entry());
196   int res = f(static_cast<float>(-3.1415));
197   ::printf("f() = %d\n", res);
198   CHECK_EQ(-3, res);
199 }
200 
201 
202 typedef int (*F4)(double x);
203 
TEST(AssemblerIa324)204 TEST(AssemblerIa324) {
205   InitializeVM();
206   if (!CpuFeatures::IsSupported(SSE2)) return;
207 
208   v8::HandleScope scope;
209 
210   v8::internal::byte buffer[256];
211   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
212 
213   CHECK(CpuFeatures::IsSupported(SSE2));
214   CpuFeatures::Scope fscope(SSE2);
215   __ cvttsd2si(eax, Operand(esp, 4));
216   __ ret(0);
217 
218   CodeDesc desc;
219   assm.GetCode(&desc);
220   Code* code = Code::cast(HEAP->CreateCode(
221       desc,
222       Code::ComputeFlags(Code::STUB),
223       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
224   // don't print the code - our disassembler can't handle cvttsd2si
225   // instead print bytes
226   Disassembler::Dump(stdout,
227                      code->instruction_start(),
228                      code->instruction_start() + code->instruction_size());
229   F4 f = FUNCTION_CAST<F4>(code->entry());
230   int res = f(2.718281828);
231   ::printf("f() = %d\n", res);
232   CHECK_EQ(2, res);
233 }
234 
235 
236 static int baz = 42;
TEST(AssemblerIa325)237 TEST(AssemblerIa325) {
238   InitializeVM();
239   v8::HandleScope scope;
240 
241   v8::internal::byte buffer[256];
242   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
243 
244   __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE));
245   __ ret(0);
246 
247   CodeDesc desc;
248   assm.GetCode(&desc);
249   Code* code = Code::cast(HEAP->CreateCode(
250       desc,
251       Code::ComputeFlags(Code::STUB),
252       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
253   F0 f = FUNCTION_CAST<F0>(code->entry());
254   int res = f();
255   CHECK_EQ(42, res);
256 }
257 
258 
259 typedef double (*F5)(double x, double y);
260 
TEST(AssemblerIa326)261 TEST(AssemblerIa326) {
262   InitializeVM();
263   if (!CpuFeatures::IsSupported(SSE2)) return;
264 
265   v8::HandleScope scope;
266   CHECK(CpuFeatures::IsSupported(SSE2));
267   CpuFeatures::Scope fscope(SSE2);
268   v8::internal::byte buffer[256];
269   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
270 
271   __ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
272   __ movdbl(xmm1, Operand(esp, 3 * kPointerSize));
273   __ addsd(xmm0, xmm1);
274   __ mulsd(xmm0, xmm1);
275   __ subsd(xmm0, xmm1);
276   __ divsd(xmm0, xmm1);
277   // Copy xmm0 to st(0) using eight bytes of stack.
278   __ sub(Operand(esp), Immediate(8));
279   __ movdbl(Operand(esp, 0), xmm0);
280   __ fld_d(Operand(esp, 0));
281   __ add(Operand(esp), Immediate(8));
282   __ ret(0);
283 
284   CodeDesc desc;
285   assm.GetCode(&desc);
286   Code* code = Code::cast(HEAP->CreateCode(
287       desc,
288       Code::ComputeFlags(Code::STUB),
289       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
290 #ifdef DEBUG
291   ::printf("\n---\n");
292   // don't print the code - our disassembler can't handle SSE instructions
293   // instead print bytes
294   Disassembler::Dump(stdout,
295                      code->instruction_start(),
296                      code->instruction_start() + code->instruction_size());
297 #endif
298   F5 f = FUNCTION_CAST<F5>(code->entry());
299   double res = f(2.2, 1.1);
300   ::printf("f() = %f\n", res);
301   CHECK(2.29 < res && res < 2.31);
302 }
303 
304 
305 typedef double (*F6)(int x);
306 
TEST(AssemblerIa328)307 TEST(AssemblerIa328) {
308   InitializeVM();
309   if (!CpuFeatures::IsSupported(SSE2)) return;
310 
311   v8::HandleScope scope;
312   CHECK(CpuFeatures::IsSupported(SSE2));
313   CpuFeatures::Scope fscope(SSE2);
314   v8::internal::byte buffer[256];
315   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
316   __ mov(eax, Operand(esp, 4));
317   __ cvtsi2sd(xmm0, Operand(eax));
318   // Copy xmm0 to st(0) using eight bytes of stack.
319   __ sub(Operand(esp), Immediate(8));
320   __ movdbl(Operand(esp, 0), xmm0);
321   __ fld_d(Operand(esp, 0));
322   __ add(Operand(esp), Immediate(8));
323   __ ret(0);
324   CodeDesc desc;
325   assm.GetCode(&desc);
326   Code* code = Code::cast(HEAP->CreateCode(
327       desc,
328       Code::ComputeFlags(Code::STUB),
329       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
330   CHECK(code->IsCode());
331 #ifdef OBJECT_PRINT
332   Code::cast(code)->Print();
333 #endif
334   F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
335   double res = f(12);
336 
337   ::printf("f() = %f\n", res);
338   CHECK(11.99 < res && res < 12.001);
339 }
340 
341 
342 typedef int (*F7)(double x, double y);
343 
TEST(AssemblerIa329)344 TEST(AssemblerIa329) {
345   InitializeVM();
346   v8::HandleScope scope;
347   v8::internal::byte buffer[256];
348   MacroAssembler assm(Isolate::Current(), buffer, sizeof buffer);
349   enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
350   Label equal_l, less_l, greater_l, nan_l;
351   __ fld_d(Operand(esp, 3 * kPointerSize));
352   __ fld_d(Operand(esp, 1 * kPointerSize));
353   __ FCmp();
354   __ j(parity_even, &nan_l, taken);
355   __ j(equal, &equal_l, taken);
356   __ j(below, &less_l, taken);
357   __ j(above, &greater_l, taken);
358 
359   __ mov(eax, kUndefined);
360   __ ret(0);
361 
362   __ bind(&equal_l);
363   __ mov(eax, kEqual);
364   __ ret(0);
365 
366   __ bind(&greater_l);
367   __ mov(eax, kGreater);
368   __ ret(0);
369 
370   __ bind(&less_l);
371   __ mov(eax, kLess);
372   __ ret(0);
373 
374   __ bind(&nan_l);
375   __ mov(eax, kNaN);
376   __ ret(0);
377 
378 
379   CodeDesc desc;
380   assm.GetCode(&desc);
381   Code* code = Code::cast(HEAP->CreateCode(
382       desc,
383       Code::ComputeFlags(Code::STUB),
384       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
385   CHECK(code->IsCode());
386 #ifdef OBJECT_PRINT
387   Code::cast(code)->Print();
388 #endif
389 
390   F7 f = FUNCTION_CAST<F7>(Code::cast(code)->entry());
391   CHECK_EQ(kLess, f(1.1, 2.2));
392   CHECK_EQ(kEqual, f(2.2, 2.2));
393   CHECK_EQ(kGreater, f(3.3, 2.2));
394   CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
395 }
396 
397 #undef __
398