Bug 20821: Cache property transitions to speed up object initialization
[WebKit-https.git] / JavaScriptCore / masm / X86Assembler.h
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef X86Assembler_h
27 #define X86Assembler_h
28
29 #if ENABLE(MASM) && PLATFORM(X86)
30
31 #include <wtf/Assertions.h>
32 #include <wtf/AlwaysInline.h>
33 #if HAVE(MMAN)
34 #include <sys/mman.h>
35 #endif
36
37 #include <string.h>
38
39 namespace JSC {
40
41 class JITCodeBuffer {
42 public:
43     JITCodeBuffer(int size)
44         : m_buffer(static_cast<char*>(fastMalloc(size)))
45         , m_size(size)
46         , m_index(0)
47     {
48     }
49
50     ~JITCodeBuffer()
51     {
52         fastFree(m_buffer);
53     }
54
55     void ensureSpace(int space)
56     {
57         if (m_index > m_size - space)
58             growBuffer();
59     }
60
61     void putByteUnchecked(int value)
62     {
63         m_buffer[m_index] = value;
64         m_index++;
65     }
66
67     void putByte(int value)
68     {
69         if (m_index > m_size - 4)
70             growBuffer();
71         putByteUnchecked(value);
72     }
73     
74     void putShortUnchecked(int value)
75     {
76         *(short*)(&m_buffer[m_index]) = value;
77         m_index += 2;
78     }
79
80     void putShort(int value)
81     {
82         if (m_index > m_size - 4)
83             growBuffer();
84         putShortUnchecked(value);
85     }
86     
87     void putIntUnchecked(int value)
88     {
89         *(int*)(&m_buffer[m_index]) = value;
90         m_index += 4;
91     }
92
93     void putInt(int value)
94     {
95         if (m_index > m_size - 4)
96             growBuffer();
97         putIntUnchecked(value);
98     }
99
100     void* getEIP()
101     {
102         return m_buffer + m_index;
103     }
104     
105     void* start()
106     {
107         return m_buffer;
108     }
109     
110     int getOffset()
111     {
112         return m_index;
113     }
114     
115     JITCodeBuffer* reset()
116     {
117         m_index = 0;
118         return this;
119     }
120     
121     void* copy()
122     {
123         if (!m_index)
124             return 0;
125
126         void* result = fastMalloc(m_index);
127
128         if (!result)
129             return 0;
130
131         return memcpy(result, m_buffer, m_index);
132     }
133
134 private:
135     void growBuffer()
136     {
137         m_size += m_size / 2;
138         m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_size));
139     }
140
141     char* m_buffer;
142     int m_size;
143     int m_index;
144 };
145
146 #define MODRM(type, reg, rm) ((type << 6) | (reg << 3) | (rm))
147 #define SIB(type, reg, rm) MODRM(type, reg, rm)
148 #define CAN_SIGN_EXTEND_8_32(value) (value == ((int)(signed char)value))
149
150 namespace X86 {
151     typedef enum {
152         eax,
153         ecx,
154         edx,
155         ebx,
156         esp,
157         ebp,
158         esi,
159         edi,
160
161         noBase = ebp,
162         hasSib = esp,
163         noScale = esp,
164     } RegisterID;
165 }
166
167 class X86Assembler {
168 public:
169     typedef X86::RegisterID RegisterID;
170
171     typedef enum {
172         OP_ADD_EvGv                     = 0x01,
173         OP_ADD_GvEv                     = 0x03,
174         OP_OR_EvGv                      = 0x09,
175         OP_2BYTE_ESCAPE                 = 0x0F,
176         OP_AND_EvGv                     = 0x21,
177         OP_SUB_EvGv                     = 0x29,
178         OP_SUB_GvEv                     = 0x2B,
179         PRE_PREDICT_BRANCH_NOT_TAKEN    = 0x2E,
180         OP_XOR_EvGv                     = 0x31,
181         OP_CMP_EvGv                     = 0x39,
182         OP_PUSH_EAX                     = 0x50,
183         OP_POP_EAX                      = 0x58,
184         PRE_OPERAND_SIZE                = 0x66,
185         OP_IMUL_GvEvIz                  = 0x69,
186         OP_GROUP1_EvIz                  = 0x81,
187         OP_GROUP1_EvIb                  = 0x83,
188         OP_TEST_EvGv                    = 0x85,
189         OP_MOV_EvGv                     = 0x89,
190         OP_MOV_GvEv                     = 0x8B,
191         OP_LEA                          = 0x8D,
192         OP_GROUP1A_Ev                   = 0x8F,
193         OP_CDQ                          = 0x99,
194         OP_GROUP2_EvIb                  = 0xC1,
195         OP_RET                          = 0xC3,
196         OP_GROUP11_EvIz                 = 0xC7,
197         OP_INT3                         = 0xCC,
198         OP_GROUP2_Ev1                   = 0xD1,
199         OP_GROUP2_EvCL                  = 0xD3,
200         OP_CALL_rel32                   = 0xE8,
201         OP_JMP_rel32                    = 0xE9,
202         OP_GROUP3_Ev                    = 0xF7,
203         OP_GROUP3_EvIz                  = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. 
204         OP_GROUP5_Ev                    = 0xFF,
205
206         OP2_JO_rel32    = 0x80,
207         OP2_JB_rel32    = 0x82,
208         OP2_JAE_rel32   = 0x83,
209         OP2_JE_rel32    = 0x84,
210         OP2_JNE_rel32   = 0x85,
211         OP2_JBE_rel32   = 0x86,
212         OP2_JL_rel32    = 0x8C,
213         OP2_JGE_rel32   = 0x8D,
214         OP2_JLE_rel32   = 0x8E,
215         OP2_IMUL_GvEv   = 0xAF,
216         OP2_MOVZX_GvEw  = 0xB7,
217
218         GROUP1_OP_ADD = 0,
219         GROUP1_OP_OR  = 1,
220         GROUP1_OP_AND = 4,
221         GROUP1_OP_SUB = 5,
222         GROUP1_OP_XOR = 6,
223         GROUP1_OP_CMP = 7,
224
225         GROUP1A_OP_POP = 0,
226
227         GROUP2_OP_SHL = 4,
228         GROUP2_OP_SAR = 7,
229
230         GROUP3_OP_TEST = 0,
231         GROUP3_OP_IDIV = 7,
232
233         GROUP5_OP_CALLN = 2,
234         GROUP5_OP_JMPN  = 4,
235         GROUP5_OP_PUSH  = 6,
236
237         GROUP11_MOV = 0,
238     } OpcodeID;
239     
240     static const int MAX_INSTRUCTION_SIZE = 16;
241
242     X86Assembler(JITCodeBuffer* m_buffer)
243         : m_buffer(m_buffer)
244     {
245         m_buffer->reset();
246     }
247
248     void emitInt3()
249     {
250         m_buffer->putByte(OP_INT3);
251     }
252     
253     void pushl_r(RegisterID reg)
254     {
255         m_buffer->putByte(OP_PUSH_EAX + reg);
256     }
257     
258     void pushl_m(int offset, RegisterID base)
259     {
260         m_buffer->putByte(OP_GROUP5_Ev);
261         emitModRm_opm(GROUP5_OP_PUSH, base, offset);
262     }
263     
264     void popl_r(RegisterID reg)
265     {
266         m_buffer->putByte(OP_POP_EAX + reg);
267     }
268
269     void popl_m(int offset, RegisterID base)
270     {
271         m_buffer->putByte(OP_GROUP1A_Ev);
272         emitModRm_opm(GROUP1A_OP_POP, base, offset);
273     }
274     
275     void movl_rr(RegisterID src, RegisterID dst)
276     {
277         m_buffer->putByte(OP_MOV_EvGv);
278         emitModRm_rr(src, dst);
279     }
280     
281     void addl_rr(RegisterID src, RegisterID dst)
282     {
283         m_buffer->putByte(OP_ADD_EvGv);
284         emitModRm_rr(src, dst);
285     }
286
287     void addl_i8r(int imm, RegisterID dst)
288     {
289         m_buffer->putByte(OP_GROUP1_EvIb);
290         emitModRm_opr(GROUP1_OP_ADD, dst);
291         m_buffer->putByte(imm);
292     }
293
294     void addl_i8m(int imm, void* addr)
295     {
296         m_buffer->putByte(OP_GROUP1_EvIb);
297         emitModRm_opm(GROUP1_OP_ADD, addr);
298         m_buffer->putByte(imm);
299     }
300
301     void addl_i32r(int imm, RegisterID dst)
302     {
303         m_buffer->putByte(OP_GROUP1_EvIz);
304         emitModRm_opr(GROUP1_OP_ADD, dst);
305         m_buffer->putInt(imm);
306     }
307
308     void addl_mr(int offset, RegisterID base, RegisterID dst)
309     {
310         m_buffer->putByte(OP_ADD_GvEv);
311         emitModRm_rm(dst, base, offset);
312     }
313
314     void andl_rr(RegisterID src, RegisterID dst)
315     {
316         m_buffer->putByte(OP_AND_EvGv);
317         emitModRm_rr(src, dst);
318     }
319
320     void andl_i32r(int imm, RegisterID dst)
321     {
322         m_buffer->putByte(OP_GROUP1_EvIz);
323         emitModRm_opr(GROUP1_OP_AND, dst);
324         m_buffer->putInt(imm);
325     }
326
327     void cmpl_i8r(int imm, RegisterID dst)
328     {
329         m_buffer->putByte(OP_GROUP1_EvIb);
330         emitModRm_opr(GROUP1_OP_CMP, dst);
331         m_buffer->putByte(imm);
332     }
333
334     void cmpl_rr(RegisterID src, RegisterID dst)
335     {
336         m_buffer->putByte(OP_CMP_EvGv);
337         emitModRm_rr(src, dst);
338     }
339
340     void cmpl_rm(RegisterID src, int offset, RegisterID base)
341     {
342         m_buffer->putByte(OP_CMP_EvGv);
343         emitModRm_rm(src, base, offset);
344     }
345
346     void cmpl_i32r(int imm, RegisterID dst)
347     {
348         m_buffer->putByte(OP_GROUP1_EvIz);
349         emitModRm_opr(GROUP1_OP_CMP, dst);
350         m_buffer->putInt(imm);
351     }
352
353     void cmpl_i32m(int imm, RegisterID dst)
354     {
355         m_buffer->putByte(OP_GROUP1_EvIz);
356         emitModRm_opm(GROUP1_OP_CMP, dst);
357         m_buffer->putInt(imm);
358     }
359
360     void cmpl_i32m(int imm, int offset, RegisterID dst)
361     {
362         m_buffer->putByte(OP_GROUP1_EvIz);
363         emitModRm_opm(GROUP1_OP_CMP, dst, offset);
364         m_buffer->putInt(imm);
365     }
366
367     void cmpl_i32m(int imm, void* addr)
368     {
369         m_buffer->putByte(OP_GROUP1_EvIz);
370         emitModRm_opm(GROUP1_OP_CMP, addr);
371         m_buffer->putInt(imm);
372     }
373
374     void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
375     {
376         m_buffer->putByte(PRE_OPERAND_SIZE);
377         m_buffer->putByte(OP_CMP_EvGv);
378         emitModRm_rmsib(src, base, index, scale);
379     }
380
381     void orl_rr(RegisterID src, RegisterID dst)
382     {
383         m_buffer->putByte(OP_OR_EvGv);
384         emitModRm_rr(src, dst);
385     }
386
387     void orl_i32r(int imm, RegisterID dst)
388     {
389         m_buffer->putByte(OP_GROUP1_EvIb);
390         emitModRm_opr(GROUP1_OP_OR, dst);
391         m_buffer->putByte(imm);
392     }
393
394     void subl_rr(RegisterID src, RegisterID dst)
395     {
396         m_buffer->putByte(OP_SUB_EvGv);
397         emitModRm_rr(src, dst);
398     }
399
400     void subl_i8r(int imm, RegisterID dst)
401     {
402         m_buffer->putByte(OP_GROUP1_EvIb);
403         emitModRm_opr(GROUP1_OP_SUB, dst);
404         m_buffer->putByte(imm);
405     }
406     
407     void subl_i8m(int imm, void* addr)
408     {
409         m_buffer->putByte(OP_GROUP1_EvIb);
410         emitModRm_opm(GROUP1_OP_SUB, addr);
411         m_buffer->putByte(imm);
412     }
413
414     void subl_i32r(int imm, RegisterID dst)
415     {
416         m_buffer->putByte(OP_GROUP1_EvIz);
417         emitModRm_opr(GROUP1_OP_SUB, dst);
418         m_buffer->putInt(imm);
419     }
420
421     void subl_mr(int offset, RegisterID base, RegisterID dst)
422     {
423         m_buffer->putByte(OP_SUB_GvEv);
424         emitModRm_rm(dst, base, offset);
425     }
426
427     void testl_i32r(int imm, RegisterID dst)
428     {
429         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
430         m_buffer->putByteUnchecked(OP_GROUP3_EvIz);
431         emitModRm_opr_Unchecked(GROUP3_OP_TEST, dst);
432         m_buffer->putIntUnchecked(imm);
433     }
434
435     void testl_rr(RegisterID src, RegisterID dst)
436     {
437         m_buffer->putByte(OP_TEST_EvGv);
438         emitModRm_rr(src, dst);
439     }
440     
441     void xorl_i8r(int imm, RegisterID dst)
442     {
443         m_buffer->putByte(OP_GROUP1_EvIb);
444         emitModRm_opr(GROUP1_OP_XOR, dst);
445         m_buffer->putByte(imm);
446     }
447
448     void xorl_rr(RegisterID src, RegisterID dst)
449     {
450         m_buffer->putByte(OP_XOR_EvGv);
451         emitModRm_rr(src, dst);
452     }
453
454     void sarl_i8r(int imm, RegisterID dst)
455     {
456         if (imm == 1) {
457             m_buffer->putByte(OP_GROUP2_Ev1);
458             emitModRm_opr(GROUP2_OP_SAR, dst);
459         } else {
460             m_buffer->putByte(OP_GROUP2_EvIb);
461             emitModRm_opr(GROUP2_OP_SAR, dst);
462             m_buffer->putByte(imm);
463         }
464     }
465
466     void sarl_CLr(RegisterID dst)
467     {
468         m_buffer->putByte(OP_GROUP2_EvCL);
469         emitModRm_opr(GROUP2_OP_SAR, dst);
470     }
471
472     void shl_i8r(int imm, RegisterID dst)
473     {
474         if (imm == 1) {
475             m_buffer->putByte(OP_GROUP2_Ev1);
476             emitModRm_opr(GROUP2_OP_SHL, dst);
477         } else {
478             m_buffer->putByte(OP_GROUP2_EvIb);
479             emitModRm_opr(GROUP2_OP_SHL, dst);
480             m_buffer->putByte(imm);
481         }
482     }
483
484     void shll_CLr(RegisterID dst)
485     {
486         m_buffer->putByte(OP_GROUP2_EvCL);
487         emitModRm_opr(GROUP2_OP_SHL, dst);
488     }
489
490     void imull_rr(RegisterID src, RegisterID dst)
491     {
492         m_buffer->putByte(OP_2BYTE_ESCAPE);
493         m_buffer->putByte(OP2_IMUL_GvEv);
494         emitModRm_rr(dst, src);
495     }
496     
497     void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
498     {
499         m_buffer->putByte(OP_IMUL_GvEvIz);
500         emitModRm_rr(dst, src);
501         m_buffer->putInt(value);
502     }
503
504     void idivl_r(RegisterID dst)
505     {
506         m_buffer->putByte(OP_GROUP3_Ev);
507         emitModRm_opr(GROUP3_OP_IDIV, dst);
508     }
509
510     void cdq()
511     {
512         m_buffer->putByte(OP_CDQ);
513     }
514
515     void movl_mr(RegisterID base, RegisterID dst)
516     {
517         m_buffer->putByte(OP_MOV_GvEv);
518         emitModRm_rm(dst, base);
519     }
520
521     void movl_mr(int offset, RegisterID base, RegisterID dst)
522     {
523         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
524         m_buffer->putByteUnchecked(OP_MOV_GvEv);
525         emitModRm_rm_Unchecked(dst, base, offset);
526     }
527
528     void movl_mr(void* addr, RegisterID dst)
529     {
530         m_buffer->putByte(OP_MOV_GvEv);
531         emitModRm_rm(dst, addr);
532     }
533
534     void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
535     {
536         m_buffer->putByte(OP_MOV_GvEv);
537         emitModRm_rmsib(dst, base, index, scale, offset);
538     }
539
540     void movzwl_mr(int offset, RegisterID base, RegisterID dst)
541     {
542         m_buffer->putByte(OP_2BYTE_ESCAPE);
543         m_buffer->putByte(OP2_MOVZX_GvEw);
544         emitModRm_rm(dst, base, offset);
545     }
546
547     void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
548     {
549         m_buffer->putByte(OP_2BYTE_ESCAPE);
550         m_buffer->putByte(OP2_MOVZX_GvEw);
551         emitModRm_rmsib(dst, base, index, scale);
552     }
553
554     void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
555     {
556         m_buffer->putByte(OP_2BYTE_ESCAPE);
557         m_buffer->putByte(OP2_MOVZX_GvEw);
558         emitModRm_rmsib(dst, base, index, scale, offset);
559     }
560
561     void movl_rm(RegisterID src, RegisterID base)
562     {
563         m_buffer->putByte(OP_MOV_EvGv);
564         emitModRm_rm(src, base);
565     }
566
567     void movl_rm(RegisterID src, int offset, RegisterID base)
568     {
569         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
570         m_buffer->putByteUnchecked(OP_MOV_EvGv);
571         emitModRm_rm_Unchecked(src, base, offset);
572     }
573     
574     void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
575     {
576         m_buffer->putByte(OP_MOV_EvGv);
577         emitModRm_rmsib(src, base, index, scale, offset);
578     }
579     
580     void movl_i32r(int imm, RegisterID dst)
581     {
582         m_buffer->putByte(OP_GROUP11_EvIz);
583         emitModRm_opr(GROUP11_MOV, dst);
584         m_buffer->putInt(imm);
585     }
586
587     void movl_i32m(int imm, int offset, RegisterID base)
588     {
589         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
590         m_buffer->putByteUnchecked(OP_GROUP11_EvIz);
591         emitModRm_opm_Unchecked(GROUP11_MOV, base, offset);
592         m_buffer->putIntUnchecked(imm);
593     }
594
595     void movl_i32m(int imm, void* addr)
596     {
597         m_buffer->putByte(OP_GROUP11_EvIz);
598         emitModRm_opm(GROUP11_MOV, addr);
599         m_buffer->putInt(imm);
600     }
601
602     void leal_mr(int offset, RegisterID base, RegisterID dst)
603     {
604         m_buffer->putByte(OP_LEA);
605         emitModRm_rm(dst, base, offset);
606     }
607
608     void ret()
609     {
610         m_buffer->putByte(OP_RET);
611     }
612     
613     void jmp_r(RegisterID dst)
614     {
615         m_buffer->putByte(OP_GROUP5_Ev);
616         emitModRm_opr(GROUP5_OP_JMPN, dst);
617     }
618     
619     void jmp_m(int offset, RegisterID base)
620     {
621         m_buffer->putByte(OP_GROUP5_Ev);
622         emitModRm_opm(GROUP5_OP_JMPN, base, offset);
623     }
624     
625     void call_r(RegisterID dst)
626     {
627         m_buffer->putByte(OP_GROUP5_Ev);
628         emitModRm_opr(GROUP5_OP_CALLN, dst);
629     }
630
631     // Opaque label types
632     
633     class JmpSrc {
634         friend class X86Assembler;
635     public:
636         JmpSrc()
637             : m_offset(-1)
638         {
639         }
640
641     private:
642         JmpSrc(int offset)
643             : m_offset(offset)
644         {
645         }
646
647         int m_offset;
648     };
649     
650     class JmpDst {
651         friend class X86Assembler;
652     public:
653         JmpDst()
654             : m_offset(-1)
655         {
656         }
657
658     private:
659         JmpDst(int offset)
660             : m_offset(offset)
661         {
662         }
663
664         int m_offset;
665     };
666
667     // FIXME: make this point to a global label, linked later.
668     JmpSrc emitCall()
669     {
670         m_buffer->putByte(OP_CALL_rel32);
671         m_buffer->putInt(0);
672         return JmpSrc(m_buffer->getOffset());
673     }
674     
675     JmpDst label()
676     {
677         return JmpDst(m_buffer->getOffset());
678     }
679     
680     JmpSrc emitUnlinkedJmp()
681     {
682         m_buffer->putByte(OP_JMP_rel32);
683         m_buffer->putInt(0);
684         return JmpSrc(m_buffer->getOffset());
685     }
686     
687     JmpSrc emitUnlinkedJne()
688     {
689         m_buffer->putByte(OP_2BYTE_ESCAPE);
690         m_buffer->putByte(OP2_JNE_rel32);
691         m_buffer->putInt(0);
692         return JmpSrc(m_buffer->getOffset());
693     }
694     
695     JmpSrc emitUnlinkedJe()
696     {
697         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
698         m_buffer->putByteUnchecked(OP_2BYTE_ESCAPE);
699         m_buffer->putByteUnchecked(OP2_JE_rel32);
700         m_buffer->putIntUnchecked(0);
701         return JmpSrc(m_buffer->getOffset());
702     }
703     
704     JmpSrc emitUnlinkedJl()
705     {
706         m_buffer->putByte(OP_2BYTE_ESCAPE);
707         m_buffer->putByte(OP2_JL_rel32);
708         m_buffer->putInt(0);
709         return JmpSrc(m_buffer->getOffset());
710     }
711     
712     JmpSrc emitUnlinkedJb()
713     {
714         m_buffer->putByte(OP_2BYTE_ESCAPE);
715         m_buffer->putByte(OP2_JB_rel32);
716         m_buffer->putInt(0);
717         return JmpSrc(m_buffer->getOffset());
718     }
719     
720     JmpSrc emitUnlinkedJle()
721     {
722         m_buffer->putByte(OP_2BYTE_ESCAPE);
723         m_buffer->putByte(OP2_JLE_rel32);
724         m_buffer->putInt(0);
725         return JmpSrc(m_buffer->getOffset());
726     }
727     
728     JmpSrc emitUnlinkedJbe()
729     {
730         m_buffer->putByte(OP_2BYTE_ESCAPE);
731         m_buffer->putByte(OP2_JBE_rel32);
732         m_buffer->putInt(0);
733         return JmpSrc(m_buffer->getOffset());
734     }
735     
736     JmpSrc emitUnlinkedJge()
737     {
738         m_buffer->putByte(OP_2BYTE_ESCAPE);
739         m_buffer->putByte(OP2_JGE_rel32);
740         m_buffer->putInt(0);
741         return JmpSrc(m_buffer->getOffset());
742     }
743     
744     JmpSrc emitUnlinkedJae()
745     {
746         m_buffer->putByte(OP_2BYTE_ESCAPE);
747         m_buffer->putByte(OP2_JAE_rel32);
748         m_buffer->putInt(0);
749         return JmpSrc(m_buffer->getOffset());
750     }
751     
752     JmpSrc emitUnlinkedJo()
753     {
754         m_buffer->putByte(OP_2BYTE_ESCAPE);
755         m_buffer->putByte(OP2_JO_rel32);
756         m_buffer->putInt(0);
757         return JmpSrc(m_buffer->getOffset());
758     }
759     
760     void emitPredictionNotTaken()
761     {
762         m_buffer->putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
763     }
764     
765     void link(JmpSrc from, JmpDst to)
766     {
767         ASSERT(to.m_offset != -1);
768         ASSERT(from.m_offset != -1);
769         
770         ((int*)(((ptrdiff_t)(m_buffer->start())) + from.m_offset))[-1] = to.m_offset - from.m_offset;
771     }
772     
773     static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address)
774     {
775         ASSERT(useOffset.m_offset != -1);
776         ASSERT(address.m_offset != -1);
777         
778         ((int*)(((ptrdiff_t)code) + useOffset.m_offset))[-1] = ((ptrdiff_t)code) + address.m_offset;
779     }
780     
781     static void link(void* code, JmpSrc from, void* to)
782     {
783         ASSERT(from.m_offset != -1);
784         
785         ((int*)((ptrdiff_t)code + from.m_offset))[-1] = (ptrdiff_t)to - ((ptrdiff_t)code + from.m_offset);
786     }
787     
788     void* getRelocatedAddress(void* code, JmpSrc jump)
789     {
790         return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
791     }
792     
793     void* getRelocatedAddress(void* code, JmpDst jump)
794     {
795         return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
796     }
797     
798     void* copy() 
799     {
800         return m_buffer->copy();
801     }
802
803 #if COMPILER(MSVC)
804     void emitConvertToFastCall()
805     {
806         movl_mr(4, X86::esp, X86::eax);
807         movl_mr(8, X86::esp, X86::edx);
808         movl_mr(12, X86::esp, X86::ecx);
809     }
810
811     void emitRestoreArgumentReference()
812     {
813         movl_rm(X86::esp, 0, X86::esp);
814     }
815 #else
816     void emitConvertToFastCall() {};
817     void emitRestoreArgumentReference() {};
818 #endif
819
820 private:
821     void emitModRm_rr(RegisterID reg, RegisterID rm)
822     {
823         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
824         emitModRm_rr_Unchecked(reg, rm);
825     }
826
827     void emitModRm_rr_Unchecked(RegisterID reg, RegisterID rm)
828     {
829         m_buffer->putByteUnchecked(MODRM(3, reg, rm));
830     }
831
832     void emitModRm_rm(RegisterID reg, void* addr)
833     {
834         m_buffer->putByte(MODRM(0, reg, X86::noBase));
835         m_buffer->putInt((int)addr);
836     }
837
838     void emitModRm_rm(RegisterID reg, RegisterID base)
839     {
840         if (base == X86::esp) {
841             m_buffer->putByte(MODRM(0, reg, X86::hasSib));
842             m_buffer->putByte(SIB(0, X86::noScale, X86::esp));
843         } else
844             m_buffer->putByte(MODRM(0, reg, base));
845     }
846
847     void emitModRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
848     {
849         if (base == X86::esp) {
850             if (CAN_SIGN_EXTEND_8_32(offset)) {
851                 m_buffer->putByteUnchecked(MODRM(1, reg, X86::hasSib));
852                 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
853                 m_buffer->putByteUnchecked(offset);
854             } else {
855                 m_buffer->putByteUnchecked(MODRM(2, reg, X86::hasSib));
856                 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
857                 m_buffer->putIntUnchecked(offset);
858             }
859         } else {
860             if (CAN_SIGN_EXTEND_8_32(offset)) {
861                 m_buffer->putByteUnchecked(MODRM(1, reg, base));
862                 m_buffer->putByteUnchecked(offset);
863             } else {
864                 m_buffer->putByteUnchecked(MODRM(2, reg, base));
865                 m_buffer->putIntUnchecked(offset);
866             }
867         }
868     }
869
870     void emitModRm_rm(RegisterID reg, RegisterID base, int offset)
871     {
872         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
873         emitModRm_rm_Unchecked(reg, base, offset);
874     }
875
876     void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
877     {
878         int shift = 0;
879         while (scale >>= 1)
880             shift++;
881     
882         m_buffer->putByte(MODRM(0, reg, X86::hasSib));
883         m_buffer->putByte(SIB(shift, index, base));
884     }
885
886     void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
887     {
888         int shift = 0;
889         while (scale >>= 1)
890             shift++;
891     
892         if (CAN_SIGN_EXTEND_8_32(offset)) {
893             m_buffer->putByte(MODRM(1, reg, X86::hasSib));
894             m_buffer->putByte(SIB(shift, index, base));
895             m_buffer->putByte(offset);
896         } else {
897             m_buffer->putByte(MODRM(2, reg, X86::hasSib));
898             m_buffer->putByte(SIB(shift, index, base));
899             m_buffer->putInt(offset);
900         }
901     }
902
903     void emitModRm_opr(OpcodeID opcode, RegisterID rm)
904     {
905         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
906         emitModRm_opr_Unchecked(opcode, rm);
907     }
908
909     void emitModRm_opr_Unchecked(OpcodeID opcode, RegisterID rm)
910     {
911         emitModRm_rr_Unchecked(static_cast<RegisterID>(opcode), rm);
912     }
913
914     void emitModRm_opm(OpcodeID opcode, RegisterID base)
915     {
916         emitModRm_rm(static_cast<RegisterID>(opcode), base);
917     }
918
919     void emitModRm_opm_Unchecked(OpcodeID opcode, RegisterID base, int offset)
920     {
921         emitModRm_rm_Unchecked(static_cast<RegisterID>(opcode), base, offset);
922     }
923
924     void emitModRm_opm(OpcodeID opcode, RegisterID base, int offset)
925     {
926         emitModRm_rm(static_cast<RegisterID>(opcode), base, offset);
927     }
928
929     void emitModRm_opm(OpcodeID opcode, void* addr)
930     {
931         emitModRm_rm(static_cast<RegisterID>(opcode), addr);
932     }
933
934     JITCodeBuffer* m_buffer;
935 };
936
937 } // namespace JSC
938
939 #endif // ENABLE(MASM) && PLATFORM(X86)
940
941 #endif // X86Assembler_h