diff options
author | Andrew Haley <aph@redhat.com> | 2016-09-30 16:24:48 +0000 |
---|---|---|
committer | Andrew Haley <aph@gcc.gnu.org> | 2016-09-30 16:24:48 +0000 |
commit | 07b78716af6a9d7c9fd1e94d9baf94a52c873947 (patch) | |
tree | 3f22b3241c513ad168c8353805614ae1249410f4 /libjava/interpret.cc | |
parent | eae993948bae8b788c53772bcb9217c063716f93 (diff) | |
download | gcc-07b78716af6a9d7c9fd1e94d9baf94a52c873947.zip gcc-07b78716af6a9d7c9fd1e94d9baf94a52c873947.tar.gz gcc-07b78716af6a9d7c9fd1e94d9baf94a52c873947.tar.bz2 |
Makefile.def: Remove libjava.
2016-09-30 Andrew Haley <aph@redhat.com>
* Makefile.def: Remove libjava.
* Makefile.tpl: Likewise.
* Makefile.in: Regenerate.
* configure.ac: Likewise.
* configure: Likewise.
* gcc/java: Remove.
* libjava: Likewise.
From-SVN: r240662
Diffstat (limited to 'libjava/interpret.cc')
-rw-r--r-- | libjava/interpret.cc | 1949 |
1 files changed, 0 insertions, 1949 deletions
diff --git a/libjava/interpret.cc b/libjava/interpret.cc deleted file mode 100644 index 78686fd..0000000 --- a/libjava/interpret.cc +++ /dev/null @@ -1,1949 +0,0 @@ -// interpret.cc - Code for the interpreter - -/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation - - This file is part of libgcj. - -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ - -/* Author: Kresten Krab Thorup <krab@gnu.org> */ - -#include <config.h> -#include <platform.h> - -#pragma implementation "java-interp.h" - -#include <jvm.h> -#include <java-cpool.h> -#include <java-interp.h> -#include <java/lang/System.h> -#include <java/lang/String.h> -#include <java/lang/Integer.h> -#include <java/lang/Long.h> -#include <java/lang/StringBuffer.h> -#include <java/lang/Class.h> -#include <java/lang/reflect/Modifier.h> -#include <java/lang/InternalError.h> -#include <java/lang/NullPointerException.h> -#include <java/lang/ArithmeticException.h> -#include <java/lang/IncompatibleClassChangeError.h> -#include <java/lang/InstantiationException.h> -#include <java/lang/Thread.h> -#include <java-insns.h> -#include <java-signal.h> -#include <java/lang/ClassFormatError.h> -#include <execution.h> -#include <java/lang/reflect/Modifier.h> - -#include <jvmti.h> -#include "jvmti-int.h" - -#include <gnu/gcj/jvmti/Breakpoint.h> -#include <gnu/gcj/jvmti/BreakpointManager.h> - -// Execution engine for interpreted code. -_Jv_InterpreterEngine _Jv_soleInterpreterEngine; - -#include <stdlib.h> - -using namespace gcj; - -static void throw_internal_error (const char *msg) - __attribute__ ((__noreturn__)); -static void throw_incompatible_class_change_error (jstring msg) - __attribute__ ((__noreturn__)); -static void throw_null_pointer_exception () - __attribute__ ((__noreturn__)); - -static void throw_class_format_error (jstring msg) - __attribute__ ((__noreturn__)); -static void throw_class_format_error (const char *msg) - __attribute__ ((__noreturn__)); - -static void find_catch_location (jthrowable, jthread, jmethodID *, jlong *); - -// A macro to facilitate JVMTI exception reporting -#define REPORT_EXCEPTION(Jthrowable) \ - do { \ - if (JVMTI_REQUESTED_EVENT (Exception)) \ - _Jv_ReportJVMTIExceptionThrow (Jthrowable); \ - } \ - while (0) - -#ifdef DIRECT_THREADED -// Lock to ensure that methods are not compiled concurrently. -// We could use a finer-grained lock here, however it is not safe to use -// the Class monitor as user code in another thread could hold it. -static _Jv_Mutex_t compile_mutex; - -// See class ThreadCountAdjuster and REWRITE_INSN for how this is -// used. -_Jv_Mutex_t _Jv_InterpMethod::rewrite_insn_mutex; - -void -_Jv_InitInterpreter() -{ - _Jv_MutexInit (&compile_mutex); - _Jv_MutexInit (&_Jv_InterpMethod::rewrite_insn_mutex); -} -#else -void _Jv_InitInterpreter() {} -#endif - -// The breakpoint instruction. For the direct threaded case, -// _Jv_InterpMethod::compile will initialize breakpoint_insn -// the first time it is called. -#ifdef DIRECT_THREADED -insn_slot _Jv_InterpMethod::bp_insn_slot; -pc_t _Jv_InterpMethod::breakpoint_insn = NULL; -#else -unsigned char _Jv_InterpMethod::bp_insn_opcode - = static_cast<unsigned char> (op_breakpoint); -pc_t _Jv_InterpMethod::breakpoint_insn = &_Jv_InterpMethod::bp_insn_opcode; -#endif - -extern "C" double __ieee754_fmod (double,double); - -static inline void dupx (_Jv_word *sp, int n, int x) -{ - // first "slide" n+x elements n to the right - int top = n-1; - for (int i = 0; i < n+x; i++) - { - sp[(top-i)] = sp[(top-i)-n]; - } - - // next, copy the n top elements, n+x down - for (int i = 0; i < n; i++) - { - sp[top-(n+x)-i] = sp[top-i]; - } -} - -// Used to convert from floating types to integral types. -template<typename TO, typename FROM> -static inline TO -convert (FROM val, TO min, TO max) -{ - TO ret; - if (val >= (FROM) max) - ret = max; - else if (val <= (FROM) min) - ret = min; - else if (val != val) - ret = 0; - else - ret = (TO) val; - return ret; -} - -#define PUSHA(V) (sp++)->o = (V) -#define PUSHI(V) (sp++)->i = (V) -#define PUSHF(V) (sp++)->f = (V) -#if SIZEOF_VOID_P == 8 -# define PUSHL(V) (sp->l = (V), sp += 2) -# define PUSHD(V) (sp->d = (V), sp += 2) -#else -# define PUSHL(V) do { _Jv_word2 w2; w2.l=(V); \ - (sp++)->ia[0] = w2.ia[0]; \ - (sp++)->ia[0] = w2.ia[1]; } while (0) -# define PUSHD(V) do { _Jv_word2 w2; w2.d=(V); \ - (sp++)->ia[0] = w2.ia[0]; \ - (sp++)->ia[0] = w2.ia[1]; } while (0) -#endif - -#define POPA() ((--sp)->o) -#define POPI() ((jint) (--sp)->i) // cast since it may be promoted -#define POPF() ((jfloat) (--sp)->f) -#if SIZEOF_VOID_P == 8 -# define POPL() (sp -= 2, (jlong) sp->l) -# define POPD() (sp -= 2, (jdouble) sp->d) -#else -# define POPL() ({ _Jv_word2 w2; \ - w2.ia[1] = (--sp)->ia[0]; \ - w2.ia[0] = (--sp)->ia[0]; w2.l; }) -# define POPD() ({ _Jv_word2 w2; \ - w2.ia[1] = (--sp)->ia[0]; \ - w2.ia[0] = (--sp)->ia[0]; w2.d; }) -#endif - -#define LOADA(I) (sp++)->o = locals[I].o -#define LOADI(I) (sp++)->i = locals[I].i -#define LOADF(I) (sp++)->f = locals[I].f -#if SIZEOF_VOID_P == 8 -# define LOADL(I) (sp->l = locals[I].l, sp += 2) -# define LOADD(I) (sp->d = locals[I].d, sp += 2) -#else -# define LOADL(I) do { jint __idx = (I); \ - (sp++)->ia[0] = locals[__idx].ia[0]; \ - (sp++)->ia[0] = locals[__idx+1].ia[0]; \ - } while (0) -# define LOADD(I) LOADL(I) -#endif - -#define STOREA(I) \ - do \ - { \ - jint __idx = (I); \ - DEBUG_LOCALS_INSN (__idx, 'o'); \ - locals[__idx].o = (--sp)->o; \ - } \ - while (0) -#define STOREI(I) \ - do \ - { \ - jint __idx = (I); \ - DEBUG_LOCALS_INSN (__idx, 'i'); \ - locals[__idx].i = (--sp)->i; \ - } while (0) -#define STOREF(I) \ - do \ - { \ - jint __idx = (I); \ - DEBUG_LOCALS_INSN (__idx, 'f'); \ - locals[__idx].f = (--sp)->f; \ - } \ - while (0) -#if SIZEOF_VOID_P == 8 -# define STOREL(I) \ - do \ - { \ - jint __idx = (I); \ - DEBUG_LOCALS_INSN (__idx, 'l'); \ - DEBUG_LOCALS_INSN (__idx + 1, 'x'); \ - (sp -= 2, locals[__idx].l = sp->l); \ - } \ - while (0) -# define STORED(I) \ - do \ - { \ - jint __idx = (I); \ - DEBUG_LOCALS_INSN (__idx, 'd'); \ - DEBUG_LOCALS_INSN (__idx + 1, 'x'); \ - (sp -= 2, locals[__idx].d = sp->d); \ - } \ - while (0) - -#else -# define STOREL(I) \ - do \ - { \ - jint __idx = (I); \ - DEBUG_LOCALS_INSN (__idx, 'l'); \ - DEBUG_LOCALS_INSN (__idx + 1, 'x'); \ - locals[__idx + 1].ia[0] = (--sp)->ia[0]; \ - locals[__idx].ia[0] = (--sp)->ia[0]; \ - } \ - while (0) -# define STORED(I) \ - do { \ - jint __idx = (I); \ - DEBUG_LOCALS_INSN (__idx, 'd'); \ - DEBUG_LOCALS_INSN (__idx + 1, 'x'); \ - locals[__idx + 1].ia[0] = (--sp)->ia[0]; \ - locals[__idx].ia[0] = (--sp)->ia[0]; \ - } while (0) -#endif - -#define PEEKI(I) (locals+(I))->i -#define PEEKA(I) (locals+(I))->o - -#define POKEI(I,V) \ - do \ - { \ - jint __idx = (I); \ - DEBUG_LOCALS_INSN (__idx, 'i'); \ - ((locals + __idx)->i = (V)); \ - } \ - while (0) - - -#define BINOPI(OP) { \ - jint value2 = POPI(); \ - jint value1 = POPI(); \ - PUSHI(value1 OP value2); \ -} - -#define BINOPF(OP) { \ - jfloat value2 = POPF(); \ - jfloat value1 = POPF(); \ - PUSHF(value1 OP value2); \ -} - -#define BINOPL(OP) { \ - jlong value2 = POPL(); \ - jlong value1 = POPL(); \ - PUSHL(value1 OP value2); \ -} - -#define BINOPD(OP) { \ - jdouble value2 = POPD(); \ - jdouble value1 = POPD(); \ - PUSHD(value1 OP value2); \ -} - -static inline jint -get1s (unsigned char* loc) -{ - return *(signed char*)loc; -} - -static inline jint -get1u (unsigned char* loc) -{ - return *loc; -} - -static inline jint -get2s(unsigned char* loc) -{ - return (((jint)*(signed char*)loc) << 8) | ((jint)*(loc+1)); -} - -static inline jint -get2u (unsigned char* loc) -{ - return (((jint)(*loc)) << 8) | ((jint)*(loc+1)); -} - -static jint -get4 (unsigned char* loc) -{ - return (((jint)(loc[0])) << 24) - | (((jint)(loc[1])) << 16) - | (((jint)(loc[2])) << 8) - | (((jint)(loc[3])) << 0); -} - -#define SAVE_PC() frame_desc.pc = pc - -// We used to define this conditionally, depending on HANDLE_SEGV. -// However, that runs into a problem if a chunk in low memory is -// mapped and we try to look at a field near the end of a large -// object. See PR 26858 for details. It is, most likely, relatively -// inexpensive to simply do this check always. -#define NULLCHECK(X) \ - do { SAVE_PC(); if ((X)==NULL) throw_null_pointer_exception (); } while (0) - -// Note that we can still conditionally define NULLARRAYCHECK, since -// we know that all uses of an array will first reference the length -// field, which is first -- and thus will trigger a SEGV. -#ifdef HANDLE_SEGV -#define NULLARRAYCHECK(X) SAVE_PC() -#else -#define NULLARRAYCHECK(X) \ - do \ - { \ - SAVE_PC(); \ - if ((X) == NULL) { throw_null_pointer_exception (); } \ - } while (0) -#endif - -#define ARRAYBOUNDSCHECK(array, index) \ - do \ - { \ - if (((unsigned) index) >= (unsigned) (array->length)) \ - _Jv_ThrowBadArrayIndex (index); \ - } while (0) - -void -_Jv_InterpMethod::run_normal (ffi_cif *, - void *ret, - INTERP_FFI_RAW_TYPE *args, - void *__this) -{ - _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; - run (ret, args, _this); -} - -void -_Jv_InterpMethod::run_normal_debug (ffi_cif *, - void *ret, - INTERP_FFI_RAW_TYPE *args, - void *__this) -{ - _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; - run_debug (ret, args, _this); -} - -void -_Jv_InterpMethod::run_synch_object (ffi_cif *, - void *ret, - INTERP_FFI_RAW_TYPE *args, - void *__this) -{ - _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; - - jobject rcv = (jobject) args[0].ptr; - JvSynchronize mutex (rcv); - - run (ret, args, _this); -} - -void -_Jv_InterpMethod::run_synch_object_debug (ffi_cif *, - void *ret, - INTERP_FFI_RAW_TYPE *args, - void *__this) -{ - _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; - - jobject rcv = (jobject) args[0].ptr; - JvSynchronize mutex (rcv); - - run_debug (ret, args, _this); -} - -void -_Jv_InterpMethod::run_class (ffi_cif *, - void *ret, - INTERP_FFI_RAW_TYPE *args, - void *__this) -{ - _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; - _Jv_InitClass (_this->defining_class); - run (ret, args, _this); -} - -void -_Jv_InterpMethod::run_class_debug (ffi_cif *, - void *ret, - INTERP_FFI_RAW_TYPE *args, - void *__this) -{ - _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; - _Jv_InitClass (_this->defining_class); - run_debug (ret, args, _this); -} - -void -_Jv_InterpMethod::run_synch_class (ffi_cif *, - void *ret, - INTERP_FFI_RAW_TYPE *args, - void *__this) -{ - _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; - - jclass sync = _this->defining_class; - _Jv_InitClass (sync); - JvSynchronize mutex (sync); - - run (ret, args, _this); -} - -void -_Jv_InterpMethod::run_synch_class_debug (ffi_cif *, - void *ret, - INTERP_FFI_RAW_TYPE *args, - void *__this) -{ - _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; - - jclass sync = _this->defining_class; - _Jv_InitClass (sync); - JvSynchronize mutex (sync); - - run_debug (ret, args, _this); -} - -#ifdef DIRECT_THREADED -// "Compile" a method by turning it from bytecode to direct-threaded -// code. -void -_Jv_InterpMethod::compile (const void * const *insn_targets) -{ - insn_slot *insns = NULL; - 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_AllocBytes (sizeof (insn_slot) * next); - number_insn_slots = next; - next = 0; - } - - unsigned char *pc = codestart; - 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; - // For an unresolved class we want to delay resolution - // until execution. - if (defining_class->constants.tags[index] == JV_CONSTANT_Class) - { - --next; - SET_INSN (insn_targets[int (op_jsr_w) + 1]); - SET_INT (index); - } - else - 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; - // For an unresolved class we want to delay resolution - // until execution. - if (defining_class->constants.tags[index] == JV_CONSTANT_Class) - { - --next; - SET_INSN (insn_targets[int (op_jsr_w) + 1]); - SET_INT (index); - } - else - 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; - - int new_pc = base_pc_val + offset; - - bool orig_was_goto = opcode == op_goto; - - // Thread jumps. We limit the loop count; this lets - // us avoid infinite loops if the bytecode contains - // such. `10' is arbitrary. - int count = 10; - while (codestart[new_pc] == op_goto && count-- > 0) - new_pc += get2s (&codestart[new_pc + 1]); - - // If the jump takes us to a `return' instruction and - // the original branch was an unconditional goto, then - // we hoist the return. - opcode = (java_opcode) codestart[new_pc]; - if (orig_was_goto - && (opcode == op_ireturn || opcode == op_lreturn - || opcode == op_freturn || opcode == op_dreturn - || opcode == op_areturn || opcode == op_return)) - { - --next; - SET_INSN (insn_targets[opcode]); - } - else - SET_DATUM (&insns[pc_mapping[new_pc]]); - } - 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]]); - pc += 8; - } - } - 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; - - // Some "can't happen" cases that we include for - // error-checking purposes. - case op_putfield_1: - case op_putfield_2: - case op_putfield_4: - case op_putfield_8: - case op_putfield_a: - case op_putstatic_1: - case op_putstatic_2: - case op_putstatic_4: - case op_putstatic_8: - case op_putstatic_a: - case op_getfield_1: - case op_getfield_2s: - case op_getfield_2u: - case op_getfield_4: - case op_getfield_8: - case op_getfield_a: - case op_getstatic_1: - case op_getstatic_2s: - case op_getstatic_2u: - case op_getstatic_4: - case op_getstatic_8: - case op_getstatic_a: - case op_breakpoint: - 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]]; - // FIXME: resolve_pool_entry can throw - we shouldn't be doing this - // during compilation. - jclass handler - = (_Jv_Linker::resolve_pool_entry (defining_class, - exc[i].handler_type.i)).clazz; - exc[i].handler_type.p = handler; - } - - // Translate entries in the LineNumberTable from bytecode PC's to direct - // threaded interpreter instruction values. - for (int i = 0; i < line_table_len; i++) - { - int byte_pc = line_table[i].bytecode_pc; - // It isn't worth throwing an exception if this table is - // corrupted, but at the same time we don't want a crash. - if (byte_pc < 0 || byte_pc >= code_length) - byte_pc = 0; - line_table[i].pc = &insns[pc_mapping[byte_pc]]; - } - - prepared = insns; - - // Now remap the variable table for this method. - for (int i = 0; i < local_var_table_len; ++i) - { - int start_byte = local_var_table[i].bytecode_pc; - if (start_byte < 0 || start_byte >= code_length) - start_byte = 0; - jlocation start = pc_mapping[start_byte]; - - int end_byte = start_byte + local_var_table[i].length; - if (end_byte < 0) - end_byte = 0; - jlocation end = ((end_byte >= code_length) - ? number_insn_slots - : pc_mapping[end_byte]); - - local_var_table[i].pc = &insns[start]; - local_var_table[i].length = end - start + 1; - } - - if (breakpoint_insn == NULL) - { - bp_insn_slot.insn = const_cast<void *> (insn_targets[op_breakpoint]); - breakpoint_insn = &bp_insn_slot; - } -} -#endif /* DIRECT_THREADED */ - -/* Run the given method. - When args is NULL, don't run anything -- just compile it. */ -void -_Jv_InterpMethod::run (void *retp, INTERP_FFI_RAW_TYPE *args, - _Jv_InterpMethod *meth) -{ -#undef __GCJ_DEBUG -#undef DEBUG_LOCALS_INSN -#define DEBUG_LOCALS_INSN(s, t) do {} while (0) - -#include "interpret-run.cc" -} - -void -_Jv_InterpMethod::run_debug (void *retp, INTERP_FFI_RAW_TYPE *args, - _Jv_InterpMethod *meth) -{ -#define __GCJ_DEBUG -#undef DEBUG_LOCALS_INSN -#define DEBUG_LOCALS_INSN(s, t) \ - do \ - { \ - frame_desc.locals_type[s] = t; \ - } \ - while (0) - -#include "interpret-run.cc" -} - -static void -throw_internal_error (const char *msg) -{ - jthrowable t = new java::lang::InternalError (JvNewStringLatin1 (msg)); - REPORT_EXCEPTION (t); - throw t; -} - -static void -throw_incompatible_class_change_error (jstring msg) -{ - jthrowable t = new java::lang::IncompatibleClassChangeError (msg); - REPORT_EXCEPTION (t); - throw t; -} - -static void -throw_null_pointer_exception () -{ - jthrowable t = new java::lang::NullPointerException; - REPORT_EXCEPTION (t); - throw t; -} - -/* Look up source code line number for given bytecode (or direct threaded - interpreter) PC. */ -int -_Jv_InterpMethod::get_source_line(pc_t mpc) -{ - int line = line_table_len > 0 ? line_table[0].line : -1; - for (int i = 1; i < line_table_len; i++) - if (line_table[i].pc > mpc) - break; - else - line = line_table[i].line; - - return line; -} - -/** Do static initialization for fields with a constant initializer */ -void -_Jv_InitField (jobject obj, jclass klass, int index) -{ - using namespace java::lang::reflect; - - if (obj != 0 && klass == 0) - klass = obj->getClass (); - - if (!_Jv_IsInterpretedClass (klass)) - return; - - _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info; - - _Jv_Field * field = (&klass->fields[0]) + index; - - if (index > klass->field_count) - throw_internal_error ("field out of range"); - - int init = iclass->field_initializers[index]; - if (init == 0) - return; - - _Jv_Constants *pool = &klass->constants; - int tag = pool->tags[init]; - - if (! field->isResolved ()) - throw_internal_error ("initializing unresolved field"); - - if (obj==0 && ((field->flags & Modifier::STATIC) == 0)) - throw_internal_error ("initializing non-static field with no object"); - - void *addr = 0; - - if ((field->flags & Modifier::STATIC) != 0) - addr = (void*) field->u.addr; - else - addr = (void*) (((char*)obj) + field->u.boffset); - - switch (tag) - { - case JV_CONSTANT_String: - { - jstring str; - str = _Jv_NewStringUtf8Const (pool->data[init].utf8); - pool->data[init].string = str; - pool->tags[init] = JV_CONSTANT_ResolvedString; - } - /* fall through */ - - case JV_CONSTANT_ResolvedString: - if (! (field->type == &java::lang::String::class$ - || field->type == &java::lang::Class::class$)) - throw_class_format_error ("string initialiser to non-string field"); - - *(jstring*)addr = pool->data[init].string; - break; - - case JV_CONSTANT_Integer: - { - int value = pool->data[init].i; - - if (field->type == JvPrimClass (boolean)) - *(jboolean*)addr = (jboolean)value; - - else if (field->type == JvPrimClass (byte)) - *(jbyte*)addr = (jbyte)value; - - else if (field->type == JvPrimClass (char)) - *(jchar*)addr = (jchar)value; - - else if (field->type == JvPrimClass (short)) - *(jshort*)addr = (jshort)value; - - else if (field->type == JvPrimClass (int)) - *(jint*)addr = (jint)value; - - else - throw_class_format_error ("erroneous field initializer"); - } - break; - - case JV_CONSTANT_Long: - if (field->type != JvPrimClass (long)) - throw_class_format_error ("erroneous field initializer"); - - *(jlong*)addr = _Jv_loadLong (&pool->data[init]); - break; - - case JV_CONSTANT_Float: - if (field->type != JvPrimClass (float)) - throw_class_format_error ("erroneous field initializer"); - - *(jfloat*)addr = pool->data[init].f; - break; - - case JV_CONSTANT_Double: - if (field->type != JvPrimClass (double)) - throw_class_format_error ("erroneous field initializer"); - - *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]); - break; - - default: - throw_class_format_error ("erroneous field initializer"); - } -} - -inline static unsigned char* -skip_one_type (unsigned char* ptr) -{ - int ch = *ptr++; - - while (ch == '[') - { - ch = *ptr++; - } - - if (ch == 'L') - { - do { ch = *ptr++; } while (ch != ';'); - } - - return ptr; -} - -static ffi_type* -get_ffi_type_from_signature (unsigned char* ptr) -{ - switch (*ptr) - { - case 'L': - case '[': - return &ffi_type_pointer; - break; - - case 'Z': - // On some platforms a bool is a byte, on others an int. - if (sizeof (jboolean) == sizeof (jbyte)) - return &ffi_type_sint8; - else - { - JvAssert (sizeof (jbyte) == sizeof (jint)); - return &ffi_type_sint32; - } - break; - - case 'B': - return &ffi_type_sint8; - break; - - case 'C': - return &ffi_type_uint16; - break; - - case 'S': - return &ffi_type_sint16; - break; - - case 'I': - return &ffi_type_sint32; - break; - - case 'J': - return &ffi_type_sint64; - break; - - case 'F': - return &ffi_type_float; - break; - - case 'D': - return &ffi_type_double; - break; - - case 'V': - return &ffi_type_void; - break; - } - - throw_internal_error ("unknown type in signature"); -} - -/* this function yields the number of actual arguments, that is, if the - * function is non-static, then one is added to the number of elements - * found in the signature */ - -int -_Jv_count_arguments (_Jv_Utf8Const *signature, - jboolean staticp) -{ - unsigned char *ptr = (unsigned char*) signature->chars(); - int arg_count = staticp ? 0 : 1; - - /* first, count number of arguments */ - - // skip '(' - ptr++; - - // count args - while (*ptr != ')') - { - ptr = skip_one_type (ptr); - arg_count += 1; - } - - return arg_count; -} - -/* This beast will build a cif, given the signature. Memory for - * the cif itself and for the argument types must be allocated by the - * caller. - */ - -int -_Jv_init_cif (_Jv_Utf8Const* signature, - int arg_count, - jboolean staticp, - ffi_cif *cif, - ffi_type **arg_types, - ffi_type **rtype_p) -{ - unsigned char *ptr = (unsigned char*) signature->chars(); - - int arg_index = 0; // arg number - int item_count = 0; // stack-item count - - // setup receiver - if (!staticp) - { - arg_types[arg_index++] = &ffi_type_pointer; - item_count += 1; - } - - // skip '(' - ptr++; - - // assign arg types - while (*ptr != ')') - { - arg_types[arg_index++] = get_ffi_type_from_signature (ptr); - - if (*ptr == 'J' || *ptr == 'D') - item_count += 2; - else - item_count += 1; - - ptr = skip_one_type (ptr); - } - - // skip ')' - ptr++; - ffi_type *rtype = get_ffi_type_from_signature (ptr); - - ptr = skip_one_type (ptr); - if (ptr != (unsigned char*)signature->chars() + signature->len()) - throw_internal_error ("did not find end of signature"); - - ffi_abi cabi = FFI_DEFAULT_ABI; -#if defined (X86_WIN32) && !defined (__CYGWIN__) - if (!staticp) - cabi = FFI_THISCALL; -#endif - if (ffi_prep_cif (cif, cabi, - arg_count, rtype, arg_types) != FFI_OK) - throw_internal_error ("ffi_prep_cif failed"); - - if (rtype_p != NULL) - *rtype_p = rtype; - - return item_count; -} - -/* we put this one here, and not in interpret.cc because it - * calls the utility routines _Jv_count_arguments - * which are static to this module. The following struct defines the - * layout we use for the stubs, it's only used in the ncode method. */ - -#if FFI_NATIVE_RAW_API -# define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure_loc -# define FFI_RAW_SIZE ffi_raw_size -typedef struct { - ffi_raw_closure closure; - _Jv_ClosureList list; - ffi_cif cif; - ffi_type *arg_types[0]; -} ncode_closure; -typedef void (*ffi_closure_fun) (ffi_cif*,void*,INTERP_FFI_RAW_TYPE*,void*); -#else -# define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure_loc -# define FFI_RAW_SIZE ffi_java_raw_size -typedef struct { - ffi_java_raw_closure closure; - _Jv_ClosureList list; - ffi_cif cif; - ffi_type *arg_types[0]; -} ncode_closure; -typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_java_raw*,void*); -#endif - -void * -_Jv_InterpMethod::ncode (jclass klass) -{ - using namespace java::lang::reflect; - - if (self->ncode != 0) - return self->ncode; - - jboolean staticp = (self->accflags & Modifier::STATIC) != 0; - int arg_count = _Jv_count_arguments (self->signature, staticp); - - void *code; - ncode_closure *closure = - (ncode_closure*)ffi_closure_alloc (sizeof (ncode_closure) - + arg_count * sizeof (ffi_type*), - &code); - closure->list.registerClosure (klass, closure); - - _Jv_init_cif (self->signature, - arg_count, - staticp, - &closure->cif, - &closure->arg_types[0], - NULL); - - ffi_closure_fun fun; - - args_raw_size = FFI_RAW_SIZE (&closure->cif); - - JvAssert ((self->accflags & Modifier::NATIVE) == 0); - - if ((self->accflags & Modifier::SYNCHRONIZED) != 0) - { - if (staticp) - { - if (JVMTI::enabled) - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class_debug; - else - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class; - } - else - { - if (JVMTI::enabled) - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object_debug; - else - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; - } - } - else - { - if (staticp) - { - if (JVMTI::enabled) - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class_debug; - else - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class; - } - else - { - if (JVMTI::enabled) - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal_debug; - else - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal; - } - } - - FFI_PREP_RAW_CLOSURE (&closure->closure, - &closure->cif, - fun, - (void*)this, - code); - - self->ncode = code; - - return self->ncode; -} - -/* Find the index of the given insn in the array of insn slots - for this method. Returns -1 if not found. */ -jlong -_Jv_InterpMethod::insn_index (pc_t pc) -{ - jlong left = 0; -#ifdef DIRECT_THREADED - jlong right = number_insn_slots; - pc_t insns = prepared; -#else - jlong right = code_length; - pc_t insns = bytecode (); -#endif - - while (right >= 0) - { - jlong mid = (left + right) / 2; - if (&insns[mid] == pc) - return mid; - - if (pc < &insns[mid]) - right = mid - 1; - else - left = mid + 1; - } - - return -1; -} - -// Method to check if an exception is caught at some location in a method -// (meth). Returns true if this method (meth) contains a catch block for the -// exception (ex). False otherwise. If there is a catch block, it sets the pc -// to the location of the beginning of the catch block. -jboolean -_Jv_InterpMethod::check_handler (pc_t *pc, _Jv_InterpMethod *meth, - java::lang::Throwable *ex) -{ -#ifdef DIRECT_THREADED - void *logical_pc = (void *) ((insn_slot *) (*pc) - 1); -#else - int logical_pc = (*pc) - 1 - meth->bytecode (); -#endif - _Jv_InterpException *exc = meth->exceptions (); - jclass exc_class = ex->getClass (); - - for (int i = 0; i < meth->exc_count; i++) - { - if (PCVAL (exc[i].start_pc) <= logical_pc - && logical_pc < PCVAL (exc[i].end_pc)) - { -#ifdef DIRECT_THREADED - jclass handler = (jclass) exc[i].handler_type.p; -#else - jclass handler = NULL; - if (exc[i].handler_type.i != 0) - handler - = (_Jv_Linker::resolve_pool_entry (meth->defining_class, - exc[i].handler_type.i)).clazz; -#endif /* DIRECT_THREADED */ - if (handler == NULL || handler->isAssignableFrom (exc_class)) - { -#ifdef DIRECT_THREADED - (*pc) = (insn_slot *) exc[i].handler_pc.p; -#else - (*pc) = meth->bytecode () + exc[i].handler_pc.i; -#endif /* DIRECT_THREADED */ - return true; - } - } - } - return false; -} - - -void -_Jv_InterpMethod::get_line_table (jlong& start, jlong& end, - jintArray& line_numbers, - jlongArray& code_indices) -{ -#ifdef DIRECT_THREADED - /* For the DIRECT_THREADED case, if the method has not yet been - * compiled, the linetable will change to insn slots instead of - * bytecode PCs. It is probably easiest, in this case, to simply - * compile the method and guarantee that we are using insn - * slots. - */ - _Jv_CompileMethod (this); - - if (line_table_len > 0) - { - start = 0; - end = number_insn_slots; - line_numbers = JvNewIntArray (line_table_len); - code_indices = JvNewLongArray (line_table_len); - - jint* lines = elements (line_numbers); - jlong* indices = elements (code_indices); - for (int i = 0; i < line_table_len; ++i) - { - lines[i] = line_table[i].line; - indices[i] = insn_index (line_table[i].pc); - } - } -#else // !DIRECT_THREADED - if (line_table_len > 0) - { - start = 0; - end = code_length; - line_numbers = JvNewIntArray (line_table_len); - code_indices = JvNewLongArray (line_table_len); - - jint* lines = elements (line_numbers); - jlong* indices = elements (code_indices); - for (int i = 0; i < line_table_len; ++i) - { - lines[i] = line_table[i].line; - indices[i] = (jlong) line_table[i].bytecode_pc; - } - } -#endif // !DIRECT_THREADED -} - -int -_Jv_InterpMethod::get_local_var_table (char **name, char **sig, - char **generic_sig, jlong *startloc, - jint *length, jint *slot, - int table_slot) -{ -#ifdef DIRECT_THREADED - _Jv_CompileMethod (this); -#endif - - if (local_var_table == NULL) - return -2; - if (table_slot >= local_var_table_len) - return -1; - else - { - *name = local_var_table[table_slot].name; - *sig = local_var_table[table_slot].descriptor; - *generic_sig = local_var_table[table_slot].descriptor; - -#ifdef DIRECT_THREADED - *startloc = insn_index (local_var_table[table_slot].pc); -#else - *startloc = static_cast<jlong> (local_var_table[table_slot].bytecode_pc); -#endif - *length = static_cast<jint> (local_var_table[table_slot].length); - *slot = static_cast<jint> (local_var_table[table_slot].slot); - } - return local_var_table_len - table_slot - 1; -} - -pc_t -_Jv_InterpMethod::install_break (jlong index) -{ - return set_insn (index, breakpoint_insn); -} - -pc_t -_Jv_InterpMethod::get_insn (jlong index) -{ - pc_t code; - -#ifdef DIRECT_THREADED - if (index >= number_insn_slots || index < 0) - return NULL; - - code = prepared; -#else // !DIRECT_THREADED - if (index >= code_length || index < 0) - return NULL; - - code = reinterpret_cast<pc_t> (bytecode ()); -#endif // !DIRECT_THREADED - - return &code[index]; -} - -pc_t -_Jv_InterpMethod::set_insn (jlong index, pc_t insn) -{ -#ifdef DIRECT_THREADED - if (index >= number_insn_slots || index < 0) - return NULL; - - pc_t code = prepared; - code[index].insn = insn->insn; -#else // !DIRECT_THREADED - if (index >= code_length || index < 0) - return NULL; - - pc_t code = reinterpret_cast<pc_t> (bytecode ()); - code[index] = *insn; -#endif // !DIRECT_THREADED - - return &code[index]; -} - -bool -_Jv_InterpMethod::breakpoint_at (jlong index) -{ - pc_t insn = get_insn (index); - if (insn != NULL) - { -#ifdef DIRECT_THREADED - return (insn->insn == breakpoint_insn->insn); -#else - pc_t code = reinterpret_cast<pc_t> (bytecode ()); - return (code[index] == bp_insn_opcode); -#endif - } - - return false; -} - -void * -_Jv_JNIMethod::ncode (jclass klass) -{ - using namespace java::lang::reflect; - - if (self->ncode != 0) - return self->ncode; - - jboolean staticp = (self->accflags & Modifier::STATIC) != 0; - int arg_count = _Jv_count_arguments (self->signature, staticp); - - void *code; - ncode_closure *closure = - (ncode_closure*)ffi_closure_alloc (sizeof (ncode_closure) - + arg_count * sizeof (ffi_type*), - &code); - closure->list.registerClosure (klass, closure); - - ffi_type *rtype; - _Jv_init_cif (self->signature, - arg_count, - staticp, - &closure->cif, - &closure->arg_types[0], - &rtype); - - ffi_closure_fun fun; - - args_raw_size = FFI_RAW_SIZE (&closure->cif); - - // Initialize the argument types and CIF that represent the actual - // underlying JNI function. - int extra_args = 1; - if ((self->accflags & Modifier::STATIC)) - ++extra_args; - jni_arg_types = (ffi_type **) _Jv_AllocBytes ((extra_args + arg_count) - * sizeof (ffi_type *)); - int offset = 0; - jni_arg_types[offset++] = &ffi_type_pointer; - if ((self->accflags & Modifier::STATIC)) - jni_arg_types[offset++] = &ffi_type_pointer; - memcpy (&jni_arg_types[offset], &closure->arg_types[0], - arg_count * sizeof (ffi_type *)); - - if (ffi_prep_cif (&jni_cif, _Jv_platform_ffi_abi, - extra_args + arg_count, rtype, - jni_arg_types) != FFI_OK) - throw_internal_error ("ffi_prep_cif failed for JNI function"); - - JvAssert ((self->accflags & Modifier::NATIVE) != 0); - - // FIXME: for now we assume that all native methods for - // interpreted code use JNI. - fun = (ffi_closure_fun) &_Jv_JNIMethod::call; - - FFI_PREP_RAW_CLOSURE (&closure->closure, - &closure->cif, - fun, - (void*) this, - code); - - self->ncode = code; - return self->ncode; -} - -static void -throw_class_format_error (jstring msg) -{ - jthrowable t = (msg - ? new java::lang::ClassFormatError (msg) - : new java::lang::ClassFormatError); - REPORT_EXCEPTION (t); - throw t; -} - -static void -throw_class_format_error (const char *msg) -{ - throw_class_format_error (JvNewStringLatin1 (msg)); -} - -/* This function finds the method and location where the exception EXC - is caught in the stack frame. On return, it sets CATCH_METHOD and - CATCH_LOCATION with the method and location where the catch will - occur. If the exception is not caught, these are set to 0. - - This function should only be used with the __GCJ_DEBUG interpreter. */ -static void -find_catch_location (::java::lang::Throwable *exc, jthread thread, - jmethodID *catch_method, jlong *catch_loc) -{ - *catch_method = 0; - *catch_loc = 0; - - _Jv_InterpFrame *frame - = reinterpret_cast<_Jv_InterpFrame *> (thread->interp_frame); - while (frame != NULL) - { - pc_t pc = frame->get_pc (); - _Jv_InterpMethod *imeth - = reinterpret_cast<_Jv_InterpMethod *> (frame->self); - if (imeth->check_handler (&pc, imeth, exc)) - { - // This method handles the exception. - *catch_method = imeth->get_method (); - *catch_loc = imeth->insn_index (pc); - return; - } - - frame = frame->next_interp; - } -} - -/* This method handles JVMTI notifications of thrown exceptions. It - calls find_catch_location to figure out where the exception is - caught (if it is caught). - - Like find_catch_location, this should only be called with the - __GCJ_DEBUG interpreter. Since a few exceptions occur outside the - interpreter proper, it is important to not call this function - without checking JVMTI_REQUESTED_EVENT(Exception) first. */ -void -_Jv_ReportJVMTIExceptionThrow (jthrowable ex) -{ - jthread thread = ::java::lang::Thread::currentThread (); - _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); - jmethodID throw_meth = frame->self->get_method (); - jlocation throw_loc = -1; - if (frame->frame_type == frame_interpreter) - { - _Jv_InterpFrame * iframe - = reinterpret_cast<_Jv_InterpFrame *> (frame); - _Jv_InterpMethod *imeth - = reinterpret_cast<_Jv_InterpMethod *> (frame->self); - throw_loc = imeth->insn_index (iframe->get_pc ()); - } - - jlong catch_loc; - jmethodID catch_method; - find_catch_location (ex, thread, &catch_method, &catch_loc); - _Jv_JVMTI_PostEvent (JVMTI_EVENT_EXCEPTION, thread, - _Jv_GetCurrentJNIEnv (), throw_meth, throw_loc, - ex, catch_method, catch_loc); -} - - - -void -_Jv_InterpreterEngine::do_verify (jclass klass) -{ - _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; - for (int i = 0; i < klass->method_count; i++) - { - using namespace java::lang::reflect; - _Jv_MethodBase *imeth = iclass->interpreted_methods[i]; - _Jv_ushort accflags = klass->methods[i].accflags; - if ((accflags & (Modifier::NATIVE | Modifier::ABSTRACT)) == 0) - { - _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth); - _Jv_VerifyMethod (im); - } - } -} - -void -_Jv_InterpreterEngine::do_create_ncode (jclass klass) -{ - _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; - for (int i = 0; i < klass->method_count; i++) - { - // Just skip abstract methods. This is particularly important - // because we don't resize the interpreted_methods array when - // miranda methods are added to it. - if ((klass->methods[i].accflags - & java::lang::reflect::Modifier::ABSTRACT) - != 0) - continue; - - _Jv_MethodBase *imeth = iclass->interpreted_methods[i]; - - if ((klass->methods[i].accflags & java::lang::reflect::Modifier::NATIVE) - != 0) - { - // You might think we could use a virtual `ncode' method in - // the _Jv_MethodBase and unify the native and non-native - // cases. Well, we can't, because we don't allocate these - // objects using `new', and thus they don't get a vtable. - _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth); - klass->methods[i].ncode = jnim->ncode (klass); - } - else if (imeth != 0) // it could be abstract - { - _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth); - klass->methods[i].ncode = im->ncode (klass); - } - } -} - -_Jv_ClosureList ** -_Jv_InterpreterEngine::do_get_closure_list (jclass klass) -{ - _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; - - if (!iclass->closures) - iclass->closures = _Jv_ClosureListFinalizer (); - - return iclass->closures; -} - -void -_Jv_InterpreterEngine::do_allocate_static_fields (jclass klass, - int pointer_size, - int other_size) -{ - _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; - - // Splitting the allocations here lets us scan reference fields and - // avoid scanning non-reference fields. How reference fields are - // scanned is a bit tricky: we allocate using _Jv_AllocRawObj, which - // means that this memory will be scanned conservatively (same - // difference, since we know all the contents here are pointers). - // Then we put pointers into this memory into the 'fields' - // structure. Most of these are interior pointers, which is ok (but - // even so the pointer to the first reference field will be used and - // that is not an interior pointer). The 'fields' array is also - // allocated with _Jv_AllocRawObj (see defineclass.cc), so it will - // be scanned. A pointer to this array is held by Class and thus - // seen by the collector. - char *reference_fields = (char *) _Jv_AllocRawObj (pointer_size); - char *non_reference_fields = (char *) _Jv_AllocBytes (other_size); - - for (int i = 0; i < klass->field_count; i++) - { - _Jv_Field *field = &klass->fields[i]; - - if ((field->flags & java::lang::reflect::Modifier::STATIC) == 0) - continue; - - char *base = field->isRef() ? reference_fields : non_reference_fields; - field->u.addr = base + field->u.boffset; - - if (iclass->field_initializers[i] != 0) - { - _Jv_Linker::resolve_field (field, klass->loader); - _Jv_InitField (0, klass, i); - } - } - - // Now we don't need the field_initializers anymore, so let the - // collector get rid of it. - iclass->field_initializers = 0; -} - -_Jv_ResolvedMethod * -_Jv_InterpreterEngine::do_resolve_method (_Jv_Method *method, jclass klass, - jboolean staticp) -{ - int arg_count = _Jv_count_arguments (method->signature, staticp); - - _Jv_ResolvedMethod* result = (_Jv_ResolvedMethod*) - _Jv_AllocBytes (sizeof (_Jv_ResolvedMethod) - + arg_count*sizeof (ffi_type*)); - - result->stack_item_count - = _Jv_init_cif (method->signature, - arg_count, - staticp, - &result->cif, - &result->arg_types[0], - NULL); - - result->method = method; - result->klass = klass; - - return result; -} - -void -_Jv_InterpreterEngine::do_post_miranda_hook (jclass klass) -{ - _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; - for (int i = 0; i < klass->method_count; i++) - { - // Just skip abstract methods. This is particularly important - // because we don't resize the interpreted_methods array when - // miranda methods are added to it. - if ((klass->methods[i].accflags - & java::lang::reflect::Modifier::ABSTRACT) - != 0) - continue; - // Miranda method additions mean that the `methods' array moves. - // We cache a pointer into this array, so we have to update. - iclass->interpreted_methods[i]->self = &klass->methods[i]; - } -} - -#ifdef DIRECT_THREADED -void -_Jv_CompileMethod (_Jv_InterpMethod* method) -{ - if (method->prepared == NULL) - { - if (JVMTI::enabled) - _Jv_InterpMethod::run_debug (NULL, NULL, method); - else - _Jv_InterpMethod::run (NULL, NULL, method); - } -} -#endif // DIRECT_THREADED |