-
Notifications
You must be signed in to change notification settings - Fork 4
/
code.h
477 lines (409 loc) · 13.1 KB
/
code.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
/*
This file is part of shuJIT,
Just In Time compiler for Sun Java Virtual Machine.
Copyright (C) 1998,1999,2000,2001,2002,2003,2005 Kazuyuki Shudo
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id$
*/
#include "config.h"
/*
* ESI: vars
* EDX: cache of stack top
* ECX: cache of stack top
*/
/*
* 5 states of Java stack
*
* state 0:
* ECX: undefined
* EDX: undefined
* state 1:
* ECX: undefined
* EDX: stack top element
* state 2:
* ECX: stack top element
* EDX: stack top-1 element
* state 3:
* EDX: undefined
* ECX: stack top element
* state 4:
* EDX: stack top element
* ECX: stack top-1 element
*/
#define ST0 0
#define ST1 1
#define ST2 2
#define ST3 3
#define ST4 4
#define STANY 5
#define STSTA 5
#define NSTATES 5
// state for next instruction of goto,jsr,ret
#define STATE_AFTER_JUMP ST0
#define STATE_AFTER_JSR ST0
#define STATE_AFTER_RETURN ST0
#define STATE_AFTER_ATHROW ST0
// should be `ST0' because we cannot expect
// the stack has elements enough for other states.
//
// space filled by compiler
//
// constant
#define SLOT_CONST 0x606060
// for exception handler
#define SLOT_BYTEPCOFF 0x626262
#define SLOT_ADDR_EXC 0x707010
// for jump instructions
#define SLOT_ADDR_JP 0x727210
// for *return instructions
#define SLOT_ADDR_FIN 0x747410
//
// utilities
//
#if GCC_VER <= 270
#define PUSH_CONSTSTR(STR) asm("PUSH %0" : : "m" (STR))
#else
#define PUSH_CONSTSTR(STR) \
{\
static char *msg = STR;\
asm("pushl %0" : : "m" (msg) : "esi");\
}
#endif
// This code must not use %esi which is the base of local variables
#if defined(linux)
# if !defined(__GLIBC__) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0))
# define PUSH_STDOUT \
asm("movl _IO_stdout_@GOT(%ebx),%eax\n\t"\
"pushl %eax");
# else
# define PUSH_STDOUT \
asm("movl stdout@GOT(%ebx),%eax\n\t"\
"pushl (%eax)");
# endif // __GLIBC__
#elif defined(__FreeBSD__) || defined(__NetBSD__)
# define PUSH_STDOUT \
asm("movl " SYMBOL(__sF) "@GOT(%ebx),%eax\n\t"\
"leal 88(%eax),%eax\n\t"\
"pushl %eax");
#elif defined(sun) && defined(__svr4__)
# define PUSH_STDOUT \
asm("movl __iob@GOT(%ebx),%eax\n\t"\
"leal 16(%eax),%eax\n\t"\
"pushl %eax");
#endif
#define FFLUSH \
PUSH_STDOUT;\
asm("call " FUNCTION(fflush) "\n\t"\
"addl $4,%esp")
#if 0
#define DEBUG_IN \
asm("pushl %eax\n\tpushl %edx\n\tpushl %ebx\n\tpushl %ecx\n\t"\
"pushl %edi\n\tpushl %esi")
#define DEBUG_OUT \
asm("popl %esi\n\tpopl %edi\n\t"\
"popl %ecx\n\tpopl %ebx\n\tpopl %edx\n\tpopl %eax")
#else
#define DEBUG_IN asm("pusha")
#define DEBUG_OUT asm("popa")
#endif
#define FUNCCALL_IN(STATE) _FUNCCALL_IN(STATE)
#define FUNCCALL_OUT(STATE) _FUNCCALL_OUT(STATE)
#define _FUNCCALL_IN(STATE) FUNCCALL_IN_##STATE
#define _FUNCCALL_OUT(STATE) FUNCCALL_OUT_##STATE
#define FUNCCALL_IN_0
#define FUNCCALL_OUT_0
#define FUNCCALL_IN_1 asm("pushl %edx")
#define FUNCCALL_OUT_1 asm("popl %edx")
#define FUNCCALL_IN_2 asm("pushl %edx\n\tpushl %ecx")
#define FUNCCALL_OUT_2 asm("popl %ecx\n\tpopl %edx")
#define FUNCCALL_IN_3 asm("pushl %ecx")
#define FUNCCALL_OUT_3 asm("popl %ecx")
#define FUNCCALL_IN_4 asm("pushl %ecx\n\tpushl %edx")
#define FUNCCALL_OUT_4 asm("popl %edx\n\tpopl %ecx")
#define STATETO00
#define STATETO10 asm("pushl %edx")
#define STATETO20 asm("pushl %edx\n\tpushl %ecx")
#define STATETO30 asm("pushl %ecx")
#define STATETO40 asm("pushl %ecx\n\tpushl %edx")
#ifndef _WIN32
# define DECL_GLOBAL_FUNC(FUNCNAME_STR) \
asm(".globl " FUNCNAME_STR "\n"\
".type " FUNCNAME_STR ",@function\n"\
FUNCNAME_STR ":");
#else
# define DECL_GLOBAL_FUNC(FUNCNAME_STR) \
asm(".globl " FUNCNAME_STR "\n"\
".def " FUNCNAME_STR ";\n\t"\
".scl 2;\n\t"\
".type 32;\n"\
".enddef\n"\
FUNCNAME_STR ":");
#endif
#define SIGNAL_ERROR_JUMP() \
asm("movl $" STR(SLOT_BYTEPCOFF) ",-4(%ebp)");\
/* bytepcoff = SLOT_BYTEPCOFF */\
asm(".byte 0xe9\n\t.long " STR(SLOT_ADDR_EXC))
#define SIGNAL_ERROR_CORE(EXCID) \
asm("movb $" #EXCID ",%al");\
SIGNAL_ERROR_JUMP()
#define SIGNAL_ERROR0(EXCID) \
asm("xorl %edx,%edx"); /* char *DetailMessage */\
SIGNAL_ERROR_CORE(EXCID)
#define SIGNAL_ERROR1(EXCID, MSG) \
{\
static char *errmsg = MSG;\
asm("movl %0,%%edx" : : "m" (errmsg)); /* char *DetailMessage */\
SIGNAL_ERROR_CORE(EXCID);\
}
#if !defined(NO_NULL_AND_ARRAY_CHECK) && !defined(NULLEXC_BY_SIGNAL)
# define NULL_TEST(REG, LABEL) \
asm("testl " #REG "," #REG "\n\t"\
"jnz " LABEL);\
SIGNAL_ERROR0(EXCID_NullPointerException);\
asm(LABEL ":")
#else
# define NULL_TEST(REG, LABEL)
#endif
/*
* code header
* for each opcode of JVM.
*
* 0xd6 (0x82, 0xd6, 0xf1 is not defined in x86 insn. set)
* 0xe9, opcode(2 byte), initial state(4 bit), last state(4 bit)
*/
#ifdef RUNTIME_DEBUG
#define CODE(OPCODE, LABEL, STATE, NEXTST, THROW_EXC) \
CODE_WITH_DEBUG(OPCODE, LABEL, STATE, NEXTST, THROW_EXC)
#else
#define CODE(OPCODE, LABEL, STATE, NEXTST, THROW_EXC) \
CODE_WITHOUT_DEBUG(OPCODE, LABEL, STATE, NEXTST, THROW_EXC)
#endif
#ifdef RUNTIME_DEBUG
# define CODE_DEBUG(LABEL) /* print %esp */\
asm("pushl %eax\n\t"\
"leal 4(%esp),%eax");\
DEBUG_IN;\
asm("pushl %eax");\
if (runtime_debug) {\
PUSH_CONSTSTR(">" LABEL " %x\n");\
asm("call " FUNCTION(printf) "\n\t"\
"addl $4,%esp");\
FFLUSH;\
}\
asm("addl $4,%esp");\
DEBUG_OUT;\
asm("popl %eax")
#else
# define CODE_DEBUG(LABEL)
#endif // RUNTIME_DEBUG
#define CODE_WITH_DEBUG(OPCODE, LABEL, STATE, NEXTST, THROW_EXC) \
_CODE_WITH_DEBUG(OPCODE, LABEL, STATE, NEXTST, THROW_EXC)
#define _CODE_WITH_DEBUG(OPCODE, LABEL, STATE, NEXTST, THROW_EXC) \
CODE_WITHOUT_DEBUG(OPCODE, LABEL, STATE, NEXTST, THROW_EXC);\
CODE_DEBUG(#LABEL ":" #STATE ">" #NEXTST );
#define CODE_WITHOUT_DEBUG(OPCODE, LABEL, STATE, NEXTST, THROW_EXC) \
_CODE_WITHOUT_DEBUG(OPCODE, LABEL, STATE, NEXTST, THROW_EXC)
#define _CODE_WITHOUT_DEBUG(OPCODE, LABEL, STATE, NEXTST, THROW_EXC) \
asm(".byte 0xd6\n\t"\
".byte 0xe9\n\t"\
".short " #OPCODE "\n\t"\
".byte (" #STATE "<<4)|" #NEXTST "," #THROW_EXC);
#define CODEEND asm(".byte 0xd6,0xd6")
//
// JDK related stuffs
//
#define UNHAND(HANDLE, DST) asm("movl (" #HANDLE ")," #DST)
#define OBJ_MONITOR(HANDLE)
#define OBJ_LENGTH(HANDLE, DST) \
asm("movl 4(" #HANDLE ")," #DST "\n\t"\
"shrl $5," #DST)
#define OBJ_METHODTABLE(HANDLE, DST) \
asm("movl 4(" #HANDLE ")," #DST)
#define OBJ_ARRAY_METHODTABLE(HANDLE, DST, LABEL) \
/* assumption: T_NORMAL_OBJECT == 0 */\
asm("movl 4(" #HANDLE ")," #DST "\n\t"\
"testl $0x1f," #DST "\n\t"\
"jz " LABEL "_mtdone");\
asm("movl classJavaLangObject@GOT(%ebx),%edi\n\t"\
"movl (%edi)," #DST);\
CB_METHODTABLE(DST, DST);\
asm(LABEL "_mtdone:")
// destroy %edi, DST can't be %edi
#define OBJ_ARRAY_METHODTABLE_TO_EAX(HANDLE, LABEL) \
/* assumption: T_NORMAL_OBJECT == 0 */\
asm("movl 4(" #HANDLE "),%eax\n\t"\
"testb $0x1f,%al\n\t"\
"jz " LABEL "_mtdone");\
asm("movl classJavaLangObject@GOT(%ebx),%edi\n\t"\
"movl (%edi),%eax");\
CB_METHODTABLE(%eax, %eax);\
asm(LABEL "_mtdone:")
#define MT_SLOT(MTBL, SLOT, DST) \
asm("movl 4(" #MTBL "," #SLOT ",4)," #DST)
#define MT_CLASSDESCRIPTOR(MTBL, DST) \
asm("movl (" #MTBL ")," #DST)
#define UOBJ_GETSLOT(OBJ, SLOT, DST) \
asm("movl (" #OBJ "," #SLOT ",4)," #DST)
#define OBJ_GETSLOT(HANDLE, SLOT, DST) \
UNHAND(HANDLE, %edi);\
UOBJ_GETSLOT(%edi, SLOT, DST)
#define UOBJ_GETSLOT2(OBJ, SLOT, DST_LOW, DST_HIGH) \
asm("leal (" #OBJ "," #SLOT ",4),%edi\n\t"\
"movl (%edi)," #DST_LOW "\n\t"\
"movl 4(%edi)," #DST_HIGH)
#define OBJ_GETSLOT2(HANDLE, SLOT, DST_LOW, DST_HIGH) \
UNHAND(HANDLE, %edi);\
UOBJ_GETSLOT2(%edi, SLOT, DST_LOW, DST_HIGH)
#define UOBJ_SETSLOT(OBJ, SLOT, VAL) \
asm("movl " #VAL ",(" #OBJ "," #SLOT ",4)")
#define OBJ_SETSLOT(HANDLE, SLOT, VAL) \
UNHAND(HANDLE, %edi);\
UOBJ_SETSLOT(%edi, SLOT, VAL)
#define UOBJ_SETSLOT2(OBJ, SLOT, VAL_LOW, VAL_HIGH) \
asm("leal (" #OBJ "," #SLOT ",4),%edi\n\t"\
"movl " #VAL_LOW ",(%edi)\n\t"\
"movl " #VAL_HIGH ",4(%edi)")
#define OBJ_SETSLOT2(HANDLE, SLOT, VAL_LOW, VAL_HIGH) \
UNHAND(HANDLE, %edi);\
UOBJ_SETSLOT2(%edi, SLOT, VAL_LOW, VAL_HIGH)
#define CB_NAME(CLAZZ, DST) \
asm("movl (" #CLAZZ "),%edi\n\t"\
"movl 4(%edi)," #DST)
#define CB_LOADER(CLAZZ, DST) \
asm("movl (" #CLAZZ "),%edi\n\t"\
"movl 24(%edi)," #DST)
#if JDK_VER >= 12
#define CB_ACCESS(CLAZZ, DST) \
asm("movl (" #CLAZZ "),%edi\n\t"\
"movzwl 84(%edi)," #DST)
#else
#define CB_ACCESS(CLAZZ, DST) \
asm("movl (" #CLAZZ "),%edi\n\t"\
"movzwl 86(%edi)," #DST)
#endif // JDK_VER
#define CB_METHODTABLE(CLAZZ, DST) \
asm("movl (" #CLAZZ "),%edi\n\t"\
"movl 48(%edi)," #DST)
#if JDK_VER >= 12
#define EE_CURRENTFRAME(EE) "8(" #EE ")"
#define EE_EXCEPTIONKIND(EE) "16(" #EE ")"
#define EE_EXCEPTION(EE) "20(" #EE ")"
#else
#define EE_CURRENTFRAME(EE) "4(" #EE ")"
#define EE_EXCEPTIONKIND(EE) "12(" #EE ")"
#define EE_EXCEPTION(EE) "16(" #EE ")"
#endif // JDK_VER
#if JDK_VER >= 12
# define ALLOC_ARRAY(TYPE, LEN) \
asm("pushl " #LEN "\n\t"\
"pushl " TYPE);\
asm("pushl %0" : : "m" (ee));\
asm("call " FUNCTION(allocArray) "\n\t"\
"addl $12,%esp");
#else
# define ALLOC_ARRAY(TYPE, LEN) \
asm("pushl " #LEN "\n\t"\
"pushl " TYPE "\n\t"\
"call " FUNCTION(ArrayAlloc) "\n\t"\
"addl $8,%esp");
#endif
#ifdef METAVM
# define EE_EXCEPTIONKIND_EAX(EE) \
asm("movsbl " EE_EXCEPTIONKIND(EE) ",%eax")
#else
# define EE_EXCEPTIONKIND_EAX(EE) \
asm("movl " EE_EXCEPTIONKIND(EE) ",%eax")
// This is rather desirable, but not compatible with MetaVM.
#endif // METAVM
#define FRAME_RETURNPC(FRAME) "4(" #FRAME ")"
#define FRAME_OPTOP(FRAME) "8(" #FRAME ")"
#define FRAME_VARS(FRAME) "12(" #FRAME ")"
// override previous definition in interpreter.h of JDK 1.2
#ifdef FRAME_PREV
#undef FRAME_PREV
#endif
#define FRAME_PREV(FRAME) "16(" #FRAME ")"
#define FRAME_LASTPC(FRAME) "24(" #FRAME ")"
#define FRAME_CURRENTMETHOD(FRAME) "28(" #FRAME ")"
#define FRAME_MONITOR(FRAME) "32(" #FRAME ")"
#define FRAME_OSTACK(FRAME) "40(" #FRAME ")"
#define METHOD_CLAZZ(MB) "(" #MB ")"
#define METHOD_SIGNATURE(MB) "4(" #MB ")"
#define METHOD_NAME(MB) "8(" #MB ")"
#define METHOD_CODE(MB) "24(" #MB ")"
#if JDK_VER >= 12
#define METHOD_ACCESS(MB) "12(" #MB ")"
#define METHOD_ACCESS_HIGH(MB) "13(" #MB ")"
#define METHOD_FB_U_OFFSET(MB) "16(" #MB ")"
#define METHOD_INVOKER(MB) "52(" #MB ")"
#define METHOD_NLOCALS(MB, DST) asm("movzwl 60(" #MB ")," #DST)
#else
#define METHOD_ACCESS(MB) "16(" #MB ")"
#define METHOD_ACCESS_HIGH(MB) "17(" #MB ")"
#define METHOD_FB_U_OFFSET(MB) "20(" #MB ")"
#define METHOD_INVOKER(MB) "56(" #MB ")"
#define METHOD_NLOCALS(MB, DST) asm("movzwl 64(" #MB ")," #DST)
#endif // JDK_VER
#define METHOD_COMPILEDCODE(MB) "68(" #MB ")"
#define METHOD_COMPILEDCODEINFO(MB) "72(" #MB ")"
#if JDK_VER >= 12
#define CATCHFRAME_COMPILED_CATCHFRAME(CF) "8(" #CF ")"
#define CATCHFRAME_COMPILED_STATE(CF) "14(" #CF ")"
#else
#define CATCHFRAME_COMPILED_CATCHFRAME(CF) "12(" #CF ")"
#define CATCHFRAME_COMPILED_STATE(CF) "18(" #CF ")"
#endif // JDK_VER
#ifdef METAVM
//
// MetaVM related stuff
//
#if JDK_VER >= 12
#define EE_REMOTE_FLAG(EE) "17(" #EE ")"
// ((char *)ee->exceptionKind) + 1
# define EE_REMOTE_ADDR(EE) "120(" #EE ")"
// ee->RESERVED3
//# define EE_REMOTE_ADDR(EE) "20(" #EE ")"
// ee->exception.exc
#else // JDK_VER
#define EE_REMOTE_FLAG(EE) "61(" #EE ")"
// ee->alloc_cache.cache_pad[0]
#define EE_REMOTE_ADDR(EE) "16(" #EE ")"
// ee->exception.exc
#endif // JDK_VER
#define JUMP_IF_NOT_REMOTE(LABEL) \
asm("movl %0,%%edi" : : "m" (ee));\
asm("movsbl " EE_REMOTE_FLAG(%edi) ",%edi");\
asm("testl %edi,%edi\n\t"\
"jz " LABEL)
// break %edi
#define METHODTABLE_OF_PROXY(DST) \
asm("movl " SYMBOL(proxy_methodtable) "@GOT(%ebx)," #DST "\n\t"\
"movl (" #DST ")," #DST)
// break no registers
#define JUMP_IF_NOT_PROXY(HANDLE_REG /* must not be %edi */, LABEL) \
METHODTABLE_OF_PROXY(%edi);\
asm("cmpl 4(" #HANDLE_REG "),%edi\n\t"\
"jnz " LABEL)
// break %edi
#define PROXY_CLAZZ(HANDLE, DST) \
UNHAND(HANDLE, DST);\
asm("movl 8(" #DST ")," #DST);
// this constant depends on the definition of `Proxy' class !
#define JUMP_IF_EXC_HASNT_OCCURRED(EE, LABEL) \
asm("movsbl " EE_EXCEPTIONKIND(EE) ",%edi");\
asm("testl %edi,%edi\n\t"\
"jz " LABEL)
#else
#define JUMP_IF_NOT_REMOTE(LABEL)
#define JUMP_IF_NOT_PROXY(HANDLE_REG, LABEL)
#endif // METAVM