natObject.cc (notify): Throw message with IllegalMonitorStateException.
[gcc.git] / libjava / interpret.cc
1 // interpret.cc - Code for the interpreter
2
3 /* Copyright (C) 1999 Cygnus Solutions
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
13 #include <config.h>
14
15 #pragma implementation "java-interp.h"
16
17 #include <jvm.h>
18 #include <java-cpool.h>
19 #include <java-interp.h>
20 #include <java/lang/fdlibm.h>
21 #include <java/lang/System.h>
22 #include <java/lang/String.h>
23 #include <java/lang/Integer.h>
24 #include <java/lang/StringBuffer.h>
25 #include <java/io/PrintStream.h>
26 #include <java/lang/Class.h>
27 #include <java/lang/reflect/Modifier.h>
28 #include <java/lang/ClassCastException.h>
29 #include <java/lang/VirtualMachineError.h>
30 #include <java/lang/InternalError.h>
31 #include <java/lang/NullPointerException.h>
32 #include <java/lang/ArithmeticException.h>
33 #include <java/lang/IncompatibleClassChangeError.h>
34 #include <java-insns.h>
35 #include <java-signal.h>
36
37 #ifndef INTERPRETER
38
39 #include <gnu/gcj/runtime/MethodInvocation.h>
40
41 /* This should never happen. */
42 void
43 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
44 gnu::gcj::RawData *)
45 {
46 JvFail ("no interpreter");
47 }
48
49 #else
50
51 #define ClassError _CL_Q34java4lang5Error
52 extern java::lang::Class ClassError;
53
54 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
55
56 static void throw_internal_error (char *msg)
57 __attribute__ ((__noreturn__));
58 static void throw_incompatible_class_change_error (jstring msg)
59 __attribute__ ((__noreturn__));
60 #if !HANDLE_SEGV
61 static void throw_null_pointer_exception ()
62 __attribute__ ((__noreturn__));
63 #endif
64 #if !HANDLE_FPE
65 static void throw_arithmetic_exception ()
66 __attribute__ ((__noreturn__));
67 #endif
68
69
70 static inline void dupx (_Jv_word *sp, int n, int x)
71 {
72 // first "slide" n+x elements n to the right
73 int top = n-1;
74 for (int i = 0; i < n+x; i++)
75 {
76 sp[(top-i)] = sp[(top-i)-n];
77 }
78
79 // next, copy the n top elements, n+x down
80 for (int i = 0; i < n; i++)
81 {
82 sp[top-(n+x)-i] = sp[top-i];
83 }
84
85 };
86
87
88 #define PUSHA(V) (sp++)->o = (V)
89 #define PUSHI(V) (sp++)->i = (V)
90 #define PUSHF(V) (sp++)->f = (V)
91 #define PUSHL(V) ({ _Jv_word2 w2; w2.l=(V); \
92 (sp++)->ia[0] = w2.ia[0]; \
93 (sp++)->ia[0] = w2.ia[1]; })
94 #define PUSHD(V) ({ _Jv_word2 w2; w2.d=(V); \
95 (sp++)->ia[0] = w2.ia[0]; \
96 (sp++)->ia[0] = w2.ia[1]; })
97
98 #define POPA() ((--sp)->o)
99 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
100 #define POPF() ((jfloat) (--sp)->f)
101 #define POPL() ({ _Jv_word2 w2; \
102 w2.ia[1] = (--sp)->ia[0]; \
103 w2.ia[0] = (--sp)->ia[0]; w2.l; })
104 #define POPD() ({ _Jv_word2 w2; \
105 w2.ia[1] = (--sp)->ia[0]; \
106 w2.ia[0] = (--sp)->ia[0]; w2.d; })
107
108 #define LOADA(I) (sp++)->o = locals[I].o
109 #define LOADI(I) (sp++)->i = locals[I].i
110 #define LOADF(I) (sp++)->f = locals[I].f
111 #define LOADL(I) ({ jint __idx = (I); \
112 (sp++)->ia[0] = locals[__idx].ia[0]; \
113 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
114 })
115 #define LOADD(I) LOADL(I)
116
117
118 #define STOREA(I) locals[I].o = (--sp)->o
119 #define STOREI(I) locals[I].i = (--sp)->i
120 #define STOREF(I) locals[I].f = (--sp)->f
121 #define STOREL(I) ({ jint __idx = (I); \
122 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
123 locals[__idx].ia[0] = (--sp)->ia[0]; \
124 })
125 #define STORED(I) STOREL(I)
126
127 #define PEEKI(I) (locals+(I))->i
128 #define PEEKA(I) (locals+(I))->o
129
130 #define POKEI(I,V) ((locals+(I))->i = (V))
131
132
133 #define BINOPI(OP) { \
134 jint value2 = POPI(); \
135 jint value1 = POPI(); \
136 PUSHI(value1 OP value2); \
137 }
138
139 #define BINOPF(OP) { \
140 jfloat value2 = POPF(); \
141 jfloat value1 = POPF(); \
142 PUSHF(value1 OP value2); \
143 }
144
145 #define BINOPL(OP) { \
146 jlong value2 = POPL(); \
147 jlong value1 = POPL(); \
148 PUSHL(value1 OP value2); \
149 }
150
151 #define BINOPD(OP) { \
152 jdouble value2 = POPD(); \
153 jdouble value1 = POPD(); \
154 PUSHD(value1 OP value2); \
155 }
156
157 static inline jint get1s(unsigned char* loc) {
158 return *(signed char*)loc;
159 }
160
161 static inline jint get1u(unsigned char* loc) {
162 return *loc;
163 }
164
165 static inline jint get2s(unsigned char* loc) {
166 return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1));
167 }
168
169 static inline jint get2u(unsigned char* loc) {
170 return (((jint)(*loc)) << 8) | ((jint)*(loc+1));
171 }
172
173 static jint get4(unsigned char* loc) {
174 return (((jint)(loc[0])) << 24)
175 | (((jint)(loc[1])) << 16)
176 | (((jint)(loc[2])) << 8)
177 | (((jint)(loc[3])) << 0);
178 }
179
180
181 #if HANDLE_SEGV
182 #define NULLCHECK(X)
183 #else
184 #define NULLCHECK(X) \
185 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
186 #endif
187
188 #if HANDLE_FPE
189 #define ZEROCHECK(X)
190 #else
191 #define ZEROCHECK(X) \
192 do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
193 #endif
194
195 // this method starts the actual running of the method. It is inlined
196 // in three different variants in the static methods run_normal,
197 // run_sync_object and run_sync_class (see below). Those static methods
198 // are installed directly in the stub for this method (by
199 // _Jv_InterpMethod::ncode, in resolve.cc).
200
201 inline jobject
202 _Jv_InterpMethod::run (ffi_cif* cif,
203 void *retp,
204 ffi_raw *args,
205 _Jv_InterpMethodInvocation *inv)
206 {
207 inv->running = this;
208 inv->pc = bytecode ();
209 inv->sp = inv->stack_base ();
210 _Jv_word *locals = inv->local_base ();
211
212 /* Go straight at it! the ffi raw format matches the internal
213 stack representation exactly. At leat, that's the idea.
214 */
215 memcpy ((void*) locals, (void*) args, args_raw_size);
216
217 next_segment:
218 /* this will call the method _Jv_InterpMethod::continue0, see below */
219 jobject ex =
220 gnu::gcj::runtime::MethodInvocation::continue0
221 ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
222
223 if (ex == 0) // no exception...
224 {
225 /* define sp locally, so the POP? macros will pick it up */
226 _Jv_word *sp = inv->sp;
227 int rtype = cif->rtype->type;
228
229 if (rtype == FFI_TYPE_POINTER)
230 {
231 jobject r = POPA();
232 *(jobject*) retp = r;
233 return 0;
234 }
235 else if (rtype == FFI_TYPE_SINT32)
236 {
237 jint r = POPI();
238 *(jint*)retp = r;
239 return 0;
240 }
241 else if (rtype == FFI_TYPE_VOID)
242 {
243 return 0;
244 }
245 else switch (rtype)
246 {
247 case FFI_TYPE_FLOAT:
248 {
249 jfloat r = POPF();
250 *(jfloat*)retp = r;
251 return 0;
252 }
253
254 case FFI_TYPE_DOUBLE:
255 {
256 jdouble r = POPD();
257 *(jdouble*)retp = r;
258 return 0;
259 }
260
261 case FFI_TYPE_UINT8:
262 case FFI_TYPE_UINT16:
263 case FFI_TYPE_UINT32:
264 case FFI_TYPE_SINT8:
265 case FFI_TYPE_SINT16:
266 {
267 jint r = POPI();
268 *(jint*)retp = r;
269 return 0;
270 }
271
272 case FFI_TYPE_SINT64:
273 {
274 jlong r = POPL();
275 *(jlong*)retp = r;
276 return 0;
277 }
278
279 default:
280 throw_internal_error ("unknown return type");
281 }
282
283 }
284
285 /** handle an exception */
286 if ( find_exception (ex, inv) )
287 goto next_segment;
288
289 java::lang::System::out->println
290 (_Jv_NewStringUTF (self->name->data));
291
292 return ex;
293 }
294
295 bool _Jv_InterpMethod::find_exception (jobject ex,
296 _Jv_InterpMethodInvocation *inv)
297 {
298 int logical_pc = inv->pc - bytecode ();
299 _Jv_InterpException *exc = exceptions ();
300 jclass exc_class = ex->getClass ();
301
302 for (int i = 0; i < exc_count; i++)
303 {
304 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
305 {
306 jclass handler;
307
308 if (exc[i].handler_type != 0)
309 handler = (_Jv_ResolvePoolEntry (defining_class,
310 exc[i].handler_type)).clazz;
311 else
312 handler = NULL;
313
314 if (handler==NULL || handler->isAssignableFrom (exc_class))
315 {
316 inv->pc = bytecode () + exc[i].handler_pc;
317 inv->sp = inv->stack_base (); // reset stack
318 (inv->sp++)->o = ex; // push exception
319 return true;
320 }
321 }
322 }
323 return false;
324 }
325
326 void _Jv_InterpMethod::run_normal (ffi_cif* cif,
327 void* ret,
328 ffi_raw * args,
329 void* __this)
330 {
331 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
332
333 // we do the alloca of the method invocation here, to allow the method
334 // "run" ro be inlined. Otherwise gcc will ignore the inline directive.
335 int storage_size = _this->max_stack+_this->max_locals;
336 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
337 alloca (sizeof (_Jv_InterpMethodInvocation)
338 + storage_size * sizeof (_Jv_word));
339
340 jobject ex = _this->run (cif, ret, args, inv);
341 if (ex != 0) _Jv_Throw (ex);
342 }
343
344 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
345 void* ret,
346 ffi_raw * args,
347 void* __this)
348 {
349 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
350 jobject rcv = (jobject)args[0].ptr;
351
352 int storage_size = _this->max_stack+_this->max_locals;
353 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
354 alloca (sizeof (_Jv_InterpMethodInvocation)
355 + storage_size * sizeof (_Jv_word));
356
357 _Jv_MonitorEnter (rcv);
358 jobject ex = _this->run (cif, ret, args, inv);
359 _Jv_MonitorExit (rcv);
360
361 if (ex != 0) _Jv_Throw (ex);
362 }
363
364 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
365 void* ret,
366 ffi_raw * args,
367 void* __this)
368 {
369 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
370 jclass sync = _this->defining_class;
371
372 int storage_size = _this->max_stack+_this->max_locals;
373 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*)
374 alloca (sizeof (_Jv_InterpMethodInvocation)
375 + storage_size * sizeof (_Jv_word));
376
377 _Jv_MonitorEnter (sync);
378 jobject ex = _this->run (cif, ret, args, inv);
379 _Jv_MonitorExit (sync);
380
381 if (ex != 0) _Jv_Throw (ex);
382 }
383
384 /* this is the exception handler hack, for the interpreter */
385 void
386 gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
387 gnu::gcj::RawData *inv)
388 {
389 _Jv_InterpMethod *meth0 = (_Jv_InterpMethod*)meth;
390 _Jv_InterpMethodInvocation *inv0 = (_Jv_InterpMethodInvocation*)inv;
391 meth0->continue1 (inv0);
392 }
393
394 /*
395 This proceeds execution, as designated in "inv". If an exception
396 happens, then it is simply thrown, and handled in Java. Thus, the pc
397 needs to be stored in the inv->pc at all times, so we can figure
398 out which handler (if any) to invoke.
399
400 One design issue, which I have not completely considered, is if it
401 should be possible to have interpreted classes linked in! Seldom used
402 (or non-critical) classes could reasonably be interpreted.
403 */
404
405
406 #ifdef __i386__
407 #define PC_REGISTER_ASM asm("%esi")
408 #else
409 #define PC_REGISTER_ASM
410 #endif
411
412 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
413 {
414 using namespace java::lang::reflect;
415
416 register _Jv_word *sp = inv->sp;
417 register unsigned char *pc PC_REGISTER_ASM = inv->pc;
418 _Jv_word *locals = inv->local_base ();
419
420 _Jv_word *pool_data = defining_class->constants.data;
421
422 /* these two are used in the invokeXXX instructions */
423 void (*fun)(...);
424 _Jv_ResolvedMethod* rmeth;
425
426 #define INSN_LABEL(op) &&insn_##op
427 #define GOTO_INSN(op) goto *(insn_target[op])
428
429 static const void *const insn_target[] =
430 {
431 INSN_LABEL(nop),
432 INSN_LABEL(aconst_null),
433 INSN_LABEL(iconst_m1),
434 INSN_LABEL(iconst_0),
435 INSN_LABEL(iconst_1),
436 INSN_LABEL(iconst_2),
437 INSN_LABEL(iconst_3),
438 INSN_LABEL(iconst_4),
439 INSN_LABEL(iconst_5),
440 INSN_LABEL(lconst_0),
441 INSN_LABEL(lconst_1),
442 INSN_LABEL(fconst_0),
443 INSN_LABEL(fconst_1),
444 INSN_LABEL(fconst_2),
445 INSN_LABEL(dconst_0),
446 INSN_LABEL(dconst_1),
447 INSN_LABEL(bipush),
448 INSN_LABEL(sipush),
449 INSN_LABEL(ldc),
450 INSN_LABEL(ldc_w),
451 INSN_LABEL(ldc2_w),
452 INSN_LABEL(iload),
453 INSN_LABEL(lload),
454 INSN_LABEL(fload),
455 INSN_LABEL(dload),
456 INSN_LABEL(aload),
457 INSN_LABEL(iload_0),
458 INSN_LABEL(iload_1),
459 INSN_LABEL(iload_2),
460 INSN_LABEL(iload_3),
461 INSN_LABEL(lload_0),
462 INSN_LABEL(lload_1),
463 INSN_LABEL(lload_2),
464 INSN_LABEL(lload_3),
465 INSN_LABEL(fload_0),
466 INSN_LABEL(fload_1),
467 INSN_LABEL(fload_2),
468 INSN_LABEL(fload_3),
469 INSN_LABEL(dload_0),
470 INSN_LABEL(dload_1),
471 INSN_LABEL(dload_2),
472 INSN_LABEL(dload_3),
473 INSN_LABEL(aload_0),
474 INSN_LABEL(aload_1),
475 INSN_LABEL(aload_2),
476 INSN_LABEL(aload_3),
477 INSN_LABEL(iaload),
478 INSN_LABEL(laload),
479 INSN_LABEL(faload),
480 INSN_LABEL(daload),
481 INSN_LABEL(aaload),
482 INSN_LABEL(baload),
483 INSN_LABEL(caload),
484 INSN_LABEL(saload),
485 INSN_LABEL(istore),
486 INSN_LABEL(lstore),
487 INSN_LABEL(fstore),
488 INSN_LABEL(dstore),
489 INSN_LABEL(astore),
490 INSN_LABEL(istore_0),
491 INSN_LABEL(istore_1),
492 INSN_LABEL(istore_2),
493 INSN_LABEL(istore_3),
494 INSN_LABEL(lstore_0),
495 INSN_LABEL(lstore_1),
496 INSN_LABEL(lstore_2),
497 INSN_LABEL(lstore_3),
498 INSN_LABEL(fstore_0),
499 INSN_LABEL(fstore_1),
500 INSN_LABEL(fstore_2),
501 INSN_LABEL(fstore_3),
502 INSN_LABEL(dstore_0),
503 INSN_LABEL(dstore_1),
504 INSN_LABEL(dstore_2),
505 INSN_LABEL(dstore_3),
506 INSN_LABEL(astore_0),
507 INSN_LABEL(astore_1),
508 INSN_LABEL(astore_2),
509 INSN_LABEL(astore_3),
510 INSN_LABEL(iastore),
511 INSN_LABEL(lastore),
512 INSN_LABEL(fastore),
513 INSN_LABEL(dastore),
514 INSN_LABEL(aastore),
515 INSN_LABEL(bastore),
516 INSN_LABEL(castore),
517 INSN_LABEL(sastore),
518 INSN_LABEL(pop),
519 INSN_LABEL(pop2),
520 INSN_LABEL(dup),
521 INSN_LABEL(dup_x1),
522 INSN_LABEL(dup_x2),
523 INSN_LABEL(dup2),
524 INSN_LABEL(dup2_x1),
525 INSN_LABEL(dup2_x2),
526 INSN_LABEL(swap),
527 INSN_LABEL(iadd),
528 INSN_LABEL(ladd),
529 INSN_LABEL(fadd),
530 INSN_LABEL(dadd),
531 INSN_LABEL(isub),
532 INSN_LABEL(lsub),
533 INSN_LABEL(fsub),
534 INSN_LABEL(dsub),
535 INSN_LABEL(imul),
536 INSN_LABEL(lmul),
537 INSN_LABEL(fmul),
538 INSN_LABEL(dmul),
539 INSN_LABEL(idiv),
540 INSN_LABEL(ldiv),
541 INSN_LABEL(fdiv),
542 INSN_LABEL(ddiv),
543 INSN_LABEL(irem),
544 INSN_LABEL(lrem),
545 INSN_LABEL(frem),
546 INSN_LABEL(drem),
547 INSN_LABEL(ineg),
548 INSN_LABEL(lneg),
549 INSN_LABEL(fneg),
550 INSN_LABEL(dneg),
551 INSN_LABEL(ishl),
552 INSN_LABEL(lshl),
553 INSN_LABEL(ishr),
554 INSN_LABEL(lshr),
555 INSN_LABEL(iushr),
556 INSN_LABEL(lushr),
557 INSN_LABEL(iand),
558 INSN_LABEL(land),
559 INSN_LABEL(ior),
560 INSN_LABEL(lor),
561 INSN_LABEL(ixor),
562 INSN_LABEL(lxor),
563 INSN_LABEL(iinc),
564 INSN_LABEL(i2l),
565 INSN_LABEL(i2f),
566 INSN_LABEL(i2d),
567 INSN_LABEL(l2i),
568 INSN_LABEL(l2f),
569 INSN_LABEL(l2d),
570 INSN_LABEL(f2i),
571 INSN_LABEL(f2l),
572 INSN_LABEL(f2d),
573 INSN_LABEL(d2i),
574 INSN_LABEL(d2l),
575 INSN_LABEL(d2f),
576 INSN_LABEL(i2b),
577 INSN_LABEL(i2c),
578 INSN_LABEL(i2s),
579 INSN_LABEL(lcmp),
580 INSN_LABEL(fcmpl),
581 INSN_LABEL(fcmpg),
582 INSN_LABEL(dcmpl),
583 INSN_LABEL(dcmpg),
584 INSN_LABEL(ifeq),
585 INSN_LABEL(ifne),
586 INSN_LABEL(iflt),
587 INSN_LABEL(ifge),
588 INSN_LABEL(ifgt),
589 INSN_LABEL(ifle),
590 INSN_LABEL(if_icmpeq),
591 INSN_LABEL(if_icmpne),
592 INSN_LABEL(if_icmplt),
593 INSN_LABEL(if_icmpge),
594 INSN_LABEL(if_icmpgt),
595 INSN_LABEL(if_icmple),
596 INSN_LABEL(if_acmpeq),
597 INSN_LABEL(if_acmpne),
598 INSN_LABEL(goto),
599 INSN_LABEL(jsr),
600 INSN_LABEL(ret),
601 INSN_LABEL(tableswitch),
602 INSN_LABEL(lookupswitch),
603 INSN_LABEL(ireturn),
604 INSN_LABEL(lreturn),
605 INSN_LABEL(freturn),
606 INSN_LABEL(dreturn),
607 INSN_LABEL(areturn),
608 INSN_LABEL(return),
609 INSN_LABEL(getstatic),
610 INSN_LABEL(putstatic),
611 INSN_LABEL(getfield),
612 INSN_LABEL(putfield),
613 INSN_LABEL(invokevirtual),
614 INSN_LABEL(invokespecial),
615 INSN_LABEL(invokestatic),
616 INSN_LABEL(invokeinterface),
617 0, /* op_xxxunusedxxx1, */
618 INSN_LABEL(new),
619 INSN_LABEL(newarray),
620 INSN_LABEL(anewarray),
621 INSN_LABEL(arraylength),
622 INSN_LABEL(athrow),
623 INSN_LABEL(checkcast),
624 INSN_LABEL(instanceof),
625 INSN_LABEL(monitorenter),
626 INSN_LABEL(monitorexit),
627 INSN_LABEL(wide),
628 INSN_LABEL(multianewarray),
629 INSN_LABEL(ifnull),
630 INSN_LABEL(ifnonnull),
631 INSN_LABEL(goto_w),
632 INSN_LABEL(jsr_w),
633
634 INSN_LABEL(putfield_1),
635 INSN_LABEL(putfield_2),
636 INSN_LABEL(putfield_4),
637 INSN_LABEL(putfield_8),
638 INSN_LABEL(putfield_a),
639
640 INSN_LABEL(putstatic_1),
641 INSN_LABEL(putstatic_2),
642 INSN_LABEL(putstatic_4),
643 INSN_LABEL(putstatic_8),
644 INSN_LABEL(putstatic_a),
645
646 INSN_LABEL(getfield_1),
647 INSN_LABEL(getfield_2s),
648 INSN_LABEL(getfield_2u),
649 INSN_LABEL(getfield_4),
650 INSN_LABEL(getfield_8),
651 INSN_LABEL(getfield_a),
652
653 INSN_LABEL(getstatic_1),
654 INSN_LABEL(getstatic_2s),
655 INSN_LABEL(getstatic_2u),
656 INSN_LABEL(getstatic_4),
657 INSN_LABEL(getstatic_8),
658 INSN_LABEL(getstatic_a),
659 };
660
661 #define SAVE_PC inv->pc = pc-1
662
663 /* If the macro INLINE_SWITCH is not defined, then the main loop
664 operates as one big (normal) switch statement. If it is defined,
665 then the case selection is performed `inline' in the end of the
666 code for each case. The latter saves a native branch instruction
667 for each java-instruction, but expands the code size somewhat.
668
669 NOTE: On i386 defining INLINE_SWITCH improves over all
670 performance approximately seven percent, but it may be different
671 for other machines. At some point, this may be made into a proper
672 configuration parameter. */
673
674 #define INLINE_SWITCH
675
676 #ifdef INLINE_SWITCH
677
678 #define NEXT_INSN GOTO_INSN(*pc++)
679 NEXT_INSN;
680 #else
681
682 #define NEXT_INSN goto next_insn
683
684 next_insn:
685 GOTO_INSN (*pc++);
686
687 #endif
688
689 /* The first few instructions here are ordered according to their
690 frequency, in the hope that this will improve code locality a
691 little. */
692
693 insn_aload_0: // 0x2a
694 LOADA(0);
695 NEXT_INSN;
696
697 insn_iload: // 0x15
698 LOADI (get1u (pc++));
699 NEXT_INSN;
700
701 insn_getfield_4: // 0xd8
702 SAVE_PC;
703 {
704 jobject obj = POPA();
705 NULLCHECK(obj);
706 jint field_offset = get2u (pc); pc += 2;
707 PUSHI (*(jint*) ((char*)obj + field_offset));
708 }
709 NEXT_INSN;
710
711 insn_iload_1: // 0x1b
712 LOADI (1);
713 NEXT_INSN;
714
715 insn_getfield_a: // 0xda
716 SAVE_PC;
717 {
718 jobject obj = POPA();
719 NULLCHECK(obj);
720 jint field_offset = get2u (pc); pc += 2;
721 PUSHA(*(jobject*) ((char*)obj + field_offset));
722 }
723 NEXT_INSN;
724
725 insn_invokevirtual: // 0xb6
726 SAVE_PC;
727 {
728 int index = get2u (pc); pc += 2;
729
730 /* _Jv_ResolvePoolEntry returns immediately if the value already
731 * is resolved. If we want to clutter up the code here to gain
732 * a little performance, then we can check the corresponding bit
733 * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I
734 * don't think it is worth it. */
735
736 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
737
738 sp -= rmeth->stack_item_count;
739 NULLCHECK(sp[0]);
740
741 if (rmeth->vtable_index == -1)
742 {
743 // final methods do not appear in the vtable,
744 // if it does not appear in the superclass.
745 fun = (void (*) (...)) rmeth->method->ncode;
746 }
747 else
748 {
749 jobject rcv = sp[0].o;
750 _Jv_VTable *table = *(_Jv_VTable**)rcv;
751 fun = (void (*) (...))table->method[rmeth->vtable_index];
752 }
753 }
754 goto perform_invoke;
755
756 perform_invoke:
757 {
758 /* here goes the magic again... */
759 ffi_cif *cif = &rmeth->cif;
760 ffi_raw *raw = (ffi_raw*) sp;
761
762 jdouble rvalue;
763
764 ffi_raw_call (cif, fun, (void*)&rvalue, raw);
765
766 int rtype = cif->rtype->type;
767
768 /* the likelyhood of object, int, or void return is very high,
769 * so those are checked before the switch */
770 if (rtype == FFI_TYPE_POINTER)
771 {
772 PUSHA (*(jobject*)&rvalue);
773 }
774 else if (rtype == FFI_TYPE_SINT32)
775 {
776 PUSHI (*(jint*)&rvalue);
777 }
778 else if (rtype == FFI_TYPE_VOID)
779 {
780 /* skip */
781 }
782 else switch (rtype)
783 {
784 case FFI_TYPE_SINT8:
785 {
786 jbyte value = (*(jint*)&rvalue) & 0xff;
787 PUSHI (value);
788 }
789 break;
790
791 case FFI_TYPE_SINT16:
792 {
793 jshort value = (*(jint*)&rvalue) & 0xffff;
794 PUSHI (value);
795 }
796 break;
797
798 case FFI_TYPE_UINT16:
799 {
800 jint value = (*(jint*)&rvalue) & 0xffff;
801 PUSHI (value);
802 }
803 break;
804
805 case FFI_TYPE_FLOAT:
806 PUSHF (*(jfloat*)&rvalue);
807 break;
808
809 case FFI_TYPE_DOUBLE:
810 PUSHD (rvalue);
811 break;
812
813 case FFI_TYPE_SINT64:
814 PUSHL (*(jlong*)&rvalue);
815 break;
816
817 default:
818 throw_internal_error ("unknown return type in invokeXXX");
819 }
820
821 }
822 NEXT_INSN;
823
824
825 insn_nop:
826 NEXT_INSN;
827
828 insn_aconst_null:
829 PUSHA (NULL);
830 NEXT_INSN;
831
832 insn_iconst_m1:
833 PUSHI (-1);
834 NEXT_INSN;
835
836 insn_iconst_0:
837 PUSHI (0);
838 NEXT_INSN;
839
840 insn_iconst_1:
841 PUSHI (1);
842 NEXT_INSN;
843
844 insn_iconst_2:
845 PUSHI (2);
846 NEXT_INSN;
847
848 insn_iconst_3:
849 PUSHI (3);
850 NEXT_INSN;
851
852 insn_iconst_4:
853 PUSHI (4);
854 NEXT_INSN;
855
856 insn_iconst_5:
857 PUSHI (5);
858 NEXT_INSN;
859
860 insn_lconst_0:
861 PUSHL (0);
862 NEXT_INSN;
863
864 insn_lconst_1:
865 PUSHL (1);
866 NEXT_INSN;
867
868 insn_fconst_0:
869 PUSHF (0);
870 NEXT_INSN;
871
872 insn_fconst_1:
873 PUSHF (1);
874 NEXT_INSN;
875
876 insn_fconst_2:
877 PUSHF (2);
878 NEXT_INSN;
879
880 insn_dconst_0:
881 PUSHD (0);
882 NEXT_INSN;
883
884 insn_dconst_1:
885 PUSHD (1);
886 NEXT_INSN;
887
888 insn_bipush:
889 PUSHI (get1s(pc++));
890 NEXT_INSN;
891
892 insn_sipush:
893 PUSHI (get2s(pc)); pc += 2;
894 NEXT_INSN;
895
896 insn_ldc:
897 {
898 int index = get1u (pc++);
899 PUSHA(pool_data[index].o);
900 }
901 NEXT_INSN;
902
903 insn_ldc_w:
904 {
905 int index = get2u (pc); pc += 2;
906 PUSHA(pool_data[index].o);
907 }
908 NEXT_INSN;
909
910 insn_ldc2_w:
911 {
912 int index = get2u (pc); pc += 2;
913 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
914 sp += 2;
915 }
916 NEXT_INSN;
917
918 insn_lload:
919 LOADL (get1u (pc++));
920 NEXT_INSN;
921
922 insn_fload:
923 LOADF (get1u (pc++));
924 NEXT_INSN;
925
926 insn_dload:
927 LOADD (get1u (pc++));
928 NEXT_INSN;
929
930 insn_aload:
931 LOADA (get1u (pc++));
932 NEXT_INSN;
933
934 insn_iload_0:
935 LOADI (0);
936 NEXT_INSN;
937
938 insn_iload_2:
939 LOADI (2);
940 NEXT_INSN;
941
942 insn_iload_3:
943 LOADI (3);
944 NEXT_INSN;
945
946 insn_lload_0:
947 LOADL (0);
948 NEXT_INSN;
949
950 insn_lload_1:
951 LOADL (1);
952 NEXT_INSN;
953
954 insn_lload_2:
955 LOADL (2);
956 NEXT_INSN;
957
958 insn_lload_3:
959 LOADL (3);
960 NEXT_INSN;
961
962 insn_fload_0:
963 LOADF (0);
964 NEXT_INSN;
965
966 insn_fload_1:
967 LOADF (1);
968 NEXT_INSN;
969
970 insn_fload_2:
971 LOADF (2);
972 NEXT_INSN;
973
974 insn_fload_3:
975 LOADF (3);
976 NEXT_INSN;
977
978 insn_dload_0:
979 LOADD (0);
980 NEXT_INSN;
981
982 insn_dload_1:
983 LOADD (1);
984 NEXT_INSN;
985
986 insn_dload_2:
987 LOADD (2);
988 NEXT_INSN;
989
990 insn_dload_3:
991 LOADD (3);
992 NEXT_INSN;
993
994 insn_aload_1:
995 LOADA(1);
996 NEXT_INSN;
997
998 insn_aload_2:
999 LOADA(2);
1000 NEXT_INSN;
1001
1002 insn_aload_3:
1003 LOADA(3);
1004 NEXT_INSN;
1005
1006 insn_iaload:
1007 SAVE_PC;
1008 {
1009 jint index = POPI();
1010 jintArray arr = (jintArray) POPA();
1011 NULLCHECK (arr);
1012 if (index < 0 || index >= arr->length)
1013 {
1014 _Jv_ThrowBadArrayIndex (index);
1015 }
1016 PUSHI( elements(arr)[index] );
1017 }
1018 NEXT_INSN;
1019
1020 insn_laload:
1021 SAVE_PC;
1022 {
1023 jint index = POPI();
1024 jlongArray arr = (jlongArray) POPA();
1025 NULLCHECK (arr);
1026 if (index < 0 || index >= arr->length)
1027 {
1028 _Jv_ThrowBadArrayIndex (index);
1029 }
1030 PUSHL( elements(arr)[index] );
1031 }
1032 NEXT_INSN;
1033
1034 insn_faload:
1035 SAVE_PC;
1036 {
1037 jint index = POPI();
1038 jfloatArray arr = (jfloatArray) POPA();
1039 NULLCHECK (arr);
1040 if (index < 0 || index >= arr->length)
1041 {
1042 _Jv_ThrowBadArrayIndex (index);
1043 }
1044 PUSHF( elements(arr)[index] );
1045 }
1046 NEXT_INSN;
1047
1048 insn_daload:
1049 SAVE_PC;
1050 {
1051 jint index = POPI();
1052 jdoubleArray arr = (jdoubleArray) POPA();
1053 NULLCHECK (arr);
1054 if (index < 0 || index >= arr->length)
1055 {
1056 _Jv_ThrowBadArrayIndex (index);
1057 }
1058 PUSHD( elements(arr)[index] );
1059 }
1060 NEXT_INSN;
1061
1062 insn_aaload:
1063 SAVE_PC;
1064 {
1065 jint index = POPI();
1066 jobjectArray arr = (jobjectArray) POPA();
1067 NULLCHECK (arr);
1068 if (index < 0 || index >= arr->length)
1069 {
1070 _Jv_ThrowBadArrayIndex (index);
1071 }
1072 PUSHA( elements(arr)[index] );
1073 }
1074 NEXT_INSN;
1075
1076 insn_baload:
1077 SAVE_PC;
1078 {
1079 jint index = POPI();
1080 jbyteArray arr = (jbyteArray) POPA();
1081 NULLCHECK (arr);
1082 if (index < 0 || index >= arr->length)
1083 {
1084 _Jv_ThrowBadArrayIndex (index);
1085 }
1086 PUSHI( elements(arr)[index] );
1087 }
1088 NEXT_INSN;
1089
1090 insn_caload:
1091 SAVE_PC;
1092 {
1093 jint index = POPI();
1094 jcharArray arr = (jcharArray) POPA();
1095 NULLCHECK (arr);
1096 if (index < 0 || index >= arr->length)
1097 {
1098 _Jv_ThrowBadArrayIndex (index);
1099 }
1100 PUSHI( elements(arr)[index] );
1101 }
1102 NEXT_INSN;
1103
1104 insn_saload:
1105 SAVE_PC;
1106 {
1107 jint index = POPI();
1108 jshortArray arr = (jshortArray) POPA();
1109 NULLCHECK (arr);
1110 if (index < 0 || index >= arr->length)
1111 {
1112 _Jv_ThrowBadArrayIndex (index);
1113 }
1114 PUSHI( elements(arr)[index] );
1115 }
1116 NEXT_INSN;
1117
1118 insn_istore:
1119 STOREI (get1u (pc++));
1120 NEXT_INSN;
1121
1122 insn_lstore:
1123 STOREL (get1u (pc++));
1124 NEXT_INSN;
1125
1126 insn_fstore:
1127 STOREF (get1u (pc++));
1128 NEXT_INSN;
1129
1130 insn_dstore:
1131 STORED (get1u (pc++));
1132 NEXT_INSN;
1133
1134 insn_astore:
1135 STOREI (get1u (pc++));
1136 NEXT_INSN;
1137
1138 insn_istore_0:
1139 STOREI (0);
1140 NEXT_INSN;
1141
1142 insn_istore_1:
1143 STOREI (1);
1144 NEXT_INSN;
1145
1146 insn_istore_2:
1147 STOREI (2);
1148 NEXT_INSN;
1149
1150 insn_istore_3:
1151 STOREI (3);
1152 NEXT_INSN;
1153
1154 insn_lstore_0:
1155 STOREL (0);
1156 NEXT_INSN;
1157
1158 insn_lstore_1:
1159 STOREL (1);
1160 NEXT_INSN;
1161
1162 insn_lstore_2:
1163 STOREL (2);
1164 NEXT_INSN;
1165
1166 insn_lstore_3:
1167 STOREL (3);
1168 NEXT_INSN;
1169
1170 insn_fstore_0:
1171 STOREF (0);
1172 NEXT_INSN;
1173
1174 insn_fstore_1:
1175 STOREF (1);
1176 NEXT_INSN;
1177
1178 insn_fstore_2:
1179 STOREF (2);
1180 NEXT_INSN;
1181
1182 insn_fstore_3:
1183 STOREF (3);
1184 NEXT_INSN;
1185
1186 insn_dstore_0:
1187 STORED (0);
1188 NEXT_INSN;
1189
1190 insn_dstore_1:
1191 STORED (1);
1192 NEXT_INSN;
1193
1194 insn_dstore_2:
1195 STORED (2);
1196 NEXT_INSN;
1197
1198 insn_dstore_3:
1199 STORED (3);
1200 NEXT_INSN;
1201
1202 insn_astore_0:
1203 STOREA(0);
1204 NEXT_INSN;
1205
1206 insn_astore_1:
1207 STOREA(1);
1208 NEXT_INSN;
1209
1210 insn_astore_2:
1211 STOREA(2);
1212 NEXT_INSN;
1213
1214 insn_astore_3:
1215 STOREA(3);
1216 NEXT_INSN;
1217
1218 insn_iastore:
1219 SAVE_PC;
1220 {
1221 jint value = POPI();
1222 jint index = POPI();
1223 jintArray arr = (jintArray) POPA();
1224 NULLCHECK (arr);
1225 if (index < 0 || index >= arr->length)
1226 {
1227 _Jv_ThrowBadArrayIndex (index);
1228 }
1229 elements(arr)[index] = value;
1230 }
1231 NEXT_INSN;
1232
1233 insn_lastore:
1234 SAVE_PC;
1235 {
1236 jlong value = POPL();
1237 jint index = POPI();
1238 jlongArray arr = (jlongArray) POPA();
1239 NULLCHECK (arr);
1240 if (index < 0 || index >= arr->length)
1241 {
1242 _Jv_ThrowBadArrayIndex (index);
1243 }
1244 elements(arr)[index] = value;
1245 }
1246 NEXT_INSN;
1247
1248 insn_fastore:
1249 SAVE_PC;
1250 {
1251 jfloat value = POPF();
1252 jint index = POPI();
1253 jfloatArray arr = (jfloatArray) POPA();
1254 NULLCHECK (arr);
1255 if (index < 0 || index >= arr->length)
1256 {
1257 _Jv_ThrowBadArrayIndex (index);
1258 }
1259 elements(arr)[index] = value;
1260 }
1261 NEXT_INSN;
1262
1263 insn_dastore:
1264 SAVE_PC;
1265 {
1266 jdouble value = POPD();
1267 jint index = POPI();
1268 jdoubleArray arr = (jdoubleArray) POPA();
1269 NULLCHECK (arr);
1270 if (index < 0 || index >= arr->length)
1271 {
1272 _Jv_ThrowBadArrayIndex (index);
1273 }
1274 elements(arr)[index] = value;
1275 }
1276 NEXT_INSN;
1277
1278 insn_aastore:
1279 SAVE_PC;
1280 {
1281 jobject value = POPA();
1282 jint index = POPI();
1283 jobjectArray arr = (jobjectArray) POPA();
1284 NULLCHECK (arr);
1285 if (index < 0 || index >= arr->length)
1286 {
1287 _Jv_ThrowBadArrayIndex (index);
1288 }
1289 _Jv_CheckArrayStore (arr, value);
1290 elements(arr)[index] = value;
1291 }
1292 NEXT_INSN;
1293
1294 insn_bastore:
1295 SAVE_PC;
1296 {
1297 jbyte value = (jbyte) POPI();
1298 jint index = POPI();
1299 jbyteArray arr = (jbyteArray) POPA();
1300 NULLCHECK (arr);
1301 if (index < 0 || index >= arr->length)
1302 {
1303 _Jv_ThrowBadArrayIndex (index);
1304 }
1305 elements(arr)[index] = value;
1306 }
1307 NEXT_INSN;
1308
1309 insn_castore:
1310 SAVE_PC;
1311 {
1312 jchar value = (jchar) POPI();
1313 jint index = POPI();
1314 jcharArray arr = (jcharArray) POPA();
1315 NULLCHECK (arr);
1316 if (index < 0 || index >= arr->length)
1317 {
1318 _Jv_ThrowBadArrayIndex (index);
1319 }
1320 elements(arr)[index] = value;
1321 }
1322 NEXT_INSN;
1323
1324 insn_sastore:
1325 SAVE_PC;
1326 {
1327 jshort value = (jshort) POPI();
1328 jint index = POPI();
1329 jshortArray arr = (jshortArray) POPA();
1330 NULLCHECK (arr);
1331 if (index < 0 || index >= arr->length)
1332 {
1333 _Jv_ThrowBadArrayIndex (index);
1334 }
1335 elements(arr)[index] = value;
1336 }
1337 NEXT_INSN;
1338
1339 insn_pop:
1340 sp -= 1;
1341 NEXT_INSN;
1342
1343 insn_pop2:
1344 sp -= 2;
1345 NEXT_INSN;
1346
1347 insn_dup:
1348 sp[0] = sp[-1];
1349 sp += 1;
1350 NEXT_INSN;
1351
1352 insn_dup_x1:
1353 dupx (sp, 1, 1); sp+=1;
1354 NEXT_INSN;
1355
1356 insn_dup_x2:
1357 dupx (sp, 1, 2); sp+=1;
1358 NEXT_INSN;
1359
1360 insn_dup2:
1361 sp[0] = sp[-2];
1362 sp[1] = sp[-1];
1363 sp += 2;
1364 NEXT_INSN;
1365
1366 insn_dup2_x1:
1367 dupx (sp, 2, 1); sp+=2;
1368 NEXT_INSN;
1369
1370 insn_dup2_x2:
1371 dupx (sp, 2, 2); sp+=2;
1372 NEXT_INSN;
1373
1374 insn_swap:
1375 {
1376 jobject tmp1 = POPA();
1377 jobject tmp2 = POPA();
1378 PUSHA (tmp1);
1379 PUSHA (tmp2);
1380 }
1381 NEXT_INSN;
1382
1383 insn_iadd:
1384 BINOPI(+);
1385 NEXT_INSN;
1386
1387 insn_ladd:
1388 BINOPL(+);
1389 NEXT_INSN;
1390
1391 insn_fadd:
1392 BINOPF(+);
1393 NEXT_INSN;
1394
1395 insn_dadd:
1396 BINOPD(+);
1397 NEXT_INSN;
1398
1399 insn_isub:
1400 BINOPI(-);
1401 NEXT_INSN;
1402
1403 insn_lsub:
1404 BINOPL(-);
1405 NEXT_INSN;
1406
1407 insn_fsub:
1408 BINOPF(-);
1409 NEXT_INSN;
1410
1411 insn_dsub:
1412 BINOPD(-);
1413 NEXT_INSN;
1414
1415 insn_imul:
1416 BINOPI(*);
1417 NEXT_INSN;
1418
1419 insn_lmul:
1420 BINOPL(*);
1421 NEXT_INSN;
1422
1423 insn_fmul:
1424 BINOPF(*);
1425 NEXT_INSN;
1426
1427 insn_dmul:
1428 BINOPD(*);
1429 NEXT_INSN;
1430
1431 insn_idiv:
1432 SAVE_PC;
1433 {
1434 jint value2 = POPI();
1435 jint value1 = POPI();
1436 ZEROCHECK (value2);
1437 jint res = value1 / value2;
1438 PUSHI (res);
1439 }
1440 NEXT_INSN;
1441
1442 insn_ldiv:
1443 SAVE_PC;
1444 {
1445 jlong value2 = POPL();
1446 jlong value1 = POPL();
1447 ZEROCHECK (value2);
1448 jlong res = value1 / value2;
1449 PUSHL (res);
1450 }
1451 NEXT_INSN;
1452
1453 insn_fdiv:
1454 SAVE_PC;
1455 {
1456 jfloat value2 = POPF();
1457 jfloat value1 = POPF();
1458 ZEROCHECK (value2);
1459 jfloat res = value1 / value2;
1460 PUSHF (res);
1461 }
1462 NEXT_INSN;
1463
1464 insn_ddiv:
1465 SAVE_PC;
1466 {
1467 jdouble value2 = POPD();
1468 jdouble value1 = POPD();
1469 ZEROCHECK (value2);
1470 jdouble res = value1 / value2;
1471 PUSHD (res);
1472 }
1473 NEXT_INSN;
1474
1475 insn_irem:
1476 SAVE_PC;
1477 {
1478 jint value2 = POPI();
1479 jint value1 = POPI();
1480 ZEROCHECK (value2);
1481 jint res = value1 % value2;
1482 PUSHI (res);
1483 }
1484 NEXT_INSN;
1485
1486 insn_lrem:
1487 SAVE_PC;
1488 {
1489 jlong value2 = POPL();
1490 jlong value1 = POPL();
1491 ZEROCHECK (value2);
1492 jlong res = value1 % value2;
1493 PUSHL (res);
1494 }
1495 NEXT_INSN;
1496
1497 insn_frem:
1498 SAVE_PC;
1499 {
1500 jfloat value2 = POPF();
1501 jfloat value1 = POPF();
1502 ZEROCHECK (value2);
1503 jfloat res = __ieee754_fmod (value1, value2);
1504 PUSHF (res);
1505 }
1506 NEXT_INSN;
1507
1508 insn_drem:
1509 SAVE_PC;
1510 {
1511 jdouble value2 = POPD();
1512 jdouble value1 = POPD();
1513 ZEROCHECK (value2);
1514 jdouble res = __ieee754_fmod (value1, value2);
1515 PUSHD (res);
1516 }
1517 NEXT_INSN;
1518
1519 insn_ineg:
1520 {
1521 jint value = POPI();
1522 PUSHI (value * -1);
1523 }
1524 NEXT_INSN;
1525
1526 insn_lneg:
1527 {
1528 jlong value = POPL();
1529 PUSHL (value * -1);
1530 }
1531 NEXT_INSN;
1532
1533 insn_fneg:
1534 {
1535 jfloat value = POPF();
1536 PUSHF (value * -1);
1537 }
1538 NEXT_INSN;
1539
1540 insn_dneg:
1541 {
1542 jdouble value = POPD();
1543 PUSHD (value * -1);
1544 }
1545 NEXT_INSN;
1546
1547 insn_ishl:
1548 {
1549 jint shift = (POPI() & 0x1f);
1550 jint value = POPI();
1551 PUSHI (value << shift);
1552 }
1553 NEXT_INSN;
1554
1555 insn_lshl:
1556 {
1557 jint shift = (POPI() & 0x3f);
1558 jlong value = POPL();
1559 PUSHL (value << shift);
1560 }
1561 NEXT_INSN;
1562
1563 insn_ishr:
1564 {
1565 jint shift = (POPI() & 0x1f);
1566 jint value = POPI();
1567 PUSHI (value >> shift);
1568 }
1569 NEXT_INSN;
1570
1571 insn_lshr:
1572 {
1573 jint shift = (POPI() & 0x3f);
1574 jlong value = POPL();
1575 PUSHL (value >> shift);
1576 }
1577 NEXT_INSN;
1578
1579 insn_iushr:
1580 {
1581 jint shift = (POPI() & 0x1f);
1582 unsigned long value = POPI();
1583 PUSHI ((jint) (value >> shift));
1584 }
1585 NEXT_INSN;
1586
1587 insn_lushr:
1588 {
1589 jint shift = (POPI() & 0x3f);
1590 UINT64 value = (UINT64) POPL();
1591 PUSHL ((value >> shift));
1592 }
1593 NEXT_INSN;
1594
1595 insn_iand:
1596 BINOPI (&);
1597 NEXT_INSN;
1598
1599 insn_land:
1600 BINOPL (&);
1601 NEXT_INSN;
1602
1603 insn_ior:
1604 BINOPI (|);
1605 NEXT_INSN;
1606
1607 insn_lor:
1608 BINOPL (|);
1609 NEXT_INSN;
1610
1611 insn_ixor:
1612 BINOPI (^);
1613 NEXT_INSN;
1614
1615 insn_lxor:
1616 BINOPL (^);
1617 NEXT_INSN;
1618
1619 insn_iinc:
1620 {
1621 jint index = get1u (pc++);
1622 jint amount = get1s (pc++);
1623 locals[index].i += amount;
1624 }
1625 NEXT_INSN;
1626
1627 insn_i2l:
1628 {jlong value = POPI(); PUSHL (value);}
1629 NEXT_INSN;
1630
1631 insn_i2f:
1632 {jfloat value = POPI(); PUSHF (value);}
1633 NEXT_INSN;
1634
1635 insn_i2d:
1636 {jdouble value = POPI(); PUSHD (value);}
1637 NEXT_INSN;
1638
1639 insn_l2i:
1640 {jint value = POPL(); PUSHI (value);}
1641 NEXT_INSN;
1642
1643 insn_l2f:
1644 {jfloat value = POPL(); PUSHF (value);}
1645 NEXT_INSN;
1646
1647 insn_l2d:
1648 {jdouble value = POPL(); PUSHD (value);}
1649 NEXT_INSN;
1650
1651 insn_f2i:
1652 { jint value = (jint)POPF (); PUSHI(value); }
1653 NEXT_INSN;
1654
1655 insn_f2l:
1656 { jlong value = (jlong)POPF (); PUSHL(value); }
1657 NEXT_INSN;
1658
1659 insn_f2d:
1660 { jdouble value = POPF (); PUSHD(value); }
1661 NEXT_INSN;
1662
1663 insn_d2i:
1664 { jint value = (jint)POPD (); PUSHI(value); }
1665 NEXT_INSN;
1666
1667 insn_d2l:
1668 { jlong value = (jlong)POPD (); PUSHL(value); }
1669 NEXT_INSN;
1670
1671 insn_d2f:
1672 { jfloat value = POPD (); PUSHF(value); }
1673 NEXT_INSN;
1674
1675 insn_i2b:
1676 { jbyte value = POPI (); PUSHI(value); }
1677 NEXT_INSN;
1678
1679 insn_i2c:
1680 { jchar value = POPI (); PUSHI(value); }
1681 NEXT_INSN;
1682
1683 insn_i2s:
1684 { jshort value = POPI (); PUSHI(value); }
1685 NEXT_INSN;
1686
1687 insn_lcmp:
1688 {
1689 jlong value2 = POPL ();
1690 jlong value1 = POPL ();
1691 if (value1 > value2)
1692 { PUSHI (1); }
1693 else if (value1 == value2)
1694 { PUSHI (0); }
1695 else
1696 { PUSHI (-1); }
1697 }
1698 NEXT_INSN;
1699
1700 insn_fcmpl:
1701 insn_fcmpg:
1702 {
1703 jfloat value2 = POPF ();
1704 jfloat value1 = POPF ();
1705 if (value1 > value2)
1706 PUSHI (1);
1707 else if (value1 == value2)
1708 PUSHI (0);
1709 else if (value1 < value2)
1710 PUSHI (-1);
1711 else if ((*(pc-1)) == op_fcmpg)
1712 PUSHI (1);
1713 else
1714 PUSHI (-1);
1715 }
1716 NEXT_INSN;
1717
1718 insn_dcmpl:
1719 insn_dcmpg:
1720 {
1721 jdouble value2 = POPD ();
1722 jdouble value1 = POPD ();
1723 if (value1 > value2)
1724 PUSHI (1);
1725 else if (value1 == value2)
1726 PUSHI (0);
1727 else if (value1 < value2)
1728 PUSHI (-1);
1729 else if ((*(pc-1)) == op_dcmpg)
1730 PUSHI (1);
1731 else
1732 PUSHI (-1);
1733 }
1734 NEXT_INSN;
1735
1736 insn_ifeq:
1737 {
1738 jint offset = get2s (pc);
1739 if (POPI() == 0)
1740 pc = pc-1+offset;
1741 else
1742 pc = pc+2;
1743 }
1744 NEXT_INSN;
1745
1746 insn_ifne:
1747 {
1748 jint offset = get2s (pc);
1749 if (POPI() != 0)
1750 pc = pc-1+offset;
1751 else
1752 pc = pc+2;
1753 }
1754 NEXT_INSN;
1755
1756 insn_iflt:
1757 {
1758 jint offset = get2s (pc);
1759 if (POPI() < 0)
1760 pc = pc-1+offset;
1761 else
1762 pc = pc+2;
1763 }
1764 NEXT_INSN;
1765
1766 insn_ifge:
1767 {
1768 jint offset = get2s (pc);
1769 if (POPI() >= 0)
1770 pc = pc-1+offset;
1771 else
1772 pc = pc+2;
1773 }
1774 NEXT_INSN;
1775
1776 insn_ifgt:
1777 {
1778 jint offset = get2s (pc);
1779 if (POPI() > 0)
1780 pc = pc-1+offset;
1781 else
1782 pc = pc+2;
1783 }
1784 NEXT_INSN;
1785
1786 insn_ifle:
1787 {
1788 jint offset = get2s (pc);
1789 if (POPI() <= 0)
1790 pc = pc-1+offset;
1791 else
1792 pc = pc+2;
1793 }
1794 NEXT_INSN;
1795
1796 insn_if_icmpeq:
1797 {
1798 jint offset = get2s (pc);
1799 jint value2 = POPI();
1800 jint value1 = POPI();
1801 if (value1 == value2)
1802 pc = pc-1+offset;
1803 else
1804 pc = pc+2;
1805 }
1806 NEXT_INSN;
1807
1808 insn_if_icmpne:
1809 {
1810 jint offset = get2s (pc);
1811 jint value2 = POPI();
1812 jint value1 = POPI();
1813 if (value1 != value2)
1814 pc = pc-1+offset;
1815 else
1816 pc = pc+2;
1817 }
1818 NEXT_INSN;
1819
1820 insn_if_icmplt:
1821 {
1822 jint offset = get2s (pc);
1823 jint value2 = POPI();
1824 jint value1 = POPI();
1825 if (value1 < value2)
1826 pc = pc-1+offset;
1827 else
1828 pc = pc+2;
1829 }
1830 NEXT_INSN;
1831
1832 insn_if_icmpge:
1833 {
1834 jint offset = get2s (pc);
1835 jint value2 = POPI();
1836 jint value1 = POPI();
1837 if (value1 >= value2)
1838 pc = pc-1+offset;
1839 else
1840 pc = pc+2;
1841 }
1842 NEXT_INSN;
1843
1844 insn_if_icmpgt:
1845 {
1846 jint offset = get2s (pc);
1847 jint value2 = POPI();
1848 jint value1 = POPI();
1849 if (value1 > value2)
1850 pc = pc-1+offset;
1851 else
1852 pc = pc+2;
1853 }
1854 NEXT_INSN;
1855
1856 insn_if_icmple:
1857 {
1858 jint offset = get2s (pc);
1859 jint value2 = POPI();
1860 jint value1 = POPI();
1861 if (value1 <= value2)
1862 pc = pc-1+offset;
1863 else
1864 pc = pc+2;
1865 }
1866 NEXT_INSN;
1867
1868 insn_if_acmpeq:
1869 {
1870 jint offset = get2s (pc);
1871 jobject value2 = POPA();
1872 jobject value1 = POPA();
1873 if (value1 == value2)
1874 pc = pc-1+offset;
1875 else
1876 pc = pc+2;
1877 }
1878 NEXT_INSN;
1879
1880 insn_if_acmpne:
1881 {
1882 jint offset = get2s (pc);
1883 jobject value2 = POPA();
1884 jobject value1 = POPA();
1885 if (value1 != value2)
1886 pc = pc-1+offset;
1887 else
1888 pc = pc+2;
1889 }
1890 NEXT_INSN;
1891
1892 insn_goto:
1893 {
1894 jint offset = get2s (pc);
1895 pc = pc-1+offset;
1896 }
1897 NEXT_INSN;
1898
1899 insn_jsr:
1900 {
1901 unsigned char *base_pc = pc-1;
1902 jint offset = get2s (pc); pc += 2;
1903 PUSHA ((jobject)pc);
1904 pc = base_pc+offset;
1905 }
1906 NEXT_INSN;
1907
1908 insn_ret:
1909 {
1910 jint index = get1u (pc);
1911 pc = (unsigned char*) PEEKA (index);
1912 }
1913 NEXT_INSN;
1914
1915 insn_tableswitch:
1916 {
1917 unsigned char *base_pc = pc-1;
1918 int index = POPI();
1919
1920 unsigned char* base = bytecode ();
1921 while ((pc-base) % 4 != 0)
1922 pc++;
1923
1924 jint def = get4 (pc);
1925 jint low = get4 (pc+4);
1926 jint high = get4 (pc+8);
1927
1928 if (index < low || index > high)
1929 pc = base_pc + def;
1930 else
1931 pc = base_pc + get4 (pc+4*(index-low+3));
1932 }
1933 NEXT_INSN;
1934
1935 insn_lookupswitch:
1936 {
1937 unsigned char *base_pc = pc-1;
1938 int index = POPI();
1939
1940 unsigned char* base = bytecode ();
1941 while ((pc-base) % 4 != 0)
1942 pc++;
1943
1944 jint def = get4 (pc);
1945 jint npairs = get4 (pc+4);
1946
1947 int max = npairs-1;
1948 int min = 0;
1949
1950 // simple binary search...
1951 while (min < max)
1952 {
1953 int half = (min+max)/2;
1954 int match = get4 (pc+ 4*(2 + 2*half));
1955
1956 if (index == match)
1957 min = max = half;
1958
1959 else if (index < match)
1960 max = half-1;
1961
1962 else
1963 min = half+1;
1964 }
1965
1966 if (index == get4 (pc+ 4*(2 + 2*min)))
1967 pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
1968 else
1969 pc = base_pc + def;
1970 }
1971 NEXT_INSN;
1972
1973 /* on return, just save the sp and return to caller */
1974 insn_ireturn:
1975 insn_lreturn:
1976 insn_freturn:
1977 insn_dreturn:
1978 insn_areturn:
1979 insn_return:
1980 inv->sp = sp;
1981 return;
1982
1983 insn_getstatic:
1984 SAVE_PC;
1985 {
1986 unsigned char *base_pc = pc-1;
1987 jint fieldref_index = get2u (pc); pc += 2;
1988 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
1989 _Jv_Field *field = pool_data[fieldref_index].field;
1990
1991 if ((field->flags & Modifier::STATIC) == 0)
1992 throw_incompatible_class_change_error
1993 (JvNewStringLatin1 ("field no longer static"));
1994
1995 jclass type = field->type;
1996
1997 if (type->isPrimitive ())
1998 {
1999 switch (type->size_in_bytes)
2000 {
2001 case 1:
2002 *base_pc = op_getstatic_1;
2003 break;
2004
2005 case 2:
2006 if (type == JvPrimClass (char))
2007 *base_pc = op_getstatic_2u;
2008 else
2009 *base_pc = op_getstatic_2s;
2010 break;
2011
2012 case 4:
2013 *base_pc = op_getstatic_4;
2014 break;
2015
2016 case 8:
2017 *base_pc = op_getstatic_8;
2018 break;
2019 }
2020 }
2021 else
2022 {
2023 *base_pc = op_getstatic_a;
2024 }
2025
2026 pc = base_pc;
2027 }
2028 NEXT_INSN;
2029
2030 insn_getfield:
2031 SAVE_PC;
2032 {
2033 unsigned char *base_pc = pc-1;
2034 jint fieldref_index = get2u (pc); pc += 2;
2035 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2036 _Jv_Field *field = pool_data[fieldref_index].field;
2037
2038 if ((field->flags & Modifier::STATIC) != 0)
2039 throw_incompatible_class_change_error
2040 (JvNewStringLatin1 ("field is static"));
2041
2042 jclass type = field->type;
2043
2044 if (type->isPrimitive ())
2045 {
2046 switch (type->size_in_bytes)
2047 {
2048 case 1:
2049 *base_pc = op_getfield_1;
2050 break;
2051
2052 case 2:
2053 if (type == JvPrimClass (char))
2054 *base_pc = op_getfield_2u;
2055 else
2056 *base_pc = op_getfield_2s;
2057 break;
2058
2059 case 4:
2060 *base_pc = op_getfield_4;
2061 break;
2062
2063 case 8:
2064 *base_pc = op_getfield_8;
2065 break;
2066 }
2067 }
2068 else
2069 {
2070 *base_pc = op_getfield_a;
2071 }
2072
2073 if (field->u.boffset > 0xffff)
2074 JvThrow (new java::lang::VirtualMachineError);
2075
2076 base_pc[1] = (field->u.boffset>>8) & 0xff;
2077 base_pc[2] = field->u.boffset & 0xff;
2078
2079 pc = base_pc;
2080 }
2081 NEXT_INSN;
2082
2083 insn_putstatic:
2084 SAVE_PC;
2085 {
2086 unsigned char* base_pc = pc-1;
2087 jint fieldref_index = get2u (pc); pc += 2;
2088 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2089 _Jv_Field *field = pool_data[fieldref_index].field;
2090
2091 jclass type = field->type;
2092
2093 // ResolvePoolEntry cannot check this
2094 if ((field->flags & Modifier::STATIC) == 0)
2095 throw_incompatible_class_change_error
2096 (JvNewStringLatin1 ("field no longer static"));
2097
2098 /* if this is patented, then maybe we could install
2099 a function in the constant pool, to do the right thing */
2100
2101 if (type->isPrimitive ())
2102 {
2103 switch (type->size_in_bytes)
2104 {
2105 case 1:
2106 *base_pc = op_putstatic_1;
2107 break;
2108
2109 case 2:
2110 *base_pc = op_putstatic_2;
2111 break;
2112
2113 case 4:
2114 *base_pc = op_putstatic_4;
2115 break;
2116
2117 case 8:
2118 *base_pc = op_putstatic_8;
2119 break;
2120 }
2121 }
2122 else
2123 {
2124 *base_pc = op_putstatic_a;
2125 }
2126
2127 // do the instruction again!
2128 pc = base_pc;
2129 }
2130 NEXT_INSN;
2131
2132
2133 insn_putfield:
2134 SAVE_PC;
2135 {
2136 unsigned char* base_pc = pc-1;
2137 jint fieldref_index = get2u (pc); pc += 2;
2138 _Jv_ResolvePoolEntry (defining_class, fieldref_index);
2139 _Jv_Field *field = pool_data[fieldref_index].field;
2140
2141 jclass type = field->type;
2142
2143 if ((field->flags & Modifier::STATIC) != 0)
2144 throw_incompatible_class_change_error
2145 (JvNewStringLatin1 ("field is static"));
2146
2147 if (type->isPrimitive ())
2148 {
2149 switch (type->size_in_bytes)
2150 {
2151 case 1:
2152 *base_pc = op_putfield_1;
2153 break;
2154
2155 case 2:
2156 *base_pc = op_putfield_2;
2157 break;
2158
2159 case 4:
2160 *base_pc = op_putfield_4;
2161 break;
2162
2163 case 8:
2164 *base_pc = op_putfield_8;
2165 break;
2166 }
2167 }
2168 else
2169 {
2170 *base_pc = op_putfield_a;
2171 }
2172
2173 if (field->u.boffset > 0xffff)
2174 JvThrow (new java::lang::VirtualMachineError);
2175
2176 base_pc[1] = (field->u.boffset>>8) & 0xff;
2177 base_pc[2] = field->u.boffset & 0xff;
2178
2179 // do the instruction again!
2180 pc = base_pc;
2181 }
2182 NEXT_INSN;
2183
2184
2185 insn_getfield_1:
2186 SAVE_PC;
2187 {
2188 jobject obj = POPA();
2189 NULLCHECK(obj);
2190 jint field_offset = get2u (pc); pc += 2;
2191 PUSHI (*(jbyte*) ((char*)obj + field_offset));
2192 }
2193 NEXT_INSN;
2194
2195 insn_getfield_2s:
2196 SAVE_PC;
2197 {
2198 jobject obj = POPA();
2199 NULLCHECK(obj);
2200 jint field_offset = get2u (pc); pc += 2;
2201 PUSHI (*(jshort*) ((char*)obj + field_offset));
2202 }
2203 NEXT_INSN;
2204
2205 insn_getfield_2u:
2206 SAVE_PC;
2207 {
2208 jobject obj = POPA();
2209 NULLCHECK(obj);
2210 jint field_offset = get2u (pc); pc += 2;
2211 PUSHI (*(jchar*) ((char*)obj + field_offset));
2212 }
2213 NEXT_INSN;
2214
2215 insn_getfield_8:
2216 SAVE_PC;
2217 {
2218 jobject obj = POPA();
2219 NULLCHECK(obj);
2220 jint field_offset = get2u (pc); pc += 2;
2221 PUSHL(*(jlong*) ((char*)obj + field_offset));
2222 }
2223 NEXT_INSN;
2224
2225 insn_getstatic_1:
2226 {
2227 jint fieldref_index = get2u (pc); pc += 2;
2228 _Jv_Field *field = pool_data[fieldref_index].field;
2229 PUSHI (*(jbyte*) (field->u.addr));
2230 }
2231 NEXT_INSN;
2232
2233 insn_getstatic_2s:
2234 {
2235 jint fieldref_index = get2u (pc); pc += 2;
2236 _Jv_Field *field = pool_data[fieldref_index].field;
2237 PUSHI(*(jshort*) (field->u.addr));
2238 }
2239 NEXT_INSN;
2240
2241 insn_getstatic_2u:
2242 {
2243 jint fieldref_index = get2u (pc); pc += 2;
2244 _Jv_Field *field = pool_data[fieldref_index].field;
2245 PUSHI(*(jchar*) (field->u.addr));
2246 }
2247 NEXT_INSN;
2248
2249 insn_getstatic_4:
2250 {
2251 jint fieldref_index = get2u (pc); pc += 2;
2252 _Jv_Field *field = pool_data[fieldref_index].field;
2253 PUSHI(*(jint*) (field->u.addr));
2254 }
2255 NEXT_INSN;
2256
2257 insn_getstatic_8:
2258 {
2259 jint fieldref_index = get2u (pc); pc += 2;
2260 _Jv_Field *field = pool_data[fieldref_index].field;
2261 PUSHL(*(jlong*) (field->u.addr));
2262 }
2263 NEXT_INSN;
2264
2265 insn_getstatic_a:
2266 {
2267 jint fieldref_index = get2u (pc); pc += 2;
2268 _Jv_Field *field = pool_data[fieldref_index].field;
2269 PUSHA(*(jobject*) (field->u.addr));
2270 }
2271 NEXT_INSN;
2272
2273 insn_putfield_1:
2274 SAVE_PC;
2275 {
2276 jint value = POPI();
2277 jobject obj = POPA();
2278 NULLCHECK(obj);
2279 jint field_offset = get2u (pc); pc += 2;
2280 *(jbyte*) ((char*)obj + field_offset) = value;
2281 }
2282 NEXT_INSN;
2283
2284 insn_putfield_2:
2285 SAVE_PC;
2286 {
2287 jint value = POPI();
2288 jobject obj = POPA();
2289 NULLCHECK(obj);
2290 jint field_offset = get2u (pc); pc += 2;
2291 *(jchar*) ((char*)obj + field_offset) = value;
2292 }
2293 NEXT_INSN;
2294
2295 insn_putfield_4:
2296 SAVE_PC;
2297 {
2298 jint value = POPI();
2299 jobject obj = POPA();
2300 NULLCHECK(obj);
2301 jint field_offset = get2u (pc); pc += 2;
2302 *(jint*) ((char*)obj + field_offset) = value;
2303 }
2304 NEXT_INSN;
2305
2306 insn_putfield_8:
2307 SAVE_PC;
2308 {
2309 jlong value = POPL();
2310 jobject obj = POPA();
2311 NULLCHECK(obj);
2312 jint field_offset = get2u (pc); pc += 2;
2313 *(jlong*) ((char*)obj + field_offset) = value;
2314 }
2315 NEXT_INSN;
2316
2317 insn_putfield_a:
2318 SAVE_PC;
2319 {
2320 jobject value = POPA();
2321 jobject obj = POPA();
2322 NULLCHECK(obj);
2323 jint field_offset = get2u (pc); pc += 2;
2324 *(jobject*) ((char*)obj + field_offset) = value;
2325 }
2326 NEXT_INSN;
2327
2328 insn_putstatic_1:
2329 {
2330 jint value = POPI();
2331 jint fieldref_index = get2u (pc); pc += 2;
2332 _Jv_Field *field = pool_data[fieldref_index].field;
2333 *(jbyte*) (field->u.addr) = value;
2334 }
2335 NEXT_INSN;
2336
2337 insn_putstatic_2:
2338 {
2339 jint value = POPI();
2340 jint fieldref_index = get2u (pc); pc += 2;
2341 _Jv_Field *field = pool_data[fieldref_index].field;
2342 *(jchar*) (field->u.addr) = value;
2343 }
2344 NEXT_INSN;
2345
2346 insn_putstatic_4:
2347 {
2348 jint value = POPI();
2349 jint fieldref_index = get2u (pc); pc += 2;
2350 _Jv_Field *field = pool_data[fieldref_index].field;
2351 *(jint*) (field->u.addr) = value;
2352 }
2353 NEXT_INSN;
2354
2355 insn_putstatic_8:
2356 {
2357 jlong value = POPL();
2358 jint fieldref_index = get2u (pc); pc += 2;
2359 _Jv_Field *field = pool_data[fieldref_index].field;
2360 *(jlong*) (field->u.addr) = value;
2361 }
2362 NEXT_INSN;
2363
2364 insn_putstatic_a:
2365 {
2366 jobject value = POPA();
2367 jint fieldref_index = get2u (pc); pc += 2;
2368 _Jv_Field *field = pool_data[fieldref_index].field;
2369 *(jobject*) (field->u.addr) = value;
2370 }
2371 NEXT_INSN;
2372
2373 insn_invokespecial:
2374 SAVE_PC;
2375 {
2376 int index = get2u (pc); pc += 2;
2377
2378 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2379
2380 sp -= rmeth->stack_item_count;
2381
2382 NULLCHECK(sp[0]);
2383
2384 fun = (void (*) (...))rmeth->method->ncode;
2385 }
2386 goto perform_invoke;
2387
2388 insn_invokestatic:
2389 SAVE_PC;
2390 {
2391 int index = get2u (pc); pc += 2;
2392
2393 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2394
2395 sp -= rmeth->stack_item_count;
2396
2397 _Jv_InitClass (rmeth->klass);
2398 fun = (void (*) (...))rmeth->method->ncode;
2399 }
2400 goto perform_invoke;
2401
2402 insn_invokeinterface:
2403 SAVE_PC;
2404 {
2405 int index = get2u (pc); pc += 2;
2406
2407 // invokeinterface has two unused bytes...
2408 pc += 2;
2409
2410 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
2411
2412 sp -= rmeth->stack_item_count;
2413 NULLCHECK(sp[0]);
2414
2415 jobject rcv = sp[0].o;
2416
2417 fun = (void (*) (...))
2418 _Jv_LookupInterfaceMethod (rcv->getClass (),
2419 rmeth->method->name,
2420 rmeth->method->signature);
2421 }
2422 goto perform_invoke;
2423
2424
2425 insn_new:
2426 SAVE_PC;
2427 {
2428 int index = get2u (pc); pc += 2;
2429 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2430 _Jv_InitClass (klass);
2431 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
2432 PUSHA (res);
2433 }
2434 NEXT_INSN;
2435
2436 insn_newarray:
2437 SAVE_PC;
2438 {
2439 int atype = get1u (pc++);
2440 int size = POPI();
2441 jobject result = _Jv_NewArray (atype, size);
2442 PUSHA (result);
2443 }
2444 NEXT_INSN;
2445
2446 insn_anewarray:
2447 SAVE_PC;
2448 {
2449 int index = get2u (pc); pc += 2;
2450 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2451 int size = POPI();
2452 _Jv_InitClass (klass);
2453 jobject result = _Jv_NewObjectArray (size, klass, 0);
2454 PUSHA (result);
2455 }
2456 NEXT_INSN;
2457
2458 insn_arraylength:
2459 SAVE_PC;
2460 {
2461 __JArray *arr = (__JArray*)POPA();
2462 PUSHI (arr->length);
2463 }
2464 NEXT_INSN;
2465
2466 insn_athrow:
2467 SAVE_PC;
2468 {
2469 jobject value = POPA();
2470 JvThrow (value);
2471 }
2472 NEXT_INSN;
2473
2474 insn_checkcast:
2475 SAVE_PC;
2476 {
2477 jobject value = POPA();
2478 jint index = get2u (pc); pc += 2;
2479 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2480
2481 if (value != NULL && ! to->isInstance (value))
2482 {
2483 JvThrow (new java::lang::ClassCastException
2484 (to->getName()));
2485 }
2486
2487 PUSHA (value);
2488 }
2489 NEXT_INSN;
2490
2491 insn_instanceof:
2492 SAVE_PC;
2493 {
2494 jobject value = POPA();
2495 jint index = get2u (pc); pc += 2;
2496 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
2497 PUSHI (to->isInstance (value));
2498 }
2499 NEXT_INSN;
2500
2501 insn_monitorenter:
2502 SAVE_PC;
2503 {
2504 jobject value = POPA();
2505 NULLCHECK(value);
2506 _Jv_MonitorEnter (value);
2507 }
2508 NEXT_INSN;
2509
2510 insn_monitorexit:
2511 SAVE_PC;
2512 {
2513 jobject value = POPA();
2514 NULLCHECK(value);
2515 _Jv_MonitorExit (value);
2516 }
2517 NEXT_INSN;
2518
2519 insn_ifnull:
2520 {
2521 unsigned char* base_pc = pc-1;
2522 jint offset = get2s (pc); pc += 2;
2523 jobject val = POPA();
2524 if (val == NULL)
2525 pc = base_pc+offset;
2526 }
2527 NEXT_INSN;
2528
2529 insn_ifnonnull:
2530 {
2531 unsigned char* base_pc = pc-1;
2532 jint offset = get2s (pc); pc += 2;
2533 jobject val = POPA();
2534 if (val != NULL)
2535 pc = base_pc+offset;
2536 }
2537 NEXT_INSN;
2538
2539 insn_wide:
2540 SAVE_PC;
2541 {
2542 jint the_mod_op = get1u (pc++);
2543 jint wide = get2u (pc); pc += 2;
2544
2545 switch (the_mod_op)
2546 {
2547 case op_istore:
2548 STOREI (wide);
2549 NEXT_INSN;
2550
2551 case op_fstore:
2552 STOREF (wide);
2553 NEXT_INSN;
2554
2555 case op_astore:
2556 STOREA (wide);
2557 NEXT_INSN;
2558
2559 case op_lload:
2560 LOADL (wide);
2561 NEXT_INSN;
2562
2563 case op_dload:
2564 LOADD (wide);
2565 NEXT_INSN;
2566
2567 case op_iload:
2568 LOADI (wide);
2569 NEXT_INSN;
2570
2571 case op_aload:
2572 LOADA (wide);
2573 NEXT_INSN;
2574
2575 case op_lstore:
2576 STOREL (wide);
2577 NEXT_INSN;
2578
2579 case op_dstore:
2580 STORED (wide);
2581 NEXT_INSN;
2582
2583 case op_ret:
2584 pc = (unsigned char*) PEEKA (wide);
2585 NEXT_INSN;
2586
2587 case op_iinc:
2588 {
2589 jint amount = get2s (pc); pc += 2;
2590 jint value = PEEKI (wide);
2591 POKEI (wide, value+amount);
2592 }
2593 NEXT_INSN;
2594
2595 default:
2596 throw_internal_error ("illegal bytecode modified by wide");
2597 }
2598
2599 }
2600
2601 insn_multianewarray:
2602 SAVE_PC;
2603 {
2604 int kind_index = get2u (pc); pc += 2;
2605 int dim = get1u (pc); pc += 1;
2606
2607 jclass type
2608 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
2609 _Jv_InitClass (type);
2610 jint *sizes = (jint*) alloca (sizeof (jint)*dim);
2611
2612 for (int i = dim - 1; i >= 0; i--)
2613 {
2614 sizes[i] = POPI ();
2615 }
2616
2617 jobject res = _Jv_NewMultiArray (type,dim, sizes);
2618
2619 PUSHA (res);
2620 }
2621 NEXT_INSN;
2622
2623 insn_goto_w:
2624 {
2625 unsigned char* base_pc = pc-1;
2626 int offset = get4 (pc); pc += 4;
2627 pc = base_pc+offset;
2628 }
2629 NEXT_INSN;
2630
2631 insn_jsr_w:
2632 {
2633 unsigned char* base_pc = pc-1;
2634 int offset = get4 (pc); pc += 4;
2635 PUSHA((jobject)pc);
2636 pc = base_pc+offset;
2637 }
2638 NEXT_INSN;
2639 }
2640
2641
2642 static void
2643 throw_internal_error (char *msg)
2644 {
2645 JvThrow (new java::lang::InternalError (JvNewStringLatin1 (msg)));
2646 }
2647
2648 static void
2649 throw_incompatible_class_change_error (jstring msg)
2650 {
2651 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
2652 }
2653
2654 #if !HANDLE_SEGV
2655 static java::lang::NullPointerException *null_pointer_exc;
2656 static void
2657 throw_null_pointer_exception ()
2658 {
2659 if (null_pointer_exc == NULL)
2660 null_pointer_exc = new java::lang::NullPointerException;
2661
2662 JvThrow (null_pointer_exc);
2663 }
2664 #endif
2665
2666 #if !HANDLE_FPE
2667 static java::lang::ArithmeticException *arithmetic_exc;
2668 static void
2669 throw_arithmetic_exception ()
2670 {
2671 if (arithmetic_exc == NULL)
2672 arithmetic_exc = new java::lang::ArithmeticException
2673 (JvNewStringLatin1 ("/ by zero"));
2674
2675 JvThrow (arithmetic_exc);
2676 }
2677 #endif
2678
2679
2680 #endif // INTERPRETER