This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
RFC: direct threading
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: 17 Feb 2002 13:09:07 -0700
- Subject: RFC: direct threading
- Reply-to: tromey at redhat dot com
I'm not checking this in yet. I'll probably check it in after the
branch is made. It is too new right now, and I don't have the time to
test it as much as would be necessary. I'm posting it for commentary.
This patch changes the libgcj interpreter to use direct threaded code
instead of a bytecode interpreter. We do a couple passes over the
bytecode to build up a new structure which is then interpreted. Some
routines, like invokestatic, then further rewrite the interpreted
structure to avoid repeatedly paying costs that only need to be paid
once. For instance, a class will be initialized only once for any
given instance of invokestatic. We also simply omit `nop' (and we
could easily do jump threading, too, if we wanted).
Running this against the infamous `prime' benchmark I saw around a 20%
speedup. That seems good, except that the JDK 1.2 interpreter is
still nearly twice as fast. My guess is that we're paying too much
for function calls, but I haven't really investigated (nor do I intend
to).
On the down side, this requires more startup the first time a method
is called, and it also requires more memory. Perhaps it isn't
worthwhile on that basis?
Tom
Index: defineclass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/defineclass.cc,v
retrieving revision 1.27
diff -u -r1.27 defineclass.cc
--- defineclass.cc 2001/12/10 01:18:30 1.27
+++ defineclass.cc 2002/02/17 19:32:17
@@ -1,6 +1,6 @@
// defineclass.cc - defining a class from .class format.
-/* Copyright (C) 1999, 2000, 2001 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
This file is part of libgcj.
@@ -1262,6 +1262,7 @@
method->exc_count = exc_table_length;
method->defining_class = def;
method->self = &def->methods[method_index];
+ method->prepared = NULL;
// grab the byte code!
memcpy ((void*) method->bytecode (),
@@ -1279,10 +1280,10 @@
(def->interpreted_methods[method_index]);
_Jv_InterpException *exc = method->exceptions ();
- exc[exc_index].start_pc = start_pc;
- exc[exc_index].end_pc = end_pc;
- exc[exc_index].handler_pc = handler_pc;
- exc[exc_index].handler_type = catch_type;
+ exc[exc_index].start_pc.i = start_pc;
+ exc[exc_index].end_pc.i = end_pc;
+ exc[exc_index].handler_pc.i = handler_pc;
+ exc[exc_index].handler_type.i = catch_type;
}
void _Jv_ClassReader::handleMethodsEnd ()
Index: interpret.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/interpret.cc,v
retrieving revision 1.31
diff -u -r1.31 interpret.cc
--- interpret.cc 2002/02/10 18:32:48 1.31
+++ interpret.cc 2002/02/17 19:32:17
@@ -51,6 +51,18 @@
extern "C" double __ieee754_fmod (double,double);
+// This represents a single slot in the "compiled" form of the
+// bytecode.
+union insn_slot
+{
+ // Address of code.
+ void *insn;
+ // An integer value used by an instruction.
+ jint int_val;
+ // A pointer value used by an instruction.
+ void *datum;
+};
+
static inline void dupx (_Jv_word *sp, int n, int x)
{
// first "slide" n+x elements n to the right
@@ -228,7 +240,7 @@
_Jv_InterpMethodInvocation *inv)
{
inv->running = this;
- inv->pc = bytecode ();
+ inv->pc = prepared;
inv->sp = inv->stack_base ();
_Jv_word *locals = inv->local_base ();
@@ -280,7 +292,7 @@
*(jfloat*)retp = r;
return 0;
}
-
+
case FFI_TYPE_DOUBLE:
{
jdouble r = POPD();
@@ -298,21 +310,21 @@
*(jint*)retp = r;
return 0;
}
-
+
case FFI_TYPE_SINT64:
{
jlong r = POPL();
*(jlong*)retp = r;
return 0;
}
-
+
default:
throw_internal_error ("unknown return type");
}
}
- /** handle an exception */
- if ( find_exception (ex, inv) )
+ /* Handle an exception. */
+ if (find_exception (ex, inv))
goto next_segment;
return ex;
@@ -320,30 +332,23 @@
#define SAVE_PC inv->pc = pc
-bool _Jv_InterpMethod::find_exception (jobject ex,
- _Jv_InterpMethodInvocation *inv)
+bool
+_Jv_InterpMethod::find_exception (jobject ex, _Jv_InterpMethodInvocation *inv)
{
// We subtract one because the PC was incremented before it was
// saved.
- int logical_pc = inv->pc - 1 - bytecode ();
+ void *logical_pc = (void *) ((insn_slot *) inv->pc - 1);
_Jv_InterpException *exc = exceptions ();
jclass exc_class = ex->getClass ();
for (int i = 0; i < exc_count; i++)
{
- if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
+ if (exc[i].start_pc.p <= logical_pc && logical_pc < exc[i].end_pc.p)
{
- jclass handler;
-
- if (exc[i].handler_type != 0)
- handler = (_Jv_ResolvePoolEntry (defining_class,
- exc[i].handler_type)).clazz;
- else
- handler = NULL;
-
- if (handler==NULL || handler->isAssignableFrom (exc_class))
+ jclass handler = (jclass) exc[i].handler_type.p;
+ if (handler == NULL || handler->isAssignableFrom (exc_class))
{
- inv->pc = bytecode () + exc[i].handler_pc;
+ inv->pc = exc[i].handler_pc.p;
inv->sp = inv->stack_base (); // reset stack
(inv->sp++)->o = ex; // push exception
return true;
@@ -411,6 +416,423 @@
if (ex != 0) throw static_cast<jthrowable>(ex);
}
+// "Compile" a method by turning it from bytecode to direct-threaded
+// code.
+void
+_Jv_InterpMethod::compile (const void * const *insn_targets)
+{
+ insn_slot *insns;
+ int next = 0;
+ unsigned char *codestart = bytecode ();
+ unsigned char *end = codestart + code_length;
+ _Jv_word *pool_data = defining_class->constants.data;
+
+#define SET_ONE(Field, Value) \
+ do \
+ { \
+ if (first_pass) \
+ ++next; \
+ else \
+ insns[next++].Field = Value; \
+ } \
+ while (0)
+
+#define SET_INSN(Value) SET_ONE (insn, (void *) Value)
+#define SET_INT(Value) SET_ONE (int_val, Value)
+#define SET_DATUM(Value) SET_ONE (datum, Value)
+
+ // Map from bytecode PC to slot in INSNS.
+ int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length);
+ for (int i = 0; i < code_length; ++i)
+ pc_mapping[i] = -1;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ jboolean first_pass = i == 0;
+
+ if (! first_pass)
+ {
+ insns = (insn_slot *) _Jv_Malloc (sizeof (insn_slot) * next);
+ next = 0;
+ }
+
+ unsigned char *pc = bytecode ();
+ while (pc < end)
+ {
+ int base_pc_val = pc - codestart;
+ if (first_pass)
+ pc_mapping[base_pc_val] = next;
+
+ java_opcode opcode = (java_opcode) *pc++;
+ // Just elide NOPs.
+ if (opcode == op_nop)
+ continue;
+ SET_INSN (insn_targets[opcode]);
+
+ switch (opcode)
+ {
+ case op_nop:
+ case op_aconst_null:
+ case op_iconst_m1:
+ case op_iconst_0:
+ case op_iconst_1:
+ case op_iconst_2:
+ case op_iconst_3:
+ case op_iconst_4:
+ case op_iconst_5:
+ case op_lconst_0:
+ case op_lconst_1:
+ case op_fconst_0:
+ case op_fconst_1:
+ case op_fconst_2:
+ case op_dconst_0:
+ case op_dconst_1:
+ case op_iload_0:
+ case op_iload_1:
+ case op_iload_2:
+ case op_iload_3:
+ case op_lload_0:
+ case op_lload_1:
+ case op_lload_2:
+ case op_lload_3:
+ case op_fload_0:
+ case op_fload_1:
+ case op_fload_2:
+ case op_fload_3:
+ case op_dload_0:
+ case op_dload_1:
+ case op_dload_2:
+ case op_dload_3:
+ case op_aload_0:
+ case op_aload_1:
+ case op_aload_2:
+ case op_aload_3:
+ case op_iaload:
+ case op_laload:
+ case op_faload:
+ case op_daload:
+ case op_aaload:
+ case op_baload:
+ case op_caload:
+ case op_saload:
+ case op_istore_0:
+ case op_istore_1:
+ case op_istore_2:
+ case op_istore_3:
+ case op_lstore_0:
+ case op_lstore_1:
+ case op_lstore_2:
+ case op_lstore_3:
+ case op_fstore_0:
+ case op_fstore_1:
+ case op_fstore_2:
+ case op_fstore_3:
+ case op_dstore_0:
+ case op_dstore_1:
+ case op_dstore_2:
+ case op_dstore_3:
+ case op_astore_0:
+ case op_astore_1:
+ case op_astore_2:
+ case op_astore_3:
+ case op_iastore:
+ case op_lastore:
+ case op_fastore:
+ case op_dastore:
+ case op_aastore:
+ case op_bastore:
+ case op_castore:
+ case op_sastore:
+ case op_pop:
+ case op_pop2:
+ case op_dup:
+ case op_dup_x1:
+ case op_dup_x2:
+ case op_dup2:
+ case op_dup2_x1:
+ case op_dup2_x2:
+ case op_swap:
+ case op_iadd:
+ case op_isub:
+ case op_imul:
+ case op_idiv:
+ case op_irem:
+ case op_ishl:
+ case op_ishr:
+ case op_iushr:
+ case op_iand:
+ case op_ior:
+ case op_ixor:
+ case op_ladd:
+ case op_lsub:
+ case op_lmul:
+ case op_ldiv:
+ case op_lrem:
+ case op_lshl:
+ case op_lshr:
+ case op_lushr:
+ case op_land:
+ case op_lor:
+ case op_lxor:
+ case op_fadd:
+ case op_fsub:
+ case op_fmul:
+ case op_fdiv:
+ case op_frem:
+ case op_dadd:
+ case op_dsub:
+ case op_dmul:
+ case op_ddiv:
+ case op_drem:
+ case op_ineg:
+ case op_i2b:
+ case op_i2c:
+ case op_i2s:
+ case op_lneg:
+ case op_fneg:
+ case op_dneg:
+ case op_i2l:
+ case op_i2f:
+ case op_i2d:
+ case op_l2i:
+ case op_l2f:
+ case op_l2d:
+ case op_f2i:
+ case op_f2l:
+ case op_f2d:
+ case op_d2i:
+ case op_d2l:
+ case op_d2f:
+ case op_lcmp:
+ case op_fcmpl:
+ case op_fcmpg:
+ case op_dcmpl:
+ case op_dcmpg:
+ case op_monitorenter:
+ case op_monitorexit:
+ case op_ireturn:
+ case op_lreturn:
+ case op_freturn:
+ case op_dreturn:
+ case op_areturn:
+ case op_return:
+ case op_athrow:
+ case op_arraylength:
+ // No argument, nothing else to do.
+ break;
+
+ case op_bipush:
+ SET_INT (get1s (pc));
+ ++pc;
+ break;
+
+ case op_ldc:
+ {
+ int index = get1u (pc);
+ ++pc;
+ SET_DATUM (pool_data[index].o);
+ }
+ break;
+
+ case op_ret:
+ case op_iload:
+ case op_lload:
+ case op_fload:
+ case op_dload:
+ case op_aload:
+ case op_istore:
+ case op_lstore:
+ case op_fstore:
+ case op_dstore:
+ case op_astore:
+ case op_newarray:
+ SET_INT (get1u (pc));
+ ++pc;
+ break;
+
+ case op_iinc:
+ SET_INT (get1u (pc));
+ SET_INT (get1s (pc + 1));
+ pc += 2;
+ break;
+
+ case op_ldc_w:
+ {
+ int index = get2u (pc);
+ pc += 2;
+ SET_DATUM (pool_data[index].o);
+ }
+ break;
+
+ case op_ldc2_w:
+ {
+ int index = get2u (pc);
+ pc += 2;
+ SET_DATUM (&pool_data[index]);
+ }
+ break;
+
+ case op_sipush:
+ SET_INT (get2s (pc));
+ pc += 2;
+ break;
+
+ case op_new:
+ case op_getstatic:
+ case op_getfield:
+ case op_putfield:
+ case op_putstatic:
+ case op_anewarray:
+ case op_instanceof:
+ case op_checkcast:
+ case op_invokespecial:
+ case op_invokestatic:
+ case op_invokevirtual:
+ SET_INT (get2u (pc));
+ pc += 2;
+ break;
+
+ case op_multianewarray:
+ SET_INT (get2u (pc));
+ SET_INT (get1u (pc + 2));
+ pc += 3;
+ break;
+
+ case op_jsr:
+ case op_ifeq:
+ case op_ifne:
+ case op_iflt:
+ case op_ifge:
+ case op_ifgt:
+ case op_ifle:
+ case op_if_icmpeq:
+ case op_if_icmpne:
+ case op_if_icmplt:
+ case op_if_icmpge:
+ case op_if_icmpgt:
+ case op_if_icmple:
+ case op_if_acmpeq:
+ case op_if_acmpne:
+ case op_ifnull:
+ case op_ifnonnull:
+ case op_goto:
+ {
+ int offset = get2s (pc);
+ pc += 2;
+ SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
+ }
+ break;
+
+ case op_tableswitch:
+ {
+ while ((pc - codestart) % 4 != 0)
+ ++pc;
+
+ jint def = get4 (pc);
+ SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
+ pc += 4;
+
+ int low = get4 (pc);
+ SET_INT (low);
+ pc += 4;
+ int high = get4 (pc);
+ SET_INT (high);
+ pc += 4;
+
+ for (int i = low; i <= high; ++i)
+ {
+ SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]);
+ pc += 4;
+ }
+ }
+ break;
+
+ case op_lookupswitch:
+ {
+ while ((pc - codestart) % 4 != 0)
+ ++pc;
+
+ jint def = get4 (pc);
+ SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
+ pc += 4;
+
+ jint npairs = get4 (pc);
+ pc += 4;
+ SET_INT (npairs);
+
+ while (npairs-- > 0)
+ {
+ jint match = get4 (pc);
+ jint offset = get4 (pc + 4);
+ SET_INT (match);
+ SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
+ }
+ }
+ break;
+
+ case op_invokeinterface:
+ {
+ jint index = get2u (pc);
+ pc += 2;
+ // We ignore the next two bytes.
+ pc += 2;
+ SET_INT (index);
+ }
+ break;
+
+ case op_wide:
+ {
+ opcode = (java_opcode) get1u (pc);
+ pc += 1;
+ jint val = get2u (pc);
+ pc += 2;
+
+ // We implement narrow and wide instructions using the
+ // same code in the interpreter. So we rewrite the
+ // instruction slot here.
+ if (! first_pass)
+ insns[next - 1].insn = (void *) insn_targets[opcode];
+ SET_INT (val);
+
+ if (opcode == op_iinc)
+ {
+ SET_INT (get2s (pc));
+ pc += 2;
+ }
+ }
+ break;
+
+ case op_jsr_w:
+ case op_goto_w:
+ {
+ jint offset = get4 (pc);
+ pc += 4;
+ SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
+ }
+ break;
+
+ default:
+ // Fail somehow.
+ break;
+ }
+ }
+ }
+
+ // Now update exceptions.
+ _Jv_InterpException *exc = exceptions ();
+ for (int i = 0; i < exc_count; ++i)
+ {
+ exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]];
+ exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]];
+ exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]];
+ jclass handler = (_Jv_ResolvePoolEntry (defining_class,
+ exc[i].handler_type.i)).clazz;
+ exc[i].handler_type.p = handler;
+ }
+
+ prepared = insns;
+}
+
/*
This proceeds execution, as designated in "inv". If an exception
happens, then it is simply thrown, and handled in Java. Thus, the pc
@@ -428,21 +850,21 @@
using namespace java::lang::reflect;
_Jv_word *sp = inv->sp;
- unsigned char *pc = inv->pc;
_Jv_word *locals = inv->local_base ();
_Jv_word *pool_data = defining_class->constants.data;
-
- /* these two are used in the invokeXXX instructions */
+
+ /* These three are temporaries for common code used by several
+ instructions. */
void (*fun)();
_Jv_ResolvedMethod* rmeth;
+ int tmpval;
#define INSN_LABEL(op) &&insn_##op
-#define GOTO_INSN(op) goto *(insn_target[op])
static const void *const insn_target[] =
{
- INSN_LABEL(nop),
+ 0, // nop
INSN_LABEL(aconst_null),
INSN_LABEL(iconst_m1),
INSN_LABEL(iconst_0),
@@ -638,52 +1060,41 @@
INSN_LABEL(instanceof),
INSN_LABEL(monitorenter),
INSN_LABEL(monitorexit),
- INSN_LABEL(wide),
+ 0, // wide
INSN_LABEL(multianewarray),
INSN_LABEL(ifnull),
INSN_LABEL(ifnonnull),
INSN_LABEL(goto_w),
INSN_LABEL(jsr_w),
+ 0
};
-
- /* If the macro INLINE_SWITCH is not defined, then the main loop
- operates as one big (normal) switch statement. If it is defined,
- then the case selection is performed `inline' in the end of the
- code for each case. The latter saves a native branch instruction
- for each java-instruction, but expands the code size somewhat.
-
- NOTE: On i386 defining INLINE_SWITCH improves over all
- performance approximately seven percent, but it may be different
- for other machines. At some point, this may be made into a proper
- configuration parameter. */
-#define INLINE_SWITCH
+ // Compile if we must.
+ if (inv->running->prepared == NULL)
+ {
+ compile (insn_target);
+ inv->pc = inv->running->prepared;
+ }
-#ifdef INLINE_SWITCH
+ insn_slot *pc = (insn_slot *) inv->pc;
-#define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
+#define NEXT_INSN goto *((pc++)->insn)
+#define INTVAL() ((pc++)->int_val)
+#define AVAL() ((pc++)->datum)
NEXT_INSN;
-#else
-
-#define NEXT_INSN goto next_insn
-
- next_insn:
- GOTO_INSN (*pc++);
-#endif
-
/* The first few instructions here are ordered according to their
frequency, in the hope that this will improve code locality a
little. */
insn_aload_0: // 0x2a
- LOADA(0);
+ LOADA (0);
NEXT_INSN;
insn_iload: // 0x15
- LOADI (get1u (pc++));
+ LOADI (INTVAL ());
NEXT_INSN;
insn_iload_1: // 0x1b
@@ -693,7 +1104,7 @@
insn_invokevirtual: // 0xb6
SAVE_PC;
{
- int index = get2u (pc); pc += 2;
+ int index = INTVAL ();
/* _Jv_ResolvePoolEntry returns immediately if the value already
* is resolved. If we want to clutter up the code here to gain
@@ -718,9 +1129,40 @@
}
else
{
+ jobject rcv = sp[0].o;
+ _Jv_VTable *table = *(_Jv_VTable**) rcv;
+ fun = (void (*)()) table->get_method (rmeth->vtable_index);
+ }
+
+ // Rewrite instruction so that we use a faster pre-resolved
+ // method.
+ pc[-2].insn = &&invokevirtual_resolved;
+ pc[-1].datum = rmeth;
+ }
+ goto perform_invoke;
+
+ invokevirtual_resolved:
+ SAVE_PC;
+ {
+ rmeth = (_Jv_ResolvedMethod *) AVAL ();
+ sp -= rmeth->stack_item_count;
+ // We don't use NULLCHECK here because we can't rely on that
+ // working if the method is final. So instead we do an
+ // explicit test.
+ if (! sp[0].o)
+ throw new java::lang::NullPointerException;
+
+ if (rmeth->vtable_index == -1)
+ {
+ // final methods do not appear in the vtable,
+ // if it does not appear in the superclass.
+ fun = (void (*)()) rmeth->method->ncode;
+ }
+ else
+ {
jobject rcv = sp[0].o;
- _Jv_VTable *table = *(_Jv_VTable**)rcv;
- fun = (void (*)()) table->get_method(rmeth->vtable_index);
+ _Jv_VTable *table = *(_Jv_VTable**) rcv;
+ fun = (void (*)()) table->get_method (rmeth->vtable_index);
}
}
goto perform_invoke;
@@ -799,10 +1241,6 @@
}
NEXT_INSN;
-
- insn_nop:
- NEXT_INSN;
-
insn_aconst_null:
PUSHA (NULL);
NEXT_INSN;
@@ -864,49 +1302,39 @@
NEXT_INSN;
insn_bipush:
- PUSHI (get1s(pc++));
- NEXT_INSN;
-
insn_sipush:
- PUSHI (get2s(pc)); pc += 2;
+ PUSHI (INTVAL ());
NEXT_INSN;
insn_ldc:
- {
- int index = get1u (pc++);
- PUSHA(pool_data[index].o);
- }
- NEXT_INSN;
-
insn_ldc_w:
{
- int index = get2u (pc); pc += 2;
- PUSHA(pool_data[index].o);
+ PUSHA ((jobject) AVAL ());
}
NEXT_INSN;
insn_ldc2_w:
{
- int index = get2u (pc); pc += 2;
- memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
+ void *where = AVAL ();
+ memcpy (sp, where, 2*sizeof (_Jv_word));
sp += 2;
}
NEXT_INSN;
insn_lload:
- LOADL (get1u (pc++));
+ LOADL (INTVAL ());
NEXT_INSN;
insn_fload:
- LOADF (get1u (pc++));
+ LOADF (INTVAL ());
NEXT_INSN;
insn_dload:
- LOADD (get1u (pc++));
+ LOADD (INTVAL ());
NEXT_INSN;
insn_aload:
- LOADA (get1u (pc++));
+ LOADA (INTVAL ());
NEXT_INSN;
insn_iload_0:
@@ -1062,23 +1490,23 @@
NEXT_INSN;
insn_istore:
- STOREI (get1u (pc++));
+ STOREI (INTVAL ());
NEXT_INSN;
insn_lstore:
- STOREL (get1u (pc++));
+ STOREL (INTVAL ());
NEXT_INSN;
insn_fstore:
- STOREF (get1u (pc++));
+ STOREF (INTVAL ());
NEXT_INSN;
insn_dstore:
- STORED (get1u (pc++));
+ STORED (INTVAL ());
NEXT_INSN;
insn_astore:
- STOREA (get1u (pc++));
+ STOREA (INTVAL ());
NEXT_INSN;
insn_istore_0:
@@ -1520,8 +1948,8 @@
insn_iinc:
{
- jint index = get1u (pc++);
- jint amount = get1s (pc++);
+ jint index = INTVAL ();
+ jint amount = INTVAL ();
locals[index].i += amount;
}
NEXT_INSN;
@@ -1616,7 +2044,13 @@
NEXT_INSN;
insn_fcmpl:
+ tmpval = -1;
+ goto fcmp;
+
insn_fcmpg:
+ tmpval = 1;
+
+ fcmp:
{
jfloat value2 = POPF ();
jfloat value1 = POPF ();
@@ -1626,15 +2060,19 @@
PUSHI (0);
else if (value1 < value2)
PUSHI (-1);
- else if ((*(pc-1)) == op_fcmpg)
- PUSHI (1);
else
- PUSHI (-1);
+ PUSHI (tmpval);
}
NEXT_INSN;
insn_dcmpl:
+ tmpval = 1;
+ goto dcmp;
+
insn_dcmpg:
+ tmpval = -1;
+
+ dcmp:
{
jdouble value2 = POPD ();
jdouble value1 = POPD ();
@@ -1644,247 +2082,219 @@
PUSHI (0);
else if (value1 < value2)
PUSHI (-1);
- else if ((*(pc-1)) == op_dcmpg)
- PUSHI (1);
else
- PUSHI (-1);
+ PUSHI (tmpval);
}
NEXT_INSN;
insn_ifeq:
{
- jint offset = get2s (pc);
if (POPI() == 0)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_ifne:
{
- jint offset = get2s (pc);
if (POPI() != 0)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_iflt:
{
- jint offset = get2s (pc);
if (POPI() < 0)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_ifge:
{
- jint offset = get2s (pc);
if (POPI() >= 0)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_ifgt:
{
- jint offset = get2s (pc);
if (POPI() > 0)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_ifle:
{
- jint offset = get2s (pc);
if (POPI() <= 0)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_if_icmpeq:
{
- jint offset = get2s (pc);
jint value2 = POPI();
jint value1 = POPI();
if (value1 == value2)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_if_icmpne:
{
- jint offset = get2s (pc);
jint value2 = POPI();
jint value1 = POPI();
if (value1 != value2)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_if_icmplt:
{
- jint offset = get2s (pc);
jint value2 = POPI();
jint value1 = POPI();
if (value1 < value2)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_if_icmpge:
{
- jint offset = get2s (pc);
jint value2 = POPI();
jint value1 = POPI();
if (value1 >= value2)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_if_icmpgt:
{
- jint offset = get2s (pc);
jint value2 = POPI();
jint value1 = POPI();
if (value1 > value2)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_if_icmple:
{
- jint offset = get2s (pc);
jint value2 = POPI();
jint value1 = POPI();
if (value1 <= value2)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_if_acmpeq:
{
- jint offset = get2s (pc);
jobject value2 = POPA();
jobject value1 = POPA();
if (value1 == value2)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
insn_if_acmpne:
{
- jint offset = get2s (pc);
jobject value2 = POPA();
jobject value1 = POPA();
if (value1 != value2)
- pc = pc-1+offset;
+ pc = (insn_slot *) pc->datum;
else
- pc = pc+2;
+ ++pc;
}
NEXT_INSN;
- insn_goto:
- {
- jint offset = get2s (pc);
- pc = pc-1+offset;
- }
+ insn_goto:
+ insn_goto_w:
+ pc = (insn_slot *) pc->datum;
NEXT_INSN;
insn_jsr:
+ insn_jsr_w:
{
- unsigned char *base_pc = pc-1;
- jint offset = get2s (pc); pc += 2;
- PUSHA ((jobject)pc);
- pc = base_pc+offset;
+ void *next = AVAL ();
+ PUSHA ((jobject) pc);
+ pc = (insn_slot *) next;
}
NEXT_INSN;
insn_ret:
{
- jint index = get1u (pc);
- pc = (unsigned char*) PEEKA (index);
+ jint index = INTVAL ();
+ pc = (insn_slot *) PEEKA (index);
}
NEXT_INSN;
insn_tableswitch:
{
- unsigned char *base_pc = pc-1;
+ void *def = (pc++)->datum;
+
int index = POPI();
- unsigned char* base = bytecode ();
- while ((pc-base) % 4 != 0)
- pc++;
-
- jint def = get4 (pc);
- jint low = get4 (pc+4);
- jint high = get4 (pc+8);
+ jint low = INTVAL ();
+ jint high = INTVAL ();
if (index < low || index > high)
- pc = base_pc + def;
+ pc = (insn_slot *) def;
else
- pc = base_pc + get4 (pc+4*(index-low+3));
+ pc = (insn_slot *) ((pc + index - low)->datum);
}
NEXT_INSN;
insn_lookupswitch:
{
- unsigned char *base_pc = pc-1;
- int index = POPI();
+ void *def = (pc++)->insn;
- unsigned char* base = bytecode ();
- while ((pc-base) % 4 != 0)
- pc++;
+ int index = POPI();
- jint def = get4 (pc);
- jint npairs = get4 (pc+4);
+ jint npairs = INTVAL ();
- int max = npairs-1;
+ int max = npairs - 1;
int min = 0;
- // simple binary search...
+ // Simple binary search...
while (min < max)
{
- int half = (min+max)/2;
- int match = get4 (pc+ 4*(2 + 2*half));
+ int half = (min + max) / 2;
+ int match = pc[2 * half].int_val;
if (index == match)
- min = max = half;
-
+ {
+ // Found it.
+ pc = (insn_slot *) pc[2 * half + 1].datum;
+ NEXT_INSN;
+ }
else if (index < match)
- max = half-1;
-
+ max = half - 1;
else
- min = half+1;
+ min = half + 1;
}
-
- if (index == get4 (pc+ 4*(2 + 2*min)))
- pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
- else
- pc = base_pc + def;
+ pc = (insn_slot *) def;
}
NEXT_INSN;
@@ -1901,7 +2311,7 @@
insn_getstatic:
SAVE_PC;
{
- jint fieldref_index = get2u (pc); pc += 2;
+ jint fieldref_index = INTVAL ();
_Jv_ResolvePoolEntry (defining_class, fieldref_index);
_Jv_Field *field = pool_data[fieldref_index].field;
@@ -1911,41 +2321,81 @@
jclass type = field->type;
+ // We rewrite the instruction once we discover what it refers
+ // to.
+ void *newinsn = NULL;
if (type->isPrimitive ())
{
switch (type->size_in_bytes)
{
case 1:
PUSHI (*(jbyte*) (field->u.addr));
+ newinsn = &&getstatic_resolved_1;
break;
case 2:
if (type == JvPrimClass (char))
- PUSHI(*(jchar*) (field->u.addr));
+ {
+ PUSHI(*(jchar*) (field->u.addr));
+ newinsn = &&getstatic_resolved_char;
+ }
else
- PUSHI(*(jshort*) (field->u.addr));
+ {
+ PUSHI(*(jshort*) (field->u.addr));
+ newinsn = &&getstatic_resolved_short;
+ }
break;
case 4:
PUSHI(*(jint*) (field->u.addr));
+ newinsn = &&getstatic_resolved_4;
break;
case 8:
PUSHL(*(jlong*) (field->u.addr));
+ newinsn = &&getstatic_resolved_8;
break;
}
}
else
{
PUSHA(*(jobject*) (field->u.addr));
+ newinsn = &&getstatic_resolved_obj;
}
+
+ pc[-2].insn = newinsn;
+ pc[-1].datum = field->u.addr;
}
NEXT_INSN;
+ getstatic_resolved_1:
+ PUSHI (*(jbyte *) AVAL ());
+ NEXT_INSN;
+
+ getstatic_resolved_char:
+ PUSHI (*(jchar *) AVAL ());
+ NEXT_INSN;
+
+ getstatic_resolved_short:
+ PUSHI (*(jshort *) AVAL ());
+ NEXT_INSN;
+
+ getstatic_resolved_4:
+ PUSHI (*(jint *) AVAL ());
+ NEXT_INSN;
+
+ getstatic_resolved_8:
+ PUSHL (*(jlong *) AVAL ());
+ NEXT_INSN;
+
+ getstatic_resolved_obj:
+ PUSHA (*(jobject *) AVAL ());
+ NEXT_INSN;
+
insn_getfield:
SAVE_PC;
{
- jint fieldref_index = get2u (pc); pc += 2;
+ jint fieldref_index = INTVAL ();
_Jv_ResolvePoolEntry (defining_class, fieldref_index);
_Jv_Field *field = pool_data[fieldref_index].field;
@@ -1961,41 +2411,109 @@
jobject obj = POPA();
NULLCHECK(obj);
+ void *newinsn = NULL;
if (type->isPrimitive ())
{
switch (type->size_in_bytes)
{
case 1:
PUSHI (*(jbyte*) ((char*)obj + field_offset));
+ newinsn = &&getfield_resolved_1;
break;
case 2:
if (type == JvPrimClass (char))
- PUSHI (*(jchar*) ((char*)obj + field_offset));
+ {
+ PUSHI (*(jchar*) ((char*)obj + field_offset));
+ newinsn = &&getfield_resolved_char;
+ }
else
- PUSHI (*(jshort*) ((char*)obj + field_offset));
+ {
+ PUSHI (*(jshort*) ((char*)obj + field_offset));
+ newinsn = &&getfield_resolved_short;
+ }
break;
case 4:
PUSHI (*(jint*) ((char*)obj + field_offset));
+ newinsn = &&getfield_resolved_4;
break;
case 8:
PUSHL(*(jlong*) ((char*)obj + field_offset));
+ newinsn = &&getfield_resolved_8;
break;
}
}
else
{
PUSHA(*(jobject*) ((char*)obj + field_offset));
+ newinsn = &&getfield_resolved_obj;
}
+
+ pc[-2].insn = newinsn;
+ pc[-1].int_val = field_offset;
}
NEXT_INSN;
+ getfield_resolved_1:
+ SAVE_PC;
+ {
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ PUSHI (*(jbyte *) (obj + INTVAL ()));
+ }
+ NEXT_INSN;
+
+ getfield_resolved_char:
+ SAVE_PC;
+ {
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ PUSHI (*(jchar *) (obj + INTVAL ()));
+ }
+ NEXT_INSN;
+
+ getfield_resolved_short:
+ SAVE_PC;
+ {
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ PUSHI (*(jshort *) (obj + INTVAL ()));
+ }
+ NEXT_INSN;
+
+ getfield_resolved_4:
+ SAVE_PC;
+ {
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ PUSHI (*(jint *) (obj + INTVAL ()));
+ }
+ NEXT_INSN;
+
+ getfield_resolved_8:
+ SAVE_PC;
+ {
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ PUSHL (*(jlong *) (obj + INTVAL ()));
+ }
+ NEXT_INSN;
+
+ getfield_resolved_obj:
+ SAVE_PC;
+ {
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ PUSHA (*(jobject *) (obj + INTVAL ()));
+ }
+ NEXT_INSN;
+
insn_putstatic:
SAVE_PC;
{
- jint fieldref_index = get2u (pc); pc += 2;
+ jint fieldref_index = INTVAL ();
_Jv_ResolvePoolEntry (defining_class, fieldref_index);
_Jv_Field *field = pool_data[fieldref_index].field;
@@ -2006,6 +2524,7 @@
throw_incompatible_class_change_error
(JvNewStringLatin1 ("field no longer static"));
+ void *newinsn = NULL;
if (type->isPrimitive ())
{
switch (type->size_in_bytes)
@@ -2014,6 +2533,7 @@
{
jint value = POPI();
*(jbyte*) (field->u.addr) = value;
+ newinsn = &&putstatic_resolved_1;
break;
}
@@ -2021,6 +2541,7 @@
{
jint value = POPI();
*(jchar*) (field->u.addr) = value;
+ newinsn = &&putstatic_resolved_2;
break;
}
@@ -2028,6 +2549,7 @@
{
jint value = POPI();
*(jint*) (field->u.addr) = value;
+ newinsn = &&putstatic_resolved_4;
break;
}
@@ -2035,6 +2557,7 @@
{
jlong value = POPL();
*(jlong*) (field->u.addr) = value;
+ newinsn = &&putstatic_resolved_8;
break;
}
}
@@ -2043,15 +2566,38 @@
{
jobject value = POPA();
*(jobject*) (field->u.addr) = value;
+ newinsn = &&putstatic_resolved_obj;
}
+
+ pc[-2].insn = newinsn;
+ pc[-1].datum = field->u.addr;
}
NEXT_INSN;
+ putstatic_resolved_1:
+ *(jbyte *) AVAL () = POPI ();
+ NEXT_INSN;
+
+ putstatic_resolved_2:
+ *(jchar *) AVAL () = POPI ();
+ NEXT_INSN;
+
+ putstatic_resolved_4:
+ *(jint *) AVAL () = POPI ();
+ NEXT_INSN;
+
+ putstatic_resolved_8:
+ *(jlong *) AVAL () = POPL ();
+ NEXT_INSN;
+
+ putstatic_resolved_obj:
+ *(jobject *) AVAL () = POPA ();
+ NEXT_INSN;
insn_putfield:
SAVE_PC;
{
- jint fieldref_index = get2u (pc); pc += 2;
+ jint fieldref_index = INTVAL ();
_Jv_ResolvePoolEntry (defining_class, fieldref_index);
_Jv_Field *field = pool_data[fieldref_index].field;
@@ -2065,6 +2611,7 @@
if (field_offset > 0xffff)
throw new java::lang::VirtualMachineError;
+ void *newinsn = NULL;
if (type->isPrimitive ())
{
switch (type->size_in_bytes)
@@ -2075,6 +2622,7 @@
jobject obj = POPA();
NULLCHECK(obj);
*(jbyte*) ((char*)obj + field_offset) = value;
+ newinsn = &&putfield_resolved_1;
break;
}
@@ -2084,6 +2632,7 @@
jobject obj = POPA();
NULLCHECK(obj);
*(jchar*) ((char*)obj + field_offset) = value;
+ newinsn = &&putfield_resolved_2;
break;
}
@@ -2093,6 +2642,7 @@
jobject obj = POPA();
NULLCHECK(obj);
*(jint*) ((char*)obj + field_offset) = value;
+ newinsn = &&putfield_resolved_4;
break;
}
@@ -2102,6 +2652,7 @@
jobject obj = POPA();
NULLCHECK(obj);
*(jlong*) ((char*)obj + field_offset) = value;
+ newinsn = &&putfield_resolved_8;
break;
}
}
@@ -2112,14 +2663,68 @@
jobject obj = POPA();
NULLCHECK(obj);
*(jobject*) ((char*)obj + field_offset) = value;
+ newinsn = &&putfield_resolved_obj;
}
+
+ pc[-2].insn = newinsn;
+ pc[-1].int_val = field_offset;
+ }
+ NEXT_INSN;
+
+ putfield_resolved_1:
+ SAVE_PC;
+ {
+ jint val = POPI ();
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ *(jbyte *) (obj + INTVAL ()) = val;
+ }
+ NEXT_INSN;
+
+ putfield_resolved_2:
+ SAVE_PC;
+ {
+ jint val = POPI ();
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ *(jchar *) (obj + INTVAL ()) = val;
+ }
+ NEXT_INSN;
+
+ putfield_resolved_4:
+ SAVE_PC;
+ {
+ jint val = POPI ();
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ *(jint *) (obj + INTVAL ()) = val;
}
NEXT_INSN;
+ putfield_resolved_8:
+ SAVE_PC;
+ {
+ jlong val = POPL ();
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ *(jlong *) (obj + INTVAL ()) = val;
+ }
+ NEXT_INSN;
+
+ putfield_resolved_obj:
+ SAVE_PC;
+ {
+ jobject val = POPA ();
+ char *obj = (char *) POPA ();
+ NULLCHECK (obj);
+ *(jobject *) (obj + INTVAL ()) = val;
+ }
+ NEXT_INSN;
+
insn_invokespecial:
SAVE_PC;
{
- int index = get2u (pc); pc += 2;
+ int index = INTVAL ();
rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
@@ -2128,13 +2733,28 @@
NULLCHECK (sp[0].o);
fun = (void (*)()) rmeth->method->ncode;
+
+ // Rewrite instruction so that we use a faster pre-resolved
+ // method.
+ pc[-2].insn = &&invokespecial_resolved;
+ pc[-1].datum = rmeth;
+ }
+ goto perform_invoke;
+
+ invokespecial_resolved:
+ SAVE_PC;
+ {
+ rmeth = (_Jv_ResolvedMethod *) AVAL ();
+ sp -= rmeth->stack_item_count;
+ NULLCHECK (sp[0].o);
+ fun = (void (*)()) rmeth->method->ncode;
}
goto perform_invoke;
insn_invokestatic:
SAVE_PC;
{
- int index = get2u (pc); pc += 2;
+ int index = INTVAL ();
rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
@@ -2142,16 +2762,27 @@
_Jv_InitClass (rmeth->klass);
fun = (void (*)()) rmeth->method->ncode;
+
+ // Rewrite instruction so that we use a faster pre-resolved
+ // method.
+ pc[-2].insn = &&invokestatic_resolved;
+ pc[-1].datum = rmeth;
}
goto perform_invoke;
- insn_invokeinterface:
+ invokestatic_resolved:
SAVE_PC;
{
- int index = get2u (pc); pc += 2;
+ rmeth = (_Jv_ResolvedMethod *) AVAL ();
+ sp -= rmeth->stack_item_count;
+ fun = (void (*)()) rmeth->method->ncode;
+ }
+ goto perform_invoke;
- // invokeinterface has two unused bytes...
- pc += 2;
+ insn_invokeinterface:
+ SAVE_PC;
+ {
+ int index = INTVAL ();
rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
@@ -2165,25 +2796,56 @@
_Jv_LookupInterfaceMethod (rcv->getClass (),
rmeth->method->name,
rmeth->method->signature);
+
+ // Rewrite instruction so that we use a faster pre-resolved
+ // method.
+ pc[-2].insn = &&invokeinterface_resolved;
+ pc[-1].datum = rmeth;
}
goto perform_invoke;
+ invokeinterface_resolved:
+ SAVE_PC;
+ {
+ rmeth = (_Jv_ResolvedMethod *) AVAL ();
+ sp -= rmeth->stack_item_count;
+ jobject rcv = sp[0].o;
+ NULLCHECK (rcv);
+ fun = (void (*)())
+ _Jv_LookupInterfaceMethod (rcv->getClass (),
+ rmeth->method->name,
+ rmeth->method->signature);
+ }
+ goto perform_invoke;
+
insn_new:
SAVE_PC;
{
- int index = get2u (pc); pc += 2;
+ int index = INTVAL ();
jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
_Jv_InitClass (klass);
jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
PUSHA (res);
+
+ pc[-2].insn = &&new_resolved;
+ pc[-1].datum = klass;
}
NEXT_INSN;
+ new_resolved:
+ SAVE_PC;
+ {
+ jclass klass = (jclass) AVAL ();
+ jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
+ PUSHA (res);
+ }
+ NEXT_INSN;
+
insn_newarray:
SAVE_PC;
{
- int atype = get1u (pc++);
+ int atype = INTVAL ();
int size = POPI();
jobject result = _Jv_NewArray (atype, size);
PUSHA (result);
@@ -2193,12 +2855,25 @@
insn_anewarray:
SAVE_PC;
{
- int index = get2u (pc); pc += 2;
+ int index = INTVAL ();
jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
int size = POPI();
_Jv_InitClass (klass);
jobject result = _Jv_NewObjectArray (size, klass, 0);
PUSHA (result);
+
+ pc[-2].insn = &&anewarray_resolved;
+ pc[-1].datum = klass;
+ }
+ NEXT_INSN;
+
+ anewarray_resolved:
+ SAVE_PC;
+ {
+ jclass klass = (jclass) AVAL ();
+ int size = POPI ();
+ jobject result = _Jv_NewObjectArray (size, klass, 0);
+ PUSHA (result);
}
NEXT_INSN;
@@ -2222,28 +2897,52 @@
SAVE_PC;
{
jobject value = POPA();
- jint index = get2u (pc); pc += 2;
+ jint index = INTVAL ();
jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
if (value != NULL && ! to->isInstance (value))
- {
- throw new java::lang::ClassCastException (to->getName());
- }
+ throw new java::lang::ClassCastException (to->getName());
PUSHA (value);
+
+ pc[-2].insn = &&checkcast_resolved;
+ pc[-1].datum = to;
}
NEXT_INSN;
+ checkcast_resolved:
+ SAVE_PC;
+ {
+ jobject value = POPA ();
+ jclass to = (jclass) AVAL ();
+ if (value != NULL && ! to->isInstance (value))
+ throw new java::lang::ClassCastException (to->getName());
+ PUSHA (value);
+ }
+ NEXT_INSN;
+
insn_instanceof:
SAVE_PC;
{
jobject value = POPA();
- jint index = get2u (pc); pc += 2;
+ jint index = INTVAL ();
jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
PUSHI (to->isInstance (value));
+
+ pc[-2].insn = &&instanceof_resolved;
+ pc[-1].datum = to;
}
NEXT_INSN;
+ instanceof_resolved:
+ SAVE_PC;
+ {
+ jobject value = POPA ();
+ jclass to = (jclass) AVAL ();
+ PUSHI (to->isInstance (value));
+ }
+ NEXT_INSN;
+
insn_monitorenter:
SAVE_PC;
{
@@ -2264,91 +2963,25 @@
insn_ifnull:
{
- unsigned char* base_pc = pc-1;
- jint offset = get2s (pc); pc += 2;
jobject val = POPA();
if (val == NULL)
- pc = base_pc+offset;
+ pc = (insn_slot *) pc->datum;
}
NEXT_INSN;
insn_ifnonnull:
{
- unsigned char* base_pc = pc-1;
- jint offset = get2s (pc); pc += 2;
jobject val = POPA();
if (val != NULL)
- pc = base_pc+offset;
+ pc = (insn_slot *) pc->datum;
}
NEXT_INSN;
- insn_wide:
- SAVE_PC;
- {
- jint the_mod_op = get1u (pc++);
- jint wide = get2u (pc); pc += 2;
-
- switch (the_mod_op)
- {
- case op_istore:
- STOREI (wide);
- NEXT_INSN;
-
- case op_fstore:
- STOREF (wide);
- NEXT_INSN;
-
- case op_astore:
- STOREA (wide);
- NEXT_INSN;
-
- case op_lload:
- LOADL (wide);
- NEXT_INSN;
-
- case op_dload:
- LOADD (wide);
- NEXT_INSN;
-
- case op_iload:
- LOADI (wide);
- NEXT_INSN;
-
- case op_aload:
- LOADA (wide);
- NEXT_INSN;
-
- case op_lstore:
- STOREL (wide);
- NEXT_INSN;
-
- case op_dstore:
- STORED (wide);
- NEXT_INSN;
-
- case op_ret:
- pc = (unsigned char*) PEEKA (wide);
- NEXT_INSN;
-
- case op_iinc:
- {
- jint amount = get2s (pc); pc += 2;
- jint value = PEEKI (wide);
- POKEI (wide, value+amount);
- }
- NEXT_INSN;
-
- default:
- throw_internal_error ("illegal bytecode modified by wide");
- }
-
- }
-
insn_multianewarray:
SAVE_PC;
{
- int kind_index = get2u (pc); pc += 2;
- int dim = get1u (pc); pc += 1;
+ int kind_index = INTVAL ();
+ int dim = INTVAL ();
jclass type
= (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
@@ -2363,23 +2996,6 @@
jobject res = _Jv_NewMultiArray (type,dim, sizes);
PUSHA (res);
- }
- NEXT_INSN;
-
- insn_goto_w:
- {
- unsigned char* base_pc = pc-1;
- int offset = get4 (pc); pc += 4;
- pc = base_pc+offset;
- }
- NEXT_INSN;
-
- insn_jsr_w:
- {
- unsigned char* base_pc = pc-1;
- int offset = get4 (pc); pc += 4;
- PUSHA((jobject)pc);
- pc = base_pc+offset;
}
NEXT_INSN;
}
Index: verify.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/verify.cc,v
retrieving revision 1.38
diff -u -r1.38 verify.cc
--- verify.cc 2002/02/15 06:55:42 1.38
+++ verify.cc 2002/02/17 19:32:19
@@ -1815,18 +1815,18 @@
// Verify exception handlers.
for (int i = 0; i < current_method->exc_count; ++i)
{
- if (! (flags[exception[i].handler_pc] & FLAG_INSN_START))
+ if (! (flags[exception[i].handler_pc.i] & FLAG_INSN_START))
verify_fail ("exception handler not at instruction start",
- exception[i].handler_pc);
- if (! (flags[exception[i].start_pc] & FLAG_INSN_START))
+ exception[i].handler_pc.i);
+ if (! (flags[exception[i].start_pc.i] & FLAG_INSN_START))
verify_fail ("exception start not at instruction start",
- exception[i].start_pc);
- if (exception[i].end_pc != current_method->code_length
- && ! (flags[exception[i].end_pc] & FLAG_INSN_START))
+ exception[i].start_pc.i);
+ if (exception[i].end_pc.i != current_method->code_length
+ && ! (flags[exception[i].end_pc.i] & FLAG_INSN_START))
verify_fail ("exception end not at instruction start",
- exception[i].end_pc);
+ exception[i].end_pc.i);
- flags[exception[i].handler_pc] |= FLAG_BRANCH_TARGET;
+ flags[exception[i].handler_pc.i] |= FLAG_BRANCH_TARGET;
}
}
@@ -2118,12 +2118,12 @@
// through them all.
for (int i = 0; i < current_method->exc_count; ++i)
{
- if (PC >= exception[i].start_pc && PC < exception[i].end_pc)
+ if (PC >= exception[i].start_pc.i && PC < exception[i].end_pc.i)
{
type handler (&java::lang::Throwable::class$);
- if (exception[i].handler_type != 0)
- handler = check_class_constant (exception[i].handler_type);
- push_exception_jump (handler, exception[i].handler_pc);
+ if (exception[i].handler_type.i != 0)
+ handler = check_class_constant (exception[i].handler_type.i);
+ push_exception_jump (handler, exception[i].handler_pc.i);
}
}
Index: include/java-interp.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/java-interp.h,v
retrieving revision 1.16
diff -u -r1.16 java-interp.h
--- include/java-interp.h 2001/11/26 06:40:05 1.16
+++ include/java-interp.h 2002/02/17 19:32:20
@@ -1,6 +1,6 @@
// java-interp.h - Header file for the bytecode interpreter. -*- c++ -*-
-/* Copyright (C) 1999, 2000, 2001 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
This file is part of libgcj.
@@ -51,12 +51,21 @@
class _Jv_InterpMethod;
class _Jv_InterpMethodInvocation;
+// Before a method is "compiled" we store values as the bytecode PC,
+// an int. Afterwards we store them as pointers into the prepared
+// code itself.
+union _Jv_InterpPC
+{
+ int i;
+ void *p;
+};
+
class _Jv_InterpException
{
- int start_pc;
- int end_pc;
- int handler_pc;
- int handler_type;
+ _Jv_InterpPC start_pc;
+ _Jv_InterpPC end_pc;
+ _Jv_InterpPC handler_pc;
+ _Jv_InterpPC handler_type;
friend class _Jv_ClassReader;
friend class _Jv_InterpMethod;
@@ -92,6 +101,8 @@
_Jv_ushort exc_count;
+ void *prepared;
+
unsigned char* bytecode ()
{
return
@@ -116,6 +127,7 @@
// return the method's invocation pointer (a stub).
void *ncode ();
void continue1 (_Jv_InterpMethodInvocation *inv);
+ void compile (const void * const *);
static void run_normal (ffi_cif*, void*, ffi_raw*, void*);
static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*);
@@ -140,7 +152,7 @@
class _Jv_InterpMethodInvocation {
_Jv_InterpMethod *running;
_Jv_word *sp;
- unsigned char *pc;
+ void *pc;
_Jv_word state[0];
_Jv_word* stack_base () { return &state[0]; }