]>
Commit | Line | Data |
---|---|---|
58eb6e7c AG |
1 | // interpret.cc - Code for the interpreter |
2 | ||
d0f4aa53 | 3 | /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation |
58eb6e7c AG |
4 | |
5 | This file is part of libgcj. | |
6 | ||
7 | This software is copyrighted work licensed under the terms of the | |
8 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | /* Author: Kresten Krab Thorup <krab@gnu.org> */ | |
12 | ||
58eb6e7c | 13 | #include <config.h> |
36739040 | 14 | #include <platform.h> |
58eb6e7c AG |
15 | |
16 | #pragma implementation "java-interp.h" | |
17 | ||
58eb6e7c | 18 | #include <jvm.h> |
58eb6e7c AG |
19 | #include <java-cpool.h> |
20 | #include <java-interp.h> | |
58eb6e7c AG |
21 | #include <java/lang/System.h> |
22 | #include <java/lang/String.h> | |
23 | #include <java/lang/Integer.h> | |
30d28794 | 24 | #include <java/lang/Long.h> |
58eb6e7c | 25 | #include <java/lang/StringBuffer.h> |
58eb6e7c AG |
26 | #include <java/lang/Class.h> |
27 | #include <java/lang/reflect/Modifier.h> | |
58eb6e7c AG |
28 | #include <java/lang/VirtualMachineError.h> |
29 | #include <java/lang/InternalError.h> | |
30 | #include <java/lang/NullPointerException.h> | |
31 | #include <java/lang/ArithmeticException.h> | |
32 | #include <java/lang/IncompatibleClassChangeError.h> | |
3ffa3729 | 33 | #include <java/lang/InstantiationException.h> |
3308c46e | 34 | #include <java/lang/Thread.h> |
58eb6e7c AG |
35 | #include <java-insns.h> |
36 | #include <java-signal.h> | |
36739040 TT |
37 | #include <java/lang/ClassFormatError.h> |
38 | #include <execution.h> | |
39 | #include <java/lang/reflect/Modifier.h> | |
58eb6e7c | 40 | |
b099f07d | 41 | #ifdef INTERPRETER |
58eb6e7c | 42 | |
36739040 TT |
43 | // Execution engine for interpreted code. |
44 | _Jv_InterpreterEngine _Jv_soleInterpreterEngine; | |
45 | ||
a9770f9a | 46 | #include <stdlib.h> |
f1aa7a52 | 47 | |
107abb2f | 48 | using namespace gcj; |
58eb6e7c | 49 | |
2cf94e58 | 50 | static void throw_internal_error (const char *msg) |
58eb6e7c AG |
51 | __attribute__ ((__noreturn__)); |
52 | static void throw_incompatible_class_change_error (jstring msg) | |
53 | __attribute__ ((__noreturn__)); | |
715bdd81 | 54 | #ifndef HANDLE_SEGV |
58eb6e7c AG |
55 | static void throw_null_pointer_exception () |
56 | __attribute__ ((__noreturn__)); | |
57 | #endif | |
58eb6e7c | 58 | |
36739040 TT |
59 | static void throw_class_format_error (jstring msg) |
60 | __attribute__ ((__noreturn__)); | |
2cf94e58 | 61 | static void throw_class_format_error (const char *msg) |
36739040 TT |
62 | __attribute__ ((__noreturn__)); |
63 | ||
6187fd28 BM |
64 | #ifdef DIRECT_THREADED |
65 | // Lock to ensure that methods are not compiled concurrently. | |
66 | // We could use a finer-grained lock here, however it is not safe to use | |
67 | // the Class monitor as user code in another thread could hold it. | |
68 | static _Jv_Mutex_t compile_mutex; | |
69 | ||
70 | void | |
71 | _Jv_InitInterpreter() | |
72 | { | |
73 | _Jv_MutexInit (&compile_mutex); | |
74 | } | |
75 | #else | |
76 | void _Jv_InitInterpreter() {} | |
77 | #endif | |
78 | ||
e7e18a21 | 79 | extern "C" double __ieee754_fmod (double,double); |
715bdd81 | 80 | |
f7b4fb11 | 81 | static inline void dupx (_Jv_word *sp, int n, int x) |
58eb6e7c AG |
82 | { |
83 | // first "slide" n+x elements n to the right | |
84 | int top = n-1; | |
85 | for (int i = 0; i < n+x; i++) | |
86 | { | |
87 | sp[(top-i)] = sp[(top-i)-n]; | |
88 | } | |
89 | ||
90 | // next, copy the n top elements, n+x down | |
91 | for (int i = 0; i < n; i++) | |
92 | { | |
93 | sp[top-(n+x)-i] = sp[top-i]; | |
94 | } | |
dfe5a36e | 95 | } |
58eb6e7c | 96 | |
30d28794 TT |
97 | // Used to convert from floating types to integral types. |
98 | template<typename TO, typename FROM> | |
99 | static inline TO | |
100 | convert (FROM val, TO min, TO max) | |
101 | { | |
102 | TO ret; | |
103 | if (val >= (FROM) max) | |
104 | ret = max; | |
105 | else if (val <= (FROM) min) | |
106 | ret = min; | |
107 | else if (val != val) | |
108 | ret = 0; | |
109 | else | |
110 | ret = (TO) val; | |
111 | return ret; | |
112 | } | |
58eb6e7c | 113 | |
eb4534a6 KKT |
114 | #define PUSHA(V) (sp++)->o = (V) |
115 | #define PUSHI(V) (sp++)->i = (V) | |
116 | #define PUSHF(V) (sp++)->f = (V) | |
99444711 TT |
117 | #if SIZEOF_VOID_P == 8 |
118 | # define PUSHL(V) (sp->l = (V), sp += 2) | |
119 | # define PUSHD(V) (sp->d = (V), sp += 2) | |
120 | #else | |
121 | # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \ | |
122 | (sp++)->ia[0] = w2.ia[0]; \ | |
123 | (sp++)->ia[0] = w2.ia[1]; } while (0) | |
124 | # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \ | |
125 | (sp++)->ia[0] = w2.ia[0]; \ | |
126 | (sp++)->ia[0] = w2.ia[1]; } while (0) | |
127 | #endif | |
7941ceab AG |
128 | |
129 | #define POPA() ((--sp)->o) | |
130 | #define POPI() ((jint) (--sp)->i) // cast since it may be promoted | |
131 | #define POPF() ((jfloat) (--sp)->f) | |
99444711 TT |
132 | #if SIZEOF_VOID_P == 8 |
133 | # define POPL() (sp -= 2, (jlong) sp->l) | |
134 | # define POPD() (sp -= 2, (jdouble) sp->d) | |
135 | #else | |
136 | # define POPL() ({ _Jv_word2 w2; \ | |
eb4534a6 KKT |
137 | w2.ia[1] = (--sp)->ia[0]; \ |
138 | w2.ia[0] = (--sp)->ia[0]; w2.l; }) | |
99444711 | 139 | # define POPD() ({ _Jv_word2 w2; \ |
eb4534a6 KKT |
140 | w2.ia[1] = (--sp)->ia[0]; \ |
141 | w2.ia[0] = (--sp)->ia[0]; w2.d; }) | |
99444711 | 142 | #endif |
7941ceab AG |
143 | |
144 | #define LOADA(I) (sp++)->o = locals[I].o | |
145 | #define LOADI(I) (sp++)->i = locals[I].i | |
146 | #define LOADF(I) (sp++)->f = locals[I].f | |
99444711 TT |
147 | #if SIZEOF_VOID_P == 8 |
148 | # define LOADL(I) (sp->l = locals[I].l, sp += 2) | |
149 | # define LOADD(I) (sp->d = locals[I].d, sp += 2) | |
150 | #else | |
151 | # define LOADL(I) do { jint __idx = (I); \ | |
152 | (sp++)->ia[0] = locals[__idx].ia[0]; \ | |
153 | (sp++)->ia[0] = locals[__idx+1].ia[0]; \ | |
154 | } while (0) | |
155 | # define LOADD(I) LOADL(I) | |
156 | #endif | |
7941ceab AG |
157 | |
158 | #define STOREA(I) locals[I].o = (--sp)->o | |
159 | #define STOREI(I) locals[I].i = (--sp)->i | |
160 | #define STOREF(I) locals[I].f = (--sp)->f | |
99444711 TT |
161 | #if SIZEOF_VOID_P == 8 |
162 | # define STOREL(I) (sp -= 2, locals[I].l = sp->l) | |
163 | # define STORED(I) (sp -= 2, locals[I].d = sp->d) | |
164 | #else | |
165 | # define STOREL(I) do { jint __idx = (I); \ | |
166 | locals[__idx+1].ia[0] = (--sp)->ia[0]; \ | |
167 | locals[__idx].ia[0] = (--sp)->ia[0]; \ | |
168 | } while (0) | |
169 | # define STORED(I) STOREL(I) | |
170 | #endif | |
7941ceab AG |
171 | |
172 | #define PEEKI(I) (locals+(I))->i | |
173 | #define PEEKA(I) (locals+(I))->o | |
58eb6e7c | 174 | |
f7b4fb11 | 175 | #define POKEI(I,V) ((locals+(I))->i = (V)) |
58eb6e7c AG |
176 | |
177 | ||
178 | #define BINOPI(OP) { \ | |
179 | jint value2 = POPI(); \ | |
180 | jint value1 = POPI(); \ | |
181 | PUSHI(value1 OP value2); \ | |
182 | } | |
183 | ||
184 | #define BINOPF(OP) { \ | |
185 | jfloat value2 = POPF(); \ | |
186 | jfloat value1 = POPF(); \ | |
187 | PUSHF(value1 OP value2); \ | |
188 | } | |
189 | ||
190 | #define BINOPL(OP) { \ | |
191 | jlong value2 = POPL(); \ | |
192 | jlong value1 = POPL(); \ | |
193 | PUSHL(value1 OP value2); \ | |
194 | } | |
195 | ||
196 | #define BINOPD(OP) { \ | |
197 | jdouble value2 = POPD(); \ | |
198 | jdouble value1 = POPD(); \ | |
199 | PUSHD(value1 OP value2); \ | |
200 | } | |
201 | ||
202 | static inline jint get1s(unsigned char* loc) { | |
203 | return *(signed char*)loc; | |
204 | } | |
205 | ||
206 | static inline jint get1u(unsigned char* loc) { | |
207 | return *loc; | |
208 | } | |
209 | ||
210 | static inline jint get2s(unsigned char* loc) { | |
211 | return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1)); | |
212 | } | |
213 | ||
214 | static inline jint get2u(unsigned char* loc) { | |
215 | return (((jint)(*loc)) << 8) | ((jint)*(loc+1)); | |
216 | } | |
217 | ||
218 | static jint get4(unsigned char* loc) { | |
219 | return (((jint)(loc[0])) << 24) | |
220 | | (((jint)(loc[1])) << 16) | |
221 | | (((jint)(loc[2])) << 8) | |
222 | | (((jint)(loc[3])) << 0); | |
223 | } | |
224 | ||
18744d9b | 225 | #define SAVE_PC() frame_desc.pc = pc |
58eb6e7c | 226 | |
715bdd81 | 227 | #ifdef HANDLE_SEGV |
18744d9b BM |
228 | #define NULLCHECK(X) SAVE_PC() |
229 | #define NULLARRAYCHECK(X) SAVE_PC() | |
58eb6e7c AG |
230 | #else |
231 | #define NULLCHECK(X) \ | |
18744d9b | 232 | do { SAVE_PC(); if ((X)==NULL) throw_null_pointer_exception (); } while (0) |
cec71868 | 233 | #define NULLARRAYCHECK(X) \ |
18744d9b | 234 | do { SAVE_PC(); if ((X)==NULL) { throw_null_pointer_exception (); } } while (0) |
58eb6e7c AG |
235 | #endif |
236 | ||
00cc944d CS |
237 | #define ARRAYBOUNDSCHECK(array, index) \ |
238 | do \ | |
239 | { \ | |
240 | if (((unsigned) index) >= (unsigned) (array->length)) \ | |
241 | _Jv_ThrowBadArrayIndex (index); \ | |
242 | } \ | |
243 | while (0) | |
58eb6e7c | 244 | |
4c98b1b0 TT |
245 | void |
246 | _Jv_InterpMethod::run_normal (ffi_cif *, | |
247 | void* ret, | |
248 | ffi_raw * args, | |
249 | void* __this) | |
58eb6e7c | 250 | { |
fdae83ab | 251 | _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; |
18744d9b | 252 | run (ret, args, _this); |
fdae83ab | 253 | } |
58eb6e7c | 254 | |
4c98b1b0 TT |
255 | void |
256 | _Jv_InterpMethod::run_synch_object (ffi_cif *, | |
257 | void* ret, | |
258 | ffi_raw * args, | |
259 | void* __this) | |
fdae83ab TT |
260 | { |
261 | _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; | |
b099f07d | 262 | |
fdae83ab TT |
263 | jobject rcv = (jobject) args[0].ptr; |
264 | JvSynchronize mutex (rcv); | |
b099f07d | 265 | |
18744d9b | 266 | run (ret, args, _this); |
fdae83ab | 267 | } |
58eb6e7c | 268 | |
4c98b1b0 TT |
269 | void |
270 | _Jv_InterpMethod::run_class (ffi_cif *, | |
271 | void* ret, | |
272 | ffi_raw * args, | |
273 | void* __this) | |
274 | { | |
275 | _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; | |
276 | _Jv_InitClass (_this->defining_class); | |
18744d9b | 277 | run (ret, args, _this); |
4c98b1b0 TT |
278 | } |
279 | ||
280 | void | |
281 | _Jv_InterpMethod::run_synch_class (ffi_cif *, | |
282 | void* ret, | |
283 | ffi_raw * args, | |
284 | void* __this) | |
fdae83ab TT |
285 | { |
286 | _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; | |
58eb6e7c | 287 | |
fdae83ab | 288 | jclass sync = _this->defining_class; |
4c98b1b0 | 289 | _Jv_InitClass (sync); |
fdae83ab | 290 | JvSynchronize mutex (sync); |
58eb6e7c | 291 | |
18744d9b | 292 | run (ret, args, _this); |
fdae83ab | 293 | } |
58eb6e7c | 294 | |
fdae83ab TT |
295 | #ifdef DIRECT_THREADED |
296 | // "Compile" a method by turning it from bytecode to direct-threaded | |
297 | // code. | |
298 | void | |
299 | _Jv_InterpMethod::compile (const void * const *insn_targets) | |
300 | { | |
301 | insn_slot *insns = NULL; | |
302 | int next = 0; | |
303 | unsigned char *codestart = bytecode (); | |
304 | unsigned char *end = codestart + code_length; | |
305 | _Jv_word *pool_data = defining_class->constants.data; | |
58eb6e7c | 306 | |
fdae83ab TT |
307 | #define SET_ONE(Field, Value) \ |
308 | do \ | |
309 | { \ | |
310 | if (first_pass) \ | |
311 | ++next; \ | |
312 | else \ | |
313 | insns[next++].Field = Value; \ | |
314 | } \ | |
315 | while (0) | |
58eb6e7c | 316 | |
fdae83ab TT |
317 | #define SET_INSN(Value) SET_ONE (insn, (void *) Value) |
318 | #define SET_INT(Value) SET_ONE (int_val, Value) | |
319 | #define SET_DATUM(Value) SET_ONE (datum, Value) | |
cec71868 | 320 | |
fdae83ab TT |
321 | // Map from bytecode PC to slot in INSNS. |
322 | int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length); | |
323 | for (int i = 0; i < code_length; ++i) | |
324 | pc_mapping[i] = -1; | |
58eb6e7c | 325 | |
fdae83ab | 326 | for (int i = 0; i < 2; ++i) |
58eb6e7c | 327 | { |
fdae83ab TT |
328 | jboolean first_pass = i == 0; |
329 | ||
330 | if (! first_pass) | |
331 | { | |
b4d0051b | 332 | insns = (insn_slot *) _Jv_AllocBytes (sizeof (insn_slot) * next); |
e939885f | 333 | number_insn_slots = next; |
fdae83ab | 334 | next = 0; |
58eb6e7c | 335 | } |
58eb6e7c | 336 | |
fdae83ab TT |
337 | unsigned char *pc = codestart; |
338 | while (pc < end) | |
339 | { | |
340 | int base_pc_val = pc - codestart; | |
341 | if (first_pass) | |
342 | pc_mapping[base_pc_val] = next; | |
58eb6e7c | 343 | |
fdae83ab TT |
344 | java_opcode opcode = (java_opcode) *pc++; |
345 | // Just elide NOPs. | |
346 | if (opcode == op_nop) | |
347 | continue; | |
348 | SET_INSN (insn_targets[opcode]); | |
58eb6e7c | 349 | |
fdae83ab TT |
350 | switch (opcode) |
351 | { | |
352 | case op_nop: | |
353 | case op_aconst_null: | |
354 | case op_iconst_m1: | |
355 | case op_iconst_0: | |
356 | case op_iconst_1: | |
357 | case op_iconst_2: | |
358 | case op_iconst_3: | |
359 | case op_iconst_4: | |
360 | case op_iconst_5: | |
361 | case op_lconst_0: | |
362 | case op_lconst_1: | |
363 | case op_fconst_0: | |
364 | case op_fconst_1: | |
365 | case op_fconst_2: | |
366 | case op_dconst_0: | |
367 | case op_dconst_1: | |
368 | case op_iload_0: | |
369 | case op_iload_1: | |
370 | case op_iload_2: | |
371 | case op_iload_3: | |
372 | case op_lload_0: | |
373 | case op_lload_1: | |
374 | case op_lload_2: | |
375 | case op_lload_3: | |
376 | case op_fload_0: | |
377 | case op_fload_1: | |
378 | case op_fload_2: | |
379 | case op_fload_3: | |
380 | case op_dload_0: | |
381 | case op_dload_1: | |
382 | case op_dload_2: | |
383 | case op_dload_3: | |
384 | case op_aload_0: | |
385 | case op_aload_1: | |
386 | case op_aload_2: | |
387 | case op_aload_3: | |
388 | case op_iaload: | |
389 | case op_laload: | |
390 | case op_faload: | |
391 | case op_daload: | |
392 | case op_aaload: | |
393 | case op_baload: | |
394 | case op_caload: | |
395 | case op_saload: | |
396 | case op_istore_0: | |
397 | case op_istore_1: | |
398 | case op_istore_2: | |
399 | case op_istore_3: | |
400 | case op_lstore_0: | |
401 | case op_lstore_1: | |
402 | case op_lstore_2: | |
403 | case op_lstore_3: | |
404 | case op_fstore_0: | |
405 | case op_fstore_1: | |
406 | case op_fstore_2: | |
407 | case op_fstore_3: | |
408 | case op_dstore_0: | |
409 | case op_dstore_1: | |
410 | case op_dstore_2: | |
411 | case op_dstore_3: | |
412 | case op_astore_0: | |
413 | case op_astore_1: | |
414 | case op_astore_2: | |
415 | case op_astore_3: | |
416 | case op_iastore: | |
417 | case op_lastore: | |
418 | case op_fastore: | |
419 | case op_dastore: | |
420 | case op_aastore: | |
421 | case op_bastore: | |
422 | case op_castore: | |
423 | case op_sastore: | |
424 | case op_pop: | |
425 | case op_pop2: | |
426 | case op_dup: | |
427 | case op_dup_x1: | |
428 | case op_dup_x2: | |
429 | case op_dup2: | |
430 | case op_dup2_x1: | |
431 | case op_dup2_x2: | |
432 | case op_swap: | |
433 | case op_iadd: | |
434 | case op_isub: | |
435 | case op_imul: | |
436 | case op_idiv: | |
437 | case op_irem: | |
438 | case op_ishl: | |
439 | case op_ishr: | |
440 | case op_iushr: | |
441 | case op_iand: | |
442 | case op_ior: | |
443 | case op_ixor: | |
444 | case op_ladd: | |
445 | case op_lsub: | |
446 | case op_lmul: | |
447 | case op_ldiv: | |
448 | case op_lrem: | |
449 | case op_lshl: | |
450 | case op_lshr: | |
451 | case op_lushr: | |
452 | case op_land: | |
453 | case op_lor: | |
454 | case op_lxor: | |
455 | case op_fadd: | |
456 | case op_fsub: | |
457 | case op_fmul: | |
458 | case op_fdiv: | |
459 | case op_frem: | |
460 | case op_dadd: | |
461 | case op_dsub: | |
462 | case op_dmul: | |
463 | case op_ddiv: | |
464 | case op_drem: | |
465 | case op_ineg: | |
466 | case op_i2b: | |
467 | case op_i2c: | |
468 | case op_i2s: | |
469 | case op_lneg: | |
470 | case op_fneg: | |
471 | case op_dneg: | |
472 | case op_i2l: | |
473 | case op_i2f: | |
474 | case op_i2d: | |
475 | case op_l2i: | |
476 | case op_l2f: | |
477 | case op_l2d: | |
478 | case op_f2i: | |
479 | case op_f2l: | |
480 | case op_f2d: | |
481 | case op_d2i: | |
482 | case op_d2l: | |
483 | case op_d2f: | |
484 | case op_lcmp: | |
485 | case op_fcmpl: | |
486 | case op_fcmpg: | |
487 | case op_dcmpl: | |
488 | case op_dcmpg: | |
489 | case op_monitorenter: | |
490 | case op_monitorexit: | |
491 | case op_ireturn: | |
492 | case op_lreturn: | |
493 | case op_freturn: | |
494 | case op_dreturn: | |
495 | case op_areturn: | |
496 | case op_return: | |
497 | case op_athrow: | |
498 | case op_arraylength: | |
499 | // No argument, nothing else to do. | |
500 | break; | |
501 | ||
502 | case op_bipush: | |
503 | SET_INT (get1s (pc)); | |
504 | ++pc; | |
505 | break; | |
506 | ||
507 | case op_ldc: | |
508 | { | |
509 | int index = get1u (pc); | |
510 | ++pc; | |
a022cd59 TT |
511 | // For an unresolved class we want to delay resolution |
512 | // until execution. | |
513 | if (defining_class->constants.tags[index] == JV_CONSTANT_Class) | |
514 | { | |
515 | --next; | |
516 | SET_INSN (insn_targets[int (op_jsr_w) + 1]); | |
517 | SET_INT (index); | |
518 | } | |
519 | else | |
520 | SET_DATUM (pool_data[index].o); | |
fdae83ab TT |
521 | } |
522 | break; | |
523 | ||
524 | case op_ret: | |
525 | case op_iload: | |
526 | case op_lload: | |
527 | case op_fload: | |
528 | case op_dload: | |
529 | case op_aload: | |
530 | case op_istore: | |
531 | case op_lstore: | |
532 | case op_fstore: | |
533 | case op_dstore: | |
534 | case op_astore: | |
535 | case op_newarray: | |
536 | SET_INT (get1u (pc)); | |
537 | ++pc; | |
538 | break; | |
539 | ||
540 | case op_iinc: | |
541 | SET_INT (get1u (pc)); | |
542 | SET_INT (get1s (pc + 1)); | |
543 | pc += 2; | |
544 | break; | |
545 | ||
546 | case op_ldc_w: | |
547 | { | |
548 | int index = get2u (pc); | |
549 | pc += 2; | |
a022cd59 TT |
550 | // For an unresolved class we want to delay resolution |
551 | // until execution. | |
552 | if (defining_class->constants.tags[index] == JV_CONSTANT_Class) | |
553 | { | |
554 | --next; | |
555 | SET_INSN (insn_targets[int (op_jsr_w) + 1]); | |
556 | SET_INT (index); | |
557 | } | |
558 | else | |
559 | SET_DATUM (pool_data[index].o); | |
fdae83ab TT |
560 | } |
561 | break; | |
58eb6e7c | 562 | |
fdae83ab TT |
563 | case op_ldc2_w: |
564 | { | |
565 | int index = get2u (pc); | |
566 | pc += 2; | |
567 | SET_DATUM (&pool_data[index]); | |
568 | } | |
569 | break; | |
570 | ||
571 | case op_sipush: | |
572 | SET_INT (get2s (pc)); | |
573 | pc += 2; | |
574 | break; | |
575 | ||
576 | case op_new: | |
577 | case op_getstatic: | |
578 | case op_getfield: | |
579 | case op_putfield: | |
580 | case op_putstatic: | |
581 | case op_anewarray: | |
582 | case op_instanceof: | |
583 | case op_checkcast: | |
584 | case op_invokespecial: | |
585 | case op_invokestatic: | |
586 | case op_invokevirtual: | |
587 | SET_INT (get2u (pc)); | |
588 | pc += 2; | |
589 | break; | |
590 | ||
591 | case op_multianewarray: | |
592 | SET_INT (get2u (pc)); | |
593 | SET_INT (get1u (pc + 2)); | |
594 | pc += 3; | |
595 | break; | |
596 | ||
597 | case op_jsr: | |
598 | case op_ifeq: | |
599 | case op_ifne: | |
600 | case op_iflt: | |
601 | case op_ifge: | |
602 | case op_ifgt: | |
603 | case op_ifle: | |
604 | case op_if_icmpeq: | |
605 | case op_if_icmpne: | |
606 | case op_if_icmplt: | |
607 | case op_if_icmpge: | |
608 | case op_if_icmpgt: | |
609 | case op_if_icmple: | |
610 | case op_if_acmpeq: | |
611 | case op_if_acmpne: | |
612 | case op_ifnull: | |
613 | case op_ifnonnull: | |
614 | case op_goto: | |
615 | { | |
616 | int offset = get2s (pc); | |
617 | pc += 2; | |
618 | ||
619 | int new_pc = base_pc_val + offset; | |
620 | ||
621 | bool orig_was_goto = opcode == op_goto; | |
622 | ||
623 | // Thread jumps. We limit the loop count; this lets | |
624 | // us avoid infinite loops if the bytecode contains | |
625 | // such. `10' is arbitrary. | |
626 | int count = 10; | |
627 | while (codestart[new_pc] == op_goto && count-- > 0) | |
628 | new_pc += get2s (&codestart[new_pc + 1]); | |
629 | ||
630 | // If the jump takes us to a `return' instruction and | |
631 | // the original branch was an unconditional goto, then | |
632 | // we hoist the return. | |
633 | opcode = (java_opcode) codestart[new_pc]; | |
634 | if (orig_was_goto | |
635 | && (opcode == op_ireturn || opcode == op_lreturn | |
636 | || opcode == op_freturn || opcode == op_dreturn | |
637 | || opcode == op_areturn || opcode == op_return)) | |
638 | { | |
639 | --next; | |
640 | SET_INSN (insn_targets[opcode]); | |
641 | } | |
642 | else | |
643 | SET_DATUM (&insns[pc_mapping[new_pc]]); | |
644 | } | |
645 | break; | |
58eb6e7c | 646 | |
fdae83ab TT |
647 | case op_tableswitch: |
648 | { | |
649 | while ((pc - codestart) % 4 != 0) | |
650 | ++pc; | |
651 | ||
652 | jint def = get4 (pc); | |
653 | SET_DATUM (&insns[pc_mapping[base_pc_val + def]]); | |
654 | pc += 4; | |
655 | ||
656 | int low = get4 (pc); | |
657 | SET_INT (low); | |
658 | pc += 4; | |
659 | int high = get4 (pc); | |
660 | SET_INT (high); | |
661 | pc += 4; | |
662 | ||
663 | for (int i = low; i <= high; ++i) | |
664 | { | |
665 | SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]); | |
666 | pc += 4; | |
667 | } | |
668 | } | |
669 | break; | |
58eb6e7c | 670 | |
fdae83ab TT |
671 | case op_lookupswitch: |
672 | { | |
673 | while ((pc - codestart) % 4 != 0) | |
674 | ++pc; | |
675 | ||
676 | jint def = get4 (pc); | |
677 | SET_DATUM (&insns[pc_mapping[base_pc_val + def]]); | |
678 | pc += 4; | |
679 | ||
680 | jint npairs = get4 (pc); | |
681 | pc += 4; | |
682 | SET_INT (npairs); | |
683 | ||
684 | while (npairs-- > 0) | |
685 | { | |
686 | jint match = get4 (pc); | |
687 | jint offset = get4 (pc + 4); | |
688 | SET_INT (match); | |
689 | SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]); | |
690 | pc += 8; | |
691 | } | |
692 | } | |
693 | break; | |
58eb6e7c | 694 | |
fdae83ab TT |
695 | case op_invokeinterface: |
696 | { | |
697 | jint index = get2u (pc); | |
698 | pc += 2; | |
699 | // We ignore the next two bytes. | |
700 | pc += 2; | |
701 | SET_INT (index); | |
702 | } | |
703 | break; | |
58eb6e7c | 704 | |
fdae83ab TT |
705 | case op_wide: |
706 | { | |
707 | opcode = (java_opcode) get1u (pc); | |
708 | pc += 1; | |
709 | jint val = get2u (pc); | |
710 | pc += 2; | |
711 | ||
712 | // We implement narrow and wide instructions using the | |
713 | // same code in the interpreter. So we rewrite the | |
714 | // instruction slot here. | |
715 | if (! first_pass) | |
716 | insns[next - 1].insn = (void *) insn_targets[opcode]; | |
717 | SET_INT (val); | |
718 | ||
719 | if (opcode == op_iinc) | |
720 | { | |
721 | SET_INT (get2s (pc)); | |
722 | pc += 2; | |
723 | } | |
724 | } | |
725 | break; | |
58eb6e7c | 726 | |
fdae83ab TT |
727 | case op_jsr_w: |
728 | case op_goto_w: | |
729 | { | |
730 | jint offset = get4 (pc); | |
731 | pc += 4; | |
732 | SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]); | |
733 | } | |
734 | break; | |
735 | ||
736 | // Some "can't happen" cases that we include for | |
737 | // error-checking purposes. | |
738 | case op_putfield_1: | |
739 | case op_putfield_2: | |
740 | case op_putfield_4: | |
741 | case op_putfield_8: | |
742 | case op_putfield_a: | |
743 | case op_putstatic_1: | |
744 | case op_putstatic_2: | |
745 | case op_putstatic_4: | |
746 | case op_putstatic_8: | |
747 | case op_putstatic_a: | |
748 | case op_getfield_1: | |
749 | case op_getfield_2s: | |
750 | case op_getfield_2u: | |
751 | case op_getfield_4: | |
752 | case op_getfield_8: | |
753 | case op_getfield_a: | |
754 | case op_getstatic_1: | |
755 | case op_getstatic_2s: | |
756 | case op_getstatic_2u: | |
757 | case op_getstatic_4: | |
758 | case op_getstatic_8: | |
759 | case op_getstatic_a: | |
760 | default: | |
761 | // Fail somehow. | |
762 | break; | |
763 | } | |
764 | } | |
765 | } | |
58eb6e7c | 766 | |
fdae83ab TT |
767 | // Now update exceptions. |
768 | _Jv_InterpException *exc = exceptions (); | |
769 | for (int i = 0; i < exc_count; ++i) | |
770 | { | |
771 | exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]]; | |
772 | exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]]; | |
773 | exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]]; | |
36739040 TT |
774 | jclass handler |
775 | = (_Jv_Linker::resolve_pool_entry (defining_class, | |
776 | exc[i].handler_type.i)).clazz; | |
fdae83ab TT |
777 | exc[i].handler_type.p = handler; |
778 | } | |
58eb6e7c | 779 | |
18744d9b BM |
780 | // Translate entries in the LineNumberTable from bytecode PC's to direct |
781 | // threaded interpreter instruction values. | |
782 | for (int i = 0; i < line_table_len; i++) | |
783 | { | |
784 | int byte_pc = line_table[i].bytecode_pc; | |
6a059870 TT |
785 | // It isn't worth throwing an exception if this table is |
786 | // corrupted, but at the same time we don't want a crash. | |
787 | if (byte_pc < 0 || byte_pc >= code_length) | |
788 | byte_pc = 0; | |
18744d9b BM |
789 | line_table[i].pc = &insns[pc_mapping[byte_pc]]; |
790 | } | |
791 | ||
fdae83ab | 792 | prepared = insns; |
58eb6e7c | 793 | } |
fdae83ab | 794 | #endif /* DIRECT_THREADED */ |
58eb6e7c | 795 | |
d0f4aa53 KS |
796 | /* Run the given method. |
797 | When args is NULL, don't run anything -- just compile it. */ | |
fdae83ab | 798 | void |
18744d9b | 799 | _Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth) |
fdae83ab TT |
800 | { |
801 | using namespace java::lang::reflect; | |
58eb6e7c | 802 | |
3308c46e TT |
803 | // FRAME_DESC registers this particular invocation as the top-most |
804 | // interpreter frame. This lets the stack tracing code (for | |
805 | // Throwable) print information about the method being interpreted | |
806 | // rather than about the interpreter itself. FRAME_DESC has a | |
807 | // destructor so it cleans up automatically when the interpreter | |
808 | // returns. | |
809 | java::lang::Thread *thread = java::lang::Thread::currentThread(); | |
1349c688 | 810 | _Jv_InterpFrame frame_desc (meth, thread); |
3308c46e | 811 | |
18744d9b | 812 | _Jv_word stack[meth->max_stack]; |
fdae83ab | 813 | _Jv_word *sp = stack; |
58eb6e7c | 814 | |
18744d9b | 815 | _Jv_word locals[meth->max_locals]; |
58eb6e7c | 816 | |
f7b4fb11 | 817 | #define INSN_LABEL(op) &&insn_##op |
f7b4fb11 KKT |
818 | |
819 | static const void *const insn_target[] = | |
820 | { | |
821 | INSN_LABEL(nop), | |
822 | INSN_LABEL(aconst_null), | |
823 | INSN_LABEL(iconst_m1), | |
824 | INSN_LABEL(iconst_0), | |
825 | INSN_LABEL(iconst_1), | |
826 | INSN_LABEL(iconst_2), | |
827 | INSN_LABEL(iconst_3), | |
828 | INSN_LABEL(iconst_4), | |
829 | INSN_LABEL(iconst_5), | |
830 | INSN_LABEL(lconst_0), | |
831 | INSN_LABEL(lconst_1), | |
832 | INSN_LABEL(fconst_0), | |
833 | INSN_LABEL(fconst_1), | |
834 | INSN_LABEL(fconst_2), | |
835 | INSN_LABEL(dconst_0), | |
836 | INSN_LABEL(dconst_1), | |
837 | INSN_LABEL(bipush), | |
838 | INSN_LABEL(sipush), | |
839 | INSN_LABEL(ldc), | |
840 | INSN_LABEL(ldc_w), | |
841 | INSN_LABEL(ldc2_w), | |
842 | INSN_LABEL(iload), | |
843 | INSN_LABEL(lload), | |
844 | INSN_LABEL(fload), | |
845 | INSN_LABEL(dload), | |
846 | INSN_LABEL(aload), | |
847 | INSN_LABEL(iload_0), | |
848 | INSN_LABEL(iload_1), | |
849 | INSN_LABEL(iload_2), | |
850 | INSN_LABEL(iload_3), | |
851 | INSN_LABEL(lload_0), | |
852 | INSN_LABEL(lload_1), | |
853 | INSN_LABEL(lload_2), | |
854 | INSN_LABEL(lload_3), | |
855 | INSN_LABEL(fload_0), | |
856 | INSN_LABEL(fload_1), | |
857 | INSN_LABEL(fload_2), | |
858 | INSN_LABEL(fload_3), | |
859 | INSN_LABEL(dload_0), | |
860 | INSN_LABEL(dload_1), | |
861 | INSN_LABEL(dload_2), | |
862 | INSN_LABEL(dload_3), | |
863 | INSN_LABEL(aload_0), | |
864 | INSN_LABEL(aload_1), | |
865 | INSN_LABEL(aload_2), | |
866 | INSN_LABEL(aload_3), | |
867 | INSN_LABEL(iaload), | |
868 | INSN_LABEL(laload), | |
869 | INSN_LABEL(faload), | |
870 | INSN_LABEL(daload), | |
871 | INSN_LABEL(aaload), | |
872 | INSN_LABEL(baload), | |
873 | INSN_LABEL(caload), | |
874 | INSN_LABEL(saload), | |
875 | INSN_LABEL(istore), | |
876 | INSN_LABEL(lstore), | |
877 | INSN_LABEL(fstore), | |
878 | INSN_LABEL(dstore), | |
879 | INSN_LABEL(astore), | |
880 | INSN_LABEL(istore_0), | |
881 | INSN_LABEL(istore_1), | |
882 | INSN_LABEL(istore_2), | |
883 | INSN_LABEL(istore_3), | |
884 | INSN_LABEL(lstore_0), | |
885 | INSN_LABEL(lstore_1), | |
886 | INSN_LABEL(lstore_2), | |
887 | INSN_LABEL(lstore_3), | |
888 | INSN_LABEL(fstore_0), | |
889 | INSN_LABEL(fstore_1), | |
890 | INSN_LABEL(fstore_2), | |
891 | INSN_LABEL(fstore_3), | |
892 | INSN_LABEL(dstore_0), | |
893 | INSN_LABEL(dstore_1), | |
894 | INSN_LABEL(dstore_2), | |
895 | INSN_LABEL(dstore_3), | |
896 | INSN_LABEL(astore_0), | |
897 | INSN_LABEL(astore_1), | |
898 | INSN_LABEL(astore_2), | |
899 | INSN_LABEL(astore_3), | |
900 | INSN_LABEL(iastore), | |
901 | INSN_LABEL(lastore), | |
902 | INSN_LABEL(fastore), | |
903 | INSN_LABEL(dastore), | |
904 | INSN_LABEL(aastore), | |
905 | INSN_LABEL(bastore), | |
906 | INSN_LABEL(castore), | |
907 | INSN_LABEL(sastore), | |
908 | INSN_LABEL(pop), | |
909 | INSN_LABEL(pop2), | |
910 | INSN_LABEL(dup), | |
911 | INSN_LABEL(dup_x1), | |
912 | INSN_LABEL(dup_x2), | |
913 | INSN_LABEL(dup2), | |
914 | INSN_LABEL(dup2_x1), | |
915 | INSN_LABEL(dup2_x2), | |
916 | INSN_LABEL(swap), | |
917 | INSN_LABEL(iadd), | |
918 | INSN_LABEL(ladd), | |
919 | INSN_LABEL(fadd), | |
920 | INSN_LABEL(dadd), | |
921 | INSN_LABEL(isub), | |
922 | INSN_LABEL(lsub), | |
923 | INSN_LABEL(fsub), | |
924 | INSN_LABEL(dsub), | |
925 | INSN_LABEL(imul), | |
926 | INSN_LABEL(lmul), | |
927 | INSN_LABEL(fmul), | |
928 | INSN_LABEL(dmul), | |
929 | INSN_LABEL(idiv), | |
930 | INSN_LABEL(ldiv), | |
931 | INSN_LABEL(fdiv), | |
932 | INSN_LABEL(ddiv), | |
933 | INSN_LABEL(irem), | |
934 | INSN_LABEL(lrem), | |
935 | INSN_LABEL(frem), | |
936 | INSN_LABEL(drem), | |
937 | INSN_LABEL(ineg), | |
938 | INSN_LABEL(lneg), | |
939 | INSN_LABEL(fneg), | |
940 | INSN_LABEL(dneg), | |
941 | INSN_LABEL(ishl), | |
942 | INSN_LABEL(lshl), | |
943 | INSN_LABEL(ishr), | |
944 | INSN_LABEL(lshr), | |
945 | INSN_LABEL(iushr), | |
946 | INSN_LABEL(lushr), | |
947 | INSN_LABEL(iand), | |
948 | INSN_LABEL(land), | |
949 | INSN_LABEL(ior), | |
950 | INSN_LABEL(lor), | |
951 | INSN_LABEL(ixor), | |
952 | INSN_LABEL(lxor), | |
953 | INSN_LABEL(iinc), | |
954 | INSN_LABEL(i2l), | |
955 | INSN_LABEL(i2f), | |
956 | INSN_LABEL(i2d), | |
957 | INSN_LABEL(l2i), | |
958 | INSN_LABEL(l2f), | |
959 | INSN_LABEL(l2d), | |
960 | INSN_LABEL(f2i), | |
961 | INSN_LABEL(f2l), | |
962 | INSN_LABEL(f2d), | |
963 | INSN_LABEL(d2i), | |
964 | INSN_LABEL(d2l), | |
965 | INSN_LABEL(d2f), | |
966 | INSN_LABEL(i2b), | |
967 | INSN_LABEL(i2c), | |
968 | INSN_LABEL(i2s), | |
969 | INSN_LABEL(lcmp), | |
970 | INSN_LABEL(fcmpl), | |
971 | INSN_LABEL(fcmpg), | |
972 | INSN_LABEL(dcmpl), | |
973 | INSN_LABEL(dcmpg), | |
974 | INSN_LABEL(ifeq), | |
975 | INSN_LABEL(ifne), | |
976 | INSN_LABEL(iflt), | |
977 | INSN_LABEL(ifge), | |
978 | INSN_LABEL(ifgt), | |
979 | INSN_LABEL(ifle), | |
980 | INSN_LABEL(if_icmpeq), | |
981 | INSN_LABEL(if_icmpne), | |
982 | INSN_LABEL(if_icmplt), | |
983 | INSN_LABEL(if_icmpge), | |
984 | INSN_LABEL(if_icmpgt), | |
985 | INSN_LABEL(if_icmple), | |
986 | INSN_LABEL(if_acmpeq), | |
987 | INSN_LABEL(if_acmpne), | |
988 | INSN_LABEL(goto), | |
989 | INSN_LABEL(jsr), | |
990 | INSN_LABEL(ret), | |
991 | INSN_LABEL(tableswitch), | |
992 | INSN_LABEL(lookupswitch), | |
993 | INSN_LABEL(ireturn), | |
994 | INSN_LABEL(lreturn), | |
995 | INSN_LABEL(freturn), | |
996 | INSN_LABEL(dreturn), | |
997 | INSN_LABEL(areturn), | |
998 | INSN_LABEL(return), | |
999 | INSN_LABEL(getstatic), | |
1000 | INSN_LABEL(putstatic), | |
1001 | INSN_LABEL(getfield), | |
1002 | INSN_LABEL(putfield), | |
1003 | INSN_LABEL(invokevirtual), | |
1004 | INSN_LABEL(invokespecial), | |
1005 | INSN_LABEL(invokestatic), | |
1006 | INSN_LABEL(invokeinterface), | |
b446a5f1 | 1007 | 0, /* Unused. */ |
f7b4fb11 KKT |
1008 | INSN_LABEL(new), |
1009 | INSN_LABEL(newarray), | |
1010 | INSN_LABEL(anewarray), | |
1011 | INSN_LABEL(arraylength), | |
1012 | INSN_LABEL(athrow), | |
1013 | INSN_LABEL(checkcast), | |
1014 | INSN_LABEL(instanceof), | |
1015 | INSN_LABEL(monitorenter), | |
1016 | INSN_LABEL(monitorexit), | |
fdae83ab TT |
1017 | #ifdef DIRECT_THREADED |
1018 | 0, // wide | |
1019 | #else | |
f7b4fb11 | 1020 | INSN_LABEL(wide), |
fdae83ab | 1021 | #endif |
f7b4fb11 KKT |
1022 | INSN_LABEL(multianewarray), |
1023 | INSN_LABEL(ifnull), | |
1024 | INSN_LABEL(ifnonnull), | |
1025 | INSN_LABEL(goto_w), | |
1026 | INSN_LABEL(jsr_w), | |
a022cd59 TT |
1027 | #ifdef DIRECT_THREADED |
1028 | INSN_LABEL (ldc_class) | |
1029 | #else | |
fdae83ab | 1030 | 0 |
a022cd59 | 1031 | #endif |
f7b4fb11 KKT |
1032 | }; |
1033 | ||
fdae83ab | 1034 | pc_t pc; |
f7b4fb11 | 1035 | |
fdae83ab | 1036 | #ifdef DIRECT_THREADED |
f7b4fb11 | 1037 | |
fdae83ab TT |
1038 | #define NEXT_INSN goto *((pc++)->insn) |
1039 | #define INTVAL() ((pc++)->int_val) | |
1040 | #define AVAL() ((pc++)->datum) | |
f7b4fb11 | 1041 | |
fdae83ab TT |
1042 | #define GET1S() INTVAL () |
1043 | #define GET2S() INTVAL () | |
1044 | #define GET1U() INTVAL () | |
1045 | #define GET2U() INTVAL () | |
1046 | #define AVAL1U() AVAL () | |
1047 | #define AVAL2U() AVAL () | |
1048 | #define AVAL2UP() AVAL () | |
1049 | #define SKIP_GOTO ++pc | |
1050 | #define GOTO_VAL() (insn_slot *) pc->datum | |
1051 | #define PCVAL(unionval) unionval.p | |
1052 | #define AMPAMP(label) &&label | |
715bdd81 | 1053 | |
6187fd28 | 1054 | // Compile if we must. NOTE: Double-check locking. |
18744d9b | 1055 | if (meth->prepared == NULL) |
6187fd28 BM |
1056 | { |
1057 | _Jv_MutexLock (&compile_mutex); | |
18744d9b BM |
1058 | if (meth->prepared == NULL) |
1059 | meth->compile (insn_target); | |
6187fd28 BM |
1060 | _Jv_MutexUnlock (&compile_mutex); |
1061 | } | |
d0f4aa53 KS |
1062 | |
1063 | // If we're only compiling, stop here | |
1064 | if (args == NULL) | |
1065 | return; | |
1066 | ||
18744d9b | 1067 | pc = (insn_slot *) meth->prepared; |
715bdd81 | 1068 | |
58eb6e7c AG |
1069 | #else |
1070 | ||
fdae83ab | 1071 | #define NEXT_INSN goto *(insn_target[*pc++]) |
58eb6e7c | 1072 | |
fdae83ab TT |
1073 | #define GET1S() get1s (pc++) |
1074 | #define GET2S() (pc += 2, get2s (pc- 2)) | |
1075 | #define GET1U() get1u (pc++) | |
1076 | #define GET2U() (pc += 2, get2u (pc - 2)) | |
a022cd59 TT |
1077 | // Note that these could be more efficient when not handling 'ldc |
1078 | // class'. | |
1079 | #define AVAL1U() \ | |
1080 | ({ int index = get1u (pc++); \ | |
1081 | resolve_pool_entry (meth->defining_class, index).o; }) | |
1082 | #define AVAL2U() \ | |
1083 | ({ int index = get2u (pc); pc += 2; \ | |
1084 | resolve_pool_entry (meth->defining_class, index).o; }) | |
1085 | // Note that we don't need to resolve the pool entry here as class | |
1086 | // constants are never wide. | |
fdae83ab TT |
1087 | #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; }) |
1088 | #define SKIP_GOTO pc += 2 | |
1089 | #define GOTO_VAL() pc - 1 + get2s (pc) | |
1090 | #define PCVAL(unionval) unionval.i | |
1091 | #define AMPAMP(label) NULL | |
58eb6e7c | 1092 | |
fdae83ab TT |
1093 | pc = bytecode (); |
1094 | ||
1095 | #endif /* DIRECT_THREADED */ | |
1096 | ||
1097 | #define TAKE_GOTO pc = GOTO_VAL () | |
1098 | ||
d0f4aa53 KS |
1099 | /* Go straight at it! the ffi raw format matches the internal |
1100 | stack representation exactly. At least, that's the idea. | |
1101 | */ | |
1102 | memcpy ((void*) locals, (void*) args, meth->args_raw_size); | |
1103 | ||
1104 | _Jv_word *pool_data = meth->defining_class->constants.data; | |
1105 | ||
1106 | /* These three are temporaries for common code used by several | |
1107 | instructions. */ | |
1108 | void (*fun)(); | |
1109 | _Jv_ResolvedMethod* rmeth; | |
1110 | int tmpval; | |
1111 | ||
fdae83ab TT |
1112 | try |
1113 | { | |
1114 | // We keep nop around. It is used if we're interpreting the | |
1115 | // bytecodes and not doing direct threading. | |
1116 | insn_nop: | |
1117 | NEXT_INSN; | |
58eb6e7c | 1118 | |
fdae83ab TT |
1119 | /* The first few instructions here are ordered according to their |
1120 | frequency, in the hope that this will improve code locality a | |
1121 | little. */ | |
f7b4fb11 | 1122 | |
fdae83ab TT |
1123 | insn_aload_0: // 0x2a |
1124 | LOADA (0); | |
f7b4fb11 | 1125 | NEXT_INSN; |
58eb6e7c | 1126 | |
fdae83ab TT |
1127 | insn_iload: // 0x15 |
1128 | LOADI (GET1U ()); | |
f7b4fb11 | 1129 | NEXT_INSN; |
58eb6e7c | 1130 | |
fdae83ab | 1131 | insn_iload_1: // 0x1b |
58eb6e7c | 1132 | LOADI (1); |
f7b4fb11 | 1133 | NEXT_INSN; |
58eb6e7c | 1134 | |
fdae83ab | 1135 | insn_invokevirtual: // 0xb6 |
58eb6e7c | 1136 | { |
fdae83ab | 1137 | int index = GET2U (); |
58eb6e7c | 1138 | |
36739040 TT |
1139 | /* _Jv_Linker::resolve_pool_entry returns immediately if the |
1140 | * value already is resolved. If we want to clutter up the | |
1141 | * code here to gain a little performance, then we can check | |
1142 | * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag | |
1143 | * directly. For now, I don't think it is worth it. */ | |
58eb6e7c | 1144 | |
18744d9b BM |
1145 | SAVE_PC(); |
1146 | rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class, | |
36739040 | 1147 | index)).rmethod; |
58eb6e7c AG |
1148 | |
1149 | sp -= rmeth->stack_item_count; | |
c6b33a47 JS |
1150 | // We don't use NULLCHECK here because we can't rely on that |
1151 | // working if the method is final. So instead we do an | |
1152 | // explicit test. | |
1153 | if (! sp[0].o) | |
18744d9b BM |
1154 | { |
1155 | //printf("invokevirtual pc = %p/%i\n", pc, meth->get_pc_val(pc)); | |
1156 | throw new java::lang::NullPointerException; | |
1157 | } | |
58eb6e7c AG |
1158 | |
1159 | if (rmeth->vtable_index == -1) | |
1160 | { | |
1161 | // final methods do not appear in the vtable, | |
1162 | // if it does not appear in the superclass. | |
79c2c6da | 1163 | fun = (void (*)()) rmeth->method->ncode; |
58eb6e7c AG |
1164 | } |
1165 | else | |
1166 | { | |
7941ceab | 1167 | jobject rcv = sp[0].o; |
fdae83ab TT |
1168 | _Jv_VTable *table = *(_Jv_VTable**) rcv; |
1169 | fun = (void (*)()) table->get_method (rmeth->vtable_index); | |
1170 | } | |
1171 | ||
1172 | #ifdef DIRECT_THREADED | |
1173 | // Rewrite instruction so that we use a faster pre-resolved | |
1174 | // method. | |
1175 | pc[-2].insn = &&invokevirtual_resolved; | |
1176 | pc[-1].datum = rmeth; | |
1177 | #endif /* DIRECT_THREADED */ | |
1178 | } | |
1179 | goto perform_invoke; | |
1180 | ||
1181 | #ifdef DIRECT_THREADED | |
1182 | invokevirtual_resolved: | |
1183 | { | |
1184 | rmeth = (_Jv_ResolvedMethod *) AVAL (); | |
1185 | sp -= rmeth->stack_item_count; | |
1186 | // We don't use NULLCHECK here because we can't rely on that | |
1187 | // working if the method is final. So instead we do an | |
1188 | // explicit test. | |
1189 | if (! sp[0].o) | |
18744d9b BM |
1190 | { |
1191 | SAVE_PC(); | |
1192 | throw new java::lang::NullPointerException; | |
1193 | } | |
fdae83ab TT |
1194 | |
1195 | if (rmeth->vtable_index == -1) | |
1196 | { | |
1197 | // final methods do not appear in the vtable, | |
1198 | // if it does not appear in the superclass. | |
1199 | fun = (void (*)()) rmeth->method->ncode; | |
1200 | } | |
1201 | else | |
1202 | { | |
1203 | jobject rcv = sp[0].o; | |
1204 | _Jv_VTable *table = *(_Jv_VTable**) rcv; | |
1205 | fun = (void (*)()) table->get_method (rmeth->vtable_index); | |
58eb6e7c AG |
1206 | } |
1207 | } | |
1208 | goto perform_invoke; | |
fdae83ab | 1209 | #endif /* DIRECT_THREADED */ |
58eb6e7c | 1210 | |
fdae83ab | 1211 | perform_invoke: |
58eb6e7c | 1212 | { |
18744d9b BM |
1213 | SAVE_PC(); |
1214 | ||
58eb6e7c AG |
1215 | /* here goes the magic again... */ |
1216 | ffi_cif *cif = &rmeth->cif; | |
7941ceab | 1217 | ffi_raw *raw = (ffi_raw*) sp; |
58eb6e7c | 1218 | |
7a1c3d48 | 1219 | _Jv_value rvalue; |
58eb6e7c | 1220 | |
99444711 TT |
1221 | #if FFI_NATIVE_RAW_API |
1222 | /* We assume that this is only implemented if it's correct */ | |
1223 | /* to use it here. On a 64 bit machine, it never is. */ | |
7941ceab | 1224 | ffi_raw_call (cif, fun, (void*)&rvalue, raw); |
99444711 TT |
1225 | #else |
1226 | ffi_java_raw_call (cif, fun, (void*)&rvalue, raw); | |
1227 | #endif | |
58eb6e7c AG |
1228 | |
1229 | int rtype = cif->rtype->type; | |
1230 | ||
1231 | /* the likelyhood of object, int, or void return is very high, | |
1232 | * so those are checked before the switch */ | |
1233 | if (rtype == FFI_TYPE_POINTER) | |
1234 | { | |
7a1c3d48 | 1235 | PUSHA (rvalue.object_value); |
58eb6e7c AG |
1236 | } |
1237 | else if (rtype == FFI_TYPE_SINT32) | |
1238 | { | |
7a1c3d48 | 1239 | PUSHI (rvalue.int_value); |
58eb6e7c AG |
1240 | } |
1241 | else if (rtype == FFI_TYPE_VOID) | |
1242 | { | |
1243 | /* skip */ | |
1244 | } | |
fdae83ab | 1245 | else |
58eb6e7c | 1246 | { |
fdae83ab TT |
1247 | switch (rtype) |
1248 | { | |
1249 | case FFI_TYPE_SINT8: | |
5549179f | 1250 | PUSHI ((jbyte)(rvalue.int_value & 0xff)); |
fdae83ab | 1251 | break; |
58eb6e7c | 1252 | |
fdae83ab | 1253 | case FFI_TYPE_SINT16: |
5549179f | 1254 | PUSHI ((jshort)(rvalue.int_value & 0xffff)); |
fdae83ab | 1255 | break; |
58eb6e7c | 1256 | |
fdae83ab | 1257 | case FFI_TYPE_UINT16: |
5549179f | 1258 | PUSHI (rvalue.int_value & 0xffff); |
fdae83ab | 1259 | break; |
58eb6e7c | 1260 | |
fdae83ab | 1261 | case FFI_TYPE_FLOAT: |
7a1c3d48 | 1262 | PUSHF (rvalue.float_value); |
fdae83ab | 1263 | break; |
58eb6e7c | 1264 | |
fdae83ab | 1265 | case FFI_TYPE_DOUBLE: |
7a1c3d48 | 1266 | PUSHD (rvalue.double_value); |
fdae83ab | 1267 | break; |
58eb6e7c | 1268 | |
fdae83ab | 1269 | case FFI_TYPE_SINT64: |
7a1c3d48 | 1270 | PUSHL (rvalue.long_value); |
fdae83ab | 1271 | break; |
f7b4fb11 | 1272 | |
fdae83ab TT |
1273 | default: |
1274 | throw_internal_error ("unknown return type in invokeXXX"); | |
1275 | } | |
58eb6e7c | 1276 | } |
58eb6e7c | 1277 | } |
f7b4fb11 | 1278 | NEXT_INSN; |
58eb6e7c | 1279 | |
fdae83ab | 1280 | insn_aconst_null: |
58eb6e7c | 1281 | PUSHA (NULL); |
f7b4fb11 KKT |
1282 | NEXT_INSN; |
1283 | ||
fdae83ab | 1284 | insn_iconst_m1: |
f7b4fb11 KKT |
1285 | PUSHI (-1); |
1286 | NEXT_INSN; | |
1287 | ||
fdae83ab | 1288 | insn_iconst_0: |
f7b4fb11 KKT |
1289 | PUSHI (0); |
1290 | NEXT_INSN; | |
1291 | ||
fdae83ab | 1292 | insn_iconst_1: |
f7b4fb11 KKT |
1293 | PUSHI (1); |
1294 | NEXT_INSN; | |
1295 | ||
fdae83ab | 1296 | insn_iconst_2: |
f7b4fb11 KKT |
1297 | PUSHI (2); |
1298 | NEXT_INSN; | |
1299 | ||
fdae83ab | 1300 | insn_iconst_3: |
f7b4fb11 KKT |
1301 | PUSHI (3); |
1302 | NEXT_INSN; | |
1303 | ||
fdae83ab | 1304 | insn_iconst_4: |
f7b4fb11 KKT |
1305 | PUSHI (4); |
1306 | NEXT_INSN; | |
1307 | ||
fdae83ab | 1308 | insn_iconst_5: |
f7b4fb11 KKT |
1309 | PUSHI (5); |
1310 | NEXT_INSN; | |
1311 | ||
fdae83ab | 1312 | insn_lconst_0: |
f7b4fb11 KKT |
1313 | PUSHL (0); |
1314 | NEXT_INSN; | |
1315 | ||
fdae83ab | 1316 | insn_lconst_1: |
f7b4fb11 KKT |
1317 | PUSHL (1); |
1318 | NEXT_INSN; | |
1319 | ||
fdae83ab | 1320 | insn_fconst_0: |
f7b4fb11 KKT |
1321 | PUSHF (0); |
1322 | NEXT_INSN; | |
1323 | ||
fdae83ab | 1324 | insn_fconst_1: |
f7b4fb11 KKT |
1325 | PUSHF (1); |
1326 | NEXT_INSN; | |
1327 | ||
fdae83ab | 1328 | insn_fconst_2: |
f7b4fb11 KKT |
1329 | PUSHF (2); |
1330 | NEXT_INSN; | |
1331 | ||
fdae83ab | 1332 | insn_dconst_0: |
f7b4fb11 KKT |
1333 | PUSHD (0); |
1334 | NEXT_INSN; | |
1335 | ||
fdae83ab | 1336 | insn_dconst_1: |
f7b4fb11 KKT |
1337 | PUSHD (1); |
1338 | NEXT_INSN; | |
1339 | ||
fdae83ab TT |
1340 | insn_bipush: |
1341 | // For direct threaded, bipush and sipush are the same. | |
1342 | #ifndef DIRECT_THREADED | |
1343 | PUSHI (GET1S ()); | |
f7b4fb11 | 1344 | NEXT_INSN; |
fdae83ab TT |
1345 | #endif /* DIRECT_THREADED */ |
1346 | insn_sipush: | |
1347 | PUSHI (GET2S ()); | |
f7b4fb11 | 1348 | NEXT_INSN; |
58eb6e7c | 1349 | |
fdae83ab TT |
1350 | insn_ldc: |
1351 | // For direct threaded, ldc and ldc_w are the same. | |
1352 | #ifndef DIRECT_THREADED | |
1353 | PUSHA ((jobject) AVAL1U ()); | |
f7b4fb11 | 1354 | NEXT_INSN; |
fdae83ab TT |
1355 | #endif /* DIRECT_THREADED */ |
1356 | insn_ldc_w: | |
1357 | PUSHA ((jobject) AVAL2U ()); | |
f7b4fb11 | 1358 | NEXT_INSN; |
58eb6e7c | 1359 | |
a022cd59 TT |
1360 | #ifdef DIRECT_THREADED |
1361 | // For direct threaded we have a separate 'ldc class' operation. | |
1362 | insn_ldc_class: | |
1363 | { | |
1364 | // We could rewrite the instruction at this point. | |
1365 | int index = INTVAL (); | |
1366 | jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class, | |
1367 | index)).o; | |
1368 | PUSHA (k); | |
1369 | } | |
1370 | NEXT_INSN; | |
1371 | #endif /* DIRECT_THREADED */ | |
1372 | ||
fdae83ab | 1373 | insn_ldc2_w: |
58eb6e7c | 1374 | { |
fdae83ab TT |
1375 | void *where = AVAL2UP (); |
1376 | memcpy (sp, where, 2*sizeof (_Jv_word)); | |
58eb6e7c AG |
1377 | sp += 2; |
1378 | } | |
f7b4fb11 | 1379 | NEXT_INSN; |
58eb6e7c | 1380 | |
fdae83ab TT |
1381 | insn_lload: |
1382 | LOADL (GET1U ()); | |
f7b4fb11 | 1383 | NEXT_INSN; |
58eb6e7c | 1384 | |
fdae83ab TT |
1385 | insn_fload: |
1386 | LOADF (GET1U ()); | |
f7b4fb11 | 1387 | NEXT_INSN; |
58eb6e7c | 1388 | |
fdae83ab TT |
1389 | insn_dload: |
1390 | LOADD (GET1U ()); | |
f7b4fb11 | 1391 | NEXT_INSN; |
58eb6e7c | 1392 | |
fdae83ab TT |
1393 | insn_aload: |
1394 | LOADA (GET1U ()); | |
f7b4fb11 | 1395 | NEXT_INSN; |
58eb6e7c | 1396 | |
fdae83ab | 1397 | insn_iload_0: |
58eb6e7c | 1398 | LOADI (0); |
f7b4fb11 | 1399 | NEXT_INSN; |
58eb6e7c | 1400 | |
fdae83ab | 1401 | insn_iload_2: |
58eb6e7c | 1402 | LOADI (2); |
f7b4fb11 | 1403 | NEXT_INSN; |
58eb6e7c | 1404 | |
fdae83ab | 1405 | insn_iload_3: |
58eb6e7c | 1406 | LOADI (3); |
f7b4fb11 KKT |
1407 | NEXT_INSN; |
1408 | ||
fdae83ab | 1409 | insn_lload_0: |
f7b4fb11 KKT |
1410 | LOADL (0); |
1411 | NEXT_INSN; | |
1412 | ||
fdae83ab | 1413 | insn_lload_1: |
f7b4fb11 KKT |
1414 | LOADL (1); |
1415 | NEXT_INSN; | |
1416 | ||
fdae83ab | 1417 | insn_lload_2: |
f7b4fb11 KKT |
1418 | LOADL (2); |
1419 | NEXT_INSN; | |
1420 | ||
fdae83ab | 1421 | insn_lload_3: |
f7b4fb11 KKT |
1422 | LOADL (3); |
1423 | NEXT_INSN; | |
1424 | ||
fdae83ab | 1425 | insn_fload_0: |
f7b4fb11 KKT |
1426 | LOADF (0); |
1427 | NEXT_INSN; | |
1428 | ||
fdae83ab | 1429 | insn_fload_1: |
f7b4fb11 KKT |
1430 | LOADF (1); |
1431 | NEXT_INSN; | |
1432 | ||
fdae83ab | 1433 | insn_fload_2: |
f7b4fb11 KKT |
1434 | LOADF (2); |
1435 | NEXT_INSN; | |
1436 | ||
fdae83ab | 1437 | insn_fload_3: |
f7b4fb11 KKT |
1438 | LOADF (3); |
1439 | NEXT_INSN; | |
1440 | ||
fdae83ab | 1441 | insn_dload_0: |
f7b4fb11 KKT |
1442 | LOADD (0); |
1443 | NEXT_INSN; | |
1444 | ||
fdae83ab | 1445 | insn_dload_1: |
f7b4fb11 KKT |
1446 | LOADD (1); |
1447 | NEXT_INSN; | |
1448 | ||
fdae83ab | 1449 | insn_dload_2: |
f7b4fb11 KKT |
1450 | LOADD (2); |
1451 | NEXT_INSN; | |
1452 | ||
fdae83ab | 1453 | insn_dload_3: |
f7b4fb11 KKT |
1454 | LOADD (3); |
1455 | NEXT_INSN; | |
1456 | ||
fdae83ab | 1457 | insn_aload_1: |
58eb6e7c | 1458 | LOADA(1); |
f7b4fb11 | 1459 | NEXT_INSN; |
58eb6e7c | 1460 | |
fdae83ab | 1461 | insn_aload_2: |
58eb6e7c | 1462 | LOADA(2); |
f7b4fb11 | 1463 | NEXT_INSN; |
58eb6e7c | 1464 | |
fdae83ab | 1465 | insn_aload_3: |
58eb6e7c | 1466 | LOADA(3); |
f7b4fb11 | 1467 | NEXT_INSN; |
58eb6e7c | 1468 | |
fdae83ab | 1469 | insn_iaload: |
58eb6e7c AG |
1470 | { |
1471 | jint index = POPI(); | |
1472 | jintArray arr = (jintArray) POPA(); | |
cec71868 | 1473 | NULLARRAYCHECK (arr); |
00cc944d | 1474 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1475 | PUSHI( elements(arr)[index] ); |
1476 | } | |
f7b4fb11 | 1477 | NEXT_INSN; |
58eb6e7c | 1478 | |
fdae83ab | 1479 | insn_laload: |
58eb6e7c AG |
1480 | { |
1481 | jint index = POPI(); | |
1482 | jlongArray arr = (jlongArray) POPA(); | |
cec71868 | 1483 | NULLARRAYCHECK (arr); |
00cc944d | 1484 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1485 | PUSHL( elements(arr)[index] ); |
1486 | } | |
f7b4fb11 | 1487 | NEXT_INSN; |
58eb6e7c | 1488 | |
fdae83ab | 1489 | insn_faload: |
58eb6e7c AG |
1490 | { |
1491 | jint index = POPI(); | |
1492 | jfloatArray arr = (jfloatArray) POPA(); | |
cec71868 | 1493 | NULLARRAYCHECK (arr); |
00cc944d | 1494 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1495 | PUSHF( elements(arr)[index] ); |
1496 | } | |
f7b4fb11 | 1497 | NEXT_INSN; |
58eb6e7c | 1498 | |
fdae83ab | 1499 | insn_daload: |
58eb6e7c AG |
1500 | { |
1501 | jint index = POPI(); | |
1502 | jdoubleArray arr = (jdoubleArray) POPA(); | |
cec71868 | 1503 | NULLARRAYCHECK (arr); |
00cc944d | 1504 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1505 | PUSHD( elements(arr)[index] ); |
1506 | } | |
f7b4fb11 | 1507 | NEXT_INSN; |
58eb6e7c | 1508 | |
fdae83ab | 1509 | insn_aaload: |
58eb6e7c AG |
1510 | { |
1511 | jint index = POPI(); | |
1512 | jobjectArray arr = (jobjectArray) POPA(); | |
cec71868 | 1513 | NULLARRAYCHECK (arr); |
00cc944d | 1514 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1515 | PUSHA( elements(arr)[index] ); |
1516 | } | |
f7b4fb11 | 1517 | NEXT_INSN; |
58eb6e7c | 1518 | |
fdae83ab | 1519 | insn_baload: |
58eb6e7c AG |
1520 | { |
1521 | jint index = POPI(); | |
1522 | jbyteArray arr = (jbyteArray) POPA(); | |
cec71868 | 1523 | NULLARRAYCHECK (arr); |
00cc944d | 1524 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1525 | PUSHI( elements(arr)[index] ); |
1526 | } | |
f7b4fb11 | 1527 | NEXT_INSN; |
58eb6e7c | 1528 | |
fdae83ab | 1529 | insn_caload: |
58eb6e7c AG |
1530 | { |
1531 | jint index = POPI(); | |
1532 | jcharArray arr = (jcharArray) POPA(); | |
cec71868 | 1533 | NULLARRAYCHECK (arr); |
00cc944d | 1534 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1535 | PUSHI( elements(arr)[index] ); |
1536 | } | |
f7b4fb11 | 1537 | NEXT_INSN; |
58eb6e7c | 1538 | |
fdae83ab | 1539 | insn_saload: |
58eb6e7c AG |
1540 | { |
1541 | jint index = POPI(); | |
1542 | jshortArray arr = (jshortArray) POPA(); | |
cec71868 | 1543 | NULLARRAYCHECK (arr); |
00cc944d | 1544 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1545 | PUSHI( elements(arr)[index] ); |
1546 | } | |
f7b4fb11 | 1547 | NEXT_INSN; |
58eb6e7c | 1548 | |
fdae83ab TT |
1549 | insn_istore: |
1550 | STOREI (GET1U ()); | |
f7b4fb11 | 1551 | NEXT_INSN; |
58eb6e7c | 1552 | |
fdae83ab TT |
1553 | insn_lstore: |
1554 | STOREL (GET1U ()); | |
f7b4fb11 | 1555 | NEXT_INSN; |
58eb6e7c | 1556 | |
fdae83ab TT |
1557 | insn_fstore: |
1558 | STOREF (GET1U ()); | |
f7b4fb11 | 1559 | NEXT_INSN; |
58eb6e7c | 1560 | |
fdae83ab TT |
1561 | insn_dstore: |
1562 | STORED (GET1U ()); | |
f7b4fb11 | 1563 | NEXT_INSN; |
58eb6e7c | 1564 | |
fdae83ab TT |
1565 | insn_astore: |
1566 | STOREA (GET1U ()); | |
f7b4fb11 KKT |
1567 | NEXT_INSN; |
1568 | ||
fdae83ab | 1569 | insn_istore_0: |
f7b4fb11 KKT |
1570 | STOREI (0); |
1571 | NEXT_INSN; | |
1572 | ||
fdae83ab | 1573 | insn_istore_1: |
f7b4fb11 KKT |
1574 | STOREI (1); |
1575 | NEXT_INSN; | |
1576 | ||
fdae83ab | 1577 | insn_istore_2: |
f7b4fb11 KKT |
1578 | STOREI (2); |
1579 | NEXT_INSN; | |
1580 | ||
fdae83ab | 1581 | insn_istore_3: |
f7b4fb11 KKT |
1582 | STOREI (3); |
1583 | NEXT_INSN; | |
1584 | ||
fdae83ab | 1585 | insn_lstore_0: |
f7b4fb11 KKT |
1586 | STOREL (0); |
1587 | NEXT_INSN; | |
1588 | ||
fdae83ab | 1589 | insn_lstore_1: |
f7b4fb11 KKT |
1590 | STOREL (1); |
1591 | NEXT_INSN; | |
1592 | ||
fdae83ab | 1593 | insn_lstore_2: |
f7b4fb11 KKT |
1594 | STOREL (2); |
1595 | NEXT_INSN; | |
1596 | ||
fdae83ab | 1597 | insn_lstore_3: |
f7b4fb11 KKT |
1598 | STOREL (3); |
1599 | NEXT_INSN; | |
1600 | ||
fdae83ab | 1601 | insn_fstore_0: |
f7b4fb11 KKT |
1602 | STOREF (0); |
1603 | NEXT_INSN; | |
1604 | ||
fdae83ab | 1605 | insn_fstore_1: |
f7b4fb11 KKT |
1606 | STOREF (1); |
1607 | NEXT_INSN; | |
1608 | ||
fdae83ab | 1609 | insn_fstore_2: |
f7b4fb11 KKT |
1610 | STOREF (2); |
1611 | NEXT_INSN; | |
1612 | ||
fdae83ab | 1613 | insn_fstore_3: |
f7b4fb11 KKT |
1614 | STOREF (3); |
1615 | NEXT_INSN; | |
1616 | ||
fdae83ab | 1617 | insn_dstore_0: |
f7b4fb11 KKT |
1618 | STORED (0); |
1619 | NEXT_INSN; | |
1620 | ||
fdae83ab | 1621 | insn_dstore_1: |
f7b4fb11 KKT |
1622 | STORED (1); |
1623 | NEXT_INSN; | |
1624 | ||
fdae83ab | 1625 | insn_dstore_2: |
f7b4fb11 KKT |
1626 | STORED (2); |
1627 | NEXT_INSN; | |
1628 | ||
fdae83ab | 1629 | insn_dstore_3: |
f7b4fb11 KKT |
1630 | STORED (3); |
1631 | NEXT_INSN; | |
1632 | ||
fdae83ab | 1633 | insn_astore_0: |
f7b4fb11 KKT |
1634 | STOREA(0); |
1635 | NEXT_INSN; | |
1636 | ||
fdae83ab | 1637 | insn_astore_1: |
f7b4fb11 KKT |
1638 | STOREA(1); |
1639 | NEXT_INSN; | |
1640 | ||
fdae83ab | 1641 | insn_astore_2: |
f7b4fb11 KKT |
1642 | STOREA(2); |
1643 | NEXT_INSN; | |
1644 | ||
fdae83ab | 1645 | insn_astore_3: |
f7b4fb11 KKT |
1646 | STOREA(3); |
1647 | NEXT_INSN; | |
1648 | ||
fdae83ab | 1649 | insn_iastore: |
58eb6e7c AG |
1650 | { |
1651 | jint value = POPI(); | |
1652 | jint index = POPI(); | |
1653 | jintArray arr = (jintArray) POPA(); | |
cec71868 | 1654 | NULLARRAYCHECK (arr); |
00cc944d | 1655 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1656 | elements(arr)[index] = value; |
1657 | } | |
f7b4fb11 | 1658 | NEXT_INSN; |
58eb6e7c | 1659 | |
fdae83ab | 1660 | insn_lastore: |
58eb6e7c AG |
1661 | { |
1662 | jlong value = POPL(); | |
1663 | jint index = POPI(); | |
1664 | jlongArray arr = (jlongArray) POPA(); | |
cec71868 | 1665 | NULLARRAYCHECK (arr); |
00cc944d | 1666 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1667 | elements(arr)[index] = value; |
1668 | } | |
f7b4fb11 | 1669 | NEXT_INSN; |
58eb6e7c | 1670 | |
fdae83ab | 1671 | insn_fastore: |
58eb6e7c AG |
1672 | { |
1673 | jfloat value = POPF(); | |
1674 | jint index = POPI(); | |
1675 | jfloatArray arr = (jfloatArray) POPA(); | |
cec71868 | 1676 | NULLARRAYCHECK (arr); |
00cc944d | 1677 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1678 | elements(arr)[index] = value; |
1679 | } | |
f7b4fb11 | 1680 | NEXT_INSN; |
58eb6e7c | 1681 | |
fdae83ab | 1682 | insn_dastore: |
58eb6e7c AG |
1683 | { |
1684 | jdouble value = POPD(); | |
1685 | jint index = POPI(); | |
1686 | jdoubleArray arr = (jdoubleArray) POPA(); | |
cec71868 | 1687 | NULLARRAYCHECK (arr); |
00cc944d | 1688 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1689 | elements(arr)[index] = value; |
1690 | } | |
f7b4fb11 | 1691 | NEXT_INSN; |
58eb6e7c | 1692 | |
fdae83ab | 1693 | insn_aastore: |
58eb6e7c AG |
1694 | { |
1695 | jobject value = POPA(); | |
1696 | jint index = POPI(); | |
1697 | jobjectArray arr = (jobjectArray) POPA(); | |
cec71868 | 1698 | NULLARRAYCHECK (arr); |
00cc944d | 1699 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1700 | _Jv_CheckArrayStore (arr, value); |
1701 | elements(arr)[index] = value; | |
1702 | } | |
f7b4fb11 | 1703 | NEXT_INSN; |
58eb6e7c | 1704 | |
fdae83ab | 1705 | insn_bastore: |
58eb6e7c AG |
1706 | { |
1707 | jbyte value = (jbyte) POPI(); | |
1708 | jint index = POPI(); | |
1709 | jbyteArray arr = (jbyteArray) POPA(); | |
cec71868 | 1710 | NULLARRAYCHECK (arr); |
00cc944d | 1711 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1712 | elements(arr)[index] = value; |
1713 | } | |
f7b4fb11 | 1714 | NEXT_INSN; |
58eb6e7c | 1715 | |
fdae83ab | 1716 | insn_castore: |
58eb6e7c AG |
1717 | { |
1718 | jchar value = (jchar) POPI(); | |
1719 | jint index = POPI(); | |
1720 | jcharArray arr = (jcharArray) POPA(); | |
cec71868 | 1721 | NULLARRAYCHECK (arr); |
00cc944d | 1722 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1723 | elements(arr)[index] = value; |
1724 | } | |
f7b4fb11 | 1725 | NEXT_INSN; |
58eb6e7c | 1726 | |
fdae83ab | 1727 | insn_sastore: |
58eb6e7c AG |
1728 | { |
1729 | jshort value = (jshort) POPI(); | |
1730 | jint index = POPI(); | |
1731 | jshortArray arr = (jshortArray) POPA(); | |
cec71868 | 1732 | NULLARRAYCHECK (arr); |
00cc944d | 1733 | ARRAYBOUNDSCHECK (arr, index); |
58eb6e7c AG |
1734 | elements(arr)[index] = value; |
1735 | } | |
f7b4fb11 | 1736 | NEXT_INSN; |
58eb6e7c | 1737 | |
fdae83ab | 1738 | insn_pop: |
58eb6e7c | 1739 | sp -= 1; |
f7b4fb11 | 1740 | NEXT_INSN; |
58eb6e7c | 1741 | |
fdae83ab | 1742 | insn_pop2: |
58eb6e7c | 1743 | sp -= 2; |
f7b4fb11 | 1744 | NEXT_INSN; |
58eb6e7c | 1745 | |
fdae83ab | 1746 | insn_dup: |
58eb6e7c AG |
1747 | sp[0] = sp[-1]; |
1748 | sp += 1; | |
f7b4fb11 | 1749 | NEXT_INSN; |
58eb6e7c | 1750 | |
fdae83ab | 1751 | insn_dup_x1: |
f7b4fb11 KKT |
1752 | dupx (sp, 1, 1); sp+=1; |
1753 | NEXT_INSN; | |
58eb6e7c | 1754 | |
fdae83ab | 1755 | insn_dup_x2: |
f7b4fb11 KKT |
1756 | dupx (sp, 1, 2); sp+=1; |
1757 | NEXT_INSN; | |
58eb6e7c | 1758 | |
fdae83ab | 1759 | insn_dup2: |
58eb6e7c AG |
1760 | sp[0] = sp[-2]; |
1761 | sp[1] = sp[-1]; | |
1762 | sp += 2; | |
f7b4fb11 | 1763 | NEXT_INSN; |
58eb6e7c | 1764 | |
fdae83ab | 1765 | insn_dup2_x1: |
f7b4fb11 KKT |
1766 | dupx (sp, 2, 1); sp+=2; |
1767 | NEXT_INSN; | |
58eb6e7c | 1768 | |
fdae83ab | 1769 | insn_dup2_x2: |
f7b4fb11 KKT |
1770 | dupx (sp, 2, 2); sp+=2; |
1771 | NEXT_INSN; | |
58eb6e7c | 1772 | |
fdae83ab | 1773 | insn_swap: |
58eb6e7c AG |
1774 | { |
1775 | jobject tmp1 = POPA(); | |
1776 | jobject tmp2 = POPA(); | |
1777 | PUSHA (tmp1); | |
1778 | PUSHA (tmp2); | |
1779 | } | |
f7b4fb11 | 1780 | NEXT_INSN; |
58eb6e7c | 1781 | |
fdae83ab | 1782 | insn_iadd: |
58eb6e7c | 1783 | BINOPI(+); |
f7b4fb11 | 1784 | NEXT_INSN; |
58eb6e7c | 1785 | |
fdae83ab | 1786 | insn_ladd: |
58eb6e7c | 1787 | BINOPL(+); |
f7b4fb11 | 1788 | NEXT_INSN; |
58eb6e7c | 1789 | |
fdae83ab | 1790 | insn_fadd: |
58eb6e7c | 1791 | BINOPF(+); |
f7b4fb11 | 1792 | NEXT_INSN; |
58eb6e7c | 1793 | |
fdae83ab | 1794 | insn_dadd: |
58eb6e7c | 1795 | BINOPD(+); |
f7b4fb11 | 1796 | NEXT_INSN; |
58eb6e7c | 1797 | |
fdae83ab | 1798 | insn_isub: |
58eb6e7c | 1799 | BINOPI(-); |
f7b4fb11 | 1800 | NEXT_INSN; |
58eb6e7c | 1801 | |
fdae83ab | 1802 | insn_lsub: |
58eb6e7c | 1803 | BINOPL(-); |
f7b4fb11 | 1804 | NEXT_INSN; |
58eb6e7c | 1805 | |
fdae83ab | 1806 | insn_fsub: |
58eb6e7c | 1807 | BINOPF(-); |
f7b4fb11 | 1808 | NEXT_INSN; |
58eb6e7c | 1809 | |
fdae83ab | 1810 | insn_dsub: |
58eb6e7c | 1811 | BINOPD(-); |
f7b4fb11 | 1812 | NEXT_INSN; |
58eb6e7c | 1813 | |
fdae83ab | 1814 | insn_imul: |
58eb6e7c | 1815 | BINOPI(*); |
f7b4fb11 | 1816 | NEXT_INSN; |
58eb6e7c | 1817 | |
fdae83ab | 1818 | insn_lmul: |
58eb6e7c | 1819 | BINOPL(*); |
f7b4fb11 | 1820 | NEXT_INSN; |
58eb6e7c | 1821 | |
fdae83ab | 1822 | insn_fmul: |
58eb6e7c | 1823 | BINOPF(*); |
f7b4fb11 | 1824 | NEXT_INSN; |
58eb6e7c | 1825 | |
fdae83ab | 1826 | insn_dmul: |
58eb6e7c | 1827 | BINOPD(*); |
f7b4fb11 | 1828 | NEXT_INSN; |
58eb6e7c | 1829 | |
fdae83ab | 1830 | insn_idiv: |
58eb6e7c AG |
1831 | { |
1832 | jint value2 = POPI(); | |
1833 | jint value1 = POPI(); | |
6c80c45e | 1834 | jint res = _Jv_divI (value1, value2); |
58eb6e7c AG |
1835 | PUSHI (res); |
1836 | } | |
f7b4fb11 | 1837 | NEXT_INSN; |
58eb6e7c | 1838 | |
fdae83ab | 1839 | insn_ldiv: |
f7b4fb11 | 1840 | { |
58eb6e7c AG |
1841 | jlong value2 = POPL(); |
1842 | jlong value1 = POPL(); | |
6c80c45e | 1843 | jlong res = _Jv_divJ (value1, value2); |
58eb6e7c AG |
1844 | PUSHL (res); |
1845 | } | |
f7b4fb11 | 1846 | NEXT_INSN; |
58eb6e7c | 1847 | |
fdae83ab | 1848 | insn_fdiv: |
58eb6e7c AG |
1849 | { |
1850 | jfloat value2 = POPF(); | |
1851 | jfloat value1 = POPF(); | |
58eb6e7c AG |
1852 | jfloat res = value1 / value2; |
1853 | PUSHF (res); | |
1854 | } | |
f7b4fb11 | 1855 | NEXT_INSN; |
58eb6e7c | 1856 | |
fdae83ab | 1857 | insn_ddiv: |
58eb6e7c AG |
1858 | { |
1859 | jdouble value2 = POPD(); | |
1860 | jdouble value1 = POPD(); | |
58eb6e7c AG |
1861 | jdouble res = value1 / value2; |
1862 | PUSHD (res); | |
1863 | } | |
f7b4fb11 | 1864 | NEXT_INSN; |
58eb6e7c | 1865 | |
fdae83ab | 1866 | insn_irem: |
58eb6e7c AG |
1867 | { |
1868 | jint value2 = POPI(); | |
6c80c45e TT |
1869 | jint value1 = POPI(); |
1870 | jint res = _Jv_remI (value1, value2); | |
58eb6e7c AG |
1871 | PUSHI (res); |
1872 | } | |
f7b4fb11 | 1873 | NEXT_INSN; |
58eb6e7c | 1874 | |
fdae83ab | 1875 | insn_lrem: |
f7b4fb11 | 1876 | { |
58eb6e7c AG |
1877 | jlong value2 = POPL(); |
1878 | jlong value1 = POPL(); | |
6c80c45e | 1879 | jlong res = _Jv_remJ (value1, value2); |
58eb6e7c AG |
1880 | PUSHL (res); |
1881 | } | |
f7b4fb11 | 1882 | NEXT_INSN; |
58eb6e7c | 1883 | |
fdae83ab | 1884 | insn_frem: |
58eb6e7c AG |
1885 | { |
1886 | jfloat value2 = POPF(); | |
1887 | jfloat value1 = POPF(); | |
58eb6e7c AG |
1888 | jfloat res = __ieee754_fmod (value1, value2); |
1889 | PUSHF (res); | |
1890 | } | |
f7b4fb11 | 1891 | NEXT_INSN; |
58eb6e7c | 1892 | |
fdae83ab | 1893 | insn_drem: |
58eb6e7c AG |
1894 | { |
1895 | jdouble value2 = POPD(); | |
1896 | jdouble value1 = POPD(); | |
58eb6e7c AG |
1897 | jdouble res = __ieee754_fmod (value1, value2); |
1898 | PUSHD (res); | |
1899 | } | |
f7b4fb11 | 1900 | NEXT_INSN; |
58eb6e7c | 1901 | |
fdae83ab | 1902 | insn_ineg: |
f7b4fb11 KKT |
1903 | { |
1904 | jint value = POPI(); | |
1905 | PUSHI (value * -1); | |
1906 | } | |
1907 | NEXT_INSN; | |
58eb6e7c | 1908 | |
fdae83ab | 1909 | insn_lneg: |
f7b4fb11 KKT |
1910 | { |
1911 | jlong value = POPL(); | |
1912 | PUSHL (value * -1); | |
1913 | } | |
1914 | NEXT_INSN; | |
58eb6e7c | 1915 | |
fdae83ab | 1916 | insn_fneg: |
f7b4fb11 KKT |
1917 | { |
1918 | jfloat value = POPF(); | |
1919 | PUSHF (value * -1); | |
1920 | } | |
1921 | NEXT_INSN; | |
58eb6e7c | 1922 | |
fdae83ab | 1923 | insn_dneg: |
f7b4fb11 KKT |
1924 | { |
1925 | jdouble value = POPD(); | |
1926 | PUSHD (value * -1); | |
1927 | } | |
1928 | NEXT_INSN; | |
58eb6e7c | 1929 | |
fdae83ab | 1930 | insn_ishl: |
58eb6e7c AG |
1931 | { |
1932 | jint shift = (POPI() & 0x1f); | |
1933 | jint value = POPI(); | |
1934 | PUSHI (value << shift); | |
1935 | } | |
f7b4fb11 | 1936 | NEXT_INSN; |
58eb6e7c | 1937 | |
fdae83ab | 1938 | insn_lshl: |
58eb6e7c AG |
1939 | { |
1940 | jint shift = (POPI() & 0x3f); | |
1941 | jlong value = POPL(); | |
1942 | PUSHL (value << shift); | |
1943 | } | |
f7b4fb11 | 1944 | NEXT_INSN; |
58eb6e7c | 1945 | |
fdae83ab | 1946 | insn_ishr: |
58eb6e7c AG |
1947 | { |
1948 | jint shift = (POPI() & 0x1f); | |
1949 | jint value = POPI(); | |
1950 | PUSHI (value >> shift); | |
1951 | } | |
f7b4fb11 | 1952 | NEXT_INSN; |
58eb6e7c | 1953 | |
fdae83ab | 1954 | insn_lshr: |
58eb6e7c AG |
1955 | { |
1956 | jint shift = (POPI() & 0x3f); | |
1957 | jlong value = POPL(); | |
1958 | PUSHL (value >> shift); | |
1959 | } | |
f7b4fb11 | 1960 | NEXT_INSN; |
58eb6e7c | 1961 | |
fdae83ab | 1962 | insn_iushr: |
58eb6e7c AG |
1963 | { |
1964 | jint shift = (POPI() & 0x1f); | |
415c96ca | 1965 | _Jv_uint value = (_Jv_uint) POPI(); |
58eb6e7c AG |
1966 | PUSHI ((jint) (value >> shift)); |
1967 | } | |
f7b4fb11 | 1968 | NEXT_INSN; |
58eb6e7c | 1969 | |
fdae83ab | 1970 | insn_lushr: |
58eb6e7c AG |
1971 | { |
1972 | jint shift = (POPI() & 0x3f); | |
415c96ca PB |
1973 | _Jv_ulong value = (_Jv_ulong) POPL(); |
1974 | PUSHL ((jlong) (value >> shift)); | |
58eb6e7c | 1975 | } |
f7b4fb11 | 1976 | NEXT_INSN; |
58eb6e7c | 1977 | |
fdae83ab | 1978 | insn_iand: |
58eb6e7c | 1979 | BINOPI (&); |
f7b4fb11 | 1980 | NEXT_INSN; |
58eb6e7c | 1981 | |
fdae83ab | 1982 | insn_land: |
58eb6e7c | 1983 | BINOPL (&); |
f7b4fb11 | 1984 | NEXT_INSN; |
58eb6e7c | 1985 | |
fdae83ab | 1986 | insn_ior: |
58eb6e7c | 1987 | BINOPI (|); |
f7b4fb11 | 1988 | NEXT_INSN; |
58eb6e7c | 1989 | |
fdae83ab | 1990 | insn_lor: |
58eb6e7c | 1991 | BINOPL (|); |
f7b4fb11 | 1992 | NEXT_INSN; |
58eb6e7c | 1993 | |
fdae83ab | 1994 | insn_ixor: |
58eb6e7c | 1995 | BINOPI (^); |
f7b4fb11 | 1996 | NEXT_INSN; |
58eb6e7c | 1997 | |
fdae83ab | 1998 | insn_lxor: |
58eb6e7c | 1999 | BINOPL (^); |
f7b4fb11 | 2000 | NEXT_INSN; |
58eb6e7c | 2001 | |
fdae83ab | 2002 | insn_iinc: |
58eb6e7c | 2003 | { |
fdae83ab TT |
2004 | jint index = GET1U (); |
2005 | jint amount = GET1S (); | |
f7b4fb11 | 2006 | locals[index].i += amount; |
58eb6e7c | 2007 | } |
f7b4fb11 | 2008 | NEXT_INSN; |
58eb6e7c | 2009 | |
fdae83ab | 2010 | insn_i2l: |
eb4534a6 | 2011 | {jlong value = POPI(); PUSHL (value);} |
f7b4fb11 | 2012 | NEXT_INSN; |
58eb6e7c | 2013 | |
fdae83ab | 2014 | insn_i2f: |
eb4534a6 | 2015 | {jfloat value = POPI(); PUSHF (value);} |
f7b4fb11 | 2016 | NEXT_INSN; |
58eb6e7c | 2017 | |
fdae83ab | 2018 | insn_i2d: |
eb4534a6 | 2019 | {jdouble value = POPI(); PUSHD (value);} |
f7b4fb11 | 2020 | NEXT_INSN; |
58eb6e7c | 2021 | |
fdae83ab | 2022 | insn_l2i: |
eb4534a6 | 2023 | {jint value = POPL(); PUSHI (value);} |
f7b4fb11 | 2024 | NEXT_INSN; |
58eb6e7c | 2025 | |
fdae83ab | 2026 | insn_l2f: |
eb4534a6 | 2027 | {jfloat value = POPL(); PUSHF (value);} |
f7b4fb11 | 2028 | NEXT_INSN; |
58eb6e7c | 2029 | |
fdae83ab | 2030 | insn_l2d: |
eb4534a6 | 2031 | {jdouble value = POPL(); PUSHD (value);} |
f7b4fb11 | 2032 | NEXT_INSN; |
58eb6e7c | 2033 | |
fdae83ab | 2034 | insn_f2i: |
30d28794 TT |
2035 | { |
2036 | using namespace java::lang; | |
2037 | jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE); | |
2038 | PUSHI(value); | |
2039 | } | |
f7b4fb11 | 2040 | NEXT_INSN; |
58eb6e7c | 2041 | |
fdae83ab | 2042 | insn_f2l: |
30d28794 TT |
2043 | { |
2044 | using namespace java::lang; | |
2045 | jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE); | |
1347adff | 2046 | PUSHL(value); |
30d28794 | 2047 | } |
f7b4fb11 | 2048 | NEXT_INSN; |
58eb6e7c | 2049 | |
fdae83ab | 2050 | insn_f2d: |
eb4534a6 | 2051 | { jdouble value = POPF (); PUSHD(value); } |
f7b4fb11 | 2052 | NEXT_INSN; |
58eb6e7c | 2053 | |
fdae83ab | 2054 | insn_d2i: |
30d28794 TT |
2055 | { |
2056 | using namespace java::lang; | |
2057 | jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE); | |
2058 | PUSHI(value); | |
2059 | } | |
f7b4fb11 | 2060 | NEXT_INSN; |
58eb6e7c | 2061 | |
fdae83ab | 2062 | insn_d2l: |
30d28794 TT |
2063 | { |
2064 | using namespace java::lang; | |
2065 | jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE); | |
2066 | PUSHL(value); | |
2067 | } | |
f7b4fb11 | 2068 | NEXT_INSN; |
58eb6e7c | 2069 | |
fdae83ab | 2070 | insn_d2f: |
eb4534a6 | 2071 | { jfloat value = POPD (); PUSHF(value); } |
f7b4fb11 | 2072 | NEXT_INSN; |
58eb6e7c | 2073 | |
fdae83ab | 2074 | insn_i2b: |
eb4534a6 | 2075 | { jbyte value = POPI (); PUSHI(value); } |
f7b4fb11 | 2076 | NEXT_INSN; |
58eb6e7c | 2077 | |
fdae83ab | 2078 | insn_i2c: |
eb4534a6 | 2079 | { jchar value = POPI (); PUSHI(value); } |
f7b4fb11 | 2080 | NEXT_INSN; |
58eb6e7c | 2081 | |
fdae83ab | 2082 | insn_i2s: |
eb4534a6 | 2083 | { jshort value = POPI (); PUSHI(value); } |
f7b4fb11 | 2084 | NEXT_INSN; |
58eb6e7c | 2085 | |
fdae83ab | 2086 | insn_lcmp: |
58eb6e7c AG |
2087 | { |
2088 | jlong value2 = POPL (); | |
2089 | jlong value1 = POPL (); | |
2090 | if (value1 > value2) | |
2091 | { PUSHI (1); } | |
2092 | else if (value1 == value2) | |
2093 | { PUSHI (0); } | |
2094 | else | |
2095 | { PUSHI (-1); } | |
2096 | } | |
f7b4fb11 | 2097 | NEXT_INSN; |
58eb6e7c | 2098 | |
fdae83ab TT |
2099 | insn_fcmpl: |
2100 | tmpval = -1; | |
2101 | goto fcmp; | |
2102 | ||
2103 | insn_fcmpg: | |
2104 | tmpval = 1; | |
2105 | ||
2106 | fcmp: | |
58eb6e7c AG |
2107 | { |
2108 | jfloat value2 = POPF (); | |
2109 | jfloat value1 = POPF (); | |
2110 | if (value1 > value2) | |
2111 | PUSHI (1); | |
2112 | else if (value1 == value2) | |
2113 | PUSHI (0); | |
2114 | else if (value1 < value2) | |
2115 | PUSHI (-1); | |
58eb6e7c | 2116 | else |
fdae83ab | 2117 | PUSHI (tmpval); |
58eb6e7c | 2118 | } |
f7b4fb11 | 2119 | NEXT_INSN; |
58eb6e7c | 2120 | |
fdae83ab | 2121 | insn_dcmpl: |
a8182d37 | 2122 | tmpval = -1; |
fdae83ab TT |
2123 | goto dcmp; |
2124 | ||
2125 | insn_dcmpg: | |
a8182d37 | 2126 | tmpval = 1; |
fdae83ab TT |
2127 | |
2128 | dcmp: | |
58eb6e7c AG |
2129 | { |
2130 | jdouble value2 = POPD (); | |
2131 | jdouble value1 = POPD (); | |
2132 | if (value1 > value2) | |
2133 | PUSHI (1); | |
2134 | else if (value1 == value2) | |
2135 | PUSHI (0); | |
2136 | else if (value1 < value2) | |
2137 | PUSHI (-1); | |
58eb6e7c | 2138 | else |
fdae83ab | 2139 | PUSHI (tmpval); |
58eb6e7c | 2140 | } |
f7b4fb11 | 2141 | NEXT_INSN; |
58eb6e7c | 2142 | |
fdae83ab | 2143 | insn_ifeq: |
58eb6e7c | 2144 | { |
58eb6e7c | 2145 | if (POPI() == 0) |
fdae83ab | 2146 | TAKE_GOTO; |
58eb6e7c | 2147 | else |
fdae83ab | 2148 | SKIP_GOTO; |
58eb6e7c | 2149 | } |
f7b4fb11 | 2150 | NEXT_INSN; |
58eb6e7c | 2151 | |
fdae83ab | 2152 | insn_ifne: |
58eb6e7c | 2153 | { |
58eb6e7c | 2154 | if (POPI() != 0) |
fdae83ab | 2155 | TAKE_GOTO; |
58eb6e7c | 2156 | else |
fdae83ab | 2157 | SKIP_GOTO; |
58eb6e7c | 2158 | } |
f7b4fb11 | 2159 | NEXT_INSN; |
58eb6e7c | 2160 | |
fdae83ab | 2161 | insn_iflt: |
58eb6e7c | 2162 | { |
58eb6e7c | 2163 | if (POPI() < 0) |
fdae83ab | 2164 | TAKE_GOTO; |
58eb6e7c | 2165 | else |
fdae83ab | 2166 | SKIP_GOTO; |
58eb6e7c | 2167 | } |
f7b4fb11 | 2168 | NEXT_INSN; |
58eb6e7c | 2169 | |
fdae83ab | 2170 | insn_ifge: |
58eb6e7c | 2171 | { |
58eb6e7c | 2172 | if (POPI() >= 0) |
fdae83ab | 2173 | TAKE_GOTO; |
58eb6e7c | 2174 | else |
fdae83ab | 2175 | SKIP_GOTO; |
58eb6e7c | 2176 | } |
f7b4fb11 | 2177 | NEXT_INSN; |
58eb6e7c | 2178 | |
fdae83ab | 2179 | insn_ifgt: |
58eb6e7c | 2180 | { |
58eb6e7c | 2181 | if (POPI() > 0) |
fdae83ab | 2182 | TAKE_GOTO; |
58eb6e7c | 2183 | else |
fdae83ab | 2184 | SKIP_GOTO; |
58eb6e7c | 2185 | } |
f7b4fb11 | 2186 | NEXT_INSN; |
58eb6e7c | 2187 | |
fdae83ab | 2188 | insn_ifle: |
58eb6e7c | 2189 | { |
58eb6e7c | 2190 | if (POPI() <= 0) |
fdae83ab | 2191 | TAKE_GOTO; |
58eb6e7c | 2192 | else |
fdae83ab | 2193 | SKIP_GOTO; |
58eb6e7c | 2194 | } |
f7b4fb11 | 2195 | NEXT_INSN; |
58eb6e7c | 2196 | |
fdae83ab | 2197 | insn_if_icmpeq: |
58eb6e7c | 2198 | { |
58eb6e7c AG |
2199 | jint value2 = POPI(); |
2200 | jint value1 = POPI(); | |
2201 | if (value1 == value2) | |
fdae83ab | 2202 | TAKE_GOTO; |
58eb6e7c | 2203 | else |
fdae83ab | 2204 | SKIP_GOTO; |
58eb6e7c | 2205 | } |
f7b4fb11 | 2206 | NEXT_INSN; |
58eb6e7c | 2207 | |
fdae83ab | 2208 | insn_if_icmpne: |
58eb6e7c | 2209 | { |
58eb6e7c AG |
2210 | jint value2 = POPI(); |
2211 | jint value1 = POPI(); | |
2212 | if (value1 != value2) | |
fdae83ab | 2213 | TAKE_GOTO; |
58eb6e7c | 2214 | else |
fdae83ab | 2215 | SKIP_GOTO; |
58eb6e7c | 2216 | } |
f7b4fb11 | 2217 | NEXT_INSN; |
58eb6e7c | 2218 | |
fdae83ab | 2219 | insn_if_icmplt: |
58eb6e7c | 2220 | { |
58eb6e7c AG |
2221 | jint value2 = POPI(); |
2222 | jint value1 = POPI(); | |
2223 | if (value1 < value2) | |
fdae83ab | 2224 | TAKE_GOTO; |
58eb6e7c | 2225 | else |
fdae83ab | 2226 | SKIP_GOTO; |
58eb6e7c | 2227 | } |
f7b4fb11 | 2228 | NEXT_INSN; |
58eb6e7c | 2229 | |
fdae83ab | 2230 | insn_if_icmpge: |
58eb6e7c | 2231 | { |
58eb6e7c AG |
2232 | jint value2 = POPI(); |
2233 | jint value1 = POPI(); | |
2234 | if (value1 >= value2) | |
fdae83ab | 2235 | TAKE_GOTO; |
58eb6e7c | 2236 | else |
fdae83ab | 2237 | SKIP_GOTO; |
58eb6e7c | 2238 | } |
f7b4fb11 | 2239 | NEXT_INSN; |
58eb6e7c | 2240 | |
fdae83ab | 2241 | insn_if_icmpgt: |
58eb6e7c | 2242 | { |
58eb6e7c AG |
2243 | jint value2 = POPI(); |
2244 | jint value1 = POPI(); | |
2245 | if (value1 > value2) | |
fdae83ab | 2246 | TAKE_GOTO; |
58eb6e7c | 2247 | else |
fdae83ab | 2248 | SKIP_GOTO; |
58eb6e7c | 2249 | } |
f7b4fb11 | 2250 | NEXT_INSN; |
58eb6e7c | 2251 | |
fdae83ab | 2252 | insn_if_icmple: |
58eb6e7c | 2253 | { |
58eb6e7c AG |
2254 | jint value2 = POPI(); |
2255 | jint value1 = POPI(); | |
2256 | if (value1 <= value2) | |
fdae83ab | 2257 | TAKE_GOTO; |
58eb6e7c | 2258 | else |
fdae83ab | 2259 | SKIP_GOTO; |
58eb6e7c | 2260 | } |
f7b4fb11 | 2261 | NEXT_INSN; |
58eb6e7c | 2262 | |
fdae83ab | 2263 | insn_if_acmpeq: |
58eb6e7c | 2264 | { |
58eb6e7c AG |
2265 | jobject value2 = POPA(); |
2266 | jobject value1 = POPA(); | |
2267 | if (value1 == value2) | |
fdae83ab | 2268 | TAKE_GOTO; |
58eb6e7c | 2269 | else |
fdae83ab | 2270 | SKIP_GOTO; |
58eb6e7c | 2271 | } |
f7b4fb11 | 2272 | NEXT_INSN; |
58eb6e7c | 2273 | |
fdae83ab | 2274 | insn_if_acmpne: |
58eb6e7c | 2275 | { |
58eb6e7c AG |
2276 | jobject value2 = POPA(); |
2277 | jobject value1 = POPA(); | |
2278 | if (value1 != value2) | |
fdae83ab | 2279 | TAKE_GOTO; |
58eb6e7c | 2280 | else |
fdae83ab | 2281 | SKIP_GOTO; |
58eb6e7c | 2282 | } |
f7b4fb11 | 2283 | NEXT_INSN; |
58eb6e7c | 2284 | |
fdae83ab TT |
2285 | insn_goto_w: |
2286 | #ifndef DIRECT_THREADED | |
2287 | // For direct threaded, goto and goto_w are the same. | |
2288 | pc = pc - 1 + get4 (pc); | |
2289 | NEXT_INSN; | |
2290 | #endif /* DIRECT_THREADED */ | |
2291 | insn_goto: | |
2292 | TAKE_GOTO; | |
2293 | NEXT_INSN; | |
2294 | ||
2295 | insn_jsr_w: | |
2296 | #ifndef DIRECT_THREADED | |
2297 | // For direct threaded, jsr and jsr_w are the same. | |
58eb6e7c | 2298 | { |
fdae83ab TT |
2299 | pc_t next = pc - 1 + get4 (pc); |
2300 | pc += 4; | |
2301 | PUSHA ((jobject) pc); | |
2302 | pc = next; | |
58eb6e7c | 2303 | } |
f7b4fb11 | 2304 | NEXT_INSN; |
fdae83ab TT |
2305 | #endif /* DIRECT_THREADED */ |
2306 | insn_jsr: | |
58eb6e7c | 2307 | { |
fdae83ab TT |
2308 | pc_t next = GOTO_VAL(); |
2309 | SKIP_GOTO; | |
2310 | PUSHA ((jobject) pc); | |
2311 | pc = next; | |
58eb6e7c | 2312 | } |
f7b4fb11 | 2313 | NEXT_INSN; |
58eb6e7c | 2314 | |
fdae83ab | 2315 | insn_ret: |
58eb6e7c | 2316 | { |
fdae83ab TT |
2317 | jint index = GET1U (); |
2318 | pc = (pc_t) PEEKA (index); | |
58eb6e7c | 2319 | } |
f7b4fb11 | 2320 | NEXT_INSN; |
58eb6e7c | 2321 | |
fdae83ab | 2322 | insn_tableswitch: |
58eb6e7c | 2323 | { |
fdae83ab TT |
2324 | #ifdef DIRECT_THREADED |
2325 | void *def = (pc++)->datum; | |
2326 | ||
58eb6e7c | 2327 | int index = POPI(); |
f7b4fb11 | 2328 | |
fdae83ab TT |
2329 | jint low = INTVAL (); |
2330 | jint high = INTVAL (); | |
58eb6e7c | 2331 | |
fdae83ab TT |
2332 | if (index < low || index > high) |
2333 | pc = (insn_slot *) def; | |
2334 | else | |
2335 | pc = (insn_slot *) ((pc + index - low)->datum); | |
2336 | #else | |
2337 | pc_t base_pc = pc - 1; | |
2338 | int index = POPI (); | |
2339 | ||
2340 | pc_t base = (pc_t) bytecode (); | |
2341 | while ((pc - base) % 4 != 0) | |
2342 | ++pc; | |
58eb6e7c | 2343 | |
fdae83ab TT |
2344 | jint def = get4 (pc); |
2345 | jint low = get4 (pc + 4); | |
2346 | jint high = get4 (pc + 8); | |
58eb6e7c | 2347 | if (index < low || index > high) |
fdae83ab | 2348 | pc = base_pc + def; |
58eb6e7c | 2349 | else |
fdae83ab TT |
2350 | pc = base_pc + get4 (pc + 4 * (index - low + 3)); |
2351 | #endif /* DIRECT_THREADED */ | |
58eb6e7c | 2352 | } |
f7b4fb11 | 2353 | NEXT_INSN; |
58eb6e7c | 2354 | |
fdae83ab | 2355 | insn_lookupswitch: |
58eb6e7c | 2356 | { |
fdae83ab TT |
2357 | #ifdef DIRECT_THREADED |
2358 | void *def = (pc++)->insn; | |
2359 | ||
2360 | int index = POPI(); | |
2361 | ||
2362 | jint npairs = INTVAL (); | |
2363 | ||
2364 | int max = npairs - 1; | |
2365 | int min = 0; | |
2366 | ||
2367 | // Simple binary search... | |
2368 | while (min < max) | |
2369 | { | |
2370 | int half = (min + max) / 2; | |
2371 | int match = pc[2 * half].int_val; | |
2372 | ||
2373 | if (index == match) | |
2374 | { | |
2375 | // Found it. | |
2376 | pc = (insn_slot *) pc[2 * half + 1].datum; | |
2377 | NEXT_INSN; | |
2378 | } | |
2379 | else if (index < match) | |
2380 | // We can use HALF - 1 here because we check again on | |
2381 | // loop exit. | |
2382 | max = half - 1; | |
2383 | else | |
2384 | // We can use HALF + 1 here because we check again on | |
2385 | // loop exit. | |
2386 | min = half + 1; | |
2387 | } | |
2388 | if (index == pc[2 * min].int_val) | |
2389 | pc = (insn_slot *) pc[2 * min + 1].datum; | |
2390 | else | |
2391 | pc = (insn_slot *) def; | |
2392 | #else | |
58eb6e7c AG |
2393 | unsigned char *base_pc = pc-1; |
2394 | int index = POPI(); | |
f7b4fb11 | 2395 | |
58eb6e7c AG |
2396 | unsigned char* base = bytecode (); |
2397 | while ((pc-base) % 4 != 0) | |
fdae83ab | 2398 | ++pc; |
f7b4fb11 | 2399 | |
58eb6e7c AG |
2400 | jint def = get4 (pc); |
2401 | jint npairs = get4 (pc+4); | |
f7b4fb11 | 2402 | |
58eb6e7c AG |
2403 | int max = npairs-1; |
2404 | int min = 0; | |
2405 | ||
fdae83ab | 2406 | // Simple binary search... |
58eb6e7c AG |
2407 | while (min < max) |
2408 | { | |
2409 | int half = (min+max)/2; | |
2410 | int match = get4 (pc+ 4*(2 + 2*half)); | |
2411 | ||
2412 | if (index == match) | |
2413 | min = max = half; | |
58eb6e7c | 2414 | else if (index < match) |
fdae83ab TT |
2415 | // We can use HALF - 1 here because we check again on |
2416 | // loop exit. | |
2417 | max = half - 1; | |
58eb6e7c | 2418 | else |
fdae83ab TT |
2419 | // We can use HALF + 1 here because we check again on |
2420 | // loop exit. | |
2421 | min = half + 1; | |
58eb6e7c | 2422 | } |
f7b4fb11 | 2423 | |
58eb6e7c AG |
2424 | if (index == get4 (pc+ 4*(2 + 2*min))) |
2425 | pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1)); | |
2426 | else | |
2427 | pc = base_pc + def; | |
fdae83ab | 2428 | #endif /* DIRECT_THREADED */ |
58eb6e7c | 2429 | } |
f7b4fb11 | 2430 | NEXT_INSN; |
58eb6e7c | 2431 | |
fdae83ab TT |
2432 | insn_areturn: |
2433 | *(jobject *) retp = POPA (); | |
58eb6e7c AG |
2434 | return; |
2435 | ||
fdae83ab TT |
2436 | insn_lreturn: |
2437 | *(jlong *) retp = POPL (); | |
2438 | return; | |
2439 | ||
2440 | insn_freturn: | |
2441 | *(jfloat *) retp = POPF (); | |
2442 | return; | |
2443 | ||
2444 | insn_dreturn: | |
2445 | *(jdouble *) retp = POPD (); | |
2446 | return; | |
2447 | ||
2448 | insn_ireturn: | |
2449 | *(jint *) retp = POPI (); | |
2450 | return; | |
2451 | ||
2452 | insn_return: | |
2453 | return; | |
2454 | ||
2455 | insn_getstatic: | |
58eb6e7c | 2456 | { |
fdae83ab | 2457 | jint fieldref_index = GET2U (); |
18744d9b BM |
2458 | SAVE_PC(); // Constant pool resolution could throw. |
2459 | _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index); | |
7941ceab | 2460 | _Jv_Field *field = pool_data[fieldref_index].field; |
58eb6e7c | 2461 | |
e409a2c8 | 2462 | if ((field->flags & Modifier::STATIC) == 0) |
58eb6e7c AG |
2463 | throw_incompatible_class_change_error |
2464 | (JvNewStringLatin1 ("field no longer static")); | |
2465 | ||
2466 | jclass type = field->type; | |
2467 | ||
fdae83ab TT |
2468 | // We rewrite the instruction once we discover what it refers |
2469 | // to. | |
2470 | void *newinsn = NULL; | |
58eb6e7c AG |
2471 | if (type->isPrimitive ()) |
2472 | { | |
2473 | switch (type->size_in_bytes) | |
2474 | { | |
2475 | case 1: | |
7a1c3d48 | 2476 | PUSHI (*field->u.byte_addr); |
fdae83ab | 2477 | newinsn = AMPAMP (getstatic_resolved_1); |
99f7658d | 2478 | break; |
f7b4fb11 | 2479 | |
58eb6e7c AG |
2480 | case 2: |
2481 | if (type == JvPrimClass (char)) | |
fdae83ab | 2482 | { |
7a1c3d48 | 2483 | PUSHI (*field->u.char_addr); |
fdae83ab TT |
2484 | newinsn = AMPAMP (getstatic_resolved_char); |
2485 | } | |
58eb6e7c | 2486 | else |
fdae83ab | 2487 | { |
7a1c3d48 | 2488 | PUSHI (*field->u.short_addr); |
fdae83ab TT |
2489 | newinsn = AMPAMP (getstatic_resolved_short); |
2490 | } | |
58eb6e7c AG |
2491 | break; |
2492 | ||
2493 | case 4: | |
7a1c3d48 | 2494 | PUSHI(*field->u.int_addr); |
fdae83ab | 2495 | newinsn = AMPAMP (getstatic_resolved_4); |
58eb6e7c AG |
2496 | break; |
2497 | ||
2498 | case 8: | |
7a1c3d48 | 2499 | PUSHL(*field->u.long_addr); |
fdae83ab | 2500 | newinsn = AMPAMP (getstatic_resolved_8); |
58eb6e7c AG |
2501 | break; |
2502 | } | |
2503 | } | |
2504 | else | |
2505 | { | |
7a1c3d48 | 2506 | PUSHA(*field->u.object_addr); |
fdae83ab | 2507 | newinsn = AMPAMP (getstatic_resolved_obj); |
58eb6e7c | 2508 | } |
fdae83ab TT |
2509 | |
2510 | #ifdef DIRECT_THREADED | |
2511 | pc[-2].insn = newinsn; | |
2512 | pc[-1].datum = field->u.addr; | |
2513 | #endif /* DIRECT_THREADED */ | |
58eb6e7c | 2514 | } |
f7b4fb11 | 2515 | NEXT_INSN; |
58eb6e7c | 2516 | |
fdae83ab TT |
2517 | #ifdef DIRECT_THREADED |
2518 | getstatic_resolved_1: | |
2519 | PUSHI (*(jbyte *) AVAL ()); | |
2520 | NEXT_INSN; | |
2521 | ||
2522 | getstatic_resolved_char: | |
2523 | PUSHI (*(jchar *) AVAL ()); | |
2524 | NEXT_INSN; | |
2525 | ||
2526 | getstatic_resolved_short: | |
2527 | PUSHI (*(jshort *) AVAL ()); | |
2528 | NEXT_INSN; | |
2529 | ||
2530 | getstatic_resolved_4: | |
2531 | PUSHI (*(jint *) AVAL ()); | |
2532 | NEXT_INSN; | |
2533 | ||
2534 | getstatic_resolved_8: | |
2535 | PUSHL (*(jlong *) AVAL ()); | |
2536 | NEXT_INSN; | |
2537 | ||
2538 | getstatic_resolved_obj: | |
2539 | PUSHA (*(jobject *) AVAL ()); | |
2540 | NEXT_INSN; | |
2541 | #endif /* DIRECT_THREADED */ | |
2542 | ||
2543 | insn_getfield: | |
58eb6e7c | 2544 | { |
fdae83ab | 2545 | jint fieldref_index = GET2U (); |
18744d9b | 2546 | _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index); |
7941ceab | 2547 | _Jv_Field *field = pool_data[fieldref_index].field; |
58eb6e7c | 2548 | |
e409a2c8 | 2549 | if ((field->flags & Modifier::STATIC) != 0) |
58eb6e7c AG |
2550 | throw_incompatible_class_change_error |
2551 | (JvNewStringLatin1 ("field is static")); | |
2552 | ||
2553 | jclass type = field->type; | |
715bdd81 AH |
2554 | jint field_offset = field->u.boffset; |
2555 | if (field_offset > 0xffff) | |
b3208f56 | 2556 | throw new java::lang::VirtualMachineError; |
715bdd81 AH |
2557 | |
2558 | jobject obj = POPA(); | |
2559 | NULLCHECK(obj); | |
58eb6e7c | 2560 | |
fdae83ab | 2561 | void *newinsn = NULL; |
7a1c3d48 | 2562 | _Jv_value *val = (_Jv_value *) ((char *)obj + field_offset); |
58eb6e7c AG |
2563 | if (type->isPrimitive ()) |
2564 | { | |
2565 | switch (type->size_in_bytes) | |
2566 | { | |
2567 | case 1: | |
7a1c3d48 | 2568 | PUSHI (val->byte_value); |
fdae83ab | 2569 | newinsn = AMPAMP (getfield_resolved_1); |
58eb6e7c | 2570 | break; |
f7b4fb11 | 2571 | |
58eb6e7c AG |
2572 | case 2: |
2573 | if (type == JvPrimClass (char)) | |
fdae83ab | 2574 | { |
7a1c3d48 | 2575 | PUSHI (val->char_value); |
fdae83ab TT |
2576 | newinsn = AMPAMP (getfield_resolved_char); |
2577 | } | |
58eb6e7c | 2578 | else |
fdae83ab | 2579 | { |
7a1c3d48 | 2580 | PUSHI (val->short_value); |
fdae83ab TT |
2581 | newinsn = AMPAMP (getfield_resolved_short); |
2582 | } | |
58eb6e7c AG |
2583 | break; |
2584 | ||
2585 | case 4: | |
7a1c3d48 | 2586 | PUSHI (val->int_value); |
fdae83ab | 2587 | newinsn = AMPAMP (getfield_resolved_4); |
58eb6e7c AG |
2588 | break; |
2589 | ||
2590 | case 8: | |
7a1c3d48 | 2591 | PUSHL (val->long_value); |
fdae83ab | 2592 | newinsn = AMPAMP (getfield_resolved_8); |
58eb6e7c AG |
2593 | break; |
2594 | } | |
2595 | } | |
2596 | else | |
2597 | { | |
7a1c3d48 | 2598 | PUSHA (val->object_value); |
fdae83ab | 2599 | newinsn = AMPAMP (getfield_resolved_obj); |
58eb6e7c | 2600 | } |
fdae83ab TT |
2601 | |
2602 | #ifdef DIRECT_THREADED | |
2603 | pc[-2].insn = newinsn; | |
2604 | pc[-1].int_val = field_offset; | |
2605 | #endif /* DIRECT_THREADED */ | |
2606 | } | |
2607 | NEXT_INSN; | |
2608 | ||
2609 | #ifdef DIRECT_THREADED | |
2610 | getfield_resolved_1: | |
2611 | { | |
2612 | char *obj = (char *) POPA (); | |
2613 | NULLCHECK (obj); | |
2614 | PUSHI (*(jbyte *) (obj + INTVAL ())); | |
58eb6e7c | 2615 | } |
f7b4fb11 | 2616 | NEXT_INSN; |
58eb6e7c | 2617 | |
fdae83ab | 2618 | getfield_resolved_char: |
58eb6e7c | 2619 | { |
fdae83ab TT |
2620 | char *obj = (char *) POPA (); |
2621 | NULLCHECK (obj); | |
2622 | PUSHI (*(jchar *) (obj + INTVAL ())); | |
2623 | } | |
2624 | NEXT_INSN; | |
2625 | ||
2626 | getfield_resolved_short: | |
2627 | { | |
2628 | char *obj = (char *) POPA (); | |
2629 | NULLCHECK (obj); | |
2630 | PUSHI (*(jshort *) (obj + INTVAL ())); | |
2631 | } | |
2632 | NEXT_INSN; | |
2633 | ||
2634 | getfield_resolved_4: | |
2635 | { | |
2636 | char *obj = (char *) POPA (); | |
2637 | NULLCHECK (obj); | |
2638 | PUSHI (*(jint *) (obj + INTVAL ())); | |
2639 | } | |
2640 | NEXT_INSN; | |
2641 | ||
2642 | getfield_resolved_8: | |
2643 | { | |
2644 | char *obj = (char *) POPA (); | |
2645 | NULLCHECK (obj); | |
2646 | PUSHL (*(jlong *) (obj + INTVAL ())); | |
2647 | } | |
2648 | NEXT_INSN; | |
2649 | ||
2650 | getfield_resolved_obj: | |
2651 | { | |
2652 | char *obj = (char *) POPA (); | |
2653 | NULLCHECK (obj); | |
2654 | PUSHA (*(jobject *) (obj + INTVAL ())); | |
2655 | } | |
2656 | NEXT_INSN; | |
2657 | #endif /* DIRECT_THREADED */ | |
2658 | ||
2659 | insn_putstatic: | |
2660 | { | |
2661 | jint fieldref_index = GET2U (); | |
18744d9b | 2662 | _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index); |
7941ceab | 2663 | _Jv_Field *field = pool_data[fieldref_index].field; |
58eb6e7c AG |
2664 | |
2665 | jclass type = field->type; | |
2666 | ||
2667 | // ResolvePoolEntry cannot check this | |
e409a2c8 | 2668 | if ((field->flags & Modifier::STATIC) == 0) |
58eb6e7c AG |
2669 | throw_incompatible_class_change_error |
2670 | (JvNewStringLatin1 ("field no longer static")); | |
2671 | ||
fdae83ab | 2672 | void *newinsn = NULL; |
58eb6e7c AG |
2673 | if (type->isPrimitive ()) |
2674 | { | |
2675 | switch (type->size_in_bytes) | |
2676 | { | |
2677 | case 1: | |
715bdd81 AH |
2678 | { |
2679 | jint value = POPI(); | |
7a1c3d48 | 2680 | *field->u.byte_addr = value; |
fdae83ab | 2681 | newinsn = AMPAMP (putstatic_resolved_1); |
715bdd81 AH |
2682 | break; |
2683 | } | |
58eb6e7c AG |
2684 | |
2685 | case 2: | |
715bdd81 AH |
2686 | { |
2687 | jint value = POPI(); | |
7a1c3d48 | 2688 | *field->u.char_addr = value; |
fdae83ab | 2689 | newinsn = AMPAMP (putstatic_resolved_2); |
715bdd81 AH |
2690 | break; |
2691 | } | |
f7b4fb11 | 2692 | |
58eb6e7c | 2693 | case 4: |
715bdd81 AH |
2694 | { |
2695 | jint value = POPI(); | |
7a1c3d48 | 2696 | *field->u.int_addr = value; |
fdae83ab | 2697 | newinsn = AMPAMP (putstatic_resolved_4); |
715bdd81 AH |
2698 | break; |
2699 | } | |
f7b4fb11 | 2700 | |
58eb6e7c | 2701 | case 8: |
715bdd81 AH |
2702 | { |
2703 | jlong value = POPL(); | |
7a1c3d48 | 2704 | *field->u.long_addr = value; |
fdae83ab | 2705 | newinsn = AMPAMP (putstatic_resolved_8); |
715bdd81 AH |
2706 | break; |
2707 | } | |
58eb6e7c AG |
2708 | } |
2709 | } | |
2710 | else | |
2711 | { | |
715bdd81 | 2712 | jobject value = POPA(); |
7a1c3d48 | 2713 | *field->u.object_addr = value; |
fdae83ab | 2714 | newinsn = AMPAMP (putstatic_resolved_obj); |
58eb6e7c | 2715 | } |
fdae83ab TT |
2716 | |
2717 | #ifdef DIRECT_THREADED | |
2718 | pc[-2].insn = newinsn; | |
2719 | pc[-1].datum = field->u.addr; | |
2720 | #endif /* DIRECT_THREADED */ | |
58eb6e7c | 2721 | } |
f7b4fb11 | 2722 | NEXT_INSN; |
58eb6e7c | 2723 | |
fdae83ab TT |
2724 | #ifdef DIRECT_THREADED |
2725 | putstatic_resolved_1: | |
2726 | *(jbyte *) AVAL () = POPI (); | |
2727 | NEXT_INSN; | |
2728 | ||
2729 | putstatic_resolved_2: | |
2730 | *(jchar *) AVAL () = POPI (); | |
2731 | NEXT_INSN; | |
2732 | ||
2733 | putstatic_resolved_4: | |
2734 | *(jint *) AVAL () = POPI (); | |
2735 | NEXT_INSN; | |
2736 | ||
2737 | putstatic_resolved_8: | |
2738 | *(jlong *) AVAL () = POPL (); | |
2739 | NEXT_INSN; | |
58eb6e7c | 2740 | |
fdae83ab TT |
2741 | putstatic_resolved_obj: |
2742 | *(jobject *) AVAL () = POPA (); | |
2743 | NEXT_INSN; | |
2744 | #endif /* DIRECT_THREADED */ | |
2745 | ||
2746 | insn_putfield: | |
58eb6e7c | 2747 | { |
fdae83ab | 2748 | jint fieldref_index = GET2U (); |
18744d9b | 2749 | _Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index); |
7941ceab | 2750 | _Jv_Field *field = pool_data[fieldref_index].field; |
58eb6e7c AG |
2751 | |
2752 | jclass type = field->type; | |
2753 | ||
e409a2c8 | 2754 | if ((field->flags & Modifier::STATIC) != 0) |
58eb6e7c AG |
2755 | throw_incompatible_class_change_error |
2756 | (JvNewStringLatin1 ("field is static")); | |
2757 | ||
715bdd81 AH |
2758 | jint field_offset = field->u.boffset; |
2759 | if (field_offset > 0xffff) | |
b3208f56 | 2760 | throw new java::lang::VirtualMachineError; |
715bdd81 | 2761 | |
fdae83ab | 2762 | void *newinsn = NULL; |
58eb6e7c AG |
2763 | if (type->isPrimitive ()) |
2764 | { | |
2765 | switch (type->size_in_bytes) | |
2766 | { | |
2767 | case 1: | |
715bdd81 AH |
2768 | { |
2769 | jint value = POPI(); | |
2770 | jobject obj = POPA(); | |
2771 | NULLCHECK(obj); | |
2772 | *(jbyte*) ((char*)obj + field_offset) = value; | |
fdae83ab | 2773 | newinsn = AMPAMP (putfield_resolved_1); |
715bdd81 AH |
2774 | break; |
2775 | } | |
58eb6e7c AG |
2776 | |
2777 | case 2: | |
715bdd81 AH |
2778 | { |
2779 | jint value = POPI(); | |
2780 | jobject obj = POPA(); | |
2781 | NULLCHECK(obj); | |
2782 | *(jchar*) ((char*)obj + field_offset) = value; | |
fdae83ab | 2783 | newinsn = AMPAMP (putfield_resolved_2); |
715bdd81 AH |
2784 | break; |
2785 | } | |
58eb6e7c AG |
2786 | |
2787 | case 4: | |
715bdd81 AH |
2788 | { |
2789 | jint value = POPI(); | |
2790 | jobject obj = POPA(); | |
2791 | NULLCHECK(obj); | |
2792 | *(jint*) ((char*)obj + field_offset) = value; | |
fdae83ab | 2793 | newinsn = AMPAMP (putfield_resolved_4); |
715bdd81 AH |
2794 | break; |
2795 | } | |
58eb6e7c AG |
2796 | |
2797 | case 8: | |
715bdd81 AH |
2798 | { |
2799 | jlong value = POPL(); | |
2800 | jobject obj = POPA(); | |
2801 | NULLCHECK(obj); | |
2802 | *(jlong*) ((char*)obj + field_offset) = value; | |
fdae83ab | 2803 | newinsn = AMPAMP (putfield_resolved_8); |
715bdd81 AH |
2804 | break; |
2805 | } | |
58eb6e7c AG |
2806 | } |
2807 | } | |
2808 | else | |
2809 | { | |
715bdd81 AH |
2810 | jobject value = POPA(); |
2811 | jobject obj = POPA(); | |
2812 | NULLCHECK(obj); | |
2813 | *(jobject*) ((char*)obj + field_offset) = value; | |
fdae83ab | 2814 | newinsn = AMPAMP (putfield_resolved_obj); |
58eb6e7c | 2815 | } |
fdae83ab TT |
2816 | |
2817 | #ifdef DIRECT_THREADED | |
2818 | pc[-2].insn = newinsn; | |
2819 | pc[-1].int_val = field_offset; | |
2820 | #endif /* DIRECT_THREADED */ | |
58eb6e7c | 2821 | } |
f7b4fb11 | 2822 | NEXT_INSN; |
58eb6e7c | 2823 | |
fdae83ab TT |
2824 | #ifdef DIRECT_THREADED |
2825 | putfield_resolved_1: | |
58eb6e7c | 2826 | { |
fdae83ab TT |
2827 | jint val = POPI (); |
2828 | char *obj = (char *) POPA (); | |
2829 | NULLCHECK (obj); | |
2830 | *(jbyte *) (obj + INTVAL ()) = val; | |
2831 | } | |
2832 | NEXT_INSN; | |
2833 | ||
2834 | putfield_resolved_2: | |
2835 | { | |
2836 | jint val = POPI (); | |
2837 | char *obj = (char *) POPA (); | |
2838 | NULLCHECK (obj); | |
2839 | *(jchar *) (obj + INTVAL ()) = val; | |
2840 | } | |
2841 | NEXT_INSN; | |
2842 | ||
2843 | putfield_resolved_4: | |
2844 | { | |
2845 | jint val = POPI (); | |
2846 | char *obj = (char *) POPA (); | |
2847 | NULLCHECK (obj); | |
2848 | *(jint *) (obj + INTVAL ()) = val; | |
2849 | } | |
2850 | NEXT_INSN; | |
2851 | ||
2852 | putfield_resolved_8: | |
2853 | { | |
2854 | jlong val = POPL (); | |
2855 | char *obj = (char *) POPA (); | |
2856 | NULLCHECK (obj); | |
2857 | *(jlong *) (obj + INTVAL ()) = val; | |
2858 | } | |
2859 | NEXT_INSN; | |
2860 | ||
2861 | putfield_resolved_obj: | |
2862 | { | |
2863 | jobject val = POPA (); | |
2864 | char *obj = (char *) POPA (); | |
2865 | NULLCHECK (obj); | |
2866 | *(jobject *) (obj + INTVAL ()) = val; | |
2867 | } | |
2868 | NEXT_INSN; | |
2869 | #endif /* DIRECT_THREADED */ | |
2870 | ||
2871 | insn_invokespecial: | |
2872 | { | |
2873 | int index = GET2U (); | |
58eb6e7c | 2874 | |
18744d9b | 2875 | rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class, |
36739040 | 2876 | index)).rmethod; |
58eb6e7c AG |
2877 | |
2878 | sp -= rmeth->stack_item_count; | |
f7b4fb11 | 2879 | |
b0fbe966 TT |
2880 | // We don't use NULLCHECK here because we can't rely on that |
2881 | // working for <init>. So instead we do an explicit test. | |
2882 | if (! sp[0].o) | |
18744d9b BM |
2883 | { |
2884 | SAVE_PC(); | |
2885 | throw new java::lang::NullPointerException; | |
2886 | } | |
58eb6e7c | 2887 | |
79c2c6da | 2888 | fun = (void (*)()) rmeth->method->ncode; |
fdae83ab TT |
2889 | |
2890 | #ifdef DIRECT_THREADED | |
2891 | // Rewrite instruction so that we use a faster pre-resolved | |
2892 | // method. | |
2893 | pc[-2].insn = &&invokespecial_resolved; | |
2894 | pc[-1].datum = rmeth; | |
2895 | #endif /* DIRECT_THREADED */ | |
2896 | } | |
2897 | goto perform_invoke; | |
2898 | ||
2899 | #ifdef DIRECT_THREADED | |
2900 | invokespecial_resolved: | |
2901 | { | |
2902 | rmeth = (_Jv_ResolvedMethod *) AVAL (); | |
2903 | sp -= rmeth->stack_item_count; | |
b0fbe966 TT |
2904 | // We don't use NULLCHECK here because we can't rely on that |
2905 | // working for <init>. So instead we do an explicit test. | |
2906 | if (! sp[0].o) | |
18744d9b BM |
2907 | { |
2908 | SAVE_PC(); | |
2909 | throw new java::lang::NullPointerException; | |
2910 | } | |
fdae83ab | 2911 | fun = (void (*)()) rmeth->method->ncode; |
58eb6e7c AG |
2912 | } |
2913 | goto perform_invoke; | |
fdae83ab | 2914 | #endif /* DIRECT_THREADED */ |
58eb6e7c | 2915 | |
fdae83ab | 2916 | insn_invokestatic: |
58eb6e7c | 2917 | { |
fdae83ab | 2918 | int index = GET2U (); |
58eb6e7c | 2919 | |
18744d9b | 2920 | rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class, |
36739040 | 2921 | index)).rmethod; |
58eb6e7c AG |
2922 | |
2923 | sp -= rmeth->stack_item_count; | |
f7b4fb11 | 2924 | |
79c2c6da | 2925 | fun = (void (*)()) rmeth->method->ncode; |
fdae83ab TT |
2926 | |
2927 | #ifdef DIRECT_THREADED | |
2928 | // Rewrite instruction so that we use a faster pre-resolved | |
2929 | // method. | |
2930 | pc[-2].insn = &&invokestatic_resolved; | |
2931 | pc[-1].datum = rmeth; | |
2932 | #endif /* DIRECT_THREADED */ | |
58eb6e7c AG |
2933 | } |
2934 | goto perform_invoke; | |
2935 | ||
fdae83ab TT |
2936 | #ifdef DIRECT_THREADED |
2937 | invokestatic_resolved: | |
58eb6e7c | 2938 | { |
fdae83ab TT |
2939 | rmeth = (_Jv_ResolvedMethod *) AVAL (); |
2940 | sp -= rmeth->stack_item_count; | |
2941 | fun = (void (*)()) rmeth->method->ncode; | |
2942 | } | |
2943 | goto perform_invoke; | |
2944 | #endif /* DIRECT_THREADED */ | |
58eb6e7c | 2945 | |
fdae83ab TT |
2946 | insn_invokeinterface: |
2947 | { | |
2948 | int index = GET2U (); | |
58eb6e7c | 2949 | |
18744d9b | 2950 | rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class, |
36739040 | 2951 | index)).rmethod; |
58eb6e7c AG |
2952 | |
2953 | sp -= rmeth->stack_item_count; | |
f7b4fb11 | 2954 | |
7941ceab | 2955 | jobject rcv = sp[0].o; |
58eb6e7c | 2956 | |
e7e18a21 AO |
2957 | NULLCHECK (rcv); |
2958 | ||
79c2c6da | 2959 | fun = (void (*)()) |
58eb6e7c AG |
2960 | _Jv_LookupInterfaceMethod (rcv->getClass (), |
2961 | rmeth->method->name, | |
2962 | rmeth->method->signature); | |
fdae83ab TT |
2963 | |
2964 | #ifdef DIRECT_THREADED | |
2965 | // Rewrite instruction so that we use a faster pre-resolved | |
2966 | // method. | |
2967 | pc[-2].insn = &&invokeinterface_resolved; | |
2968 | pc[-1].datum = rmeth; | |
2969 | #else | |
2970 | // Skip dummy bytes. | |
2971 | pc += 2; | |
2972 | #endif /* DIRECT_THREADED */ | |
58eb6e7c AG |
2973 | } |
2974 | goto perform_invoke; | |
2975 | ||
fdae83ab TT |
2976 | #ifdef DIRECT_THREADED |
2977 | invokeinterface_resolved: | |
2978 | { | |
2979 | rmeth = (_Jv_ResolvedMethod *) AVAL (); | |
2980 | sp -= rmeth->stack_item_count; | |
2981 | jobject rcv = sp[0].o; | |
2982 | NULLCHECK (rcv); | |
2983 | fun = (void (*)()) | |
2984 | _Jv_LookupInterfaceMethod (rcv->getClass (), | |
2985 | rmeth->method->name, | |
2986 | rmeth->method->signature); | |
2987 | } | |
2988 | goto perform_invoke; | |
2989 | #endif /* DIRECT_THREADED */ | |
58eb6e7c | 2990 | |
fdae83ab | 2991 | insn_new: |
58eb6e7c | 2992 | { |
fdae83ab | 2993 | int index = GET2U (); |
18744d9b | 2994 | jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class, |
36739040 | 2995 | index)).clazz; |
3ffa3729 CW |
2996 | /* VM spec, section 3.11.5 */ |
2997 | if ((klass->getModifiers() & Modifier::ABSTRACT) | |
2998 | || klass->isInterface()) | |
2999 | throw new java::lang::InstantiationException; | |
bf7ad402 | 3000 | jobject res = _Jv_AllocObject (klass); |
58eb6e7c | 3001 | PUSHA (res); |
fdae83ab TT |
3002 | |
3003 | #ifdef DIRECT_THREADED | |
3004 | pc[-2].insn = &&new_resolved; | |
3005 | pc[-1].datum = klass; | |
3006 | #endif /* DIRECT_THREADED */ | |
58eb6e7c | 3007 | } |
f7b4fb11 | 3008 | NEXT_INSN; |
58eb6e7c | 3009 | |
fdae83ab TT |
3010 | #ifdef DIRECT_THREADED |
3011 | new_resolved: | |
58eb6e7c | 3012 | { |
fdae83ab | 3013 | jclass klass = (jclass) AVAL (); |
bf7ad402 | 3014 | jobject res = _Jv_AllocObject (klass); |
fdae83ab TT |
3015 | PUSHA (res); |
3016 | } | |
3017 | NEXT_INSN; | |
3018 | #endif /* DIRECT_THREADED */ | |
3019 | ||
3020 | insn_newarray: | |
3021 | { | |
3022 | int atype = GET1U (); | |
58eb6e7c AG |
3023 | int size = POPI(); |
3024 | jobject result = _Jv_NewArray (atype, size); | |
3025 | PUSHA (result); | |
3026 | } | |
f7b4fb11 KKT |
3027 | NEXT_INSN; |
3028 | ||
fdae83ab | 3029 | insn_anewarray: |
58eb6e7c | 3030 | { |
fdae83ab | 3031 | int index = GET2U (); |
18744d9b | 3032 | jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class, |
36739040 | 3033 | index)).clazz; |
58eb6e7c | 3034 | int size = POPI(); |
58eb6e7c AG |
3035 | jobject result = _Jv_NewObjectArray (size, klass, 0); |
3036 | PUSHA (result); | |
fdae83ab TT |
3037 | |
3038 | #ifdef DIRECT_THREADED | |
3039 | pc[-2].insn = &&anewarray_resolved; | |
3040 | pc[-1].datum = klass; | |
3041 | #endif /* DIRECT_THREADED */ | |
3042 | } | |
3043 | NEXT_INSN; | |
3044 | ||
3045 | #ifdef DIRECT_THREADED | |
3046 | anewarray_resolved: | |
3047 | { | |
3048 | jclass klass = (jclass) AVAL (); | |
3049 | int size = POPI (); | |
3050 | jobject result = _Jv_NewObjectArray (size, klass, 0); | |
3051 | PUSHA (result); | |
58eb6e7c | 3052 | } |
f7b4fb11 | 3053 | NEXT_INSN; |
fdae83ab | 3054 | #endif /* DIRECT_THREADED */ |
58eb6e7c | 3055 | |
fdae83ab | 3056 | insn_arraylength: |
58eb6e7c AG |
3057 | { |
3058 | __JArray *arr = (__JArray*)POPA(); | |
cec71868 | 3059 | NULLARRAYCHECK (arr); |
58eb6e7c AG |
3060 | PUSHI (arr->length); |
3061 | } | |
f7b4fb11 | 3062 | NEXT_INSN; |
58eb6e7c | 3063 | |
fdae83ab | 3064 | insn_athrow: |
58eb6e7c AG |
3065 | { |
3066 | jobject value = POPA(); | |
b3208f56 | 3067 | throw static_cast<jthrowable>(value); |
58eb6e7c | 3068 | } |
f7b4fb11 | 3069 | NEXT_INSN; |
58eb6e7c | 3070 | |
fdae83ab | 3071 | insn_checkcast: |
58eb6e7c | 3072 | { |
18744d9b | 3073 | SAVE_PC(); |
58eb6e7c | 3074 | jobject value = POPA(); |
fdae83ab | 3075 | jint index = GET2U (); |
18744d9b | 3076 | jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class, |
36739040 | 3077 | index)).clazz; |
58eb6e7c | 3078 | |
9cc2dc63 | 3079 | value = (jobject) _Jv_CheckCast (to, value); |
58eb6e7c AG |
3080 | |
3081 | PUSHA (value); | |
fdae83ab TT |
3082 | |
3083 | #ifdef DIRECT_THREADED | |
3084 | pc[-2].insn = &&checkcast_resolved; | |
3085 | pc[-1].datum = to; | |
3086 | #endif /* DIRECT_THREADED */ | |
3087 | } | |
3088 | NEXT_INSN; | |
3089 | ||
3090 | #ifdef DIRECT_THREADED | |
3091 | checkcast_resolved: | |
3092 | { | |
18744d9b | 3093 | SAVE_PC(); |
fdae83ab TT |
3094 | jobject value = POPA (); |
3095 | jclass to = (jclass) AVAL (); | |
9cc2dc63 | 3096 | value = (jobject) _Jv_CheckCast (to, value); |
fdae83ab | 3097 | PUSHA (value); |
58eb6e7c | 3098 | } |
f7b4fb11 | 3099 | NEXT_INSN; |
fdae83ab | 3100 | #endif /* DIRECT_THREADED */ |
58eb6e7c | 3101 | |
fdae83ab | 3102 | insn_instanceof: |
58eb6e7c | 3103 | { |
18744d9b | 3104 | SAVE_PC(); |
58eb6e7c | 3105 | jobject value = POPA(); |
fdae83ab | 3106 | jint index = GET2U (); |
18744d9b | 3107 | jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class, |
36739040 | 3108 | index)).clazz; |
58eb6e7c | 3109 | PUSHI (to->isInstance (value)); |
fdae83ab TT |
3110 | |
3111 | #ifdef DIRECT_THREADED | |
3112 | pc[-2].insn = &&instanceof_resolved; | |
3113 | pc[-1].datum = to; | |
3114 | #endif /* DIRECT_THREADED */ | |
3115 | } | |
3116 | NEXT_INSN; | |
3117 | ||
3118 | #ifdef DIRECT_THREADED | |
3119 | instanceof_resolved: | |
3120 | { | |
3121 | jobject value = POPA (); | |
3122 | jclass to = (jclass) AVAL (); | |
3123 | PUSHI (to->isInstance (value)); | |
58eb6e7c | 3124 | } |
f7b4fb11 | 3125 | NEXT_INSN; |
fdae83ab | 3126 | #endif /* DIRECT_THREADED */ |
58eb6e7c | 3127 | |
fdae83ab | 3128 | insn_monitorenter: |
58eb6e7c AG |
3129 | { |
3130 | jobject value = POPA(); | |
3131 | NULLCHECK(value); | |
3132 | _Jv_MonitorEnter (value); | |
3133 | } | |
f7b4fb11 | 3134 | NEXT_INSN; |
58eb6e7c | 3135 | |
fdae83ab | 3136 | insn_monitorexit: |
58eb6e7c AG |
3137 | { |
3138 | jobject value = POPA(); | |
3139 | NULLCHECK(value); | |
3140 | _Jv_MonitorExit (value); | |
3141 | } | |
f7b4fb11 | 3142 | NEXT_INSN; |
58eb6e7c | 3143 | |
fdae83ab | 3144 | insn_ifnull: |
58eb6e7c | 3145 | { |
58eb6e7c AG |
3146 | jobject val = POPA(); |
3147 | if (val == NULL) | |
fdae83ab TT |
3148 | TAKE_GOTO; |
3149 | else | |
3150 | SKIP_GOTO; | |
58eb6e7c | 3151 | } |
f7b4fb11 | 3152 | NEXT_INSN; |
58eb6e7c | 3153 | |
fdae83ab | 3154 | insn_ifnonnull: |
58eb6e7c | 3155 | { |
58eb6e7c AG |
3156 | jobject val = POPA(); |
3157 | if (val != NULL) | |
fdae83ab TT |
3158 | TAKE_GOTO; |
3159 | else | |
3160 | SKIP_GOTO; | |
58eb6e7c | 3161 | } |
f7b4fb11 | 3162 | NEXT_INSN; |
58eb6e7c | 3163 | |
fdae83ab TT |
3164 | insn_multianewarray: |
3165 | { | |
3166 | int kind_index = GET2U (); | |
3167 | int dim = GET1U (); | |
3168 | ||
3169 | jclass type | |
18744d9b | 3170 | = (_Jv_Linker::resolve_pool_entry (meth->defining_class, |
36739040 | 3171 | kind_index)).clazz; |
fdae83ab TT |
3172 | jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim); |
3173 | ||
3174 | for (int i = dim - 1; i >= 0; i--) | |
3175 | { | |
3176 | sizes[i] = POPI (); | |
3177 | } | |
3178 | ||
3179 | jobject res = _Jv_NewMultiArray (type,dim, sizes); | |
3180 | ||
3181 | PUSHA (res); | |
3182 | } | |
3183 | NEXT_INSN; | |
3184 | ||
3185 | #ifndef DIRECT_THREADED | |
3186 | insn_wide: | |
58eb6e7c AG |
3187 | { |
3188 | jint the_mod_op = get1u (pc++); | |
3189 | jint wide = get2u (pc); pc += 2; | |
3190 | ||
3191 | switch (the_mod_op) | |
3192 | { | |
3193 | case op_istore: | |
3194 | STOREI (wide); | |
f7b4fb11 | 3195 | NEXT_INSN; |
58eb6e7c AG |
3196 | |
3197 | case op_fstore: | |
3198 | STOREF (wide); | |
f7b4fb11 | 3199 | NEXT_INSN; |
58eb6e7c AG |
3200 | |
3201 | case op_astore: | |
3202 | STOREA (wide); | |
f7b4fb11 | 3203 | NEXT_INSN; |
58eb6e7c AG |
3204 | |
3205 | case op_lload: | |
3206 | LOADL (wide); | |
f7b4fb11 | 3207 | NEXT_INSN; |
58eb6e7c AG |
3208 | |
3209 | case op_dload: | |
3210 | LOADD (wide); | |
f7b4fb11 | 3211 | NEXT_INSN; |
58eb6e7c AG |
3212 | |
3213 | case op_iload: | |
3214 | LOADI (wide); | |
f7b4fb11 | 3215 | NEXT_INSN; |
58eb6e7c | 3216 | |
618df745 TT |
3217 | case op_fload: |
3218 | LOADF (wide); | |
3219 | NEXT_INSN; | |
3220 | ||
58eb6e7c AG |
3221 | case op_aload: |
3222 | LOADA (wide); | |
f7b4fb11 | 3223 | NEXT_INSN; |
58eb6e7c AG |
3224 | |
3225 | case op_lstore: | |
3226 | STOREL (wide); | |
f7b4fb11 | 3227 | NEXT_INSN; |
58eb6e7c AG |
3228 | |
3229 | case op_dstore: | |
3230 | STORED (wide); | |
f7b4fb11 | 3231 | NEXT_INSN; |
58eb6e7c AG |
3232 | |
3233 | case op_ret: | |
3234 | pc = (unsigned char*) PEEKA (wide); | |
f7b4fb11 | 3235 | NEXT_INSN; |
58eb6e7c AG |
3236 | |
3237 | case op_iinc: | |
3238 | { | |
3239 | jint amount = get2s (pc); pc += 2; | |
3240 | jint value = PEEKI (wide); | |
3241 | POKEI (wide, value+amount); | |
3242 | } | |
f7b4fb11 | 3243 | NEXT_INSN; |
58eb6e7c AG |
3244 | |
3245 | default: | |
3246 | throw_internal_error ("illegal bytecode modified by wide"); | |
3247 | } | |
3248 | ||
3249 | } | |
fdae83ab TT |
3250 | #endif /* DIRECT_THREADED */ |
3251 | } | |
3252 | catch (java::lang::Throwable *ex) | |
3253 | { | |
3254 | #ifdef DIRECT_THREADED | |
3255 | void *logical_pc = (void *) ((insn_slot *) pc - 1); | |
3256 | #else | |
3257 | int logical_pc = pc - 1 - bytecode (); | |
3258 | #endif | |
18744d9b | 3259 | _Jv_InterpException *exc = meth->exceptions (); |
fdae83ab | 3260 | jclass exc_class = ex->getClass (); |
58eb6e7c | 3261 | |
18744d9b | 3262 | for (int i = 0; i < meth->exc_count; i++) |
fdae83ab TT |
3263 | { |
3264 | if (PCVAL (exc[i].start_pc) <= logical_pc | |
3265 | && logical_pc < PCVAL (exc[i].end_pc)) | |
3266 | { | |
3267 | #ifdef DIRECT_THREADED | |
3268 | jclass handler = (jclass) exc[i].handler_type.p; | |
3269 | #else | |
3270 | jclass handler = NULL; | |
3271 | if (exc[i].handler_type.i != 0) | |
36739040 TT |
3272 | handler = (_Jv_Linker::resolve_pool_entry (defining_class, |
3273 | exc[i].handler_type.i)).clazz; | |
fdae83ab | 3274 | #endif /* DIRECT_THREADED */ |
58eb6e7c | 3275 | |
fdae83ab TT |
3276 | if (handler == NULL || handler->isAssignableFrom (exc_class)) |
3277 | { | |
3278 | #ifdef DIRECT_THREADED | |
3279 | pc = (insn_slot *) exc[i].handler_pc.p; | |
3280 | #else | |
3281 | pc = bytecode () + exc[i].handler_pc.i; | |
3282 | #endif /* DIRECT_THREADED */ | |
3283 | sp = stack; | |
3284 | sp++->o = ex; // Push exception. | |
3285 | NEXT_INSN; | |
3286 | } | |
3287 | } | |
3288 | } | |
58eb6e7c | 3289 | |
fdae83ab TT |
3290 | // No handler, so re-throw. |
3291 | throw ex; | |
3292 | } | |
58eb6e7c AG |
3293 | } |
3294 | ||
58eb6e7c | 3295 | static void |
2cf94e58 | 3296 | throw_internal_error (const char *msg) |
58eb6e7c | 3297 | { |
b3208f56 | 3298 | throw new java::lang::InternalError (JvNewStringLatin1 (msg)); |
58eb6e7c AG |
3299 | } |
3300 | ||
3301 | static void | |
3302 | throw_incompatible_class_change_error (jstring msg) | |
3303 | { | |
b3208f56 | 3304 | throw new java::lang::IncompatibleClassChangeError (msg); |
58eb6e7c AG |
3305 | } |
3306 | ||
715bdd81 | 3307 | #ifndef HANDLE_SEGV |
58eb6e7c AG |
3308 | static java::lang::NullPointerException *null_pointer_exc; |
3309 | static void | |
3310 | throw_null_pointer_exception () | |
3311 | { | |
3312 | if (null_pointer_exc == NULL) | |
3313 | null_pointer_exc = new java::lang::NullPointerException; | |
3314 | ||
b3208f56 | 3315 | throw null_pointer_exc; |
58eb6e7c AG |
3316 | } |
3317 | #endif | |
3318 | ||
18744d9b BM |
3319 | /* Look up source code line number for given bytecode (or direct threaded |
3320 | interpreter) PC. */ | |
3321 | int | |
3322 | _Jv_InterpMethod::get_source_line(pc_t mpc) | |
3323 | { | |
3324 | int line = line_table_len > 0 ? line_table[0].line : -1; | |
3325 | for (int i = 1; i < line_table_len; i++) | |
3326 | if (line_table[i].pc > mpc) | |
3327 | break; | |
3328 | else | |
3329 | line = line_table[i].line; | |
3330 | ||
3331 | return line; | |
3332 | } | |
3333 | ||
36739040 TT |
3334 | /** Do static initialization for fields with a constant initializer */ |
3335 | void | |
3336 | _Jv_InitField (jobject obj, jclass klass, int index) | |
3337 | { | |
3338 | using namespace java::lang::reflect; | |
3339 | ||
3340 | if (obj != 0 && klass == 0) | |
3341 | klass = obj->getClass (); | |
3342 | ||
3343 | if (!_Jv_IsInterpretedClass (klass)) | |
3344 | return; | |
3345 | ||
3346 | _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info; | |
3347 | ||
3348 | _Jv_Field * field = (&klass->fields[0]) + index; | |
3349 | ||
3350 | if (index > klass->field_count) | |
3351 | throw_internal_error ("field out of range"); | |
3352 | ||
3353 | int init = iclass->field_initializers[index]; | |
3354 | if (init == 0) | |
3355 | return; | |
3356 | ||
3357 | _Jv_Constants *pool = &klass->constants; | |
3358 | int tag = pool->tags[init]; | |
3359 | ||
3360 | if (! field->isResolved ()) | |
3361 | throw_internal_error ("initializing unresolved field"); | |
3362 | ||
3363 | if (obj==0 && ((field->flags & Modifier::STATIC) == 0)) | |
3364 | throw_internal_error ("initializing non-static field with no object"); | |
3365 | ||
3366 | void *addr = 0; | |
3367 | ||
3368 | if ((field->flags & Modifier::STATIC) != 0) | |
3369 | addr = (void*) field->u.addr; | |
3370 | else | |
3371 | addr = (void*) (((char*)obj) + field->u.boffset); | |
3372 | ||
3373 | switch (tag) | |
3374 | { | |
3375 | case JV_CONSTANT_String: | |
3376 | { | |
3377 | jstring str; | |
3378 | str = _Jv_NewStringUtf8Const (pool->data[init].utf8); | |
3379 | pool->data[init].string = str; | |
3380 | pool->tags[init] = JV_CONSTANT_ResolvedString; | |
3381 | } | |
3382 | /* fall through */ | |
3383 | ||
3384 | case JV_CONSTANT_ResolvedString: | |
3385 | if (! (field->type == &java::lang::String::class$ | |
3386 | || field->type == &java::lang::Class::class$)) | |
3387 | throw_class_format_error ("string initialiser to non-string field"); | |
3388 | ||
3389 | *(jstring*)addr = pool->data[init].string; | |
3390 | break; | |
3391 | ||
3392 | case JV_CONSTANT_Integer: | |
3393 | { | |
3394 | int value = pool->data[init].i; | |
3395 | ||
3396 | if (field->type == JvPrimClass (boolean)) | |
3397 | *(jboolean*)addr = (jboolean)value; | |
3398 | ||
3399 | else if (field->type == JvPrimClass (byte)) | |
3400 | *(jbyte*)addr = (jbyte)value; | |
3401 | ||
3402 | else if (field->type == JvPrimClass (char)) | |
3403 | *(jchar*)addr = (jchar)value; | |
3404 | ||
3405 | else if (field->type == JvPrimClass (short)) | |
3406 | *(jshort*)addr = (jshort)value; | |
3407 | ||
3408 | else if (field->type == JvPrimClass (int)) | |
3409 | *(jint*)addr = (jint)value; | |
3410 | ||
3411 | else | |
3412 | throw_class_format_error ("erroneous field initializer"); | |
3413 | } | |
3414 | break; | |
3415 | ||
3416 | case JV_CONSTANT_Long: | |
3417 | if (field->type != JvPrimClass (long)) | |
3418 | throw_class_format_error ("erroneous field initializer"); | |
3419 | ||
3420 | *(jlong*)addr = _Jv_loadLong (&pool->data[init]); | |
3421 | break; | |
3422 | ||
3423 | case JV_CONSTANT_Float: | |
3424 | if (field->type != JvPrimClass (float)) | |
3425 | throw_class_format_error ("erroneous field initializer"); | |
3426 | ||
3427 | *(jfloat*)addr = pool->data[init].f; | |
3428 | break; | |
3429 | ||
3430 | case JV_CONSTANT_Double: | |
3431 | if (field->type != JvPrimClass (double)) | |
3432 | throw_class_format_error ("erroneous field initializer"); | |
3433 | ||
3434 | *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]); | |
3435 | break; | |
3436 | ||
3437 | default: | |
3438 | throw_class_format_error ("erroneous field initializer"); | |
3439 | } | |
3440 | } | |
3441 | ||
3442 | inline static unsigned char* | |
3443 | skip_one_type (unsigned char* ptr) | |
3444 | { | |
3445 | int ch = *ptr++; | |
3446 | ||
3447 | while (ch == '[') | |
3448 | { | |
3449 | ch = *ptr++; | |
3450 | } | |
3451 | ||
3452 | if (ch == 'L') | |
3453 | { | |
3454 | do { ch = *ptr++; } while (ch != ';'); | |
3455 | } | |
3456 | ||
3457 | return ptr; | |
3458 | } | |
3459 | ||
3460 | static ffi_type* | |
3461 | get_ffi_type_from_signature (unsigned char* ptr) | |
3462 | { | |
3463 | switch (*ptr) | |
3464 | { | |
3465 | case 'L': | |
3466 | case '[': | |
3467 | return &ffi_type_pointer; | |
3468 | break; | |
3469 | ||
3470 | case 'Z': | |
3471 | // On some platforms a bool is a byte, on others an int. | |
3472 | if (sizeof (jboolean) == sizeof (jbyte)) | |
3473 | return &ffi_type_sint8; | |
3474 | else | |
3475 | { | |
3476 | JvAssert (sizeof (jbyte) == sizeof (jint)); | |
3477 | return &ffi_type_sint32; | |
3478 | } | |
3479 | break; | |
3480 | ||
3481 | case 'B': | |
3482 | return &ffi_type_sint8; | |
3483 | break; | |
3484 | ||
3485 | case 'C': | |
3486 | return &ffi_type_uint16; | |
3487 | break; | |
3488 | ||
3489 | case 'S': | |
3490 | return &ffi_type_sint16; | |
3491 | break; | |
3492 | ||
3493 | case 'I': | |
3494 | return &ffi_type_sint32; | |
3495 | break; | |
3496 | ||
3497 | case 'J': | |
3498 | return &ffi_type_sint64; | |
3499 | break; | |
3500 | ||
3501 | case 'F': | |
3502 | return &ffi_type_float; | |
3503 | break; | |
3504 | ||
3505 | case 'D': | |
3506 | return &ffi_type_double; | |
3507 | break; | |
3508 | ||
3509 | case 'V': | |
3510 | return &ffi_type_void; | |
3511 | break; | |
3512 | } | |
3513 | ||
3514 | throw_internal_error ("unknown type in signature"); | |
3515 | } | |
3516 | ||
3517 | /* this function yields the number of actual arguments, that is, if the | |
3518 | * function is non-static, then one is added to the number of elements | |
3519 | * found in the signature */ | |
3520 | ||
3521 | int | |
3522 | _Jv_count_arguments (_Jv_Utf8Const *signature, | |
3523 | jboolean staticp) | |
3524 | { | |
3525 | unsigned char *ptr = (unsigned char*) signature->chars(); | |
3526 | int arg_count = staticp ? 0 : 1; | |
3527 | ||
3528 | /* first, count number of arguments */ | |
3529 | ||
3530 | // skip '(' | |
3531 | ptr++; | |
3532 | ||
3533 | // count args | |
3534 | while (*ptr != ')') | |
3535 | { | |
3536 | ptr = skip_one_type (ptr); | |
3537 | arg_count += 1; | |
3538 | } | |
3539 | ||
3540 | return arg_count; | |
3541 | } | |
3542 | ||
3543 | /* This beast will build a cif, given the signature. Memory for | |
3544 | * the cif itself and for the argument types must be allocated by the | |
3545 | * caller. | |
3546 | */ | |
3547 | ||
3548 | static int | |
3549 | init_cif (_Jv_Utf8Const* signature, | |
3550 | int arg_count, | |
3551 | jboolean staticp, | |
3552 | ffi_cif *cif, | |
3553 | ffi_type **arg_types, | |
3554 | ffi_type **rtype_p) | |
3555 | { | |
3556 | unsigned char *ptr = (unsigned char*) signature->chars(); | |
3557 | ||
3558 | int arg_index = 0; // arg number | |
3559 | int item_count = 0; // stack-item count | |
3560 | ||
3561 | // setup receiver | |
3562 | if (!staticp) | |
3563 | { | |
3564 | arg_types[arg_index++] = &ffi_type_pointer; | |
3565 | item_count += 1; | |
3566 | } | |
3567 | ||
3568 | // skip '(' | |
3569 | ptr++; | |
3570 | ||
3571 | // assign arg types | |
3572 | while (*ptr != ')') | |
3573 | { | |
3574 | arg_types[arg_index++] = get_ffi_type_from_signature (ptr); | |
3575 | ||
3576 | if (*ptr == 'J' || *ptr == 'D') | |
3577 | item_count += 2; | |
3578 | else | |
3579 | item_count += 1; | |
3580 | ||
3581 | ptr = skip_one_type (ptr); | |
3582 | } | |
3583 | ||
3584 | // skip ')' | |
3585 | ptr++; | |
3586 | ffi_type *rtype = get_ffi_type_from_signature (ptr); | |
3587 | ||
3588 | ptr = skip_one_type (ptr); | |
3589 | if (ptr != (unsigned char*)signature->chars() + signature->len()) | |
3590 | throw_internal_error ("did not find end of signature"); | |
3591 | ||
3592 | if (ffi_prep_cif (cif, FFI_DEFAULT_ABI, | |
3593 | arg_count, rtype, arg_types) != FFI_OK) | |
3594 | throw_internal_error ("ffi_prep_cif failed"); | |
3595 | ||
3596 | if (rtype_p != NULL) | |
3597 | *rtype_p = rtype; | |
3598 | ||
3599 | return item_count; | |
3600 | } | |
3601 | ||
3602 | #if FFI_NATIVE_RAW_API | |
3603 | # define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure | |
3604 | # define FFI_RAW_SIZE ffi_raw_size | |
3605 | #else | |
3606 | # define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure | |
3607 | # define FFI_RAW_SIZE ffi_java_raw_size | |
3608 | #endif | |
3609 | ||
3610 | /* we put this one here, and not in interpret.cc because it | |
3611 | * calls the utility routines _Jv_count_arguments | |
3612 | * which are static to this module. The following struct defines the | |
3613 | * layout we use for the stubs, it's only used in the ncode method. */ | |
3614 | ||
3615 | typedef struct { | |
3616 | ffi_raw_closure closure; | |
3617 | ffi_cif cif; | |
3618 | ffi_type *arg_types[0]; | |
3619 | } ncode_closure; | |
3620 | ||
3621 | typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*); | |
3622 | ||
3623 | void * | |
3624 | _Jv_InterpMethod::ncode () | |
3625 | { | |
3626 | using namespace java::lang::reflect; | |
3627 | ||
3628 | if (self->ncode != 0) | |
3629 | return self->ncode; | |
3630 | ||
3631 | jboolean staticp = (self->accflags & Modifier::STATIC) != 0; | |
3632 | int arg_count = _Jv_count_arguments (self->signature, staticp); | |
3633 | ||
3634 | ncode_closure *closure = | |
3635 | (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure) | |
3636 | + arg_count * sizeof (ffi_type*)); | |
3637 | ||
3638 | init_cif (self->signature, | |
3639 | arg_count, | |
3640 | staticp, | |
3641 | &closure->cif, | |
3642 | &closure->arg_types[0], | |
3643 | NULL); | |
3644 | ||
3645 | ffi_closure_fun fun; | |
3646 | ||
3647 | args_raw_size = FFI_RAW_SIZE (&closure->cif); | |
3648 | ||
3649 | JvAssert ((self->accflags & Modifier::NATIVE) == 0); | |
3650 | ||
3651 | if ((self->accflags & Modifier::SYNCHRONIZED) != 0) | |
3652 | { | |
3653 | if (staticp) | |
3654 | fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class; | |
3655 | else | |
3656 | fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; | |
3657 | } | |
3658 | else | |
3659 | { | |
3660 | if (staticp) | |
3661 | fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class; | |
3662 | else | |
3663 | fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal; | |
3664 | } | |
3665 | ||
3666 | FFI_PREP_RAW_CLOSURE (&closure->closure, | |
3667 | &closure->cif, | |
3668 | fun, | |
3669 | (void*)this); | |
3670 | ||
3671 | self->ncode = (void*)closure; | |
3672 | return self->ncode; | |
3673 | } | |
3674 | ||
e939885f KS |
3675 | #ifdef DIRECT_THREADED |
3676 | /* Find the index of the given insn in the array of insn slots | |
3677 | for this method. Returns -1 if not found. */ | |
3678 | jlong | |
3679 | _Jv_InterpMethod::insn_index (pc_t pc) | |
3680 | { | |
3681 | jlong left = 0; | |
3682 | jlong right = number_insn_slots; | |
3683 | insn_slot* slots = reinterpret_cast<insn_slot*> (prepared); | |
3684 | ||
3685 | while (right >= 0) | |
3686 | { | |
3687 | jlong mid = (left + right) / 2; | |
3688 | if (&slots[mid] == pc) | |
3689 | return mid; | |
3690 | ||
3691 | if (pc < &slots[mid]) | |
3692 | right = mid - 1; | |
3693 | else | |
3694 | left = mid + 1; | |
3695 | } | |
3696 | ||
3697 | return -1; | |
3698 | } | |
3699 | #endif // DIRECT_THREADED | |
3700 | ||
3701 | void | |
3702 | _Jv_InterpMethod::get_line_table (jlong& start, jlong& end, | |
3703 | jintArray& line_numbers, | |
3704 | jlongArray& code_indices) | |
3705 | { | |
3706 | #ifdef DIRECT_THREADED | |
3707 | /* For the DIRECT_THREADED case, if the method has not yet been | |
3708 | * compiled, the linetable will change to insn slots instead of | |
3709 | * bytecode PCs. It is probably easiest, in this case, to simply | |
3710 | * compile the method and guarantee that we are using insn | |
3711 | * slots. | |
3712 | */ | |
3713 | _Jv_CompileMethod (this); | |
3714 | ||
3715 | if (line_table_len > 0) | |
3716 | { | |
3717 | start = 0; | |
3718 | end = number_insn_slots; | |
3719 | line_numbers = JvNewIntArray (line_table_len); | |
3720 | code_indices = JvNewLongArray (line_table_len); | |
3721 | ||
3722 | jint* lines = elements (line_numbers); | |
3723 | jlong* indices = elements (code_indices); | |
3724 | for (int i = 0; i < line_table_len; ++i) | |
3725 | { | |
3726 | lines[i] = line_table[i].line; | |
3727 | indices[i] = insn_index (line_table[i].pc); | |
3728 | } | |
3729 | } | |
3730 | #else // !DIRECT_THREADED | |
3731 | if (line_table_len > 0) | |
3732 | { | |
3733 | start = 0; | |
3734 | end = code_length; | |
3735 | line_numbers = JvNewIntArray (line_table_len); | |
3736 | code_indices = JvNewLongArray (line_table_len); | |
3737 | ||
3738 | jint* lines = elements (line_numbers); | |
3739 | jlong* indices = elements (code_indices); | |
3740 | for (int i = 0; i < line_table_len; ++i) | |
3741 | { | |
3742 | lines[i] = line_table[i].line; | |
3743 | indices[i] = (jlong) line_table[i].bytecode_pc; | |
3744 | } | |
3745 | } | |
3746 | #endif // !DIRECT_THREADED | |
3747 | } | |
3748 | ||
36739040 TT |
3749 | void * |
3750 | _Jv_JNIMethod::ncode () | |
3751 | { | |
3752 | using namespace java::lang::reflect; | |
3753 | ||
3754 | if (self->ncode != 0) | |
3755 | return self->ncode; | |
3756 | ||
3757 | jboolean staticp = (self->accflags & Modifier::STATIC) != 0; | |
3758 | int arg_count = _Jv_count_arguments (self->signature, staticp); | |
3759 | ||
3760 | ncode_closure *closure = | |
3761 | (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure) | |
3762 | + arg_count * sizeof (ffi_type*)); | |
3763 | ||
3764 | ffi_type *rtype; | |
3765 | init_cif (self->signature, | |
3766 | arg_count, | |
3767 | staticp, | |
3768 | &closure->cif, | |
3769 | &closure->arg_types[0], | |
3770 | &rtype); | |
3771 | ||
3772 | ffi_closure_fun fun; | |
3773 | ||
3774 | args_raw_size = FFI_RAW_SIZE (&closure->cif); | |
3775 | ||
3776 | // Initialize the argument types and CIF that represent the actual | |
3777 | // underlying JNI function. | |
3778 | int extra_args = 1; | |
3779 | if ((self->accflags & Modifier::STATIC)) | |
3780 | ++extra_args; | |
3781 | jni_arg_types = (ffi_type **) _Jv_AllocBytes ((extra_args + arg_count) | |
3782 | * sizeof (ffi_type *)); | |
3783 | int offset = 0; | |
3784 | jni_arg_types[offset++] = &ffi_type_pointer; | |
3785 | if ((self->accflags & Modifier::STATIC)) | |
3786 | jni_arg_types[offset++] = &ffi_type_pointer; | |
3787 | memcpy (&jni_arg_types[offset], &closure->arg_types[0], | |
3788 | arg_count * sizeof (ffi_type *)); | |
3789 | ||
3790 | if (ffi_prep_cif (&jni_cif, _Jv_platform_ffi_abi, | |
3791 | extra_args + arg_count, rtype, | |
3792 | jni_arg_types) != FFI_OK) | |
3793 | throw_internal_error ("ffi_prep_cif failed for JNI function"); | |
3794 | ||
3795 | JvAssert ((self->accflags & Modifier::NATIVE) != 0); | |
3796 | ||
3797 | // FIXME: for now we assume that all native methods for | |
3798 | // interpreted code use JNI. | |
3799 | fun = (ffi_closure_fun) &_Jv_JNIMethod::call; | |
3800 | ||
3801 | FFI_PREP_RAW_CLOSURE (&closure->closure, | |
3802 | &closure->cif, | |
3803 | fun, | |
3804 | (void*) this); | |
3805 | ||
3806 | self->ncode = (void *) closure; | |
3807 | return self->ncode; | |
3808 | } | |
3809 | ||
3810 | static void | |
3811 | throw_class_format_error (jstring msg) | |
3812 | { | |
3813 | throw (msg | |
3814 | ? new java::lang::ClassFormatError (msg) | |
3815 | : new java::lang::ClassFormatError); | |
3816 | } | |
3817 | ||
3818 | static void | |
2cf94e58 | 3819 | throw_class_format_error (const char *msg) |
36739040 TT |
3820 | { |
3821 | throw_class_format_error (JvNewStringLatin1 (msg)); | |
3822 | } | |
3823 | ||
3824 | \f | |
3825 | ||
3826 | void | |
3827 | _Jv_InterpreterEngine::do_verify (jclass klass) | |
3828 | { | |
3829 | _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; | |
3830 | for (int i = 0; i < klass->method_count; i++) | |
3831 | { | |
3832 | using namespace java::lang::reflect; | |
3833 | _Jv_MethodBase *imeth = iclass->interpreted_methods[i]; | |
3834 | _Jv_ushort accflags = klass->methods[i].accflags; | |
3835 | if ((accflags & (Modifier::NATIVE | Modifier::ABSTRACT)) == 0) | |
3836 | { | |
3837 | _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth); | |
3838 | _Jv_VerifyMethod (im); | |
3839 | } | |
3840 | } | |
3841 | } | |
3842 | ||
3843 | void | |
3844 | _Jv_InterpreterEngine::do_create_ncode (jclass klass) | |
3845 | { | |
3846 | _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; | |
3847 | for (int i = 0; i < klass->method_count; i++) | |
3848 | { | |
3849 | // Just skip abstract methods. This is particularly important | |
3850 | // because we don't resize the interpreted_methods array when | |
3851 | // miranda methods are added to it. | |
3852 | if ((klass->methods[i].accflags | |
3853 | & java::lang::reflect::Modifier::ABSTRACT) | |
3854 | != 0) | |
3855 | continue; | |
3856 | ||
3857 | _Jv_MethodBase *imeth = iclass->interpreted_methods[i]; | |
3858 | ||
3859 | if ((klass->methods[i].accflags & java::lang::reflect::Modifier::NATIVE) | |
3860 | != 0) | |
3861 | { | |
3862 | // You might think we could use a virtual `ncode' method in | |
3863 | // the _Jv_MethodBase and unify the native and non-native | |
3864 | // cases. Well, we can't, because we don't allocate these | |
3865 | // objects using `new', and thus they don't get a vtable. | |
3866 | _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth); | |
3867 | klass->methods[i].ncode = jnim->ncode (); | |
3868 | } | |
3869 | else if (imeth != 0) // it could be abstract | |
3870 | { | |
3871 | _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth); | |
3872 | klass->methods[i].ncode = im->ncode (); | |
3873 | } | |
3874 | } | |
3875 | } | |
3876 | ||
3877 | void | |
3878 | _Jv_InterpreterEngine::do_allocate_static_fields (jclass klass, | |
8b1753e3 TT |
3879 | int pointer_size, |
3880 | int other_size) | |
36739040 TT |
3881 | { |
3882 | _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; | |
3883 | ||
8b1753e3 | 3884 | // Splitting the allocations here lets us scan reference fields and |
d07548f9 TT |
3885 | // avoid scanning non-reference fields. How reference fields are |
3886 | // scanned is a bit tricky: we allocate using _Jv_AllocRawObj, which | |
3887 | // means that this memory will be scanned conservatively (same | |
3888 | // difference, since we know all the contents here are pointers). | |
3889 | // Then we put pointers into this memory into the 'fields' | |
3890 | // structure. Most of these are interior pointers, which is ok (but | |
3891 | // even so the pointer to the first reference field will be used and | |
3892 | // that is not an interior pointer). The 'fields' array is also | |
3893 | // allocated with _Jv_AllocRawObj (see defineclass.cc), so it will | |
3894 | // be scanned. A pointer to this array is held by Class and thus | |
3895 | // seen by the collector. | |
8b1753e3 TT |
3896 | char *reference_fields = (char *) _Jv_AllocRawObj (pointer_size); |
3897 | char *non_reference_fields = (char *) _Jv_AllocBytes (other_size); | |
36739040 TT |
3898 | |
3899 | for (int i = 0; i < klass->field_count; i++) | |
3900 | { | |
3901 | _Jv_Field *field = &klass->fields[i]; | |
3902 | ||
8b1753e3 TT |
3903 | if ((field->flags & java::lang::reflect::Modifier::STATIC) == 0) |
3904 | continue; | |
3905 | ||
3906 | char *base = field->isRef() ? reference_fields : non_reference_fields; | |
3907 | field->u.addr = base + field->u.boffset; | |
3908 | ||
3909 | if (iclass->field_initializers[i] != 0) | |
36739040 | 3910 | { |
8b1753e3 TT |
3911 | _Jv_Linker::resolve_field (field, klass->loader); |
3912 | _Jv_InitField (0, klass, i); | |
36739040 TT |
3913 | } |
3914 | } | |
3915 | ||
3916 | // Now we don't need the field_initializers anymore, so let the | |
3917 | // collector get rid of it. | |
3918 | iclass->field_initializers = 0; | |
3919 | } | |
3920 | ||
3921 | _Jv_ResolvedMethod * | |
3922 | _Jv_InterpreterEngine::do_resolve_method (_Jv_Method *method, jclass klass, | |
3923 | jboolean staticp, jint vtable_index) | |
3924 | { | |
3925 | int arg_count = _Jv_count_arguments (method->signature, staticp); | |
3926 | ||
3927 | _Jv_ResolvedMethod* result = (_Jv_ResolvedMethod*) | |
3928 | _Jv_AllocBytes (sizeof (_Jv_ResolvedMethod) | |
3929 | + arg_count*sizeof (ffi_type*)); | |
3930 | ||
3931 | result->stack_item_count | |
3932 | = init_cif (method->signature, | |
3933 | arg_count, | |
3934 | staticp, | |
3935 | &result->cif, | |
3936 | &result->arg_types[0], | |
3937 | NULL); | |
3938 | ||
3939 | result->vtable_index = vtable_index; | |
3940 | result->method = method; | |
3941 | result->klass = klass; | |
3942 | ||
3943 | return result; | |
3944 | } | |
3945 | ||
3946 | void | |
3947 | _Jv_InterpreterEngine::do_post_miranda_hook (jclass klass) | |
3948 | { | |
3949 | _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; | |
3950 | for (int i = 0; i < klass->method_count; i++) | |
3951 | { | |
3952 | // Just skip abstract methods. This is particularly important | |
3953 | // because we don't resize the interpreted_methods array when | |
3954 | // miranda methods are added to it. | |
3955 | if ((klass->methods[i].accflags | |
3956 | & java::lang::reflect::Modifier::ABSTRACT) | |
3957 | != 0) | |
3958 | continue; | |
3959 | // Miranda method additions mean that the `methods' array moves. | |
3960 | // We cache a pointer into this array, so we have to update. | |
3961 | iclass->interpreted_methods[i]->self = &klass->methods[i]; | |
3962 | } | |
3963 | } | |
3964 | ||
d0f4aa53 KS |
3965 | #ifdef DIRECT_THREADED |
3966 | void | |
3967 | _Jv_CompileMethod (_Jv_InterpMethod* method) | |
3968 | { | |
3969 | if (method->prepared == NULL) | |
3970 | _Jv_InterpMethod::run (NULL, NULL, method); | |
3971 | } | |
3972 | #endif // DIRECT_THREADED | |
3973 | ||
58eb6e7c | 3974 | #endif // INTERPRETER |