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-disasm-x64.cc
Go to the documentation of this file.
1 // Copyright 2011 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 "debug.h"
33 #include "disasm.h"
34 #include "disassembler.h"
35 #include "macro-assembler.h"
36 #include "serialize.h"
37 #include "stub-cache.h"
38 #include "cctest.h"
39 
40 using namespace v8::internal;
41 
42 
43 #define __ assm.
44 
45 
46 static void DummyStaticFunction(Object* result) {
47 }
48 
49 
50 TEST(DisasmX64) {
52  Isolate* isolate = CcTest::i_isolate();
53  HandleScope scope(isolate);
54  v8::internal::byte buffer[2048];
55  Assembler assm(isolate, buffer, sizeof buffer);
56  DummyStaticFunction(NULL); // just bloody use it (DELETE; debugging)
57 
58  // Short immediate instructions
59  __ addq(rax, Immediate(12345678));
60  __ orq(rax, Immediate(12345678));
61  __ subq(rax, Immediate(12345678));
62  __ xorq(rax, Immediate(12345678));
63  __ andq(rax, Immediate(12345678));
64 
65  // ---- This one caused crash
66  __ movq(rbx, Operand(rsp, rcx, times_2, 0)); // [rsp+rcx*4]
67 
68  // ---- All instructions that I can think of
69  __ addq(rdx, rbx);
70  __ addq(rdx, Operand(rbx, 0));
71  __ addq(rdx, Operand(rbx, 16));
72  __ addq(rdx, Operand(rbx, 1999));
73  __ addq(rdx, Operand(rbx, -4));
74  __ addq(rdx, Operand(rbx, -1999));
75  __ addq(rdx, Operand(rsp, 0));
76  __ addq(rdx, Operand(rsp, 16));
77  __ addq(rdx, Operand(rsp, 1999));
78  __ addq(rdx, Operand(rsp, -4));
79  __ addq(rdx, Operand(rsp, -1999));
80  __ nop();
81  __ addq(rsi, Operand(rcx, times_4, 0));
82  __ addq(rsi, Operand(rcx, times_4, 24));
83  __ addq(rsi, Operand(rcx, times_4, -4));
84  __ addq(rsi, Operand(rcx, times_4, -1999));
85  __ nop();
86  __ addq(rdi, Operand(rbp, rcx, times_4, 0));
87  __ addq(rdi, Operand(rbp, rcx, times_4, 12));
88  __ addq(rdi, Operand(rbp, rcx, times_4, -8));
89  __ addq(rdi, Operand(rbp, rcx, times_4, -3999));
90  __ addq(Operand(rbp, rcx, times_4, 12), Immediate(12));
91 
92  __ nop();
93  __ addq(rbx, Immediate(12));
94  __ nop();
95  __ nop();
96  __ andq(rdx, Immediate(3));
97  __ andq(rdx, Operand(rsp, 4));
98  __ cmpq(rdx, Immediate(3));
99  __ cmpq(rdx, Operand(rsp, 4));
100  __ cmpq(Operand(rbp, rcx, times_4, 0), Immediate(1000));
101  __ cmpb(rbx, Operand(rbp, rcx, times_2, 0));
102  __ cmpb(Operand(rbp, rcx, times_2, 0), rbx);
103  __ orq(rdx, Immediate(3));
104  __ xorq(rdx, Immediate(3));
105  __ nop();
106  __ cpuid();
107  __ movsxbq(rdx, Operand(rcx, 0));
108  __ movsxwq(rdx, Operand(rcx, 0));
109  __ movzxbl(rdx, Operand(rcx, 0));
110  __ movzxwl(rdx, Operand(rcx, 0));
111  __ movzxbq(rdx, Operand(rcx, 0));
112  __ movzxwq(rdx, Operand(rcx, 0));
113 
114  __ nop();
115  __ imulq(rdx, rcx);
116  __ shld(rdx, rcx);
117  __ shrd(rdx, rcx);
118  __ bts(Operand(rdx, 0), rcx);
119  __ bts(Operand(rbx, rcx, times_4, 0), rcx);
120  __ nop();
121  __ pushq(Immediate(12));
122  __ pushq(Immediate(23456));
123  __ pushq(rcx);
124  __ pushq(rsi);
126  __ pushq(Operand(rbx, rcx, times_4, 0));
127  __ pushq(Operand(rbx, rcx, times_4, 0));
128  __ pushq(Operand(rbx, rcx, times_4, 10000));
129  __ popq(rdx);
130  __ popq(rax);
131  __ popq(Operand(rbx, rcx, times_4, 0));
132  __ nop();
133 
134  __ addq(rdx, Operand(rsp, 16));
135  __ addq(rdx, rcx);
136  __ movb(rdx, Operand(rcx, 0));
137  __ movb(rcx, Immediate(6));
138  __ movb(Operand(rsp, 16), rdx);
139  __ movw(Operand(rsp, 16), rdx);
140  __ nop();
141  __ movsxwq(rdx, Operand(rsp, 12));
142  __ movsxbq(rdx, Operand(rsp, 12));
143  __ movsxlq(rdx, Operand(rsp, 12));
144  __ movzxwq(rdx, Operand(rsp, 12));
145  __ movzxbq(rdx, Operand(rsp, 12));
146  __ nop();
147  __ movq(rdx, Immediate(1234567));
148  __ movq(rdx, Operand(rsp, 12));
149  __ movq(Operand(rbx, rcx, times_4, 10000), Immediate(12345));
150  __ movq(Operand(rbx, rcx, times_4, 10000), rdx);
151  __ nop();
152  __ decb(rdx);
153  __ decb(Operand(rax, 10));
154  __ decb(Operand(rbx, rcx, times_4, 10000));
155  __ decq(rdx);
156  __ cdq();
157 
158  __ nop();
159  __ idivq(rdx);
160  __ mul(rdx);
161  __ negq(rdx);
162  __ notq(rdx);
163  __ testq(Operand(rbx, rcx, times_4, 10000), rdx);
164 
165  __ imulq(rdx, Operand(rbx, rcx, times_4, 10000));
166  __ imulq(rdx, rcx, Immediate(12));
167  __ imulq(rdx, rcx, Immediate(1000));
168 
169  __ incq(rdx);
170  __ incq(Operand(rbx, rcx, times_4, 10000));
171  __ pushq(Operand(rbx, rcx, times_4, 10000));
172  __ popq(Operand(rbx, rcx, times_4, 10000));
173  // TODO(mstarzinger): The following is protected.
174  // __ jmp(Operand(rbx, rcx, times_4, 10000));
175 
176  __ leaq(rdx, Operand(rbx, rcx, times_4, 10000));
177  __ orq(rdx, Immediate(12345));
178  __ orq(rdx, Operand(rbx, rcx, times_4, 10000));
179 
180  __ nop();
181 
182  __ rcl(rdx, Immediate(1));
183  __ rcl(rdx, Immediate(7));
184  __ rcr(rdx, Immediate(1));
185  __ rcr(rdx, Immediate(7));
186  __ sar(rdx, Immediate(1));
187  __ sar(rdx, Immediate(6));
188  __ sar_cl(rdx);
189  __ sbbq(rdx, rbx);
190  __ shld(rdx, rbx);
191  __ shl(rdx, Immediate(1));
192  __ shl(rdx, Immediate(6));
193  __ shl_cl(rdx);
194  __ shrd(rdx, rbx);
195  __ shr(rdx, Immediate(1));
196  __ shr(rdx, Immediate(7));
197  __ shr_cl(rdx);
198 
199 
200  // Immediates
201 
202  __ addq(rbx, Immediate(12));
203  __ addq(Operand(rdx, rcx, times_4, 10000), Immediate(12));
204 
205  __ andq(rbx, Immediate(12345));
206 
207  __ cmpq(rbx, Immediate(12345));
208  __ cmpq(rbx, Immediate(12));
209  __ cmpq(Operand(rdx, rcx, times_4, 10000), Immediate(12));
210  __ cmpb(rax, Immediate(100));
211 
212  __ orq(rbx, Immediate(12345));
213 
214  __ subq(rbx, Immediate(12));
215  __ subq(Operand(rdx, rcx, times_4, 10000), Immediate(12));
216 
217  __ xorq(rbx, Immediate(12345));
218 
219  __ imulq(rdx, rcx, Immediate(12));
220  __ imulq(rdx, rcx, Immediate(1000));
221 
222  __ cld();
223 
224  __ subq(rdx, Operand(rbx, rcx, times_4, 10000));
225  __ subq(rdx, rbx);
226 
227  __ testq(rdx, Immediate(12345));
228  __ testq(Operand(rbx, rcx, times_8, 10000), rdx);
229  __ testb(Operand(rcx, rbx, times_2, 1000), rdx);
230  __ testb(Operand(rax, -20), Immediate(0x9A));
231  __ nop();
232 
233  __ xorq(rdx, Immediate(12345));
234  __ xorq(rdx, Operand(rbx, rcx, times_8, 10000));
235  __ bts(Operand(rbx, rcx, times_8, 10000), rdx);
236  __ hlt();
237  __ int3();
238  __ ret(0);
239  __ ret(8);
240 
241  // Calls
242 
243  Label L1, L2;
244  __ bind(&L1);
245  __ nop();
246  __ call(&L1);
247  __ call(&L2);
248  __ nop();
249  __ bind(&L2);
250  // TODO(mstarzinger): The following is protected.
251  // __ call(Operand(rbx, rcx, times_4, 10000));
252  __ nop();
254  __ call(ic, RelocInfo::CODE_TARGET);
255  __ nop();
256  __ nop();
257 
258  __ jmp(&L1);
259  // TODO(mstarzinger): The following is protected.
260  // __ jmp(Operand(rbx, rcx, times_4, 10000));
261 #ifdef ENABLE_DEBUGGER_SUPPORT
262  ExternalReference after_break_target =
263  ExternalReference(Debug_Address::AfterBreakTarget(), isolate);
264  USE(after_break_target);
265 #endif // ENABLE_DEBUGGER_SUPPORT
266  __ jmp(ic, RelocInfo::CODE_TARGET);
267  __ nop();
268 
269 
270  Label Ljcc;
271  __ nop();
272  // long jumps
273  __ j(overflow, &Ljcc);
274  __ j(no_overflow, &Ljcc);
275  __ j(below, &Ljcc);
276  __ j(above_equal, &Ljcc);
277  __ j(equal, &Ljcc);
278  __ j(not_equal, &Ljcc);
279  __ j(below_equal, &Ljcc);
280  __ j(above, &Ljcc);
281  __ j(sign, &Ljcc);
282  __ j(not_sign, &Ljcc);
283  __ j(parity_even, &Ljcc);
284  __ j(parity_odd, &Ljcc);
285  __ j(less, &Ljcc);
286  __ j(greater_equal, &Ljcc);
287  __ j(less_equal, &Ljcc);
288  __ j(greater, &Ljcc);
289  __ nop();
290  __ bind(&Ljcc);
291  // short jumps
292  __ j(overflow, &Ljcc);
293  __ j(no_overflow, &Ljcc);
294  __ j(below, &Ljcc);
295  __ j(above_equal, &Ljcc);
296  __ j(equal, &Ljcc);
297  __ j(not_equal, &Ljcc);
298  __ j(below_equal, &Ljcc);
299  __ j(above, &Ljcc);
300  __ j(sign, &Ljcc);
301  __ j(not_sign, &Ljcc);
302  __ j(parity_even, &Ljcc);
303  __ j(parity_odd, &Ljcc);
304  __ j(less, &Ljcc);
305  __ j(greater_equal, &Ljcc);
306  __ j(less_equal, &Ljcc);
307  __ j(greater, &Ljcc);
308 
309  // 0xD9 instructions
310  __ nop();
311 
312  __ fld(1);
313  __ fld1();
314  __ fldz();
315  __ fldpi();
316  __ fabs();
317  __ fchs();
318  __ fprem();
319  __ fprem1();
320  __ fincstp();
321  __ ftst();
322  __ fxch(3);
323  __ fld_s(Operand(rbx, rcx, times_4, 10000));
324  __ fstp_s(Operand(rbx, rcx, times_4, 10000));
325  __ ffree(3);
326  __ fld_d(Operand(rbx, rcx, times_4, 10000));
327  __ fstp_d(Operand(rbx, rcx, times_4, 10000));
328  __ nop();
329 
330  __ fild_s(Operand(rbx, rcx, times_4, 10000));
331  __ fistp_s(Operand(rbx, rcx, times_4, 10000));
332  __ fild_d(Operand(rbx, rcx, times_4, 10000));
333  __ fistp_d(Operand(rbx, rcx, times_4, 10000));
334  __ fnstsw_ax();
335  __ nop();
336  __ fadd(3);
337  __ fsub(3);
338  __ fmul(3);
339  __ fdiv(3);
340 
341  __ faddp(3);
342  __ fsubp(3);
343  __ fmulp(3);
344  __ fdivp(3);
345  __ fcompp();
346  __ fwait();
347  __ frndint();
348  __ fninit();
349  __ nop();
350 
351  // SSE instruction
352  {
353  // Move operation
354  __ cvttss2si(rdx, Operand(rbx, rcx, times_4, 10000));
355  __ cvttss2si(rdx, xmm1);
356  __ movaps(xmm0, xmm1);
357 
358  // logic operation
359  __ andps(xmm0, xmm1);
360  __ andps(xmm0, Operand(rbx, rcx, times_4, 10000));
361  __ orps(xmm0, xmm1);
362  __ orps(xmm0, Operand(rbx, rcx, times_4, 10000));
363  __ xorps(xmm0, xmm1);
364  __ xorps(xmm0, Operand(rbx, rcx, times_4, 10000));
365 
366  // Arithmetic operation
367  __ addps(xmm1, xmm0);
368  __ addps(xmm1, Operand(rbx, rcx, times_4, 10000));
369  __ subps(xmm1, xmm0);
370  __ subps(xmm1, Operand(rbx, rcx, times_4, 10000));
371  __ mulps(xmm1, xmm0);
372  __ mulps(xmm1, Operand(rbx, rcx, times_4, 10000));
373  __ divps(xmm1, xmm0);
374  __ divps(xmm1, Operand(rbx, rcx, times_4, 10000));
375  }
376  // SSE 2 instructions
377  {
378  __ cvttsd2si(rdx, Operand(rbx, rcx, times_4, 10000));
379  __ cvttsd2si(rdx, xmm1);
380  __ cvttsd2siq(rdx, xmm1);
381  __ movsd(xmm1, Operand(rbx, rcx, times_4, 10000));
382  __ movsd(Operand(rbx, rcx, times_4, 10000), xmm1);
383  // 128 bit move instructions.
384  __ movdqa(xmm0, Operand(rbx, rcx, times_4, 10000));
385  __ movdqa(Operand(rbx, rcx, times_4, 10000), xmm0);
386 
387  __ addsd(xmm1, xmm0);
388  __ mulsd(xmm1, xmm0);
389  __ subsd(xmm1, xmm0);
390  __ divsd(xmm1, xmm0);
391  __ ucomisd(xmm0, xmm1);
392 
393  __ andpd(xmm0, xmm1);
394  }
395 
396  // cmov.
397  {
398  __ cmovq(overflow, rax, Operand(rax, 0));
399  __ cmovq(no_overflow, rax, Operand(rax, 1));
400  __ cmovq(below, rax, Operand(rax, 2));
401  __ cmovq(above_equal, rax, Operand(rax, 3));
402  __ cmovq(equal, rax, Operand(rbx, 0));
403  __ cmovq(not_equal, rax, Operand(rbx, 1));
404  __ cmovq(below_equal, rax, Operand(rbx, 2));
405  __ cmovq(above, rax, Operand(rbx, 3));
406  __ cmovq(sign, rax, Operand(rcx, 0));
407  __ cmovq(not_sign, rax, Operand(rcx, 1));
408  __ cmovq(parity_even, rax, Operand(rcx, 2));
409  __ cmovq(parity_odd, rax, Operand(rcx, 3));
410  __ cmovq(less, rax, Operand(rdx, 0));
411  __ cmovq(greater_equal, rax, Operand(rdx, 1));
412  __ cmovq(less_equal, rax, Operand(rdx, 2));
413  __ cmovq(greater, rax, Operand(rdx, 3));
414  }
415 
416  {
418  CpuFeatureScope scope(&assm, SSE4_1);
419  __ extractps(rax, xmm1, 0);
420  }
421  }
422 
423  // Nop instructions
424  for (int i = 0; i < 16; i++) {
425  __ Nop(i);
426  }
427 
428  __ ret(0);
429 
430  CodeDesc desc;
431  assm.GetCode(&desc);
433  desc,
435  Handle<Code>())->ToObjectChecked();
436  CHECK(code->IsCode());
437 #ifdef OBJECT_PRINT
438  Code::cast(code)->Print();
439  byte* begin = Code::cast(code)->instruction_start();
440  byte* end = begin + Code::cast(code)->instruction_size();
441  disasm::Disassembler::Disassemble(stdout, begin, end);
442 #endif
443 }
444 
445 #undef __
#define __
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
static void Disassemble(FILE *f, byte *begin, byte *end)
const Register rbp
const Register rsi
static bool IsSupported(CpuFeature f)
Definition: assembler-arm.h:68
static i::Heap * heap()
Definition: cctest.h:106
#define CHECK(condition)
Definition: checks.h:75
static Handle< Code > initialize_stub(Isolate *isolate, ExtraICState extra_state)
Definition: ic.cc:782
static Code * cast(Object *obj)
uint8_t byte
Definition: globals.h:185
const XMMRegister xmm1
byte * instruction_start()
Definition: objects-inl.h:5857
void GetCode(CodeDesc *desc)
const Register rbx
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
static i::Isolate * i_isolate()
Definition: cctest.h:102
const Register rax
const Register rdi
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
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
const Register rcx
void USE(T)
Definition: globals.h:341
const XMMRegister xmm0