v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-assembler-x64.cc
Go to the documentation of this file.
1 // Copyright 2009 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 "macro-assembler.h"
33 #include "factory.h"
34 #include "platform.h"
35 #include "serialize.h"
36 #include "cctest.h"
37 
38 using namespace v8::internal;
39 
40 // Test the x64 assembler by compiling some simple functions into
41 // a buffer and executing them. These tests do not initialize the
42 // V8 library, create a context, or use any V8 objects.
43 // The AMD64 calling convention is used, with the first six arguments
44 // in RDI, RSI, RDX, RCX, R8, and R9, and floating point arguments in
45 // the XMM registers. The return value is in RAX.
46 // This calling convention is used on Linux, with GCC, and on Mac OS,
47 // with GCC. A different convention is used on 64-bit windows,
48 // where the first four integer arguments are passed in RCX, RDX, R8 and R9.
49 
50 typedef int (*F0)();
51 typedef int (*F1)(int64_t x);
52 typedef int (*F2)(int64_t x, int64_t y);
53 typedef int (*F3)(double x);
54 typedef int64_t (*F4)(int64_t* x, int64_t* y);
55 typedef int64_t (*F5)(int64_t x);
56 
57 #ifdef _WIN64
58 static const Register arg1 = rcx;
59 static const Register arg2 = rdx;
60 #else
61 static const Register arg1 = rdi;
62 static const Register arg2 = rsi;
63 #endif
64 
65 #define __ assm.
66 
67 
68 TEST(AssemblerX64ReturnOperation) {
69  // Allocate an executable page of memory.
70  size_t actual_size;
71  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
72  &actual_size,
73  true));
74  CHECK(buffer);
75  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
76 
77  // Assemble a simple function that copies argument 2 and returns it.
78  __ movq(rax, arg2);
79  __ nop();
80  __ ret(0);
81 
82  CodeDesc desc;
83  assm.GetCode(&desc);
84  // Call the function from C++.
85  int result = FUNCTION_CAST<F2>(buffer)(3, 2);
86  CHECK_EQ(2, result);
87 }
88 
89 
90 TEST(AssemblerX64StackOperations) {
91  // Allocate an executable page of memory.
92  size_t actual_size;
93  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
94  &actual_size,
95  true));
96  CHECK(buffer);
97  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
98 
99  // Assemble a simple function that copies argument 2 and returns it.
100  // We compile without stack frame pointers, so the gdb debugger shows
101  // incorrect stack frames when debugging this function (which has them).
102  __ pushq(rbp);
103  __ movq(rbp, rsp);
104  __ pushq(arg2); // Value at (rbp - 8)
105  __ pushq(arg2); // Value at (rbp - 16)
106  __ pushq(arg1); // Value at (rbp - 24)
107  __ popq(rax);
108  __ popq(rax);
109  __ popq(rax);
110  __ popq(rbp);
111  __ nop();
112  __ ret(0);
113 
114  CodeDesc desc;
115  assm.GetCode(&desc);
116  // Call the function from C++.
117  int result = FUNCTION_CAST<F2>(buffer)(3, 2);
118  CHECK_EQ(2, result);
119 }
120 
121 
122 TEST(AssemblerX64ArithmeticOperations) {
123  // Allocate an executable page of memory.
124  size_t actual_size;
125  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
126  &actual_size,
127  true));
128  CHECK(buffer);
129  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
130 
131  // Assemble a simple function that adds arguments returning the sum.
132  __ movq(rax, arg2);
133  __ addq(rax, arg1);
134  __ ret(0);
135 
136  CodeDesc desc;
137  assm.GetCode(&desc);
138  // Call the function from C++.
139  int result = FUNCTION_CAST<F2>(buffer)(3, 2);
140  CHECK_EQ(5, result);
141 }
142 
143 
144 TEST(AssemblerX64ImulOperation) {
145  // Allocate an executable page of memory.
146  size_t actual_size;
147  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
148  &actual_size,
149  true));
150  CHECK(buffer);
151  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
152 
153  // Assemble a simple function that multiplies arguments returning the high
154  // word.
155  __ movq(rax, arg2);
156  __ imulq(arg1);
157  __ movq(rax, rdx);
158  __ ret(0);
159 
160  CodeDesc desc;
161  assm.GetCode(&desc);
162  // Call the function from C++.
163  int result = FUNCTION_CAST<F2>(buffer)(3, 2);
164  CHECK_EQ(0, result);
165  result = FUNCTION_CAST<F2>(buffer)(0x100000000l, 0x100000000l);
166  CHECK_EQ(1, result);
167  result = FUNCTION_CAST<F2>(buffer)(-0x100000000l, 0x100000000l);
168  CHECK_EQ(-1, result);
169 }
170 
171 
172 TEST(AssemblerX64XchglOperations) {
173  // Allocate an executable page of memory.
174  size_t actual_size;
175  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
176  &actual_size,
177  true));
178  CHECK(buffer);
179  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
180 
181  __ movq(rax, Operand(arg1, 0));
182  __ movq(r11, Operand(arg2, 0));
183  __ xchgl(rax, r11);
184  __ movq(Operand(arg1, 0), rax);
185  __ movq(Operand(arg2, 0), r11);
186  __ ret(0);
187 
188  CodeDesc desc;
189  assm.GetCode(&desc);
190  // Call the function from C++.
191  int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
192  int64_t right = V8_2PART_UINT64_C(0x30000000, 40000000);
193  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
194  CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 40000000), left);
195  CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 20000000), right);
196  USE(result);
197 }
198 
199 
200 TEST(AssemblerX64OrlOperations) {
201  // Allocate an executable page of memory.
202  size_t actual_size;
203  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
204  &actual_size,
205  true));
206  CHECK(buffer);
207  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
208 
209  __ movq(rax, Operand(arg2, 0));
210  __ orl(Operand(arg1, 0), rax);
211  __ ret(0);
212 
213  CodeDesc desc;
214  assm.GetCode(&desc);
215  // Call the function from C++.
216  int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
217  int64_t right = V8_2PART_UINT64_C(0x30000000, 40000000);
218  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
219  CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 60000000), left);
220  USE(result);
221 }
222 
223 
224 TEST(AssemblerX64RollOperations) {
225  // Allocate an executable page of memory.
226  size_t actual_size;
227  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
228  &actual_size,
229  true));
230  CHECK(buffer);
231  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
232 
233  __ movq(rax, arg1);
234  __ roll(rax, Immediate(1));
235  __ ret(0);
236 
237  CodeDesc desc;
238  assm.GetCode(&desc);
239  // Call the function from C++.
240  int64_t src = V8_2PART_UINT64_C(0x10000000, C0000000);
241  int64_t result = FUNCTION_CAST<F5>(buffer)(src);
242  CHECK_EQ(V8_2PART_UINT64_C(0x00000000, 80000001), result);
243 }
244 
245 
246 TEST(AssemblerX64SublOperations) {
247  // Allocate an executable page of memory.
248  size_t actual_size;
249  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
250  &actual_size,
251  true));
252  CHECK(buffer);
253  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
254 
255  __ movq(rax, Operand(arg2, 0));
256  __ subl(Operand(arg1, 0), rax);
257  __ ret(0);
258 
259  CodeDesc desc;
260  assm.GetCode(&desc);
261  // Call the function from C++.
262  int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
263  int64_t right = V8_2PART_UINT64_C(0x30000000, 40000000);
264  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
265  CHECK_EQ(V8_2PART_UINT64_C(0x10000000, e0000000), left);
266  USE(result);
267 }
268 
269 
270 TEST(AssemblerX64TestlOperations) {
271  // Allocate an executable page of memory.
272  size_t actual_size;
273  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
274  &actual_size,
275  true));
276  CHECK(buffer);
277  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
278 
279  // Set rax with the ZF flag of the testl instruction.
280  Label done;
281  __ movq(rax, Immediate(1));
282  __ movq(r11, Operand(arg2, 0));
283  __ testl(Operand(arg1, 0), r11);
284  __ j(zero, &done, Label::kNear);
285  __ movq(rax, Immediate(0));
286  __ bind(&done);
287  __ ret(0);
288 
289  CodeDesc desc;
290  assm.GetCode(&desc);
291  // Call the function from C++.
292  int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
293  int64_t right = V8_2PART_UINT64_C(0x30000000, 00000000);
294  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
295  CHECK_EQ(static_cast<int64_t>(1), result);
296 }
297 
298 
299 TEST(AssemblerX64XorlOperations) {
300  // Allocate an executable page of memory.
301  size_t actual_size;
302  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
303  &actual_size,
304  true));
305  CHECK(buffer);
306  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
307 
308  __ movq(rax, Operand(arg2, 0));
309  __ xorl(Operand(arg1, 0), rax);
310  __ ret(0);
311 
312  CodeDesc desc;
313  assm.GetCode(&desc);
314  // Call the function from C++.
315  int64_t left = V8_2PART_UINT64_C(0x10000000, 20000000);
316  int64_t right = V8_2PART_UINT64_C(0x30000000, 60000000);
317  int64_t result = FUNCTION_CAST<F4>(buffer)(&left, &right);
318  CHECK_EQ(V8_2PART_UINT64_C(0x10000000, 40000000), left);
319  USE(result);
320 }
321 
322 
323 TEST(AssemblerX64MemoryOperands) {
324  // Allocate an executable page of memory.
325  size_t actual_size;
326  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
327  &actual_size,
328  true));
329  CHECK(buffer);
330  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
331 
332  // Assemble a simple function that copies argument 2 and returns it.
333  __ pushq(rbp);
334  __ movq(rbp, rsp);
335 
336  __ pushq(arg2); // Value at (rbp - 8)
337  __ pushq(arg2); // Value at (rbp - 16)
338  __ pushq(arg1); // Value at (rbp - 24)
339 
340  const int kStackElementSize = 8;
341  __ movq(rax, Operand(rbp, -3 * kStackElementSize));
342  __ popq(arg2);
343  __ popq(arg2);
344  __ popq(arg2);
345  __ popq(rbp);
346  __ nop();
347  __ ret(0);
348 
349  CodeDesc desc;
350  assm.GetCode(&desc);
351  // Call the function from C++.
352  int result = FUNCTION_CAST<F2>(buffer)(3, 2);
353  CHECK_EQ(3, result);
354 }
355 
356 
357 TEST(AssemblerX64ControlFlow) {
358  // Allocate an executable page of memory.
359  size_t actual_size;
360  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
361  &actual_size,
362  true));
363  CHECK(buffer);
364  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
365 
366  // Assemble a simple function that copies argument 1 and returns it.
367  __ pushq(rbp);
368 
369  __ movq(rbp, rsp);
370  __ movq(rax, arg1);
371  Label target;
372  __ jmp(&target);
373  __ movq(rax, arg2);
374  __ bind(&target);
375  __ popq(rbp);
376  __ ret(0);
377 
378  CodeDesc desc;
379  assm.GetCode(&desc);
380  // Call the function from C++.
381  int result = FUNCTION_CAST<F2>(buffer)(3, 2);
382  CHECK_EQ(3, result);
383 }
384 
385 
386 TEST(AssemblerX64LoopImmediates) {
387  // Allocate an executable page of memory.
388  size_t actual_size;
389  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
390  &actual_size,
391  true));
392  CHECK(buffer);
393  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
394  // Assemble two loops using rax as counter, and verify the ending counts.
395  Label Fail;
396  __ movq(rax, Immediate(-3));
397  Label Loop1_test;
398  Label Loop1_body;
399  __ jmp(&Loop1_test);
400  __ bind(&Loop1_body);
401  __ addq(rax, Immediate(7));
402  __ bind(&Loop1_test);
403  __ cmpq(rax, Immediate(20));
404  __ j(less_equal, &Loop1_body);
405  // Did the loop terminate with the expected value?
406  __ cmpq(rax, Immediate(25));
407  __ j(not_equal, &Fail);
408 
409  Label Loop2_test;
410  Label Loop2_body;
411  __ movq(rax, Immediate(0x11FEED00));
412  __ jmp(&Loop2_test);
413  __ bind(&Loop2_body);
414  __ addq(rax, Immediate(-0x1100));
415  __ bind(&Loop2_test);
416  __ cmpq(rax, Immediate(0x11FE8000));
417  __ j(greater, &Loop2_body);
418  // Did the loop terminate with the expected value?
419  __ cmpq(rax, Immediate(0x11FE7600));
420  __ j(not_equal, &Fail);
421 
422  __ movq(rax, Immediate(1));
423  __ ret(0);
424  __ bind(&Fail);
425  __ movq(rax, Immediate(0));
426  __ ret(0);
427 
428  CodeDesc desc;
429  assm.GetCode(&desc);
430  // Call the function from C++.
431  int result = FUNCTION_CAST<F0>(buffer)();
432  CHECK_EQ(1, result);
433 }
434 
435 
436 TEST(OperandRegisterDependency) {
437  int offsets[4] = {0, 1, 0xfed, 0xbeefcad};
438  for (int i = 0; i < 4; i++) {
439  int offset = offsets[i];
440  CHECK(Operand(rax, offset).AddressUsesRegister(rax));
441  CHECK(!Operand(rax, offset).AddressUsesRegister(r8));
442  CHECK(!Operand(rax, offset).AddressUsesRegister(rcx));
443 
444  CHECK(Operand(rax, rax, times_1, offset).AddressUsesRegister(rax));
445  CHECK(!Operand(rax, rax, times_1, offset).AddressUsesRegister(r8));
446  CHECK(!Operand(rax, rax, times_1, offset).AddressUsesRegister(rcx));
447 
448  CHECK(Operand(rax, rcx, times_1, offset).AddressUsesRegister(rax));
449  CHECK(Operand(rax, rcx, times_1, offset).AddressUsesRegister(rcx));
450  CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(r8));
451  CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(r9));
452  CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(rdx));
453  CHECK(!Operand(rax, rcx, times_1, offset).AddressUsesRegister(rsp));
454 
455  CHECK(Operand(rsp, offset).AddressUsesRegister(rsp));
456  CHECK(!Operand(rsp, offset).AddressUsesRegister(rax));
457  CHECK(!Operand(rsp, offset).AddressUsesRegister(r15));
458 
459  CHECK(Operand(rbp, offset).AddressUsesRegister(rbp));
460  CHECK(!Operand(rbp, offset).AddressUsesRegister(rax));
461  CHECK(!Operand(rbp, offset).AddressUsesRegister(r13));
462 
463  CHECK(Operand(rbp, rax, times_1, offset).AddressUsesRegister(rbp));
464  CHECK(Operand(rbp, rax, times_1, offset).AddressUsesRegister(rax));
465  CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(rcx));
466  CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(r13));
467  CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(r8));
468  CHECK(!Operand(rbp, rax, times_1, offset).AddressUsesRegister(rsp));
469 
470  CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rsp));
471  CHECK(Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rbp));
472  CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(rax));
473  CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r15));
474  CHECK(!Operand(rsp, rbp, times_1, offset).AddressUsesRegister(r13));
475  }
476 }
477 
478 
479 TEST(AssemblerX64LabelChaining) {
480  // Test chaining of label usages within instructions (issue 1644).
483  Assembler assm(CcTest::i_isolate(), NULL, 0);
484 
485  Label target;
486  __ j(equal, &target);
487  __ j(not_equal, &target);
488  __ bind(&target);
489  __ nop();
490 }
491 
492 
493 TEST(AssemblerMultiByteNop) {
496  byte buffer[1024];
497  Isolate* isolate = CcTest::i_isolate();
498  Assembler assm(isolate, buffer, sizeof(buffer));
499  __ pushq(rbx);
500  __ pushq(rcx);
501  __ pushq(rdx);
502  __ pushq(rdi);
503  __ pushq(rsi);
504  __ movq(rax, Immediate(1));
505  __ movq(rbx, Immediate(2));
506  __ movq(rcx, Immediate(3));
507  __ movq(rdx, Immediate(4));
508  __ movq(rdi, Immediate(5));
509  __ movq(rsi, Immediate(6));
510  for (int i = 0; i < 16; i++) {
511  int before = assm.pc_offset();
512  __ Nop(i);
513  CHECK_EQ(assm.pc_offset() - before, i);
514  }
515 
516  Label fail;
517  __ cmpq(rax, Immediate(1));
518  __ j(not_equal, &fail);
519  __ cmpq(rbx, Immediate(2));
520  __ j(not_equal, &fail);
521  __ cmpq(rcx, Immediate(3));
522  __ j(not_equal, &fail);
523  __ cmpq(rdx, Immediate(4));
524  __ j(not_equal, &fail);
525  __ cmpq(rdi, Immediate(5));
526  __ j(not_equal, &fail);
527  __ cmpq(rsi, Immediate(6));
528  __ j(not_equal, &fail);
529  __ movq(rax, Immediate(42));
530  __ popq(rsi);
531  __ popq(rdi);
532  __ popq(rdx);
533  __ popq(rcx);
534  __ popq(rbx);
535  __ ret(0);
536  __ bind(&fail);
537  __ movq(rax, Immediate(13));
538  __ popq(rsi);
539  __ popq(rdi);
540  __ popq(rdx);
541  __ popq(rcx);
542  __ popq(rbx);
543  __ ret(0);
544 
545  CodeDesc desc;
546  assm.GetCode(&desc);
547  Code* code = Code::cast(isolate->heap()->CreateCode(
548  desc,
550  Handle<Code>())->ToObjectChecked());
551  CHECK(code->IsCode());
552 
553  F0 f = FUNCTION_CAST<F0>(code->entry());
554  int res = f();
555  CHECK_EQ(42, res);
556 }
557 
558 
559 #ifdef __GNUC__
560 #define ELEMENT_COUNT 4
561 
562 void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
564  byte buffer[1024];
565 
566  CHECK(args[0]->IsArray());
568  CHECK_EQ(ELEMENT_COUNT, vec->Length());
569 
570  Isolate* isolate = CcTest::i_isolate();
571  Assembler assm(isolate, buffer, sizeof(buffer));
572 
573  // Remove return address from the stack for fix stack frame alignment.
574  __ popq(rcx);
575 
576  // Store input vector on the stack.
577  for (int i = 0; i < ELEMENT_COUNT; i++) {
578  __ movl(rax, Immediate(vec->Get(i)->Int32Value()));
579  __ shl(rax, Immediate(0x20));
580  __ orq(rax, Immediate(vec->Get(++i)->Int32Value()));
581  __ pushq(rax);
582  }
583 
584  // Read vector into a xmm register.
585  __ xorps(xmm0, xmm0);
586  __ movdqa(xmm0, Operand(rsp, 0));
587  // Create mask and store it in the return register.
588  __ movmskps(rax, xmm0);
589 
590  // Remove unused data from the stack.
591  __ addq(rsp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
592  // Restore return address.
593  __ pushq(rcx);
594 
595  __ ret(0);
596 
597  CodeDesc desc;
598  assm.GetCode(&desc);
599  Code* code = Code::cast(isolate->heap()->CreateCode(
600  desc,
602  Handle<Code>())->ToObjectChecked());
603  CHECK(code->IsCode());
604 
605  F0 f = FUNCTION_CAST<F0>(code->entry());
606  int res = f();
607  args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
608 }
609 
610 
611 TEST(StackAlignmentForSSE2) {
614 
615  v8::Isolate* isolate = CcTest::isolate();
616  v8::HandleScope handle_scope(isolate);
617  v8::Handle<v8::ObjectTemplate> global_template =
618  v8::ObjectTemplate::New(isolate);
619  global_template->Set(v8_str("do_sse2"),
620  v8::FunctionTemplate::New(isolate, DoSSE2));
621 
622  LocalContext env(NULL, global_template);
623  CompileRun(
624  "function foo(vec) {"
625  " return do_sse2(vec);"
626  "}");
627 
628  v8::Local<v8::Object> global_object = env->Global();
630  v8::Local<v8::Function>::Cast(global_object->Get(v8_str("foo")));
631 
632  int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
633  v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
634  for (int i = 0; i < ELEMENT_COUNT; i++) {
635  v8_vec->Set(i, v8_num(vec[i]));
636  }
637 
638  v8::Local<v8::Value> args[] = { v8_vec };
639  v8::Local<v8::Value> result = foo->Call(global_object, 1, args);
640 
641  // The mask should be 0b1000.
642  CHECK_EQ(8, result->Int32Value());
643 }
644 
645 #undef ELEMENT_COUNT
646 #endif // __GNUC__
647 
648 
649 TEST(AssemblerX64Extractps) {
651  if (!CpuFeatures::IsSupported(SSE4_1)) return;
652 
654  byte buffer[256];
655  Isolate* isolate = CcTest::i_isolate();
656  Assembler assm(isolate, buffer, sizeof(buffer));
657  { CpuFeatureScope fscope2(&assm, SSE4_1);
658  __ extractps(rax, xmm0, 0x1);
659  __ ret(0);
660  }
661 
662  CodeDesc desc;
663  assm.GetCode(&desc);
664  Code* code = Code::cast(isolate->heap()->CreateCode(
665  desc,
667  Handle<Code>())->ToObjectChecked());
668  CHECK(code->IsCode());
669 #ifdef OBJECT_PRINT
670  Code::cast(code)->Print();
671 #endif
672 
673  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
674  uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
675  CHECK_EQ(0x12345678, f(uint64_to_double(value1)));
676  uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
677  CHECK_EQ(0x87654321, f(uint64_to_double(value2)));
678 }
679 
680 
681 typedef int (*F6)(float x, float y);
682 TEST(AssemblerX64SSE) {
684 
685  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
686  HandleScope scope(isolate);
687  v8::internal::byte buffer[256];
688  MacroAssembler assm(isolate, buffer, sizeof buffer);
689  {
690  __ shufps(xmm0, xmm0, 0x0); // brocast first argument
691  __ shufps(xmm1, xmm1, 0x0); // brocast second argument
692  __ movaps(xmm2, xmm1);
693  __ addps(xmm2, xmm0);
694  __ mulps(xmm2, xmm1);
695  __ subps(xmm2, xmm0);
696  __ divps(xmm2, xmm1);
697  __ cvttss2si(rax, xmm2);
698  __ ret(0);
699  }
700 
701  CodeDesc desc;
702  assm.GetCode(&desc);
703  Code* code = Code::cast(isolate->heap()->CreateCode(
704  desc,
706  Handle<Code>())->ToObjectChecked());
707  CHECK(code->IsCode());
708 #ifdef OBJECT_PRINT
709  Code::cast(code)->Print();
710 #endif
711 
712  F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
713  CHECK_EQ(2, f(1.0, 2.0));
714 }
715 #undef __
const Register rdx
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
void Fail(const v8::FunctionCallbackInfo< v8::Value > &args)
#define CHECK_EQ(expected, value)
Definition: checks.h:252
Local< Value > Call(Handle< Value > recv, int argc, Handle< Value > argv[])
Definition: api.cc:3996
const Register r11
Local< Value > Get(Handle< Value > key)
Definition: api.cc:3139
const Register rbp
V8_INLINE ReturnValue< T > GetReturnValue() const
Definition: v8.h:6067
const Register rsi
int int32_t
Definition: unicode.cc:47
static const int kMinimalBufferSize
Definition: assembler.h:89
static bool IsSupported(CpuFeature f)
Definition: assembler-arm.h:68
static Local< Integer > New(Isolate *isolate, int32_t value)
Definition: api.cc:6233
#define CHECK(condition)
Definition: checks.h:75
void Set(Handle< String > name, Handle< Data > value, PropertyAttribute attributes=None)
Definition: api.cc:841
int(* F1)(int64_t x)
static Code * cast(Object *obj)
int foo
uint8_t byte
Definition: globals.h:185
static Local< ObjectTemplate > New()
Definition: api.cc:1286
const XMMRegister xmm1
void GetCode(CodeDesc *desc)
const Register r9
const Register rbx
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >(), int length=0)
Definition: api.cc:942
const Register rsp
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
double uint64_to_double(uint64_t d64)
Definition: double.h:38
int(* F2)(int64_t x, int64_t y)
static i::Isolate * i_isolate()
Definition: cctest.h:102
const Register rax
const Register r13
const Register rdi
#define V8_2PART_UINT64_C(a, b)
Definition: globals.h:226
Definition: v8.h:123
int64_t(* F4)(int64_t *x, int64_t *y)
static Local< Array > New(Isolate *isolate, int length=0)
Definition: api.cc:5786
static V8_INLINE Local< T > Cast(Local< S > that)
Definition: v8.h:372
MUST_USE_RESULT MaybeObject * CreateCode(const CodeDesc &desc, Code::Flags flags, Handle< Object > self_reference, bool immovable=false, bool crankshafted=false, int prologue_offset=Code::kPrologueOffsetNotSet)
Definition: heap.cc:4119
#define __
static void InitializeVM()
Definition: cctest.h:116
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, StubType type=NORMAL, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:4601
static void * Allocate(const size_t requested, size_t *allocated, bool is_executable)
int64_t(* F5)(int64_t x)
const Register r8
const Register rcx
void USE(T)
Definition: globals.h:341
static int ActivationFrameAlignment()
int(* F6)(float x, float y)
uint32_t Length() const
Definition: api.cc:5800
const XMMRegister xmm2
int(* F3)(double x)
Definition: v8.h:124
const Register r15
bool Set(Handle< Value > key, Handle< Value > value, PropertyAttribute attribs=None)
Definition: api.cc:3044
static v8::Isolate * isolate()
Definition: cctest.h:96
const XMMRegister xmm0
F0Type * F0