1 // interpret.cc - Code for the interpreter
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
11 /* Author: Kresten Krab Thorup <krab@gnu.org> */
16 // Define this to get the direct-threaded interpreter. If undefined,
17 // we revert to a basic bytecode interpreter. The former is faster
18 // but uses more memory.
19 #define DIRECT_THREADED
21 #pragma implementation "java-interp.h"
24 #include <java-cpool.h>
25 #include <java-interp.h>
26 #include <java/lang/System.h>
27 #include <java/lang/String.h>
28 #include <java/lang/Integer.h>
29 #include <java/lang/Long.h>
30 #include <java/lang/StringBuffer.h>
31 #include <java/lang/Class.h>
32 #include <java/lang/reflect/Modifier.h>
33 #include <java/lang/ClassCastException.h>
34 #include <java/lang/VirtualMachineError.h>
35 #include <java/lang/InternalError.h>
36 #include <java/lang/NullPointerException.h>
37 #include <java/lang/ArithmeticException.h>
38 #include <java/lang/IncompatibleClassChangeError.h>
39 #include <java/lang/Thread.h>
40 #include <java-insns.h>
41 #include <java-signal.h>
42 #include <java/lang/ClassFormatError.h>
43 #include <execution.h>
44 #include <java/lang/reflect/Modifier.h>
48 // Execution engine for interpreted code.
49 _Jv_InterpreterEngine _Jv_soleInterpreterEngine
;
55 static void throw_internal_error (char *msg
)
56 __attribute__ ((__noreturn__
));
57 static void throw_incompatible_class_change_error (jstring msg
)
58 __attribute__ ((__noreturn__
));
60 static void throw_null_pointer_exception ()
61 __attribute__ ((__noreturn__
));
64 static void throw_class_format_error (jstring msg
)
65 __attribute__ ((__noreturn__
));
66 static void throw_class_format_error (char *msg
)
67 __attribute__ ((__noreturn__
));
69 #ifdef DIRECT_THREADED
70 // Lock to ensure that methods are not compiled concurrently.
71 // We could use a finer-grained lock here, however it is not safe to use
72 // the Class monitor as user code in another thread could hold it.
73 static _Jv_Mutex_t compile_mutex
;
78 _Jv_MutexInit (&compile_mutex
);
81 void _Jv_InitInterpreter() {}
84 extern "C" double __ieee754_fmod (double,double);
86 // This represents a single slot in the "compiled" form of the
92 // An integer value used by an instruction.
94 // A pointer value used by an instruction.
98 // The type of the PC depends on whether we're doing direct threading
99 // or a more ordinary bytecode interpreter.
100 #ifdef DIRECT_THREADED
101 typedef insn_slot
*pc_t
;
103 typedef unsigned char *pc_t
;
106 static inline void dupx (_Jv_word
*sp
, int n
, int x
)
108 // first "slide" n+x elements n to the right
110 for (int i
= 0; i
< n
+x
; i
++)
112 sp
[(top
-i
)] = sp
[(top
-i
)-n
];
115 // next, copy the n top elements, n+x down
116 for (int i
= 0; i
< n
; i
++)
118 sp
[top
-(n
+x
)-i
] = sp
[top
-i
];
123 // Used to convert from floating types to integral types.
124 template<typename TO
, typename FROM
>
126 convert (FROM val
, TO min
, TO max
)
129 if (val
>= (FROM
) max
)
131 else if (val
<= (FROM
) min
)
140 #define PUSHA(V) (sp++)->o = (V)
141 #define PUSHI(V) (sp++)->i = (V)
142 #define PUSHF(V) (sp++)->f = (V)
143 #if SIZEOF_VOID_P == 8
144 # define PUSHL(V) (sp->l = (V), sp += 2)
145 # define PUSHD(V) (sp->d = (V), sp += 2)
147 # define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \
148 (sp++)->ia[0] = w2.ia[0]; \
149 (sp++)->ia[0] = w2.ia[1]; } while (0)
150 # define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \
151 (sp++)->ia[0] = w2.ia[0]; \
152 (sp++)->ia[0] = w2.ia[1]; } while (0)
155 #define POPA() ((--sp)->o)
156 #define POPI() ((jint) (--sp)->i) // cast since it may be promoted
157 #define POPF() ((jfloat) (--sp)->f)
158 #if SIZEOF_VOID_P == 8
159 # define POPL() (sp -= 2, (jlong) sp->l)
160 # define POPD() (sp -= 2, (jdouble) sp->d)
162 # define POPL() ({ _Jv_word2 w2; \
163 w2.ia[1] = (--sp)->ia[0]; \
164 w2.ia[0] = (--sp)->ia[0]; w2.l; })
165 # define POPD() ({ _Jv_word2 w2; \
166 w2.ia[1] = (--sp)->ia[0]; \
167 w2.ia[0] = (--sp)->ia[0]; w2.d; })
170 #define LOADA(I) (sp++)->o = locals[I].o
171 #define LOADI(I) (sp++)->i = locals[I].i
172 #define LOADF(I) (sp++)->f = locals[I].f
173 #if SIZEOF_VOID_P == 8
174 # define LOADL(I) (sp->l = locals[I].l, sp += 2)
175 # define LOADD(I) (sp->d = locals[I].d, sp += 2)
177 # define LOADL(I) do { jint __idx = (I); \
178 (sp++)->ia[0] = locals[__idx].ia[0]; \
179 (sp++)->ia[0] = locals[__idx+1].ia[0]; \
181 # define LOADD(I) LOADL(I)
184 #define STOREA(I) locals[I].o = (--sp)->o
185 #define STOREI(I) locals[I].i = (--sp)->i
186 #define STOREF(I) locals[I].f = (--sp)->f
187 #if SIZEOF_VOID_P == 8
188 # define STOREL(I) (sp -= 2, locals[I].l = sp->l)
189 # define STORED(I) (sp -= 2, locals[I].d = sp->d)
191 # define STOREL(I) do { jint __idx = (I); \
192 locals[__idx+1].ia[0] = (--sp)->ia[0]; \
193 locals[__idx].ia[0] = (--sp)->ia[0]; \
195 # define STORED(I) STOREL(I)
198 #define PEEKI(I) (locals+(I))->i
199 #define PEEKA(I) (locals+(I))->o
201 #define POKEI(I,V) ((locals+(I))->i = (V))
204 #define BINOPI(OP) { \
205 jint value2 = POPI(); \
206 jint value1 = POPI(); \
207 PUSHI(value1 OP value2); \
210 #define BINOPF(OP) { \
211 jfloat value2 = POPF(); \
212 jfloat value1 = POPF(); \
213 PUSHF(value1 OP value2); \
216 #define BINOPL(OP) { \
217 jlong value2 = POPL(); \
218 jlong value1 = POPL(); \
219 PUSHL(value1 OP value2); \
222 #define BINOPD(OP) { \
223 jdouble value2 = POPD(); \
224 jdouble value1 = POPD(); \
225 PUSHD(value1 OP value2); \
228 static inline jint
get1s(unsigned char* loc
) {
229 return *(signed char*)loc
;
232 static inline jint
get1u(unsigned char* loc
) {
236 static inline jint
get2s(unsigned char* loc
) {
237 return (((jint
)*(signed char*)loc
) << 8) | ((jint
)*(loc
+1));
240 static inline jint
get2u(unsigned char* loc
) {
241 return (((jint
)(*loc
)) << 8) | ((jint
)*(loc
+1));
244 static jint
get4(unsigned char* loc
) {
245 return (((jint
)(loc
[0])) << 24)
246 | (((jint
)(loc
[1])) << 16)
247 | (((jint
)(loc
[2])) << 8)
248 | (((jint
)(loc
[3])) << 0);
254 #define NULLARRAYCHECK(X)
256 #define NULLCHECK(X) \
257 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
258 #define NULLARRAYCHECK(X) \
259 do { if ((X)==NULL) { throw_null_pointer_exception (); } } while (0)
262 #define ARRAYBOUNDSCHECK(array, index) \
265 if (((unsigned) index) >= (unsigned) (array->length)) \
266 _Jv_ThrowBadArrayIndex (index); \
271 _Jv_InterpMethod::run_normal (ffi_cif
*,
276 _Jv_InterpMethod
*_this
= (_Jv_InterpMethod
*) __this
;
277 _this
->run (ret
, args
);
281 _Jv_InterpMethod::run_synch_object (ffi_cif
*,
286 _Jv_InterpMethod
*_this
= (_Jv_InterpMethod
*) __this
;
288 jobject rcv
= (jobject
) args
[0].ptr
;
289 JvSynchronize
mutex (rcv
);
291 _this
->run (ret
, args
);
295 _Jv_InterpMethod::run_class (ffi_cif
*,
300 _Jv_InterpMethod
*_this
= (_Jv_InterpMethod
*) __this
;
301 _Jv_InitClass (_this
->defining_class
);
302 _this
->run (ret
, args
);
306 _Jv_InterpMethod::run_synch_class (ffi_cif
*,
311 _Jv_InterpMethod
*_this
= (_Jv_InterpMethod
*) __this
;
313 jclass sync
= _this
->defining_class
;
314 _Jv_InitClass (sync
);
315 JvSynchronize
mutex (sync
);
317 _this
->run (ret
, args
);
320 #ifdef DIRECT_THREADED
321 // "Compile" a method by turning it from bytecode to direct-threaded
324 _Jv_InterpMethod::compile (const void * const *insn_targets
)
326 insn_slot
*insns
= NULL
;
328 unsigned char *codestart
= bytecode ();
329 unsigned char *end
= codestart
+ code_length
;
330 _Jv_word
*pool_data
= defining_class
->constants
.data
;
332 #define SET_ONE(Field, Value) \
338 insns[next++].Field = Value; \
342 #define SET_INSN(Value) SET_ONE (insn, (void *) Value)
343 #define SET_INT(Value) SET_ONE (int_val, Value)
344 #define SET_DATUM(Value) SET_ONE (datum, Value)
346 // Map from bytecode PC to slot in INSNS.
347 int *pc_mapping
= (int *) __builtin_alloca (sizeof (int) * code_length
);
348 for (int i
= 0; i
< code_length
; ++i
)
351 for (int i
= 0; i
< 2; ++i
)
353 jboolean first_pass
= i
== 0;
357 insns
= (insn_slot
*) _Jv_AllocBytes (sizeof (insn_slot
) * next
);
361 unsigned char *pc
= codestart
;
364 int base_pc_val
= pc
- codestart
;
366 pc_mapping
[base_pc_val
] = next
;
368 java_opcode opcode
= (java_opcode
) *pc
++;
370 if (opcode
== op_nop
)
372 SET_INSN (insn_targets
[opcode
]);
513 case op_monitorenter
:
523 // No argument, nothing else to do.
527 SET_INT (get1s (pc
));
533 int index
= get1u (pc
);
535 SET_DATUM (pool_data
[index
].o
);
551 SET_INT (get1u (pc
));
556 SET_INT (get1u (pc
));
557 SET_INT (get1s (pc
+ 1));
563 int index
= get2u (pc
);
565 SET_DATUM (pool_data
[index
].o
);
571 int index
= get2u (pc
);
573 SET_DATUM (&pool_data
[index
]);
578 SET_INT (get2s (pc
));
590 case op_invokespecial
:
591 case op_invokestatic
:
592 case op_invokevirtual
:
593 SET_INT (get2u (pc
));
597 case op_multianewarray
:
598 SET_INT (get2u (pc
));
599 SET_INT (get1u (pc
+ 2));
622 int offset
= get2s (pc
);
625 int new_pc
= base_pc_val
+ offset
;
627 bool orig_was_goto
= opcode
== op_goto
;
629 // Thread jumps. We limit the loop count; this lets
630 // us avoid infinite loops if the bytecode contains
631 // such. `10' is arbitrary.
633 while (codestart
[new_pc
] == op_goto
&& count
-- > 0)
634 new_pc
+= get2s (&codestart
[new_pc
+ 1]);
636 // If the jump takes us to a `return' instruction and
637 // the original branch was an unconditional goto, then
638 // we hoist the return.
639 opcode
= (java_opcode
) codestart
[new_pc
];
641 && (opcode
== op_ireturn
|| opcode
== op_lreturn
642 || opcode
== op_freturn
|| opcode
== op_dreturn
643 || opcode
== op_areturn
|| opcode
== op_return
))
646 SET_INSN (insn_targets
[opcode
]);
649 SET_DATUM (&insns
[pc_mapping
[new_pc
]]);
655 while ((pc
- codestart
) % 4 != 0)
658 jint def
= get4 (pc
);
659 SET_DATUM (&insns
[pc_mapping
[base_pc_val
+ def
]]);
665 int high
= get4 (pc
);
669 for (int i
= low
; i
<= high
; ++i
)
671 SET_DATUM (&insns
[pc_mapping
[base_pc_val
+ get4 (pc
)]]);
677 case op_lookupswitch
:
679 while ((pc
- codestart
) % 4 != 0)
682 jint def
= get4 (pc
);
683 SET_DATUM (&insns
[pc_mapping
[base_pc_val
+ def
]]);
686 jint npairs
= get4 (pc
);
692 jint match
= get4 (pc
);
693 jint offset
= get4 (pc
+ 4);
695 SET_DATUM (&insns
[pc_mapping
[base_pc_val
+ offset
]]);
701 case op_invokeinterface
:
703 jint index
= get2u (pc
);
705 // We ignore the next two bytes.
713 opcode
= (java_opcode
) get1u (pc
);
715 jint val
= get2u (pc
);
718 // We implement narrow and wide instructions using the
719 // same code in the interpreter. So we rewrite the
720 // instruction slot here.
722 insns
[next
- 1].insn
= (void *) insn_targets
[opcode
];
725 if (opcode
== op_iinc
)
727 SET_INT (get2s (pc
));
736 jint offset
= get4 (pc
);
738 SET_DATUM (&insns
[pc_mapping
[base_pc_val
+ offset
]]);
742 // Some "can't happen" cases that we include for
743 // error-checking purposes.
761 case op_getstatic_2s
:
762 case op_getstatic_2u
:
773 // Now update exceptions.
774 _Jv_InterpException
*exc
= exceptions ();
775 for (int i
= 0; i
< exc_count
; ++i
)
777 exc
[i
].start_pc
.p
= &insns
[pc_mapping
[exc
[i
].start_pc
.i
]];
778 exc
[i
].end_pc
.p
= &insns
[pc_mapping
[exc
[i
].end_pc
.i
]];
779 exc
[i
].handler_pc
.p
= &insns
[pc_mapping
[exc
[i
].handler_pc
.i
]];
781 = (_Jv_Linker::resolve_pool_entry (defining_class
,
782 exc
[i
].handler_type
.i
)).clazz
;
783 exc
[i
].handler_type
.p
= handler
;
788 #endif /* DIRECT_THREADED */
790 // These exist so that the stack-tracing code can find the boundaries
791 // of the interpreter.
792 void *_Jv_StartOfInterpreter
;
793 void *_Jv_EndOfInterpreter
;
794 extern "C" void *_Unwind_FindEnclosingFunction (void *pc
);
797 _Jv_InterpMethod::run (void *retp
, ffi_raw
*args
)
799 using namespace java::lang::reflect
;
801 // Record the address of the start of this member function in
802 // _Jv_StartOfInterpreter. Such a write to a global variable
803 // without acquiring a lock is correct iff reads and writes of words
804 // in memory are atomic, but Java requires that anyway.
806 if (_Jv_StartOfInterpreter
== NULL
)
807 _Jv_StartOfInterpreter
= _Unwind_FindEnclosingFunction (&&foo
);
809 // FRAME_DESC registers this particular invocation as the top-most
810 // interpreter frame. This lets the stack tracing code (for
811 // Throwable) print information about the method being interpreted
812 // rather than about the interpreter itself. FRAME_DESC has a
813 // destructor so it cleans up automatically when the interpreter
815 java::lang::Thread
*thread
= java::lang::Thread::currentThread();
816 _Jv_MethodChain
frame_desc (this,
817 (_Jv_MethodChain
**) &thread
->interp_frame
);
819 _Jv_word stack
[max_stack
];
820 _Jv_word
*sp
= stack
;
822 _Jv_word locals
[max_locals
];
824 /* Go straight at it! the ffi raw format matches the internal
825 stack representation exactly. At least, that's the idea.
827 memcpy ((void*) locals
, (void*) args
, args_raw_size
);
829 _Jv_word
*pool_data
= defining_class
->constants
.data
;
831 /* These three are temporaries for common code used by several
834 _Jv_ResolvedMethod
* rmeth
;
837 #define INSN_LABEL(op) &&insn_##op
839 static const void *const insn_target
[] =
842 INSN_LABEL(aconst_null
),
843 INSN_LABEL(iconst_m1
),
844 INSN_LABEL(iconst_0
),
845 INSN_LABEL(iconst_1
),
846 INSN_LABEL(iconst_2
),
847 INSN_LABEL(iconst_3
),
848 INSN_LABEL(iconst_4
),
849 INSN_LABEL(iconst_5
),
850 INSN_LABEL(lconst_0
),
851 INSN_LABEL(lconst_1
),
852 INSN_LABEL(fconst_0
),
853 INSN_LABEL(fconst_1
),
854 INSN_LABEL(fconst_2
),
855 INSN_LABEL(dconst_0
),
856 INSN_LABEL(dconst_1
),
900 INSN_LABEL(istore_0
),
901 INSN_LABEL(istore_1
),
902 INSN_LABEL(istore_2
),
903 INSN_LABEL(istore_3
),
904 INSN_LABEL(lstore_0
),
905 INSN_LABEL(lstore_1
),
906 INSN_LABEL(lstore_2
),
907 INSN_LABEL(lstore_3
),
908 INSN_LABEL(fstore_0
),
909 INSN_LABEL(fstore_1
),
910 INSN_LABEL(fstore_2
),
911 INSN_LABEL(fstore_3
),
912 INSN_LABEL(dstore_0
),
913 INSN_LABEL(dstore_1
),
914 INSN_LABEL(dstore_2
),
915 INSN_LABEL(dstore_3
),
916 INSN_LABEL(astore_0
),
917 INSN_LABEL(astore_1
),
918 INSN_LABEL(astore_2
),
919 INSN_LABEL(astore_3
),
1000 INSN_LABEL(if_icmpeq
),
1001 INSN_LABEL(if_icmpne
),
1002 INSN_LABEL(if_icmplt
),
1003 INSN_LABEL(if_icmpge
),
1004 INSN_LABEL(if_icmpgt
),
1005 INSN_LABEL(if_icmple
),
1006 INSN_LABEL(if_acmpeq
),
1007 INSN_LABEL(if_acmpne
),
1011 INSN_LABEL(tableswitch
),
1012 INSN_LABEL(lookupswitch
),
1013 INSN_LABEL(ireturn
),
1014 INSN_LABEL(lreturn
),
1015 INSN_LABEL(freturn
),
1016 INSN_LABEL(dreturn
),
1017 INSN_LABEL(areturn
),
1019 INSN_LABEL(getstatic
),
1020 INSN_LABEL(putstatic
),
1021 INSN_LABEL(getfield
),
1022 INSN_LABEL(putfield
),
1023 INSN_LABEL(invokevirtual
),
1024 INSN_LABEL(invokespecial
),
1025 INSN_LABEL(invokestatic
),
1026 INSN_LABEL(invokeinterface
),
1029 INSN_LABEL(newarray
),
1030 INSN_LABEL(anewarray
),
1031 INSN_LABEL(arraylength
),
1033 INSN_LABEL(checkcast
),
1034 INSN_LABEL(instanceof
),
1035 INSN_LABEL(monitorenter
),
1036 INSN_LABEL(monitorexit
),
1037 #ifdef DIRECT_THREADED
1042 INSN_LABEL(multianewarray
),
1044 INSN_LABEL(ifnonnull
),
1052 #ifdef DIRECT_THREADED
1054 #define NEXT_INSN goto *((pc++)->insn)
1055 #define INTVAL() ((pc++)->int_val)
1056 #define AVAL() ((pc++)->datum)
1058 #define GET1S() INTVAL ()
1059 #define GET2S() INTVAL ()
1060 #define GET1U() INTVAL ()
1061 #define GET2U() INTVAL ()
1062 #define AVAL1U() AVAL ()
1063 #define AVAL2U() AVAL ()
1064 #define AVAL2UP() AVAL ()
1065 #define SKIP_GOTO ++pc
1066 #define GOTO_VAL() (insn_slot *) pc->datum
1067 #define PCVAL(unionval) unionval.p
1068 #define AMPAMP(label) &&label
1070 // Compile if we must. NOTE: Double-check locking.
1071 if (prepared
== NULL
)
1073 _Jv_MutexLock (&compile_mutex
);
1074 if (prepared
== NULL
)
1075 compile (insn_target
);
1076 _Jv_MutexUnlock (&compile_mutex
);
1078 pc
= (insn_slot
*) prepared
;
1082 #define NEXT_INSN goto *(insn_target[*pc++])
1084 #define GET1S() get1s (pc++)
1085 #define GET2S() (pc += 2, get2s (pc- 2))
1086 #define GET1U() get1u (pc++)
1087 #define GET2U() (pc += 2, get2u (pc - 2))
1088 #define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; })
1089 #define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; })
1090 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
1091 #define SKIP_GOTO pc += 2
1092 #define GOTO_VAL() pc - 1 + get2s (pc)
1093 #define PCVAL(unionval) unionval.i
1094 #define AMPAMP(label) NULL
1098 #endif /* DIRECT_THREADED */
1100 #define TAKE_GOTO pc = GOTO_VAL ()
1104 // We keep nop around. It is used if we're interpreting the
1105 // bytecodes and not doing direct threading.
1109 /* The first few instructions here are ordered according to their
1110 frequency, in the hope that this will improve code locality a
1113 insn_aload_0
: // 0x2a
1121 insn_iload_1
: // 0x1b
1125 insn_invokevirtual
: // 0xb6
1127 int index
= GET2U ();
1129 /* _Jv_Linker::resolve_pool_entry returns immediately if the
1130 * value already is resolved. If we want to clutter up the
1131 * code here to gain a little performance, then we can check
1132 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
1133 * directly. For now, I don't think it is worth it. */
1135 rmeth
= (_Jv_Linker::resolve_pool_entry (defining_class
,
1138 sp
-= rmeth
->stack_item_count
;
1139 // We don't use NULLCHECK here because we can't rely on that
1140 // working if the method is final. So instead we do an
1143 throw new java::lang::NullPointerException
;
1145 if (rmeth
->vtable_index
== -1)
1147 // final methods do not appear in the vtable,
1148 // if it does not appear in the superclass.
1149 fun
= (void (*)()) rmeth
->method
->ncode
;
1153 jobject rcv
= sp
[0].o
;
1154 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
1155 fun
= (void (*)()) table
->get_method (rmeth
->vtable_index
);
1158 #ifdef DIRECT_THREADED
1159 // Rewrite instruction so that we use a faster pre-resolved
1161 pc
[-2].insn
= &&invokevirtual_resolved
;
1162 pc
[-1].datum
= rmeth
;
1163 #endif /* DIRECT_THREADED */
1165 goto perform_invoke
;
1167 #ifdef DIRECT_THREADED
1168 invokevirtual_resolved
:
1170 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
1171 sp
-= rmeth
->stack_item_count
;
1172 // We don't use NULLCHECK here because we can't rely on that
1173 // working if the method is final. So instead we do an
1176 throw new java::lang::NullPointerException
;
1178 if (rmeth
->vtable_index
== -1)
1180 // final methods do not appear in the vtable,
1181 // if it does not appear in the superclass.
1182 fun
= (void (*)()) rmeth
->method
->ncode
;
1186 jobject rcv
= sp
[0].o
;
1187 _Jv_VTable
*table
= *(_Jv_VTable
**) rcv
;
1188 fun
= (void (*)()) table
->get_method (rmeth
->vtable_index
);
1191 goto perform_invoke
;
1192 #endif /* DIRECT_THREADED */
1196 /* here goes the magic again... */
1197 ffi_cif
*cif
= &rmeth
->cif
;
1198 ffi_raw
*raw
= (ffi_raw
*) sp
;
1202 #if FFI_NATIVE_RAW_API
1203 /* We assume that this is only implemented if it's correct */
1204 /* to use it here. On a 64 bit machine, it never is. */
1205 ffi_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
1207 ffi_java_raw_call (cif
, fun
, (void*)&rvalue
, raw
);
1210 int rtype
= cif
->rtype
->type
;
1212 /* the likelyhood of object, int, or void return is very high,
1213 * so those are checked before the switch */
1214 if (rtype
== FFI_TYPE_POINTER
)
1216 PUSHA (rvalue
.object_value
);
1218 else if (rtype
== FFI_TYPE_SINT32
)
1220 PUSHI (rvalue
.int_value
);
1222 else if (rtype
== FFI_TYPE_VOID
)
1230 case FFI_TYPE_SINT8
:
1231 PUSHI ((jbyte
)(rvalue
.int_value
& 0xff));
1234 case FFI_TYPE_SINT16
:
1235 PUSHI ((jshort
)(rvalue
.int_value
& 0xffff));
1238 case FFI_TYPE_UINT16
:
1239 PUSHI (rvalue
.int_value
& 0xffff);
1242 case FFI_TYPE_FLOAT
:
1243 PUSHF (rvalue
.float_value
);
1246 case FFI_TYPE_DOUBLE
:
1247 PUSHD (rvalue
.double_value
);
1250 case FFI_TYPE_SINT64
:
1251 PUSHL (rvalue
.long_value
);
1255 throw_internal_error ("unknown return type in invokeXXX");
1322 // For direct threaded, bipush and sipush are the same.
1323 #ifndef DIRECT_THREADED
1326 #endif /* DIRECT_THREADED */
1332 // For direct threaded, ldc and ldc_w are the same.
1333 #ifndef DIRECT_THREADED
1334 PUSHA ((jobject
) AVAL1U ());
1336 #endif /* DIRECT_THREADED */
1338 PUSHA ((jobject
) AVAL2U ());
1343 void *where
= AVAL2UP ();
1344 memcpy (sp
, where
, 2*sizeof (_Jv_word
));
1439 jint index
= POPI();
1440 jintArray arr
= (jintArray
) POPA();
1441 NULLARRAYCHECK (arr
);
1442 ARRAYBOUNDSCHECK (arr
, index
);
1443 PUSHI( elements(arr
)[index
] );
1449 jint index
= POPI();
1450 jlongArray arr
= (jlongArray
) POPA();
1451 NULLARRAYCHECK (arr
);
1452 ARRAYBOUNDSCHECK (arr
, index
);
1453 PUSHL( elements(arr
)[index
] );
1459 jint index
= POPI();
1460 jfloatArray arr
= (jfloatArray
) POPA();
1461 NULLARRAYCHECK (arr
);
1462 ARRAYBOUNDSCHECK (arr
, index
);
1463 PUSHF( elements(arr
)[index
] );
1469 jint index
= POPI();
1470 jdoubleArray arr
= (jdoubleArray
) POPA();
1471 NULLARRAYCHECK (arr
);
1472 ARRAYBOUNDSCHECK (arr
, index
);
1473 PUSHD( elements(arr
)[index
] );
1479 jint index
= POPI();
1480 jobjectArray arr
= (jobjectArray
) POPA();
1481 NULLARRAYCHECK (arr
);
1482 ARRAYBOUNDSCHECK (arr
, index
);
1483 PUSHA( elements(arr
)[index
] );
1489 jint index
= POPI();
1490 jbyteArray arr
= (jbyteArray
) POPA();
1491 NULLARRAYCHECK (arr
);
1492 ARRAYBOUNDSCHECK (arr
, index
);
1493 PUSHI( elements(arr
)[index
] );
1499 jint index
= POPI();
1500 jcharArray arr
= (jcharArray
) POPA();
1501 NULLARRAYCHECK (arr
);
1502 ARRAYBOUNDSCHECK (arr
, index
);
1503 PUSHI( elements(arr
)[index
] );
1509 jint index
= POPI();
1510 jshortArray arr
= (jshortArray
) POPA();
1511 NULLARRAYCHECK (arr
);
1512 ARRAYBOUNDSCHECK (arr
, index
);
1513 PUSHI( elements(arr
)[index
] );
1619 jint value
= POPI();
1620 jint index
= POPI();
1621 jintArray arr
= (jintArray
) POPA();
1622 NULLARRAYCHECK (arr
);
1623 ARRAYBOUNDSCHECK (arr
, index
);
1624 elements(arr
)[index
] = value
;
1630 jlong value
= POPL();
1631 jint index
= POPI();
1632 jlongArray arr
= (jlongArray
) POPA();
1633 NULLARRAYCHECK (arr
);
1634 ARRAYBOUNDSCHECK (arr
, index
);
1635 elements(arr
)[index
] = value
;
1641 jfloat value
= POPF();
1642 jint index
= POPI();
1643 jfloatArray arr
= (jfloatArray
) POPA();
1644 NULLARRAYCHECK (arr
);
1645 ARRAYBOUNDSCHECK (arr
, index
);
1646 elements(arr
)[index
] = value
;
1652 jdouble value
= POPD();
1653 jint index
= POPI();
1654 jdoubleArray arr
= (jdoubleArray
) POPA();
1655 NULLARRAYCHECK (arr
);
1656 ARRAYBOUNDSCHECK (arr
, index
);
1657 elements(arr
)[index
] = value
;
1663 jobject value
= POPA();
1664 jint index
= POPI();
1665 jobjectArray arr
= (jobjectArray
) POPA();
1666 NULLARRAYCHECK (arr
);
1667 ARRAYBOUNDSCHECK (arr
, index
);
1668 _Jv_CheckArrayStore (arr
, value
);
1669 elements(arr
)[index
] = value
;
1675 jbyte value
= (jbyte
) POPI();
1676 jint index
= POPI();
1677 jbyteArray arr
= (jbyteArray
) POPA();
1678 NULLARRAYCHECK (arr
);
1679 ARRAYBOUNDSCHECK (arr
, index
);
1680 elements(arr
)[index
] = value
;
1686 jchar value
= (jchar
) POPI();
1687 jint index
= POPI();
1688 jcharArray arr
= (jcharArray
) POPA();
1689 NULLARRAYCHECK (arr
);
1690 ARRAYBOUNDSCHECK (arr
, index
);
1691 elements(arr
)[index
] = value
;
1697 jshort value
= (jshort
) POPI();
1698 jint index
= POPI();
1699 jshortArray arr
= (jshortArray
) POPA();
1700 NULLARRAYCHECK (arr
);
1701 ARRAYBOUNDSCHECK (arr
, index
);
1702 elements(arr
)[index
] = value
;
1720 dupx (sp
, 1, 1); sp
+=1;
1724 dupx (sp
, 1, 2); sp
+=1;
1734 dupx (sp
, 2, 1); sp
+=2;
1738 dupx (sp
, 2, 2); sp
+=2;
1743 jobject tmp1
= POPA();
1744 jobject tmp2
= POPA();
1800 jint value2
= POPI();
1801 jint value1
= POPI();
1802 jint res
= _Jv_divI (value1
, value2
);
1809 jlong value2
= POPL();
1810 jlong value1
= POPL();
1811 jlong res
= _Jv_divJ (value1
, value2
);
1818 jfloat value2
= POPF();
1819 jfloat value1
= POPF();
1820 jfloat res
= value1
/ value2
;
1827 jdouble value2
= POPD();
1828 jdouble value1
= POPD();
1829 jdouble res
= value1
/ value2
;
1836 jint value2
= POPI();
1837 jint value1
= POPI();
1838 jint res
= _Jv_remI (value1
, value2
);
1845 jlong value2
= POPL();
1846 jlong value1
= POPL();
1847 jlong res
= _Jv_remJ (value1
, value2
);
1854 jfloat value2
= POPF();
1855 jfloat value1
= POPF();
1856 jfloat res
= __ieee754_fmod (value1
, value2
);
1863 jdouble value2
= POPD();
1864 jdouble value1
= POPD();
1865 jdouble res
= __ieee754_fmod (value1
, value2
);
1872 jint value
= POPI();
1879 jlong value
= POPL();
1886 jfloat value
= POPF();
1893 jdouble value
= POPD();
1900 jint shift
= (POPI() & 0x1f);
1901 jint value
= POPI();
1902 PUSHI (value
<< shift
);
1908 jint shift
= (POPI() & 0x3f);
1909 jlong value
= POPL();
1910 PUSHL (value
<< shift
);
1916 jint shift
= (POPI() & 0x1f);
1917 jint value
= POPI();
1918 PUSHI (value
>> shift
);
1924 jint shift
= (POPI() & 0x3f);
1925 jlong value
= POPL();
1926 PUSHL (value
>> shift
);
1932 jint shift
= (POPI() & 0x1f);
1933 _Jv_uint value
= (_Jv_uint
) POPI();
1934 PUSHI ((jint
) (value
>> shift
));
1940 jint shift
= (POPI() & 0x3f);
1941 _Jv_ulong value
= (_Jv_ulong
) POPL();
1942 PUSHL ((jlong
) (value
>> shift
));
1972 jint index
= GET1U ();
1973 jint amount
= GET1S ();
1974 locals
[index
].i
+= amount
;
1979 {jlong value
= POPI(); PUSHL (value
);}
1983 {jfloat value
= POPI(); PUSHF (value
);}
1987 {jdouble value
= POPI(); PUSHD (value
);}
1991 {jint value
= POPL(); PUSHI (value
);}
1995 {jfloat value
= POPL(); PUSHF (value
);}
1999 {jdouble value
= POPL(); PUSHD (value
);}
2004 using namespace java::lang
;
2005 jint value
= convert (POPF (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
2012 using namespace java::lang
;
2013 jlong value
= convert (POPF (), Long::MIN_VALUE
, Long::MAX_VALUE
);
2019 { jdouble value
= POPF (); PUSHD(value
); }
2024 using namespace java::lang
;
2025 jint value
= convert (POPD (), Integer::MIN_VALUE
, Integer::MAX_VALUE
);
2032 using namespace java::lang
;
2033 jlong value
= convert (POPD (), Long::MIN_VALUE
, Long::MAX_VALUE
);
2039 { jfloat value
= POPD (); PUSHF(value
); }
2043 { jbyte value
= POPI (); PUSHI(value
); }
2047 { jchar value
= POPI (); PUSHI(value
); }
2051 { jshort value
= POPI (); PUSHI(value
); }
2056 jlong value2
= POPL ();
2057 jlong value1
= POPL ();
2058 if (value1
> value2
)
2060 else if (value1
== value2
)
2076 jfloat value2
= POPF ();
2077 jfloat value1
= POPF ();
2078 if (value1
> value2
)
2080 else if (value1
== value2
)
2082 else if (value1
< value2
)
2098 jdouble value2
= POPD ();
2099 jdouble value1
= POPD ();
2100 if (value1
> value2
)
2102 else if (value1
== value2
)
2104 else if (value1
< value2
)
2167 jint value2
= POPI();
2168 jint value1
= POPI();
2169 if (value1
== value2
)
2178 jint value2
= POPI();
2179 jint value1
= POPI();
2180 if (value1
!= value2
)
2189 jint value2
= POPI();
2190 jint value1
= POPI();
2191 if (value1
< value2
)
2200 jint value2
= POPI();
2201 jint value1
= POPI();
2202 if (value1
>= value2
)
2211 jint value2
= POPI();
2212 jint value1
= POPI();
2213 if (value1
> value2
)
2222 jint value2
= POPI();
2223 jint value1
= POPI();
2224 if (value1
<= value2
)
2233 jobject value2
= POPA();
2234 jobject value1
= POPA();
2235 if (value1
== value2
)
2244 jobject value2
= POPA();
2245 jobject value1
= POPA();
2246 if (value1
!= value2
)
2254 #ifndef DIRECT_THREADED
2255 // For direct threaded, goto and goto_w are the same.
2256 pc
= pc
- 1 + get4 (pc
);
2258 #endif /* DIRECT_THREADED */
2264 #ifndef DIRECT_THREADED
2265 // For direct threaded, jsr and jsr_w are the same.
2267 pc_t next
= pc
- 1 + get4 (pc
);
2269 PUSHA ((jobject
) pc
);
2273 #endif /* DIRECT_THREADED */
2276 pc_t next
= GOTO_VAL();
2278 PUSHA ((jobject
) pc
);
2285 jint index
= GET1U ();
2286 pc
= (pc_t
) PEEKA (index
);
2292 #ifdef DIRECT_THREADED
2293 void *def
= (pc
++)->datum
;
2297 jint low
= INTVAL ();
2298 jint high
= INTVAL ();
2300 if (index
< low
|| index
> high
)
2301 pc
= (insn_slot
*) def
;
2303 pc
= (insn_slot
*) ((pc
+ index
- low
)->datum
);
2305 pc_t base_pc
= pc
- 1;
2306 int index
= POPI ();
2308 pc_t base
= (pc_t
) bytecode ();
2309 while ((pc
- base
) % 4 != 0)
2312 jint def
= get4 (pc
);
2313 jint low
= get4 (pc
+ 4);
2314 jint high
= get4 (pc
+ 8);
2315 if (index
< low
|| index
> high
)
2318 pc
= base_pc
+ get4 (pc
+ 4 * (index
- low
+ 3));
2319 #endif /* DIRECT_THREADED */
2325 #ifdef DIRECT_THREADED
2326 void *def
= (pc
++)->insn
;
2330 jint npairs
= INTVAL ();
2332 int max
= npairs
- 1;
2335 // Simple binary search...
2338 int half
= (min
+ max
) / 2;
2339 int match
= pc
[2 * half
].int_val
;
2344 pc
= (insn_slot
*) pc
[2 * half
+ 1].datum
;
2347 else if (index
< match
)
2348 // We can use HALF - 1 here because we check again on
2352 // We can use HALF + 1 here because we check again on
2356 if (index
== pc
[2 * min
].int_val
)
2357 pc
= (insn_slot
*) pc
[2 * min
+ 1].datum
;
2359 pc
= (insn_slot
*) def
;
2361 unsigned char *base_pc
= pc
-1;
2364 unsigned char* base
= bytecode ();
2365 while ((pc
-base
) % 4 != 0)
2368 jint def
= get4 (pc
);
2369 jint npairs
= get4 (pc
+4);
2374 // Simple binary search...
2377 int half
= (min
+max
)/2;
2378 int match
= get4 (pc
+ 4*(2 + 2*half
));
2382 else if (index
< match
)
2383 // We can use HALF - 1 here because we check again on
2387 // We can use HALF + 1 here because we check again on
2392 if (index
== get4 (pc
+ 4*(2 + 2*min
)))
2393 pc
= base_pc
+ get4 (pc
+ 4*(2 + 2*min
+ 1));
2396 #endif /* DIRECT_THREADED */
2401 *(jobject
*) retp
= POPA ();
2405 *(jlong
*) retp
= POPL ();
2409 *(jfloat
*) retp
= POPF ();
2413 *(jdouble
*) retp
= POPD ();
2417 *(jint
*) retp
= POPI ();
2425 jint fieldref_index
= GET2U ();
2426 _Jv_Linker::resolve_pool_entry (defining_class
, fieldref_index
);
2427 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2429 if ((field
->flags
& Modifier::STATIC
) == 0)
2430 throw_incompatible_class_change_error
2431 (JvNewStringLatin1 ("field no longer static"));
2433 jclass type
= field
->type
;
2435 // We rewrite the instruction once we discover what it refers
2437 void *newinsn
= NULL
;
2438 if (type
->isPrimitive ())
2440 switch (type
->size_in_bytes
)
2443 PUSHI (*field
->u
.byte_addr
);
2444 newinsn
= AMPAMP (getstatic_resolved_1
);
2448 if (type
== JvPrimClass (char))
2450 PUSHI (*field
->u
.char_addr
);
2451 newinsn
= AMPAMP (getstatic_resolved_char
);
2455 PUSHI (*field
->u
.short_addr
);
2456 newinsn
= AMPAMP (getstatic_resolved_short
);
2461 PUSHI(*field
->u
.int_addr
);
2462 newinsn
= AMPAMP (getstatic_resolved_4
);
2466 PUSHL(*field
->u
.long_addr
);
2467 newinsn
= AMPAMP (getstatic_resolved_8
);
2473 PUSHA(*field
->u
.object_addr
);
2474 newinsn
= AMPAMP (getstatic_resolved_obj
);
2477 #ifdef DIRECT_THREADED
2478 pc
[-2].insn
= newinsn
;
2479 pc
[-1].datum
= field
->u
.addr
;
2480 #endif /* DIRECT_THREADED */
2484 #ifdef DIRECT_THREADED
2485 getstatic_resolved_1
:
2486 PUSHI (*(jbyte
*) AVAL ());
2489 getstatic_resolved_char
:
2490 PUSHI (*(jchar
*) AVAL ());
2493 getstatic_resolved_short
:
2494 PUSHI (*(jshort
*) AVAL ());
2497 getstatic_resolved_4
:
2498 PUSHI (*(jint
*) AVAL ());
2501 getstatic_resolved_8
:
2502 PUSHL (*(jlong
*) AVAL ());
2505 getstatic_resolved_obj
:
2506 PUSHA (*(jobject
*) AVAL ());
2508 #endif /* DIRECT_THREADED */
2512 jint fieldref_index
= GET2U ();
2513 _Jv_Linker::resolve_pool_entry (defining_class
, fieldref_index
);
2514 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2516 if ((field
->flags
& Modifier::STATIC
) != 0)
2517 throw_incompatible_class_change_error
2518 (JvNewStringLatin1 ("field is static"));
2520 jclass type
= field
->type
;
2521 jint field_offset
= field
->u
.boffset
;
2522 if (field_offset
> 0xffff)
2523 throw new java::lang::VirtualMachineError
;
2525 jobject obj
= POPA();
2528 void *newinsn
= NULL
;
2529 _Jv_value
*val
= (_Jv_value
*) ((char *)obj
+ field_offset
);
2530 if (type
->isPrimitive ())
2532 switch (type
->size_in_bytes
)
2535 PUSHI (val
->byte_value
);
2536 newinsn
= AMPAMP (getfield_resolved_1
);
2540 if (type
== JvPrimClass (char))
2542 PUSHI (val
->char_value
);
2543 newinsn
= AMPAMP (getfield_resolved_char
);
2547 PUSHI (val
->short_value
);
2548 newinsn
= AMPAMP (getfield_resolved_short
);
2553 PUSHI (val
->int_value
);
2554 newinsn
= AMPAMP (getfield_resolved_4
);
2558 PUSHL (val
->long_value
);
2559 newinsn
= AMPAMP (getfield_resolved_8
);
2565 PUSHA (val
->object_value
);
2566 newinsn
= AMPAMP (getfield_resolved_obj
);
2569 #ifdef DIRECT_THREADED
2570 pc
[-2].insn
= newinsn
;
2571 pc
[-1].int_val
= field_offset
;
2572 #endif /* DIRECT_THREADED */
2576 #ifdef DIRECT_THREADED
2577 getfield_resolved_1
:
2579 char *obj
= (char *) POPA ();
2581 PUSHI (*(jbyte
*) (obj
+ INTVAL ()));
2585 getfield_resolved_char
:
2587 char *obj
= (char *) POPA ();
2589 PUSHI (*(jchar
*) (obj
+ INTVAL ()));
2593 getfield_resolved_short
:
2595 char *obj
= (char *) POPA ();
2597 PUSHI (*(jshort
*) (obj
+ INTVAL ()));
2601 getfield_resolved_4
:
2603 char *obj
= (char *) POPA ();
2605 PUSHI (*(jint
*) (obj
+ INTVAL ()));
2609 getfield_resolved_8
:
2611 char *obj
= (char *) POPA ();
2613 PUSHL (*(jlong
*) (obj
+ INTVAL ()));
2617 getfield_resolved_obj
:
2619 char *obj
= (char *) POPA ();
2621 PUSHA (*(jobject
*) (obj
+ INTVAL ()));
2624 #endif /* DIRECT_THREADED */
2628 jint fieldref_index
= GET2U ();
2629 _Jv_Linker::resolve_pool_entry (defining_class
, fieldref_index
);
2630 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2632 jclass type
= field
->type
;
2634 // ResolvePoolEntry cannot check this
2635 if ((field
->flags
& Modifier::STATIC
) == 0)
2636 throw_incompatible_class_change_error
2637 (JvNewStringLatin1 ("field no longer static"));
2639 void *newinsn
= NULL
;
2640 if (type
->isPrimitive ())
2642 switch (type
->size_in_bytes
)
2646 jint value
= POPI();
2647 *field
->u
.byte_addr
= value
;
2648 newinsn
= AMPAMP (putstatic_resolved_1
);
2654 jint value
= POPI();
2655 *field
->u
.char_addr
= value
;
2656 newinsn
= AMPAMP (putstatic_resolved_2
);
2662 jint value
= POPI();
2663 *field
->u
.int_addr
= value
;
2664 newinsn
= AMPAMP (putstatic_resolved_4
);
2670 jlong value
= POPL();
2671 *field
->u
.long_addr
= value
;
2672 newinsn
= AMPAMP (putstatic_resolved_8
);
2679 jobject value
= POPA();
2680 *field
->u
.object_addr
= value
;
2681 newinsn
= AMPAMP (putstatic_resolved_obj
);
2684 #ifdef DIRECT_THREADED
2685 pc
[-2].insn
= newinsn
;
2686 pc
[-1].datum
= field
->u
.addr
;
2687 #endif /* DIRECT_THREADED */
2691 #ifdef DIRECT_THREADED
2692 putstatic_resolved_1
:
2693 *(jbyte
*) AVAL () = POPI ();
2696 putstatic_resolved_2
:
2697 *(jchar
*) AVAL () = POPI ();
2700 putstatic_resolved_4
:
2701 *(jint
*) AVAL () = POPI ();
2704 putstatic_resolved_8
:
2705 *(jlong
*) AVAL () = POPL ();
2708 putstatic_resolved_obj
:
2709 *(jobject
*) AVAL () = POPA ();
2711 #endif /* DIRECT_THREADED */
2715 jint fieldref_index
= GET2U ();
2716 _Jv_Linker::resolve_pool_entry (defining_class
, fieldref_index
);
2717 _Jv_Field
*field
= pool_data
[fieldref_index
].field
;
2719 jclass type
= field
->type
;
2721 if ((field
->flags
& Modifier::STATIC
) != 0)
2722 throw_incompatible_class_change_error
2723 (JvNewStringLatin1 ("field is static"));
2725 jint field_offset
= field
->u
.boffset
;
2726 if (field_offset
> 0xffff)
2727 throw new java::lang::VirtualMachineError
;
2729 void *newinsn
= NULL
;
2730 if (type
->isPrimitive ())
2732 switch (type
->size_in_bytes
)
2736 jint value
= POPI();
2737 jobject obj
= POPA();
2739 *(jbyte
*) ((char*)obj
+ field_offset
) = value
;
2740 newinsn
= AMPAMP (putfield_resolved_1
);
2746 jint value
= POPI();
2747 jobject obj
= POPA();
2749 *(jchar
*) ((char*)obj
+ field_offset
) = value
;
2750 newinsn
= AMPAMP (putfield_resolved_2
);
2756 jint value
= POPI();
2757 jobject obj
= POPA();
2759 *(jint
*) ((char*)obj
+ field_offset
) = value
;
2760 newinsn
= AMPAMP (putfield_resolved_4
);
2766 jlong value
= POPL();
2767 jobject obj
= POPA();
2769 *(jlong
*) ((char*)obj
+ field_offset
) = value
;
2770 newinsn
= AMPAMP (putfield_resolved_8
);
2777 jobject value
= POPA();
2778 jobject obj
= POPA();
2780 *(jobject
*) ((char*)obj
+ field_offset
) = value
;
2781 newinsn
= AMPAMP (putfield_resolved_obj
);
2784 #ifdef DIRECT_THREADED
2785 pc
[-2].insn
= newinsn
;
2786 pc
[-1].int_val
= field_offset
;
2787 #endif /* DIRECT_THREADED */
2791 #ifdef DIRECT_THREADED
2792 putfield_resolved_1
:
2795 char *obj
= (char *) POPA ();
2797 *(jbyte
*) (obj
+ INTVAL ()) = val
;
2801 putfield_resolved_2
:
2804 char *obj
= (char *) POPA ();
2806 *(jchar
*) (obj
+ INTVAL ()) = val
;
2810 putfield_resolved_4
:
2813 char *obj
= (char *) POPA ();
2815 *(jint
*) (obj
+ INTVAL ()) = val
;
2819 putfield_resolved_8
:
2821 jlong val
= POPL ();
2822 char *obj
= (char *) POPA ();
2824 *(jlong
*) (obj
+ INTVAL ()) = val
;
2828 putfield_resolved_obj
:
2830 jobject val
= POPA ();
2831 char *obj
= (char *) POPA ();
2833 *(jobject
*) (obj
+ INTVAL ()) = val
;
2836 #endif /* DIRECT_THREADED */
2840 int index
= GET2U ();
2842 rmeth
= (_Jv_Linker::resolve_pool_entry (defining_class
,
2845 sp
-= rmeth
->stack_item_count
;
2847 // We don't use NULLCHECK here because we can't rely on that
2848 // working for <init>. So instead we do an explicit test.
2850 throw new java::lang::NullPointerException
;
2852 fun
= (void (*)()) rmeth
->method
->ncode
;
2854 #ifdef DIRECT_THREADED
2855 // Rewrite instruction so that we use a faster pre-resolved
2857 pc
[-2].insn
= &&invokespecial_resolved
;
2858 pc
[-1].datum
= rmeth
;
2859 #endif /* DIRECT_THREADED */
2861 goto perform_invoke
;
2863 #ifdef DIRECT_THREADED
2864 invokespecial_resolved
:
2866 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2867 sp
-= rmeth
->stack_item_count
;
2868 // We don't use NULLCHECK here because we can't rely on that
2869 // working for <init>. So instead we do an explicit test.
2871 throw new java::lang::NullPointerException
;
2872 fun
= (void (*)()) rmeth
->method
->ncode
;
2874 goto perform_invoke
;
2875 #endif /* DIRECT_THREADED */
2879 int index
= GET2U ();
2881 rmeth
= (_Jv_Linker::resolve_pool_entry (defining_class
,
2884 sp
-= rmeth
->stack_item_count
;
2886 fun
= (void (*)()) rmeth
->method
->ncode
;
2888 #ifdef DIRECT_THREADED
2889 // Rewrite instruction so that we use a faster pre-resolved
2891 pc
[-2].insn
= &&invokestatic_resolved
;
2892 pc
[-1].datum
= rmeth
;
2893 #endif /* DIRECT_THREADED */
2895 goto perform_invoke
;
2897 #ifdef DIRECT_THREADED
2898 invokestatic_resolved
:
2900 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2901 sp
-= rmeth
->stack_item_count
;
2902 fun
= (void (*)()) rmeth
->method
->ncode
;
2904 goto perform_invoke
;
2905 #endif /* DIRECT_THREADED */
2907 insn_invokeinterface
:
2909 int index
= GET2U ();
2911 rmeth
= (_Jv_Linker::resolve_pool_entry (defining_class
,
2914 sp
-= rmeth
->stack_item_count
;
2916 jobject rcv
= sp
[0].o
;
2921 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2922 rmeth
->method
->name
,
2923 rmeth
->method
->signature
);
2925 #ifdef DIRECT_THREADED
2926 // Rewrite instruction so that we use a faster pre-resolved
2928 pc
[-2].insn
= &&invokeinterface_resolved
;
2929 pc
[-1].datum
= rmeth
;
2931 // Skip dummy bytes.
2933 #endif /* DIRECT_THREADED */
2935 goto perform_invoke
;
2937 #ifdef DIRECT_THREADED
2938 invokeinterface_resolved
:
2940 rmeth
= (_Jv_ResolvedMethod
*) AVAL ();
2941 sp
-= rmeth
->stack_item_count
;
2942 jobject rcv
= sp
[0].o
;
2945 _Jv_LookupInterfaceMethod (rcv
->getClass (),
2946 rmeth
->method
->name
,
2947 rmeth
->method
->signature
);
2949 goto perform_invoke
;
2950 #endif /* DIRECT_THREADED */
2954 int index
= GET2U ();
2955 jclass klass
= (_Jv_Linker::resolve_pool_entry (defining_class
,
2957 jobject res
= _Jv_AllocObject (klass
);
2960 #ifdef DIRECT_THREADED
2961 pc
[-2].insn
= &&new_resolved
;
2962 pc
[-1].datum
= klass
;
2963 #endif /* DIRECT_THREADED */
2967 #ifdef DIRECT_THREADED
2970 jclass klass
= (jclass
) AVAL ();
2971 jobject res
= _Jv_AllocObject (klass
);
2975 #endif /* DIRECT_THREADED */
2979 int atype
= GET1U ();
2981 jobject result
= _Jv_NewArray (atype
, size
);
2988 int index
= GET2U ();
2989 jclass klass
= (_Jv_Linker::resolve_pool_entry (defining_class
,
2992 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
2995 #ifdef DIRECT_THREADED
2996 pc
[-2].insn
= &&anewarray_resolved
;
2997 pc
[-1].datum
= klass
;
2998 #endif /* DIRECT_THREADED */
3002 #ifdef DIRECT_THREADED
3005 jclass klass
= (jclass
) AVAL ();
3007 jobject result
= _Jv_NewObjectArray (size
, klass
, 0);
3011 #endif /* DIRECT_THREADED */
3015 __JArray
*arr
= (__JArray
*)POPA();
3016 NULLARRAYCHECK (arr
);
3017 PUSHI (arr
->length
);
3023 jobject value
= POPA();
3024 throw static_cast<jthrowable
>(value
);
3030 jobject value
= POPA();
3031 jint index
= GET2U ();
3032 jclass to
= (_Jv_Linker::resolve_pool_entry (defining_class
,
3035 if (value
!= NULL
&& ! to
->isInstance (value
))
3036 throw new java::lang::ClassCastException (to
->getName());
3040 #ifdef DIRECT_THREADED
3041 pc
[-2].insn
= &&checkcast_resolved
;
3043 #endif /* DIRECT_THREADED */
3047 #ifdef DIRECT_THREADED
3050 jobject value
= POPA ();
3051 jclass to
= (jclass
) AVAL ();
3052 if (value
!= NULL
&& ! to
->isInstance (value
))
3053 throw new java::lang::ClassCastException (to
->getName());
3057 #endif /* DIRECT_THREADED */
3061 jobject value
= POPA();
3062 jint index
= GET2U ();
3063 jclass to
= (_Jv_Linker::resolve_pool_entry (defining_class
,
3065 PUSHI (to
->isInstance (value
));
3067 #ifdef DIRECT_THREADED
3068 pc
[-2].insn
= &&instanceof_resolved
;
3070 #endif /* DIRECT_THREADED */
3074 #ifdef DIRECT_THREADED
3075 instanceof_resolved
:
3077 jobject value
= POPA ();
3078 jclass to
= (jclass
) AVAL ();
3079 PUSHI (to
->isInstance (value
));
3082 #endif /* DIRECT_THREADED */
3086 jobject value
= POPA();
3088 _Jv_MonitorEnter (value
);
3094 jobject value
= POPA();
3096 _Jv_MonitorExit (value
);
3102 jobject val
= POPA();
3112 jobject val
= POPA();
3120 insn_multianewarray
:
3122 int kind_index
= GET2U ();
3126 = (_Jv_Linker::resolve_pool_entry (defining_class
,
3128 jint
*sizes
= (jint
*) __builtin_alloca (sizeof (jint
)*dim
);
3130 for (int i
= dim
- 1; i
>= 0; i
--)
3135 jobject res
= _Jv_NewMultiArray (type
,dim
, sizes
);
3141 #ifndef DIRECT_THREADED
3144 jint the_mod_op
= get1u (pc
++);
3145 jint wide
= get2u (pc
); pc
+= 2;
3190 pc
= (unsigned char*) PEEKA (wide
);
3195 jint amount
= get2s (pc
); pc
+= 2;
3196 jint value
= PEEKI (wide
);
3197 POKEI (wide
, value
+amount
);
3202 throw_internal_error ("illegal bytecode modified by wide");
3206 #endif /* DIRECT_THREADED */
3208 catch (java::lang::Throwable
*ex
)
3210 #ifdef DIRECT_THREADED
3211 void *logical_pc
= (void *) ((insn_slot
*) pc
- 1);
3213 int logical_pc
= pc
- 1 - bytecode ();
3215 _Jv_InterpException
*exc
= exceptions ();
3216 jclass exc_class
= ex
->getClass ();
3218 for (int i
= 0; i
< exc_count
; i
++)
3220 if (PCVAL (exc
[i
].start_pc
) <= logical_pc
3221 && logical_pc
< PCVAL (exc
[i
].end_pc
))
3223 #ifdef DIRECT_THREADED
3224 jclass handler
= (jclass
) exc
[i
].handler_type
.p
;
3226 jclass handler
= NULL
;
3227 if (exc
[i
].handler_type
.i
!= 0)
3228 handler
= (_Jv_Linker::resolve_pool_entry (defining_class
,
3229 exc
[i
].handler_type
.i
)).clazz
;
3230 #endif /* DIRECT_THREADED */
3232 if (handler
== NULL
|| handler
->isAssignableFrom (exc_class
))
3234 #ifdef DIRECT_THREADED
3235 pc
= (insn_slot
*) exc
[i
].handler_pc
.p
;
3237 pc
= bytecode () + exc
[i
].handler_pc
.i
;
3238 #endif /* DIRECT_THREADED */
3240 sp
++->o
= ex
; // Push exception.
3246 // No handler, so re-throw.
3252 throw_internal_error (char *msg
)
3254 throw new java::lang::InternalError (JvNewStringLatin1 (msg
));
3258 throw_incompatible_class_change_error (jstring msg
)
3260 throw new java::lang::IncompatibleClassChangeError (msg
);
3264 static java::lang::NullPointerException
*null_pointer_exc
;
3266 throw_null_pointer_exception ()
3268 if (null_pointer_exc
== NULL
)
3269 null_pointer_exc
= new java::lang::NullPointerException
;
3271 throw null_pointer_exc
;
3275 /** Do static initialization for fields with a constant initializer */
3277 _Jv_InitField (jobject obj
, jclass klass
, int index
)
3279 using namespace java::lang::reflect
;
3281 if (obj
!= 0 && klass
== 0)
3282 klass
= obj
->getClass ();
3284 if (!_Jv_IsInterpretedClass (klass
))
3287 _Jv_InterpClass
*iclass
= (_Jv_InterpClass
*)klass
->aux_info
;
3289 _Jv_Field
* field
= (&klass
->fields
[0]) + index
;
3291 if (index
> klass
->field_count
)
3292 throw_internal_error ("field out of range");
3294 int init
= iclass
->field_initializers
[index
];
3298 _Jv_Constants
*pool
= &klass
->constants
;
3299 int tag
= pool
->tags
[init
];
3301 if (! field
->isResolved ())
3302 throw_internal_error ("initializing unresolved field");
3304 if (obj
==0 && ((field
->flags
& Modifier::STATIC
) == 0))
3305 throw_internal_error ("initializing non-static field with no object");
3309 if ((field
->flags
& Modifier::STATIC
) != 0)
3310 addr
= (void*) field
->u
.addr
;
3312 addr
= (void*) (((char*)obj
) + field
->u
.boffset
);
3316 case JV_CONSTANT_String
:
3319 str
= _Jv_NewStringUtf8Const (pool
->data
[init
].utf8
);
3320 pool
->data
[init
].string
= str
;
3321 pool
->tags
[init
] = JV_CONSTANT_ResolvedString
;
3325 case JV_CONSTANT_ResolvedString
:
3326 if (! (field
->type
== &java::lang::String::class$
3327 || field
->type
== &java::lang::Class::class$
))
3328 throw_class_format_error ("string initialiser to non-string field");
3330 *(jstring
*)addr
= pool
->data
[init
].string
;
3333 case JV_CONSTANT_Integer
:
3335 int value
= pool
->data
[init
].i
;
3337 if (field
->type
== JvPrimClass (boolean
))
3338 *(jboolean
*)addr
= (jboolean
)value
;
3340 else if (field
->type
== JvPrimClass (byte
))
3341 *(jbyte
*)addr
= (jbyte
)value
;
3343 else if (field
->type
== JvPrimClass (char))
3344 *(jchar
*)addr
= (jchar
)value
;
3346 else if (field
->type
== JvPrimClass (short))
3347 *(jshort
*)addr
= (jshort
)value
;
3349 else if (field
->type
== JvPrimClass (int))
3350 *(jint
*)addr
= (jint
)value
;
3353 throw_class_format_error ("erroneous field initializer");
3357 case JV_CONSTANT_Long
:
3358 if (field
->type
!= JvPrimClass (long))
3359 throw_class_format_error ("erroneous field initializer");
3361 *(jlong
*)addr
= _Jv_loadLong (&pool
->data
[init
]);
3364 case JV_CONSTANT_Float
:
3365 if (field
->type
!= JvPrimClass (float))
3366 throw_class_format_error ("erroneous field initializer");
3368 *(jfloat
*)addr
= pool
->data
[init
].f
;
3371 case JV_CONSTANT_Double
:
3372 if (field
->type
!= JvPrimClass (double))
3373 throw_class_format_error ("erroneous field initializer");
3375 *(jdouble
*)addr
= _Jv_loadDouble (&pool
->data
[init
]);
3379 throw_class_format_error ("erroneous field initializer");
3383 inline static unsigned char*
3384 skip_one_type (unsigned char* ptr
)
3395 do { ch
= *ptr
++; } while (ch
!= ';');
3402 get_ffi_type_from_signature (unsigned char* ptr
)
3408 return &ffi_type_pointer
;
3412 // On some platforms a bool is a byte, on others an int.
3413 if (sizeof (jboolean
) == sizeof (jbyte
))
3414 return &ffi_type_sint8
;
3417 JvAssert (sizeof (jbyte
) == sizeof (jint
));
3418 return &ffi_type_sint32
;
3423 return &ffi_type_sint8
;
3427 return &ffi_type_uint16
;
3431 return &ffi_type_sint16
;
3435 return &ffi_type_sint32
;
3439 return &ffi_type_sint64
;
3443 return &ffi_type_float
;
3447 return &ffi_type_double
;
3451 return &ffi_type_void
;
3455 throw_internal_error ("unknown type in signature");
3458 /* this function yields the number of actual arguments, that is, if the
3459 * function is non-static, then one is added to the number of elements
3460 * found in the signature */
3463 _Jv_count_arguments (_Jv_Utf8Const
*signature
,
3466 unsigned char *ptr
= (unsigned char*) signature
->chars();
3467 int arg_count
= staticp
? 0 : 1;
3469 /* first, count number of arguments */
3477 ptr
= skip_one_type (ptr
);
3484 /* This beast will build a cif, given the signature. Memory for
3485 * the cif itself and for the argument types must be allocated by the
3490 init_cif (_Jv_Utf8Const
* signature
,
3494 ffi_type
**arg_types
,
3497 unsigned char *ptr
= (unsigned char*) signature
->chars();
3499 int arg_index
= 0; // arg number
3500 int item_count
= 0; // stack-item count
3505 arg_types
[arg_index
++] = &ffi_type_pointer
;
3515 arg_types
[arg_index
++] = get_ffi_type_from_signature (ptr
);
3517 if (*ptr
== 'J' || *ptr
== 'D')
3522 ptr
= skip_one_type (ptr
);
3527 ffi_type
*rtype
= get_ffi_type_from_signature (ptr
);
3529 ptr
= skip_one_type (ptr
);
3530 if (ptr
!= (unsigned char*)signature
->chars() + signature
->len())
3531 throw_internal_error ("did not find end of signature");
3533 if (ffi_prep_cif (cif
, FFI_DEFAULT_ABI
,
3534 arg_count
, rtype
, arg_types
) != FFI_OK
)
3535 throw_internal_error ("ffi_prep_cif failed");
3537 if (rtype_p
!= NULL
)
3543 #if FFI_NATIVE_RAW_API
3544 # define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure
3545 # define FFI_RAW_SIZE ffi_raw_size
3547 # define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure
3548 # define FFI_RAW_SIZE ffi_java_raw_size
3551 /* we put this one here, and not in interpret.cc because it
3552 * calls the utility routines _Jv_count_arguments
3553 * which are static to this module. The following struct defines the
3554 * layout we use for the stubs, it's only used in the ncode method. */
3557 ffi_raw_closure closure
;
3559 ffi_type
*arg_types
[0];
3562 typedef void (*ffi_closure_fun
) (ffi_cif
*,void*,ffi_raw
*,void*);
3565 _Jv_InterpMethod::ncode ()
3567 using namespace java::lang::reflect
;
3569 if (self
->ncode
!= 0)
3572 jboolean staticp
= (self
->accflags
& Modifier::STATIC
) != 0;
3573 int arg_count
= _Jv_count_arguments (self
->signature
, staticp
);
3575 ncode_closure
*closure
=
3576 (ncode_closure
*)_Jv_AllocBytes (sizeof (ncode_closure
)
3577 + arg_count
* sizeof (ffi_type
*));
3579 init_cif (self
->signature
,
3583 &closure
->arg_types
[0],
3586 ffi_closure_fun fun
;
3588 args_raw_size
= FFI_RAW_SIZE (&closure
->cif
);
3590 JvAssert ((self
->accflags
& Modifier::NATIVE
) == 0);
3592 if ((self
->accflags
& Modifier::SYNCHRONIZED
) != 0)
3595 fun
= (ffi_closure_fun
)&_Jv_InterpMethod::run_synch_class
;
3597 fun
= (ffi_closure_fun
)&_Jv_InterpMethod::run_synch_object
;
3602 fun
= (ffi_closure_fun
)&_Jv_InterpMethod::run_class
;
3604 fun
= (ffi_closure_fun
)&_Jv_InterpMethod::run_normal
;
3607 FFI_PREP_RAW_CLOSURE (&closure
->closure
,
3612 self
->ncode
= (void*)closure
;
3617 _Jv_JNIMethod::ncode ()
3619 using namespace java::lang::reflect
;
3621 if (self
->ncode
!= 0)
3624 jboolean staticp
= (self
->accflags
& Modifier::STATIC
) != 0;
3625 int arg_count
= _Jv_count_arguments (self
->signature
, staticp
);
3627 ncode_closure
*closure
=
3628 (ncode_closure
*)_Jv_AllocBytes (sizeof (ncode_closure
)
3629 + arg_count
* sizeof (ffi_type
*));
3632 init_cif (self
->signature
,
3636 &closure
->arg_types
[0],
3639 ffi_closure_fun fun
;
3641 args_raw_size
= FFI_RAW_SIZE (&closure
->cif
);
3643 // Initialize the argument types and CIF that represent the actual
3644 // underlying JNI function.
3646 if ((self
->accflags
& Modifier::STATIC
))
3648 jni_arg_types
= (ffi_type
**) _Jv_AllocBytes ((extra_args
+ arg_count
)
3649 * sizeof (ffi_type
*));
3651 jni_arg_types
[offset
++] = &ffi_type_pointer
;
3652 if ((self
->accflags
& Modifier::STATIC
))
3653 jni_arg_types
[offset
++] = &ffi_type_pointer
;
3654 memcpy (&jni_arg_types
[offset
], &closure
->arg_types
[0],
3655 arg_count
* sizeof (ffi_type
*));
3657 if (ffi_prep_cif (&jni_cif
, _Jv_platform_ffi_abi
,
3658 extra_args
+ arg_count
, rtype
,
3659 jni_arg_types
) != FFI_OK
)
3660 throw_internal_error ("ffi_prep_cif failed for JNI function");
3662 JvAssert ((self
->accflags
& Modifier::NATIVE
) != 0);
3664 // FIXME: for now we assume that all native methods for
3665 // interpreted code use JNI.
3666 fun
= (ffi_closure_fun
) &_Jv_JNIMethod::call
;
3668 FFI_PREP_RAW_CLOSURE (&closure
->closure
,
3673 self
->ncode
= (void *) closure
;
3678 throw_class_format_error (jstring msg
)
3681 ? new java::lang::ClassFormatError (msg
)
3682 : new java::lang::ClassFormatError
);
3686 throw_class_format_error (char *msg
)
3688 throw_class_format_error (JvNewStringLatin1 (msg
));
3694 _Jv_InterpreterEngine::do_verify (jclass klass
)
3696 _Jv_InterpClass
*iclass
= (_Jv_InterpClass
*) klass
->aux_info
;
3697 for (int i
= 0; i
< klass
->method_count
; i
++)
3699 using namespace java::lang::reflect
;
3700 _Jv_MethodBase
*imeth
= iclass
->interpreted_methods
[i
];
3701 _Jv_ushort accflags
= klass
->methods
[i
].accflags
;
3702 if ((accflags
& (Modifier::NATIVE
| Modifier::ABSTRACT
)) == 0)
3704 _Jv_InterpMethod
*im
= reinterpret_cast<_Jv_InterpMethod
*> (imeth
);
3705 _Jv_VerifyMethod (im
);
3711 _Jv_InterpreterEngine::do_create_ncode (jclass klass
)
3713 _Jv_InterpClass
*iclass
= (_Jv_InterpClass
*) klass
->aux_info
;
3714 for (int i
= 0; i
< klass
->method_count
; i
++)
3716 // Just skip abstract methods. This is particularly important
3717 // because we don't resize the interpreted_methods array when
3718 // miranda methods are added to it.
3719 if ((klass
->methods
[i
].accflags
3720 & java::lang::reflect::Modifier::ABSTRACT
)
3724 _Jv_MethodBase
*imeth
= iclass
->interpreted_methods
[i
];
3726 if ((klass
->methods
[i
].accflags
& java::lang::reflect::Modifier::NATIVE
)
3729 // You might think we could use a virtual `ncode' method in
3730 // the _Jv_MethodBase and unify the native and non-native
3731 // cases. Well, we can't, because we don't allocate these
3732 // objects using `new', and thus they don't get a vtable.
3733 _Jv_JNIMethod
*jnim
= reinterpret_cast<_Jv_JNIMethod
*> (imeth
);
3734 klass
->methods
[i
].ncode
= jnim
->ncode ();
3736 else if (imeth
!= 0) // it could be abstract
3738 _Jv_InterpMethod
*im
= reinterpret_cast<_Jv_InterpMethod
*> (imeth
);
3739 klass
->methods
[i
].ncode
= im
->ncode ();
3745 _Jv_InterpreterEngine::do_allocate_static_fields (jclass klass
,
3748 _Jv_InterpClass
*iclass
= (_Jv_InterpClass
*) klass
->aux_info
;
3750 char *static_data
= (char *) _Jv_AllocBytes (static_size
);
3751 memset (static_data
, 0, static_size
);
3753 for (int i
= 0; i
< klass
->field_count
; i
++)
3755 _Jv_Field
*field
= &klass
->fields
[i
];
3757 if ((field
->flags
& java::lang::reflect::Modifier::STATIC
) != 0)
3759 field
->u
.addr
= static_data
+ field
->u
.boffset
;
3761 if (iclass
->field_initializers
[i
] != 0)
3763 _Jv_Linker::resolve_field (field
, klass
->loader
);
3764 _Jv_InitField (0, klass
, i
);
3769 // Now we don't need the field_initializers anymore, so let the
3770 // collector get rid of it.
3771 iclass
->field_initializers
= 0;
3774 _Jv_ResolvedMethod
*
3775 _Jv_InterpreterEngine::do_resolve_method (_Jv_Method
*method
, jclass klass
,
3776 jboolean staticp
, jint vtable_index
)
3778 int arg_count
= _Jv_count_arguments (method
->signature
, staticp
);
3780 _Jv_ResolvedMethod
* result
= (_Jv_ResolvedMethod
*)
3781 _Jv_AllocBytes (sizeof (_Jv_ResolvedMethod
)
3782 + arg_count
*sizeof (ffi_type
*));
3784 result
->stack_item_count
3785 = init_cif (method
->signature
,
3789 &result
->arg_types
[0],
3792 result
->vtable_index
= vtable_index
;
3793 result
->method
= method
;
3794 result
->klass
= klass
;
3800 _Jv_InterpreterEngine::do_post_miranda_hook (jclass klass
)
3802 _Jv_InterpClass
*iclass
= (_Jv_InterpClass
*) klass
->aux_info
;
3803 for (int i
= 0; i
< klass
->method_count
; i
++)
3805 // Just skip abstract methods. This is particularly important
3806 // because we don't resize the interpreted_methods array when
3807 // miranda methods are added to it.
3808 if ((klass
->methods
[i
].accflags
3809 & java::lang::reflect::Modifier::ABSTRACT
)
3812 // Miranda method additions mean that the `methods' array moves.
3813 // We cache a pointer into this array, so we have to update.
3814 iclass
->interpreted_methods
[i
]->self
= &klass
->methods
[i
];
3818 #endif // INTERPRETER