You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2005/10/05 04:20:10 UTC
svn commit: r294974 [12/25] - in
/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm: ./ jchevm/
jchevm/doc/ jchevm/etc/ jchevm/include/ jchevm/java/ jchevm/java/org/
jchevm/java/org/dellroad/ jchevm/java/org/dellroad/jc/
jchevm/java/org/dellroad...
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/definitions.h
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/definitions.h?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/definitions.h (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/definitions.h Tue Oct 4 19:19:16 2005
@@ -0,0 +1,792 @@
+
+/*
+ * Copyright 2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: definitions.h,v 1.17 2005/05/24 01:09:38 archiecobbs Exp $
+ */
+
+#ifndef _DEFINITIONS_H_
+#define _DEFINITIONS_H_
+
+/*
+ * We like this definition for NULL because it generates more
+ * gcc compiler warnings than just plain "0" would.
+ */
+#undef NULL
+#define NULL ((void *)0)
+
+/*
+ * Round up 'x' to a multiple of 'y' (must be a power of two).
+ */
+#define _JC_ROUNDUP2(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
+
+/*
+ * Count how many 'y' required to cover 'x'.
+ */
+#define _JC_HOWMANY(x, y) (((x) + ((y) - 1)) / (y))
+
+/*
+ * Number of bits in a '_jc_word' type.
+ */
+#define _JC_BITS_PER_WORD (sizeof(_jc_word) << 3)
+
+/*
+ * Value of a hex digit.
+ */
+#define _JC_HEXVAL(c) (isdigit(c) ? (c) - '0' : tolower(c) - 'a' + 10)
+
+/*
+ * Name of the system thread group.
+ */
+#define _JC_SYSTEM_THREADGROUP_NAME "Internal"
+
+/*
+ * Thread status values.
+ *
+ * Each running thread is either running in Java mode or native mode.
+ * In native mode, the thread is not allowed to directly touch any VM state.
+ * In either case, the thread is "halting" if another thread wishes for
+ * it to halt. Once it does halt, it enters the halted state.
+ */
+enum {
+ _JC_THRDSTAT_RUNNING_NORMAL = 1, /* running in java mode */
+ _JC_THRDSTAT_HALTING_NORMAL, /* java, halt requested */
+ _JC_THRDSTAT_RUNNING_NONJAVA, /* running in native mode */
+ _JC_THRDSTAT_HALTING_NONJAVA, /* native, halt requested */
+ _JC_THRDSTAT_HALTED /* halted */
+};
+
+/*
+ * Thread interrupt status. These values are used to implement
+ * Thread.interrupt() and friends.
+ */
+enum {
+ _JC_INTERRUPT_CLEAR = 0, /* not interrupted, not interruptible */
+ _JC_INTERRUPT_INTERRUPTIBLE, /* sleeping away and interruptible */
+ _JC_INTERRUPT_SET, /* interrupted, but not handled yet */
+ _JC_INTERRUPT_INTERRUPTED, /* waking up to handle interruption */
+};
+
+/*
+ * Verbosity flags.
+ */
+enum {
+ _JC_VERBOSE_CLASS,
+ _JC_VERBOSE_GC,
+ _JC_VERBOSE_JNI,
+ _JC_VERBOSE_EXCEPTIONS,
+ _JC_VERBOSE_RESOLUTION,
+ _JC_VERBOSE_INIT,
+ _JC_VERBOSE_GEN,
+ _JC_VERBOSE_JNI_INVOKE,
+ _JC_VERBOSE_OBJ,
+ _JC_VERBOSE_MAX
+};
+
+/*
+ * Exceptions generated by the virtual machine itself.
+ * We have special handling for these to avoid recursively
+ * trying to throw the same exception over and over again.
+ */
+enum {
+ _JC_AbstractMethodError,
+ _JC_ArithmeticException,
+ _JC_ArrayIndexOutOfBoundsException,
+ _JC_ArrayStoreException,
+ _JC_ClassCastException,
+ _JC_ClassCircularityError,
+ _JC_ClassFormatError,
+ _JC_ClassNotFoundException,
+ _JC_CloneNotSupportedException,
+ _JC_ExceptionInInitializerError,
+ _JC_IOException,
+ _JC_IllegalAccessError,
+ _JC_IllegalAccessException,
+ _JC_IllegalArgumentException,
+ _JC_IllegalMonitorStateException,
+ _JC_IllegalThreadStateException,
+ _JC_IncompatibleClassChangeError,
+ _JC_InstantiationError,
+ _JC_InstantiationException,
+ _JC_InternalError,
+ _JC_InterruptedException,
+ _JC_InvocationTargetException,
+ _JC_LinkageError,
+ _JC_NegativeArraySizeException,
+ _JC_NoClassDefFoundError,
+ _JC_NoSuchFieldError,
+ _JC_NoSuchMethodError,
+ _JC_NullPointerException,
+ _JC_OutOfMemoryError,
+ _JC_StackOverflowError,
+ _JC_ThreadDeath,
+ _JC_UnsatisfiedLinkError,
+ _JC_UnsupportedClassVersionError,
+ _JC_VMEXCEPTION_MAX
+};
+
+/*
+ * Macros to convert between splay tree nodes and the larger
+ * structure containing the _jc_splay_node node structure.
+ */
+#define _JC_NODE2ITEM(tree, node) \
+ ((void *)((char *)(node) - (tree)->offset))
+#define _JC_ITEM2NODE(tree, item) \
+ ((_jc_splay_node *)((char *)(item) + (tree)->offset))
+
+/*
+ * Macros to convert between internal and JNI VM and thread pointers.
+ */
+#define _JC_ENV2JNI(env) \
+ ((JNIEnv *)((char *)(env) + _JC_OFFSETOF(_jc_env, jni_interface)))
+#define _JC_JNI2ENV(jni_ptr) \
+ ((_jc_env *)((char *)(jni_ptr) - _JC_OFFSETOF(_jc_env, jni_interface)))
+#define _JC_JVM2JNI(jvm) \
+ ((JavaVM *)((char *)(jvm) + _JC_OFFSETOF(_jc_jvm, jni_interface)))
+#define _JC_JNI2JVM(jni_ptr) \
+ ((_jc_jvm *)((char *)(jni_ptr) - _JC_OFFSETOF(_jc_jvm, jni_interface)))
+
+/*
+ * Some pseudo-bytecodes
+ */
+#define _JC_ldc_string 0xe0
+
+/*
+ * Lockword layout
+ * ---------------
+ *
+ * The lockword is a _jc_word (of which we only use the bottom 32 bits).
+ * The top bits are used for locking, the bottom for misc type info that
+ * helps us avoid dereferencing obj->type.
+ *
+ * Bits Meaning
+ * ---- -------
+ * 31 0 = lock is THIN, 1 = lock is FAT
+ * 16-30 FAT: fat lock ID
+ * 21-30 THIN: owner thread ID (or zero if not locked)
+ * 16-20 THIN: number of times locked - 1
+ * 10-15 Number of reference fields in object (0x3f = overflow)
+ * 9 Finalize bit: object requires finalization (heap objects only)
+ * 9 Visited bit: object seen this GC cycle (stack objects only)
+ * 8 Live bit: object is live (reachable from root set)
+ * 7 Keep bit: don't reclaim object (e.g., finalize() reachable)
+ * 6 Special bit: special GC handling required (e.g., ClassLoader)
+ * 5 0 = non-array, 1 = array
+ * 1-4 Array: element_type->flags & _JC_TYPE_MASK
+ * Non-array: _JC_TYPE_REFERENCE
+ * 0 Always 1 to distinguish from a reference (aligned pointer)
+ */
+#define _JC_LW_FAT_BIT 0x80000000
+#define _JC_LW_FAT_ID_MASK 0x7fff0000
+#define _JC_LW_FAT_ID_SHIFT 16
+#define _JC_LW_THIN_TID_MASK 0x7fe00000
+#define _JC_LW_THIN_TID_SHIFT 21
+#define _JC_LW_THIN_COUNT_MASK 0x001f0000
+#define _JC_LW_THIN_COUNT_SHIFT 16
+#define _JC_LW_INFO_MASK 0x0000ffff
+#define _JC_LW_INFO_SHIFT 0
+#define _JC_LW_REF_COUNT_MASK 0x0000fc00
+#define _JC_LW_REF_COUNT_SHIFT 10
+#define _JC_LW_FINALIZE_BIT 0x00000200
+#define _JC_LW_VISITED_BIT 0x00000200
+#define _JC_LW_LIVE_BIT 0x00000100
+#define _JC_LW_KEEP_BIT 0x00000080
+#define _JC_LW_SPECIAL_BIT 0x00000040
+#define _JC_LW_ARRAY_BIT 0x00000020
+#define _JC_LW_TYPE_MASK 0x0000001e
+#define _JC_LW_TYPE_SHIFT 1
+#define _JC_LW_ODD_BIT 0x00000001
+
+/* Macros for testing and extracting lockword bits */
+#define _JC_LW_TEST(w, bit) \
+ (((w) & _JC_LW_ ## bit ## _BIT) != 0)
+#define _JC_LW_EXTRACT(w, fld) \
+ (((_jc_word)(w) & _JC_LW_ ## fld ## _MASK) >> _JC_LW_ ## fld ## _SHIFT)
+#define _JC_LW_MAX(fld) \
+ (((_jc_word)_JC_LW_ ## fld ## _MASK >> _JC_LW_ ## fld ## _SHIFT) + 1)
+
+/* Hard limits derived from the sizes of the above bit fields */
+#define _JC_MAX_THREADS _JC_LW_MAX(THIN_TID)
+#define _JC_MAX_FATLOCKS _JC_LW_MAX(FAT_ID)
+#define _JC_MAX_THIN_RECURSION _JC_LW_MAX(THIN_COUNT)
+
+/*
+ * Access to special object fields.
+ */
+#ifndef NDEBUG
+#define _JC_VMFIELD(_vm, _obj, _class, _field, _type) \
+ ({ \
+ _jc_field *const _f = _vm->boot.fields._class._field; \
+ \
+ _JC_ASSERT(_jc_subclass_of((_obj), _f->class)); \
+ _JC_ASSERT(!_JC_ACC_TEST(_f, STATIC)); \
+ (_type *)((char *)(_obj) + _f->offset); \
+ })
+#define _JC_VMSTATICFIELD(_vm, _class, _field, _type) \
+ ({ \
+ _jc_field *const _f = _vm->boot.fields._class._field; \
+ \
+ _JC_ASSERT(_JC_ACC_TEST(_f, STATIC)); \
+ (_type *)((char *)_vm->boot.types._class->u.nonarray \
+ .class_fields + _vm->boot.fields._class._field->offset); \
+ })
+#else
+#define _JC_VMFIELD(_vm, _obj, _class, _field, _type) \
+ ((_type *)((char *)(_obj) \
+ + _vm->boot.fields._class._field->offset))
+#define _JC_VMSTATICFIELD(_vm, _class, _field, _type) \
+ ((_type *)((char *)_vm->boot.types._class->u.nonarray \
+ .class_fields + _vm->boot.fields._class._field->offset))
+#endif
+
+/*
+ * How many references in a native reference frame.
+ *
+ * Do not change this, as the structure of 'struct _jc_native_frame'
+ * depends on it.
+ */
+#define _JC_NATIVE_REFS_PER_FRAME 29
+#define _JC_NATIVE_REFS_MIN_PER_FRAME 16 /* per the JNI spec */
+
+/*
+ * Maximum number of free thread structures to keep around.
+ */
+#define _JC_MAX_FREE_THREADS 128
+
+/*
+ * Length of thread status buffer (used for debugging).
+ */
+#define _JC_MAX_TEXT_STATUS 64
+
+/*
+ * Size of an uni-allocator page header.
+ */
+#define _JC_UNI_HDR_SIZE \
+ _JC_ROUNDUP2(sizeof(_jc_uni_pages), _JC_FULL_ALIGNMENT)
+
+/*
+ * Minimum number of uni-allocator pages to grab when additional
+ * class loader memory is needed.
+ */
+#define _JC_CL_ALLOC_MIN_PAGES 32
+
+/*
+ * How many class loader implicit references to allocate at a time
+ */
+#define _JC_CL_ALLOC_IMPLICIT_REFS 32
+
+/*
+ * Short name for internal java.lang native library.
+ */
+#define _JC_INTERNAL_NATIVE_LIBRARY "JC virtual machine"
+
+/*
+ * Number of pages to reserve for low memory situations where
+ * an OutOfMemoryError must be thrown.
+ */
+#define _JC_HEAP_RESERVED_PAGES 10
+
+/*
+ * How many heap pages to initialize at a time
+ */
+#define _JC_HEAP_INIT_PAGES(heap) \
+ ((heap)->num_pages == 0 ? \
+ (2 * 1024 * 1024 / _JC_PAGE_SIZE) : \
+ (heap)->max_pages / 8)
+
+/*
+ * Minimum number of references an object must contain before we
+ * consider putting in a skip word at the beginning of the heap block.
+ */
+#define _JC_SKIPWORD_MIN_REFS 3
+
+/*
+ * Bits defined for 'flags' field in a native reference frame.
+ * The lower three bits are defined here. The top 29 bits are
+ * used as a free entry bitmap.
+ */
+#define _JC_NATIVE_REF_ODD_BIT 0x00000001
+#define _JC_NATIVE_REF_STACK_ALLOC 0x00000002
+#define _JC_NATIVE_REF_EXTENSION 0x00000004
+#define _JC_NATIVE_REF_FREE_BITS 0xfffffff8
+
+#define _JC_NATIVE_REF_IS_FREE(frame, i) \
+ (((frame)->flags & (1 << (i + 3))) != 0)
+#define _JC_NATIVE_REF_ANY_FREE(frame) \
+ (((frame)->flags & _JC_NATIVE_REF_FREE_BITS) != 0)
+#define _JC_NATIVE_REF_ANY_USED(frame) \
+ (((frame)->flags & _JC_NATIVE_REF_FREE_BITS) \
+ != _JC_NATIVE_REF_FREE_BITS)
+#define _JC_NATIVE_REF_MARK_FREE(frame, i) \
+ ((frame)->flags |= (1 << (i + 3)))
+#define _JC_NATIVE_REF_MARK_IN_USE(frame, i) \
+ ((frame)->flags &= ~(1 << (i + 3)))
+
+/*
+ * ELF types (32/64 bit)
+ */
+#undef Elf_Addr
+#undef Elf_Ehdr
+#undef Elf_Off
+#undef Elf_Rel
+#undef Elf_Rela
+#undef Elf_Shdr
+#undef Elf_Word
+#undef Elf_Sym
+#undef ELF_R_TYPE
+#undef ELF_R_SYM
+#if _JC_ELF_CLASS == ELFCLASS32
+#define Elf_Addr Elf32_Addr
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Off Elf32_Off
+#define Elf_Rel Elf32_Rel
+#define Elf_Rela Elf32_Rela
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Word Elf32_Word
+#define Elf_Sym Elf32_Sym
+#define ELF_R_TYPE(x) ELF32_R_TYPE(x)
+#define ELF_R_SYM(x) ELF32_R_SYM(x)
+#elif _JC_ELF_CLASS == ELFCLASS64
+#define Elf_Addr Elf64_Addr
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Off Elf64_Off
+#define Elf_Rel Elf64_Rel
+#define Elf_Rela Elf64_Rela
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Word Elf64_Word
+#define Elf_Sym Elf64_Sym
+#define ELF_R_TYPE(x) ELF64_R_TYPE(x)
+#define ELF_R_SYM(x) ELF64_R_SYM(x)
+#else
+#error "Invalid value for _JC_ELF_CLASS"
+#endif
+
+/*
+ * Supported ELF line info debug sections supported.
+ */
+enum {
+ _JC_LINE_DEBUG_NONE,
+ _JC_LINE_DEBUG_DWARF1,
+ _JC_LINE_DEBUG_DWARF2,
+ _JC_LINE_DEBUG_STABS,
+};
+
+/* Stabs debugging section entry types */
+#define STAB_FUN 0x24
+#define STAB_SLINE 0x44
+
+/* DWARF 2.0 .debug_line sections definitions (partial list) */
+#define DW_LNE_end_sequence 1
+#define DW_LNE_set_address 2
+#define DW_LNS_copy 1
+#define DW_LNS_advance_pc 2
+#define DW_LNS_advance_line 3
+#define DW_LNS_const_add_pc 8
+#define DW_LNS_fixed_advance_pc 9
+
+/* Size of one page */
+#define _JC_PAGE_SIZE (1 << _JC_PAGE_SHIFT)
+
+/* Convert page index to _jc_word pointer */
+#define _JC_PAGE_ADDR(ptr, i) \
+ ((_jc_word *)((char *)(ptr) + (i) * _JC_PAGE_SIZE))
+
+/* Convert page pointer to page index */
+#define _JC_PAGE_INDEX(heap, ptr) \
+ (((char *)(ptr) - (char *)(heap)->pages) / _JC_PAGE_SIZE)
+
+/*
+ * Heap page info layout
+ * ---------------------
+ *
+ * Each page of the heap has an info word at its beginning, except for
+ * pages that are the second or later pages in a multi-page large object.
+ *
+ * Bits Meaning
+ * ---- -------
+ * 30-31 00 = free, 01 = small, 10 = large, 11 = being allocated
+ * 24-29 SMALL: block size index
+ * 0-23 SMALL: next page in list (all ones for end of list)
+ * 0-29 LARGE: number of pages in the range
+ * 0-29 ALLOC: number of pages in the range being allocated
+ */
+#define _JC_HEAP_PTYPE_MASK 0xc0000000
+#define _JC_HEAP_PTYPE_SHIFT 30
+#define _JC_HEAP_NPAGES_MASK 0x3fffffff
+#define _JC_HEAP_NPAGES_SHIFT 0
+#define _JC_HEAP_BSI_MASK 0x3f000000
+#define _JC_HEAP_BSI_SHIFT 24
+#define _JC_HEAP_NEXT_MASK 0x00ffffff
+#define _JC_HEAP_NEXT_SHIFT 0
+
+/*
+ * Heap page types, contained in the 'PTYPE' bits.
+ */
+#define _JC_HEAP_PAGE_FREE 0
+#define _JC_HEAP_PAGE_SMALL 1
+#define _JC_HEAP_PAGE_LARGE 2
+#define _JC_HEAP_PAGE_ALLOC 3
+
+/*
+ * Heap block header/skip word (optional).
+ */
+#define _JC_HEAP_BTYPE_MASK 0x0000001f
+#define _JC_HEAP_BTYPE_SHIFT 0
+#define _JC_HEAP_SKIP_MASK 0xffffffe0
+#define _JC_HEAP_SKIP_SHIFT 5
+
+/*
+ * Values for BTYPE bits in the first word of a heap block.
+ *
+ * In the case of _JC_HEAP_BLOCK_SKIP, the upper 27 bits contain the offset
+ * in words from the start of the heap block to the object header.
+ *
+ * If the value of BTYPE is other than listed here, then the first word
+ * of the block is also the first word of the object.
+ */
+#define _JC_HEAP_BLOCK_FREE 0x00000001 /* free block */
+#define _JC_HEAP_BLOCK_ALLOC 0x00000003 /* being allocated */
+#define _JC_HEAP_BLOCK_SKIP 0x0000001f /* skipword + object */
+
+/* Macros for extracting heap bits */
+#define _JC_HEAP_EXTRACT(w, fld) \
+ (((_jc_word)(w) & _JC_HEAP_ ## fld ## _MASK) \
+ >> _JC_HEAP_ ## fld ## _SHIFT)
+#define _JC_HEAP_MAX(fld) \
+ (((_jc_word)_JC_HEAP_ ## fld ## _MASK \
+ >> _JC_HEAP_ ## fld ## _SHIFT) + 1)
+
+/* Determine if two pointers point within the same page */
+#define _JC_HEAP_SAME_PAGE(ptr1, ptr2) \
+ ((((_jc_word)(ptr1) ^ (_jc_word)(ptr2)) \
+ & ~(_JC_PAGE_SIZE - 1)) == 0)
+
+/* Determine if an address lies within heap memory */
+#define _JC_IN_HEAP(heap, addr) \
+ ((char *)(addr) >= (char *)(heap)->pages \
+ && (char *)(addr) < (char *)(heap)->pages \
+ + ((heap)->num_pages * _JC_PAGE_SIZE))
+
+/* Offset from the start of a heap page to the start of the first block */
+#define _JC_HEAP_BLOCK_OFFSET \
+ (_JC_HOWMANY(sizeof(_jc_word), _JC_FULL_ALIGNMENT) * _JC_FULL_ALIGNMENT)
+
+/*
+ * Random portability fixes.
+ */
+#ifndef ULLONG_MAX
+#define ULLONG_MAX (~(unsigned long long)0)
+#endif
+#ifndef SIZE_T_MAX
+#define SIZE_T_MAX (~(size_t)0)
+#endif
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#ifdef PRIxFAST64
+#define _JC_JLONG_FMT PRIxFAST64
+#else
+#define _JC_JLONG_FMT "llx" /* a guess */
+#endif
+#endif /* HAVE_INTTYPES_H */
+
+#define _JC_LIBRARY_PATH _JC_CLASSPATH_HOME "/lib/classpath"
+#define _JC_INCLUDE_DIR _AC_INCLUDEDIR "/jc"
+#define _JC_BOOT_SOURCE_DIR _AC_DATADIR "/jc/src"
+#define _JC_BOOT_OBJECT_DIR _AC_LIBDIR "/jc/obj"
+
+#define _JC_BOOT_CLASS_PATH \
+ _AC_DATADIR "/jc/jc.zip" \
+ _JC_PATH_SEPARATOR _JC_CLASSPATH_HOME "/share/classpath/glibj.zip" \
+ _JC_PATH_SEPARATOR _AC_DATADIR \
+ "/jc/sootclasses-" SOOT_VERSION ".jar" \
+ _JC_PATH_SEPARATOR _AC_DATADIR \
+ "/jc/jasminclasses-sable-" JASMIN_VERSION ".jar" \
+ _JC_PATH_SEPARATOR _AC_DATADIR \
+ "/jc/polyglot-" POLYGLOT_VERSION ".jar"
+
+/*
+ * Core classes that must be loaded by the boot loader.
+ */
+#define _JC_CORE_CLASS(name) \
+ (strncmp((name), "java/", 5) == 0 \
+ || strncmp((name), "gnu/java/", 9) == 0)
+
+/*
+ * Package object file name
+ */
+#define _JC_PACKAGE_OBJECT_NAME "_package.o"
+
+/*
+ * Class path entry types.
+ */
+#define _JC_CPATH_UNKNOWN 0
+#define _JC_CPATH_DIRECTORY 1
+#define _JC_CPATH_ZIPFILE 2
+#define _JC_CPATH_ERROR 3
+
+/*
+ * Object path entry types.
+ */
+#define _JC_OBJPATH_UNKNOWN 0
+#define _JC_OBJPATH_DIRECTORY 1
+#define _JC_OBJPATH_ELFFILE 2
+#define _JC_OBJPATH_ERROR 3
+
+/*
+ * Macro to check if a PC value lies within a method.
+ */
+#define _JC_INMETHOD(meth, pc) \
+ ((pc) > (meth)->function && (pc) <= (meth)->function_end)
+
+/*
+ * Array bounds check for offset + length. Returns true if bounds are OK.
+ *
+ * We have to be careful because of potential 32-bit overflow.
+ */
+#define _JC_BOUNDS_CHECK(ary, off, len) \
+ ({ \
+ const jint _alen = (ary)->length; \
+ const jint _off = (off); \
+ const jint _len = (len); \
+ const jint _end = (_off + _len); \
+ \
+ ((_len | _off | _end) >= 0) && _end <= _alen; \
+ })
+
+/*
+ * _JC_FULL_ALIGNMENT is the minimum alignment that satisfies all alignment
+ * requirements. This is also the aligment guaranteed by malloc().
+ */
+struct _jc_align {
+ char c;
+ _jc_value u;
+};
+#define _JC_FULL_ALIGNMENT \
+ ((char *)&((struct _jc_align *)0)->u - (char *)0)
+
+/* Bit mask for page alignment */
+#define _JC_PAGE_MASK (_JC_PAGE_SIZE - 1)
+
+/*
+ * ELF symbol resolver function type.
+ */
+typedef jint _jc_elf_resolver(_jc_env *env, void *arg,
+ const char *name, Elf_Addr *result);
+
+/*
+ * Splay tree node comparision function type.
+ */
+typedef int _jc_splay_cmp_t(const void *item1, const void *item2);
+
+/*
+ * Store exception information in the thread structure.
+ */
+#define _JC_EX_STORE(env, e, fmt, args...) \
+ do { \
+ _jc_env *const _env = (env); \
+ \
+ _env->ex.num = _JC_ ## e; \
+ snprintf(_env->ex.msg, sizeof(_env->ex.msg), fmt , ## args); \
+ } while (0)
+
+/*
+ * Allocate some memory on the stack, and throw a StackOverflowError
+ * if that fails. This does not directly check for stack overflow, which
+ * is especially hard to do in native threads. We rely on "reasonable"
+ * values being allocated, within the stack space used by internal code.
+ *
+ * If unsuccessful an exception is stored (not posted).
+ */
+#define _JC_STACK_ALLOC(env, size) \
+ ({ \
+ _jc_env *const _env = (env); \
+ void *_mem; \
+ \
+ if ((_mem = alloca(size)) == NULL) { \
+ _env->ex.num = _JC_StackOverflowError; \
+ *_env->ex.msg = '\0'; \
+ } \
+ _mem; \
+ })
+
+/*
+ * Macros for formatting arbitrary strings into stack-allocated buffers.
+ *
+ * If unsuccessful an exception is stored (not posted).
+ */
+#define _JC_FORMAT_STRING(env, fmt, args...) \
+ ({ \
+ const char *const _fmt = (fmt); \
+ size_t _len; \
+ char *_buf; \
+ \
+ /* Print into nonexistent buffer to compute length */ \
+ _len = snprintf(NULL, 0, _fmt , ## args); \
+ \
+ /* Allocate buffer, then print into it */ \
+ if ((_buf = _JC_STACK_ALLOC((env), _len + 1)) != NULL) \
+ sprintf(_buf, _fmt , ## args); \
+ \
+ /* Return buffer */ \
+ _buf; \
+ })
+
+#define _JC_FORMAT_STRINGV(env, fmt, args) \
+ ({ \
+ const char *const _fmt = (fmt); \
+ const va_list _args = (args); \
+ size_t _len; \
+ char *_buf; \
+ \
+ /* Print into nonexistent buffer to compute length */ \
+ _len = vsnprintf(NULL, 0, _fmt, _args); \
+ \
+ /* Allocate buffer, then print into it */ \
+ if ((_buf = _JC_STACK_ALLOC((env), _len + 1)) != NULL) \
+ vsprintf(_buf, _fmt, _args); \
+ \
+ /* Return buffer */ \
+ _buf; \
+ })
+
+/*
+ * Macro for testing class, field, or method access flags.
+ */
+#define _JC_ACC_TEST(thing, flag) \
+ (((thing)->access_flags & _JC_ACC_ ## flag) != 0)
+#define _JC_FLG_TEST(thing, flag) \
+ (((thing)->flags & _JC_TYPE_ ## flag) != 0)
+
+/*
+ * Assertion macro.
+ */
+#ifndef NDEBUG
+#define _JC_ASSERT(x) \
+ do { \
+ if (!(x)) { \
+ fprintf(stderr, "jc: assertion failure: %s\n", #x); \
+ fprintf(stderr, "jc: location: file `%s' line %d\n", \
+ __FILE__, __LINE__); \
+ abort(); \
+ } \
+ } while (0)
+#else
+#define _JC_ASSERT(x) do { } while (0)
+#endif
+
+/*
+ * Mutex macros, in debugging and normal versions.
+ */
+#ifndef NDEBUG
+#define _JC_MUTEX_LOCK(env, mutex) \
+ do { \
+ pthread_mutex_t *const _mutex = &(mutex); \
+ _jc_env *const _env = (env); \
+ int _r; \
+ \
+ _JC_ASSERT(_env == NULL || (mutex ## _owner) != _env); \
+ _r = pthread_mutex_lock(_mutex); \
+ _JC_ASSERT(_r == 0); \
+ (mutex ## _owner) = _env; \
+ } while (0)
+#define _JC_MUTEX_UNLOCK(env, mutex) \
+ do { \
+ pthread_mutex_t *const _mutex = &(mutex); \
+ _jc_env *const _env = (env); \
+ int _r; \
+ \
+ _JC_ASSERT((mutex ## _owner) == _env); \
+ (mutex ## _owner) = NULL; \
+ _r = pthread_mutex_unlock(_mutex); \
+ _JC_ASSERT(_r == 0); \
+ } while (0)
+#define _JC_MUTEX_ASSERT(env, mutex) \
+ do { \
+ _JC_ASSERT((mutex ## _owner) == (env)); \
+ } while (0)
+#define _JC_COND_WAIT(env, cond, mutex) \
+ do { \
+ pthread_cond_t *const _cond = &(cond); \
+ pthread_mutex_t *const _mutex = &(mutex); \
+ _jc_env *const _env = (env); \
+ int _r; \
+ \
+ _JC_ASSERT((mutex ## _owner) == _env); \
+ (mutex ## _owner) = NULL; \
+ _r = pthread_cond_wait(_cond, _mutex); \
+ _JC_ASSERT(_r == 0); \
+ _JC_ASSERT((mutex ## _owner) == NULL); \
+ (mutex ## _owner) = _env; \
+ } while (0)
+#define _JC_COND_TIMEDWAIT(env, cond, mutex, wakeup) \
+ do { \
+ pthread_cond_t *const _cond = &(cond); \
+ pthread_mutex_t *const _mutex = &(mutex); \
+ _jc_env *const _env = (env); \
+ int _r; \
+ \
+ _JC_ASSERT((mutex ## _owner) == _env); \
+ (mutex ## _owner) = NULL; \
+ _r = pthread_cond_timedwait(_cond, _mutex, (wakeup)); \
+ _JC_ASSERT(_r == 0 || _r == ETIMEDOUT); \
+ _JC_ASSERT((mutex ## _owner) == NULL); \
+ (mutex ## _owner) = _env; \
+ } while (0)
+#define _JC_COND_SIGNAL(cond) \
+ do { \
+ pthread_cond_t *const _cond = &(cond); \
+ int _r; \
+ \
+ _r = pthread_cond_signal(_cond); \
+ _JC_ASSERT(_r == 0); \
+ } while (0)
+#define _JC_COND_BROADCAST(cond) \
+ do { \
+ pthread_cond_t *const _cond = &(cond); \
+ int _r; \
+ \
+ _r = pthread_cond_broadcast(_cond); \
+ _JC_ASSERT(_r == 0); \
+ } while (0)
+
+#else
+
+#define _JC_MUTEX_LOCK(env, mutex) pthread_mutex_lock(&(mutex))
+#define _JC_MUTEX_UNLOCK(env, mutex) pthread_mutex_unlock(&(mutex))
+#define _JC_MUTEX_ASSERT(env, mutex) do { } while (0)
+#define _JC_COND_WAIT(env, cond, mutex) \
+ pthread_cond_wait(&(cond), &(mutex))
+#define _JC_COND_TIMEDWAIT(env, cond, mutex, wakeup) \
+ pthread_cond_timedwait(&(cond), &(mutex), (wakeup))
+#define _JC_COND_SIGNAL(cond) pthread_cond_signal(&(cond))
+#define _JC_COND_BROADCAST(cond) pthread_cond_broadcast(&(cond))
+#endif /* NDEBUG */
+
+/*
+ * Verbosity.
+ */
+#define VERBOSE_INDX(indx, vm, fmt, args...) \
+ do { \
+ if (((vm)->verbose_flags & (1 << (indx))) != 0) { \
+ _jc_printf((vm), "[verbose %s: " fmt "]\n", \
+ _jc_verbose_names[indx] , ## args); \
+ } \
+ } while (0)
+
+#define VERBOSE(flag, vm, fmt, args...) \
+ VERBOSE_INDX(_JC_VERBOSE_ ## flag, vm, fmt , ## args)
+
+#endif /* _DEFINITIONS_H_ */
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/derive.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/derive.c?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/derive.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/derive.c Tue Oct 4 19:19:16 2005
@@ -0,0 +1,903 @@
+
+/*
+ * Copyright 2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: derive.c,v 1.20 2005/05/10 14:41:38 archiecobbs Exp $
+ */
+
+#include "libjc.h"
+
+/* Internal functions */
+static jint _jc_derive_type(_jc_env *env, _jc_type *type,
+ _jc_type_node *node);
+static void _jc_underive_type(_jc_env *env, _jc_type *type,
+ _jc_type_node *node);
+
+/*
+ * List of types that need to be specially recognized during garbage
+ * collection in order to handle implicit references. All under java.lang.
+ */
+static const char *const _jc_special_classes[] = {
+ "Class",
+ "ClassLoader",
+ "VMThrowable",
+ "ref/Reference",
+ NULL
+};
+
+/*
+ * Given the bytes of a class file, derive the internal representation
+ * of the corresponding Java run-time type. This assumes the type node
+ * is in the loader's initiating types tree. We try to either find the
+ * type structure in an ELF file (possibly generating it on demand), or
+ * else we create one from the class file.
+ *
+ * If successful, the type is added to both the class loader's
+ * initiated and defined types trees.
+ *
+ * If unsuccessful, an exception is posted.
+ */
+_jc_type *
+_jc_derive_type_from_classfile(_jc_env *env, _jc_class_loader *loader,
+ const char *name, _jc_classbytes *cbytes)
+{
+ _jc_jvm *const vm = env->vm;
+ jboolean deriving_node = JNI_FALSE;
+ _jc_type *const key = (_jc_type *)((char *)&name
+ - _JC_OFFSETOF(_jc_type, name));
+ _jc_super_info *supers = NULL;
+ _jc_class_node *cnode = NULL;
+ _jc_classfile *cfile;
+ _jc_type_node node;
+ _jc_type *type = NULL;
+ _jc_type *stype;
+ int i;
+
+ /* Parse class file */
+ if ((cfile = _jc_parse_classfile(env, cbytes, 1)) == NULL) {
+ _jc_post_exception_info(env);
+ goto fail;
+ }
+
+ /*
+ * If name not explicitly supplied, get it from the classfile.
+ * Otherwise, verify that the name matches what we expect.
+ */
+ if (name == NULL)
+ name = cfile->name;
+ else if (strcmp(cfile->name, name) != 0) {
+ _jc_post_exception_msg(env, _JC_NoClassDefFoundError,
+ "class file for `%s' actually defines `%s'",
+ name, cfile->name);
+ goto fail;
+ }
+
+ /* The bootstrap loader must always be used for core Java types */
+ if (loader != vm->boot.loader && _JC_CORE_CLASS(name)) {
+ _jc_post_exception_msg(env, _JC_LinkageError,
+ "type `%s' must be defined by the bootstrap loader", name);
+ goto fail;
+ }
+
+ /* Lock VM */
+ _JC_MUTEX_LOCK(env, vm->mutex);
+
+ /* Add class file to VM class file tree */
+ if ((cnode = _jc_ref_class_node(env,
+ name, cbytes->hash, cbytes)) == NULL) {
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+ _jc_post_exception_info(env);
+ return NULL;
+ }
+
+ /* Unlock VM */
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+
+ /* Create a temporary fake type node for the deriving types tree */
+ memset(&node, 0, sizeof(node));
+ node.type = (_jc_type *)((char *)&name - _JC_OFFSETOF(_jc_type, name));
+
+ /* Lock loader */
+ _JC_MUTEX_LOCK(env, loader->mutex);
+
+ /* Has this loader already been recorded as an initiating loader? */
+ if (_jc_splay_find(&loader->initiated_types, &node) != NULL) {
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+ _jc_post_exception_msg(env, _JC_LinkageError,
+ "type `%s' has already been defined", name);
+ goto fail;
+ }
+
+ /* Detect attempts to recursively derive the same type */
+ if (_jc_splay_find(&loader->deriving_types, &node) != NULL) {
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+ _jc_post_exception_msg(env, _JC_ClassCircularityError,
+ "class `%s'", name);
+ goto fail;
+ }
+
+ /* Sanity check */
+ _JC_ASSERT(_jc_splay_find(&loader->defined_types, node.type) == NULL);
+
+ /* Add node to partially derived types tree */
+ _jc_splay_insert(&loader->deriving_types, &node);
+ deriving_node = JNI_TRUE;
+
+ /* Unlock loader */
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+
+ /* Allocate structure for temporarily saving super types */
+ if (!vm->loader_enabled || !vm->generation_enabled) {
+ if ((supers = _jc_vm_alloc(env,
+ sizeof(*supers) + cfile->num_interfaces
+ * sizeof(*supers->interfaces))) == NULL) {
+ _jc_post_exception_info(env);
+ goto fail;
+ }
+ }
+
+ /* Skip loading superclass for java.lang.Object */
+ if (cfile->superclass == NULL) {
+ stype = NULL;
+ goto no_superclass;
+ }
+
+ /* Load and validate superclass */
+ if ((stype = _jc_load_type(env, loader, cfile->superclass)) == NULL)
+ goto fail;
+ if ((_JC_ACC_TEST(cfile, INTERFACE) && stype != vm->boot.types.Object)
+ || (stype->access_flags & (_JC_ACC_INTERFACE|_JC_ACC_FINAL)) != 0) {
+ _jc_post_exception_msg(env, _JC_IncompatibleClassChangeError,
+ "%s `%s' cannot be the superclass of `%s'",
+ _JC_ACC_TEST(stype, INTERFACE) ?
+ "interface" : "final class", stype->name, name);
+ goto fail;
+ }
+ if (supers != NULL)
+ supers->superclass = stype;
+
+no_superclass:
+ /* Load and validate superinterfaces */
+ for (i = 0; i < cfile->num_interfaces; i++) {
+ _jc_type *siface;
+
+ if ((siface = _jc_load_type(env,
+ loader, cfile->interfaces[i])) == NULL)
+ goto fail;
+ if (!_JC_ACC_TEST(siface, INTERFACE)) {
+ _jc_post_exception_msg(env,
+ _JC_IncompatibleClassChangeError, "non-interface"
+ " class `%s' cannot be a superinterface of `%s'",
+ siface->name, name);
+ goto fail;
+ }
+ if (supers != NULL)
+ supers->interfaces[i] = siface;
+ }
+
+ /* Loading supertypes may have loaded ELF object with type as well */
+ _JC_MUTEX_LOCK(env, loader->mutex);
+ type = _jc_splay_find(&loader->defined_types, key);
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+ if (type != NULL)
+ goto done;
+
+ /* If the ELF loader is disabled, we must interpret */
+ if (!vm->loader_enabled)
+ goto create_type;
+
+ /* Try to load an ELF object containing the type */
+ if (_jc_load_object(env, loader, name) == JNI_OK)
+ goto find_type;
+
+ /* If something unexpected happened, bail out */
+ if (env->ex.num != _JC_LinkageError) {
+ _jc_post_exception_info(env);
+ goto fail;
+ }
+
+ /* If on-demand object generation is disabled, interpret */
+ if (!vm->generation_enabled)
+ goto create_type;
+
+ /* Generate a new ELF object file for this class */
+ if (_jc_generate_object(env, loader, name) != JNI_OK)
+ goto fail;
+
+ /* Try again to load object file containing the type */
+ if (_jc_load_object(env, loader, name) != JNI_OK) {
+ _jc_post_exception_info(env);
+ goto fail;
+ }
+
+find_type:
+ /*
+ * We've done our best to load the right ELF object.
+ * Look in the types tree to see if our type is there.
+ */
+ _JC_MUTEX_LOCK(env, loader->mutex);
+ type = _jc_splay_find(&loader->defined_types, key);
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+ if (type == NULL) {
+ _jc_post_exception_msg(env, _JC_LinkageError,
+ "no ELF object found containing `%s'", name);
+ goto fail;
+ }
+
+ /* Save super types (so we can access them before resolution) */
+ type->u.nonarray.supers = supers;
+ supers = NULL;
+
+ /* Done */
+ goto done;
+
+create_type:
+ /*
+ * We are unable or unwilling to find or create an ELF object.
+ * We must interpret this Java class.
+ */
+ if ((type = _jc_derive_type_interp(env, loader, cbytes)) == NULL) {
+ _jc_post_exception_info(env);
+ goto fail;
+ }
+ goto done;
+
+fail:
+ _JC_ASSERT(type == NULL);
+
+done:
+ /* Remove node from the loader's deriving types tree */
+ if (deriving_node) {
+ _JC_MUTEX_LOCK(env, loader->mutex);
+ _jc_splay_remove(&loader->deriving_types, &node);
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+ }
+
+ /* Unreference class file in VM class file tree */
+ _JC_MUTEX_LOCK(env, vm->mutex);
+ _jc_unref_class_node(vm, &cnode);
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+
+ /* Destroy parsed class file */
+ _jc_destroy_classfile(&cfile);
+
+ /* If this thread wants to save class file, save it */
+ if (type == NULL) {
+ _jc_class_save *csave;
+
+ for (csave = env->class_save;
+ csave != NULL; csave = csave->next) {
+ if (strcmp(csave->name, name) == 0) {
+ _JC_ASSERT(csave->bytes == NULL);
+ csave->bytes = _jc_dup_classbytes(cbytes);
+ break;
+ }
+ }
+ }
+
+ /* Free leftover supers info (if any) */
+ _jc_vm_free(&supers);
+
+ /* Done */
+ _JC_ASSERT(type == NULL || _JC_FLG_TEST(type, LOADED));
+ return type;
+}
+
+/*
+ * Given an object file, load all the types defined in that file at once.
+ *
+ * If unsuccessful an exception is stored.
+ */
+jint
+_jc_derive_types_from_object(_jc_env *env, _jc_elf *elf)
+{
+ _jc_jvm *const vm = env->vm;
+ const int num_types = elf->types.size;
+ _jc_class_loader *const loader = elf->loader;
+ _jc_type_node *nodes = NULL;
+ _jc_type **types;
+ int i;
+
+ /* Get the list of types defined in this object */
+ if ((types = _JC_STACK_ALLOC(env, num_types * sizeof(*types))) == NULL)
+ return JNI_ERR;
+ _jc_splay_list(&elf->types, (void **)types);
+
+ /* Point types at ELF file and verify object versions */
+ for (i = 0; i < num_types; i++) {
+ _jc_type *const type = types[i];
+
+ type->u.nonarray.u.elf = elf;
+ if (type->u.nonarray.block_size_index != _JC_LIBJC_VERSION) {
+ _JC_EX_STORE(env, LinkageError,
+ "type `%s' in ELF object `%s' was created from an"
+ " incompatible `_jc_defs.h' version 0x%04x !="
+ " 0x%04x", type->name, elf->pathname,
+ type->u.nonarray.block_size_index,
+ _JC_LIBJC_VERSION);
+ return JNI_ERR;
+ }
+ }
+
+ /* Lock loader */
+ _JC_MUTEX_LOCK(env, loader->mutex);
+
+ /* Verify that all types defined in the object are not yet loaded */
+ for (i = 0; i < num_types; i++) {
+ _jc_type *const type = types[i];
+ _jc_type *otype;
+
+ if ((otype = _jc_splay_find(&loader->defined_types,
+ type)) != NULL) {
+ _JC_EX_STORE(env, LinkageError,
+ "can't load `%s' because it defines the type `%s'"
+ " which was already defined by the previously"
+ " loaded object `%s'", elf->pathname, type->name,
+ otype->u.nonarray.u.elf->pathname);
+ goto fail;
+ }
+ }
+
+ /* Allocate and initialize type nodes */
+ if ((nodes = _jc_cl_alloc(env, loader,
+ num_types * sizeof(*nodes))) == NULL)
+ goto fail;
+ for (i = 0; i < num_types; i++) {
+ _jc_type_node *const node = &nodes[i];
+
+ /* Initialize node */
+ node->type = types[i];
+ node->thread = NULL;
+#ifndef NDEBUG
+ memset(&node->node, 0, sizeof(node->node));
+#endif
+ }
+
+ /* Derive all types; if something fails, un-do everything */
+ for (i = 0; i < num_types; i++) {
+ _jc_type_node *const node = &nodes[i];
+ _jc_type *const type = types[i];
+
+ if (_jc_derive_type(env, type, node) != JNI_OK) {
+ while (--i > 0)
+ _jc_underive_type(env, types[i], &nodes[i]);
+ goto fail;
+ }
+ }
+
+ /* Unlock loader */
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+
+ /* Verbosity */
+ if ((vm->verbose_flags & (1 << _JC_VERBOSE_OBJ)) != 0) {
+ if (num_types == 1) {
+ _jc_printf(vm, "[verbose %s: loaded `%s' from `%s']\n",
+ _jc_verbose_names[_JC_VERBOSE_OBJ], types[0]->name,
+ elf->pathname);
+ } else {
+ _jc_printf(vm, "[verbose %s: types loaded from `%s':\n",
+ _jc_verbose_names[_JC_VERBOSE_OBJ], elf->pathname);
+ for (i = 0; i < num_types; i++) {
+ _jc_type *const type = types[i];
+
+ _jc_printf(vm, "\t%s%s\n", type->name,
+ i == num_types - 1 ? "]" : "");
+ }
+ }
+ }
+
+ /* Done */
+ return JNI_OK;
+
+fail:
+ /* Attempt to give back class loader memory */
+ _jc_cl_unalloc(loader, &nodes, num_types * sizeof(*nodes));
+
+ /* Done */
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+ return JNI_ERR;
+}
+
+/*
+ * Derive a non-array type. This fills in all the runtime field of
+ * the _jc_type structure and adds the type to the derived types tree.
+ *
+ * If unsuccessful an exception is stored.
+ *
+ * NOTE: This assumes the type's class loader mutex is locked.
+ */
+static jint
+_jc_derive_type(_jc_env *env, _jc_type *type, _jc_type_node *node)
+{
+ _jc_jvm *const vm = env->vm;
+ _jc_nonarray_type *const ntype = &type->u.nonarray;
+ _jc_class_loader *const loader = type->loader;
+ _jc_class_node *cnode;
+ int i;
+
+ /* Sanity check */
+ _JC_ASSERT(!_JC_FLG_TEST(type, ARRAY));
+ _JC_ASSERT(!_JC_FLG_TEST(type, LOADED));
+ _JC_MUTEX_ASSERT(env, loader->mutex);
+
+ /*
+ * Create the java.lang.Class instance for this type, unless during
+ * initialization when java.lang.Class hasn't been loaded yet.
+ */
+ if ((vm->initialization == NULL || vm->initialization->create_class)
+ && _jc_create_class_instance(env, type) != JNI_OK)
+ return JNI_ERR;
+
+ /* Create mtable if needed (i.e., if interpreter is enabled) */
+ if (!_JC_ACC_TEST(type, INTERFACE)
+ && (!vm->loader_enabled || !vm->generation_enabled)) {
+
+ /* Allocate mtable */
+ if ((ntype->mtable = _jc_cl_alloc(env, loader,
+ ntype->num_vmethods * sizeof(*ntype->mtable))) == NULL)
+ return JNI_ERR;
+
+ /* Fill in this class' portion */
+ for (i = 0; i < ntype->num_methods; i++) {
+ _jc_method *const method = ntype->methods[i];
+
+ if (_JC_ACC_TEST(method, STATIC)
+ || *method->name == '<')
+ continue;
+ _JC_ASSERT(method->vtable_index < ntype->num_vmethods);
+ _JC_ASSERT(type->vtable[method->vtable_index]
+ == method->function);
+ ntype->mtable[method->vtable_index] = method;
+ }
+ }
+
+ /* Lock VM */
+ _JC_MUTEX_LOCK(env, vm->mutex);
+
+ /* Add reference to the type's class file in the VM class file tree */
+ if ((cnode = _jc_ref_class_node(env,
+ type->name, ntype->hash, NULL)) == NULL) {
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+ goto fail;
+ }
+
+ /* Add reference to all other class files this type depends on */
+ for (i = 0; i < ntype->num_class_depends; i++) {
+ _jc_class_depend *const dep
+ = &type->u.nonarray.class_depends[i];
+
+ /* Find/create class file node and add reference to it */
+ if (_jc_ref_class_node(env,
+ dep->name, dep->hash, NULL) != NULL)
+ continue;
+
+ /* Failed; un-reference previously referenced class nodes */
+ _jc_unref_class_deps(vm, ntype->class_depends, i);
+ _jc_unref_class_node(vm, &cnode);
+
+ /* Bail out */
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+ goto fail;
+ }
+
+ /* Add this class' methods to the VM method tree */
+ for (i = 0; i < ntype->num_methods; i++) {
+ _jc_method *method = ntype->methods[i];
+
+ /* Add method to the method tree if it exists */
+ if (method->function != NULL)
+ _jc_splay_insert(&vm->method_tree, method);
+ }
+
+ /* Unlock VM */
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+
+ /* Initialize heap block size index skip word flag */
+ if (!_JC_ACC_TEST(type, ABSTRACT))
+ _jc_initialize_bsi(vm, type);
+
+ /* Add node to the loader's initiated types tree */
+ _jc_splay_insert(&loader->initiated_types, node);
+
+ /* Remove type from the ELF file's unloaded types tree */
+ _jc_splay_remove(&ntype->u.elf->types, type);
+
+ /* Add type to the loader's defined types tree */
+ _jc_splay_insert(&loader->defined_types, type);
+
+ /* Point type node at real type */
+ _JC_ASSERT(strcmp(node->type->name, type->name) == 0);
+ node->type = type;
+
+ /* Add reference to ELF file */
+ _jc_elf_addref(ntype->u.elf);
+
+ /* Set type loaded flag */
+ type->flags |= _JC_TYPE_LOADED;
+
+ /* Done */
+ return JNI_OK;
+
+fail:
+ /* Give back Class object memory */
+ if (vm->initialization == NULL || vm->initialization->create_class) {
+ _jc_cl_unalloc(loader, &type->instance,
+ vm->boot.types.Class->u.nonarray.instance_size);
+ }
+
+ /* Done */
+ return JNI_ERR;
+}
+
+/*
+ * Reverse the effects of _jc_derive_type().
+ *
+ * NOTE: This assumes the type's class loader mutex is locked.
+ */
+static void
+_jc_underive_type(_jc_env *env, _jc_type *type, _jc_type_node *node)
+{
+ _jc_jvm *const vm = env->vm;
+ _jc_nonarray_type *const ntype = &type->u.nonarray;
+ _jc_class_loader *const loader = type->loader;
+ _jc_class_node key;
+ _jc_class_node *cnode;
+ int i;
+
+ /* Sanity check */
+ _JC_ASSERT(!_JC_FLG_TEST(type, ARRAY));
+ _JC_ASSERT(_JC_FLG_TEST(type, LOADED));
+ _JC_ASSERT(type->instance != NULL
+ || (vm->initialization != NULL
+ && !vm->initialization->create_class));
+ _JC_MUTEX_ASSERT(env, loader->mutex);
+
+ /* Unset type loaded flag */
+ type->flags &= ~_JC_TYPE_LOADED;
+
+ /* Remove type from the loader's defined types tree */
+ _jc_splay_remove(&loader->defined_types, type);
+
+ /* Put type back in ELF file's unloaded types tree */
+ _jc_splay_insert(&ntype->u.elf->types, type);
+
+ /* Remove type node from the loader's initiated types tree */
+ _jc_splay_remove(&loader->initiated_types, node);
+
+ /* Unreference ELF file */
+ _jc_elf_unref(&ntype->u.elf);
+
+ /* Lock VM */
+ _JC_MUTEX_LOCK(env, vm->mutex);
+
+ /* Unreference class file in VM class file tree */
+ key.name = type->name;
+ cnode = _jc_splay_find(&vm->classfiles, &key);
+ _JC_ASSERT(node != NULL);
+ _jc_unref_class_node(vm, &cnode);
+
+ /* Unreference class file dependencies */
+ _jc_unref_class_deps(vm, ntype->class_depends,
+ ntype->num_class_depends);
+
+ /* Remove class' methods from the VM method tree */
+ for (i = 0; i < ntype->num_methods; i++) {
+ _jc_method *method = ntype->methods[i];
+
+ /* Add method to the method tree if it exists */
+ if (method->function != NULL)
+ _jc_splay_remove(&vm->method_tree, method);
+ }
+
+ /* Unlock VM */
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+
+ /* Give back java.lang.Class object memory */
+ if (vm->initialization == NULL || vm->initialization->create_class) {
+ _jc_cl_unalloc(loader, &type->instance,
+ vm->boot.types.Class->u.nonarray.instance_size);
+ }
+}
+
+/*
+ * Derive an array type using the supplied loader.
+ */
+_jc_type *
+_jc_derive_array_type(_jc_env *env, _jc_class_loader *loader, const char *name)
+{
+ _jc_jvm *const vm = env->vm;
+ _jc_type *const obj_type = vm->boot.types.Object;
+ _jc_type *elem_type = NULL;
+ _jc_type *type = NULL;
+ const char *base_name;
+ _jc_type *base_type;
+ _jc_type_node *node;
+ _jc_type_node key;
+ u_char base_ptype;
+ void *mark;
+ int dims;
+
+ /* Sanity check */
+ _JC_ASSERT(vm->boot.types.Object != NULL);
+ _JC_ASSERT(*name == '[');
+
+ /* Count number of dimensions and get base class name */
+ for (base_name = name; *++base_name == '['; );
+ dims = base_name - name;
+
+ /* Check number of dimensions */
+ if (dims < 0 || dims > 255) {
+ _jc_post_exception_msg(env, _JC_NoClassDefFoundError,
+ "array type has too many (%d) dimensions: %s",
+ dims, name);
+ return NULL;
+ }
+
+ /* Remaining class name must not contain any '[' characters */
+ if (strchr(base_name, '[') != NULL) {
+ _jc_post_exception_msg(env, _JC_NoClassDefFoundError,
+ "%s", name);
+ return NULL;
+ }
+
+ /* Recursively load element type if multi-dimensional */
+ if (dims > 1) {
+ if ((elem_type = _jc_load_type(env, loader, name + 1)) == NULL)
+ return NULL;
+ base_type = elem_type->u.array.base_type;
+ goto got_elem_type;
+ }
+
+ /* Create/find base type */
+ base_ptype = _jc_sig_types[(u_char)*base_name];
+ switch (base_ptype) {
+ case _JC_TYPE_BOOLEAN:
+ case _JC_TYPE_BYTE:
+ case _JC_TYPE_CHAR:
+ case _JC_TYPE_SHORT:
+ case _JC_TYPE_INT:
+ case _JC_TYPE_LONG:
+ case _JC_TYPE_FLOAT:
+ case _JC_TYPE_DOUBLE:
+ if (base_name[1] != '\0')
+ goto invalid;
+ base_type = vm->boot.types.prim[base_ptype];
+ _JC_ASSERT(base_type != NULL);
+ break;
+ case _JC_TYPE_REFERENCE:
+ {
+ const size_t base_name_len = strlen(base_name);
+ char *bname;
+
+ /* Extract base class name */
+ if (base_name[0] != 'L'
+ || base_name_len < 3
+ || base_name[base_name_len - 1] != ';')
+ goto invalid;
+ if ((bname = _JC_STACK_ALLOC(env, base_name_len - 1)) == NULL) {
+ _jc_post_exception_info(env);
+ return NULL;
+ }
+ memcpy(bname, base_name + 1, base_name_len - 2);
+ bname[base_name_len - 2] = '\0';
+
+ /* Load/find base class */
+ if ((base_type = _jc_load_type(env, loader, bname)) == NULL)
+ return NULL;
+ break;
+ }
+ default:
+ invalid:
+ _jc_post_exception_msg(env, _JC_NoClassDefFoundError,
+ "invalid class name: %s", name);
+ return NULL;
+ }
+ elem_type = base_type;
+
+got_elem_type:
+ /*
+ * The array type's defining loader is the same as it's base type.
+ * If this is different from the initiating loader, then load the
+ * type via the defining loader first. This ensures that the type
+ * ends up in the defining loader's initiated types tree as required.
+ */
+ if (base_type->loader != loader) {
+ if ((type = _jc_load_type(env,
+ base_type->loader, name)) == NULL)
+ return NULL;
+ return type;
+ }
+
+ /* Lock loader and mark memory */
+ _JC_MUTEX_LOCK(env, loader->mutex);
+ mark = _jc_uni_mark(&loader->uni);
+
+ /* Check whether another thread has beaten us to the punch */
+ key.type = (_jc_type *)((char *)&name - _JC_OFFSETOF(_jc_type, name));
+ _JC_ASSERT(_jc_splay_find(&loader->deriving_types, &key) == NULL);
+ if ((type = _jc_splay_find(&loader->defined_types, key.type)) != NULL) {
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+ return type;
+ }
+
+ /*
+ * Allocate memory for the new type descriptor plus a copy of
+ * java.lang.Object's vtable (and mtable if Object is interpreted).
+ */
+ _JC_ASSERT(obj_type->u.nonarray.num_vmethods != 0);
+ if ((type = _jc_cl_alloc(env, loader,
+ sizeof(*type) + obj_type->u.nonarray.num_vmethods
+ * sizeof(*type->vtable))) == NULL)
+ goto fail;
+
+ /* Initialize type */
+ memset(type, 0, sizeof(*type));
+ if ((type->name = _jc_cl_strdup(env, loader, name)) == NULL)
+ goto fail;
+ type->loader = loader;
+ type->superclass = vm->boot.types.Object;
+ type->u.array.dimensions = dims;
+ type->u.array.base_type = base_type;
+ type->u.array.element_type = elem_type;
+ type->access_flags = base_type->access_flags
+ & (_JC_ACC_PUBLIC|_JC_ACC_PROTECTED|_JC_ACC_PRIVATE);
+ type->access_flags |= _JC_ACC_FINAL | _JC_ACC_ABSTRACT;
+ type->flags = (_JC_TYPE_ARRAY | _JC_TYPE_REFERENCE)
+ | _JC_TYPE_RESOLVED | _JC_TYPE_VERIFIED | _JC_TYPE_PREPARED
+ | _JC_TYPE_INITIALIZED | _JC_TYPE_LOADED;
+ type->initial_lockword =
+ ((elem_type->flags & _JC_TYPE_MASK) << _JC_LW_TYPE_SHIFT)
+ | _JC_LW_LIVE_BIT | _JC_LW_KEEP_BIT
+ | _JC_LW_ARRAY_BIT | _JC_LW_ODD_BIT;
+
+ /* Copy Object's vtable */
+ memcpy(type->vtable, obj_type->vtable,
+ obj_type->u.nonarray.num_vmethods * sizeof(*type->vtable));
+
+ /* Copy java.lang.Object's interface method lookup info */
+ _JC_ASSERT(vm->boot.array.interfaces != NULL);
+ type->num_interfaces = vm->boot.array.num_interfaces;
+ type->interfaces = vm->boot.array.interfaces;
+ type->imethod_hash_table = vm->boot.array.imethod_hash_table;
+ type->imethod_quick_table = vm->boot.array.imethod_quick_table;
+
+ /* Initialize type node */
+ if ((node = _jc_cl_zalloc(env, loader, sizeof(*node))) == NULL)
+ goto fail;
+ memset(node, 0, sizeof(*node));
+ node->type = type;
+
+ /* Create Class instance (unless Class itself is not loaded yet) */
+ if ((vm->initialization == NULL || vm->initialization->create_class)
+ && _jc_create_class_instance(env, type) != JNI_OK)
+ goto fail;
+
+ /* Add type node to the loader's initiated types tree */
+ _jc_splay_insert(&loader->initiated_types, node);
+
+ /* Add type to the loader's defined types tree */
+ _jc_splay_insert(&loader->defined_types, type);
+
+ /* Unlock loader */
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+
+ /* Done */
+ return type;
+
+fail:
+ /* Give back loader memory */
+ _jc_uni_reset(&loader->uni, mark);
+
+ /* Unlock loader */
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+
+ /* Post exception and exit */
+ _jc_post_exception_info(env);
+ return NULL;
+}
+
+/*
+ * Initialize the lockword for a class (i.e., non-array, non-interface) type.
+ * We initialize abstract class lockwords even though they are never directly
+ * used. This is so concrete subclasses can use some of the lockword bits.
+ */
+void
+_jc_initialize_lockword(_jc_env *env, _jc_type *type, _jc_type *stype)
+{
+ _jc_word lockword = 0;
+ int ref_count_field;
+
+ /* Sanity check */
+ _JC_ASSERT(!_JC_FLG_TEST(type, ARRAY));
+ _JC_ASSERT(!_JC_ACC_TEST(type, INTERFACE));
+ _JC_ASSERT(stype == NULL || stype->initial_lockword != 0);
+
+ /* Set number of reference fields */
+ ref_count_field =
+ type->u.nonarray.num_virtual_refs < _JC_LW_MAX(REF_COUNT) - 1 ?
+ type->u.nonarray.num_virtual_refs : _JC_LW_MAX(REF_COUNT) - 1;
+ lockword |= ref_count_field << _JC_LW_REF_COUNT_SHIFT;
+
+ /* java.lang.Object gets neither SPECIAL nor FINALIZE bits */
+ if (stype == NULL)
+ goto no_superclass;
+
+ /*
+ * If superclass is special, then so is this class. All
+ * top level special classes are in the java.lang package.
+ */
+ if (_JC_LW_TEST(stype->initial_lockword, SPECIAL))
+ lockword |= _JC_LW_SPECIAL_BIT;
+ else if (strncmp(type->name, "java/lang/", 10) == 0) {
+ const char *const subname = type->name + 10;
+ const char *const *sp;
+
+ /* See if this class is listed as special */
+ for (sp = _jc_special_classes; *sp != NULL; sp++) {
+ if (strcmp(subname, *sp) == 0) {
+ lockword |= _JC_LW_SPECIAL_BIT;
+ break;
+ }
+ }
+ }
+
+ /* Determine if class or a superclass overrides Object.finalize() */
+ if (_JC_LW_TEST(stype->initial_lockword, FINALIZE)
+ || _jc_get_declared_method(env, type,
+ "finalize", "()V", _JC_ACC_STATIC, 0) != NULL)
+ lockword |= _JC_LW_FINALIZE_BIT;
+
+no_superclass:
+ /* Set type bits and odd bit */
+ lockword |= (_JC_TYPE_REFERENCE << _JC_LW_TYPE_SHIFT)
+ | _JC_LW_LIVE_BIT | _JC_LW_KEEP_BIT | _JC_LW_ODD_BIT;
+
+ /* Done */
+ type->initial_lockword = lockword;
+}
+
+/*
+ * Initialize heap block size index for a class and set the
+ * _JC_TYPE_SKIPWORD flag in type->flags if appropriate.
+ */
+void
+_jc_initialize_bsi(_jc_jvm *vm, _jc_type *type)
+{
+ _jc_nonarray_type *const ntype = &type->u.nonarray;
+ int block_size;
+ int bsi;
+
+ /* Sanity check */
+ _JC_ASSERT(!_JC_FLG_TEST(type, ARRAY));
+ _JC_ASSERT(!_JC_ACC_TEST(type, ABSTRACT));
+
+ /* Get block size index */
+ bsi = _jc_heap_block_size(vm, ntype->instance_size);
+
+ /* Reverse-engineer actual block size */
+ block_size = bsi < 0 ?
+ ((-bsi * _JC_PAGE_SIZE) - _JC_HEAP_BLOCK_OFFSET) :
+ vm->heap.sizes[bsi].size;
+
+ /* Determine if there's room for a skip word */
+ if (block_size - sizeof(_jc_word) >= ntype->instance_size
+ && ntype->num_virtual_refs >= _JC_SKIPWORD_MIN_REFS)
+ type->flags |= _JC_TYPE_SKIPWORD;
+
+ /* Done */
+ ntype->block_size_index = bsi;
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/derive2.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/derive2.c?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/derive2.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/derive2.c Tue Oct 4 19:19:16 2005
@@ -0,0 +1,450 @@
+
+/*
+ * Copyright 2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: derive2.c,v 1.4 2005/05/08 21:12:07 archiecobbs Exp $
+ */
+
+#include "libjc.h"
+
+/*
+ * This file performs class derivation for interpreted classes.
+ * I.e., it is the non-ELF equivalent of derive.c.
+ */
+
+/* Internal functions */
+static jint _jc_derive_fields(_jc_env *env, _jc_type *type);
+static jint _jc_derive_methods(_jc_env *env, _jc_type *type);
+
+/*
+ * Given a class file, create a corresponding internal representation
+ * of the Java run-time type. This is done when there is no ELF object
+ * available, so we have to create the type structure at runtime and
+ * interpret the class' bytecode for method execution.
+ *
+ * If unsuccessful, an exception is stored.
+ */
+_jc_type *
+_jc_derive_type_interp(_jc_env *env,
+ _jc_class_loader *loader, _jc_classbytes *cbytes)
+{
+ _jc_jvm *const vm = env->vm;
+ _jc_class_node *cnode = NULL;
+ int num_class_vmethods;
+ int num_super_vmethods;
+ int num_vmethods;
+ _jc_nonarray_type *ntype;
+ _jc_type **interfaces;
+ _jc_type *superclass;
+ _jc_classfile *cfile;
+ _jc_type_node node_key;
+ _jc_type_node *node;
+ size_t virtual_offset;
+ size_t static_offset;
+ int vtable_index;
+ _jc_type *type;
+ void *mark;
+ int i;
+
+ /* Parse class file */
+ if ((cfile = _jc_parse_classfile(env, cbytes, 2)) == NULL)
+ return NULL;
+
+ /* Lock loader */
+ _JC_MUTEX_LOCK(env, loader->mutex);
+
+ /* Mark top of class loader memory */
+ mark = _jc_uni_mark(&loader->uni);
+
+ /* Get superclass (it should already be loaded) */
+ if (cfile->superclass != NULL) {
+ node_key.type = (_jc_type *)((char *)&cfile->superclass
+ - _JC_OFFSETOF(_jc_type, name));
+ node = _jc_splay_find(&loader->initiated_types, &node_key);
+ _JC_ASSERT(node != NULL && node->type != NULL);
+ superclass = node->type;
+ } else
+ superclass = NULL;
+
+ /* Get interfaces (they should already be loaded) */
+ if (cfile->num_interfaces > 0) {
+
+ /* Allocate array */
+ if ((interfaces = _JC_STACK_ALLOC(env, cfile->num_interfaces
+ * sizeof(*interfaces))) == NULL)
+ goto fail;
+
+ /* Fill array */
+ for (i = 0; i < cfile->num_interfaces; i++) {
+ node_key.type = (_jc_type *)((char *)&cfile
+ ->interfaces[i] - _JC_OFFSETOF(_jc_type, name));
+ node = _jc_splay_find(&loader->initiated_types,
+ &node_key);
+ _JC_ASSERT(node != NULL && node->type != NULL);
+ interfaces[i] = node->type;
+ }
+ } else
+ interfaces = NULL;
+
+ /* Compute the size of this class' vtable */
+ num_class_vmethods = 0;
+ num_super_vmethods = 0;
+ if (!_JC_ACC_TEST(cfile, INTERFACE)) {
+
+ /* Get total virtual methods in all superclasses */
+ if (superclass != NULL) {
+ num_super_vmethods
+ = superclass->u.nonarray.num_vmethods;
+ }
+
+ /* Count virtual methods in this class */
+ for (i = 0; i < cfile->num_methods; i++) {
+ _jc_cf_method *const method = &cfile->methods[i];
+
+ if (!_JC_ACC_TEST(method, STATIC)
+ && *method->name != '<')
+ num_class_vmethods++;
+ }
+ }
+ num_vmethods = num_super_vmethods + num_class_vmethods;
+
+ /* Allocate and start building the type structure */
+ if ((type = _jc_cl_alloc(env, loader, sizeof(*type)
+ + num_vmethods * sizeof(*type->vtable))) == NULL)
+ goto fail;
+ memset(type, 0, sizeof(*type));
+ ntype = &type->u.nonarray;
+ ntype->num_vmethods = num_vmethods;
+ type->superclass = superclass;
+ type->access_flags = cfile->access_flags | _JC_ACC_INTERP;
+ type->flags = _JC_TYPE_REFERENCE | _JC_TYPE_LOADED;
+ type->loader = loader;
+ ntype->u.cfile = cfile;
+ ntype->hash = cbytes->hash;
+
+ /* Allocate memory for mtable */
+ if (num_vmethods > 0
+ && (ntype->mtable = _jc_cl_alloc(env, loader,
+ num_vmethods * sizeof(*ntype->mtable))) == NULL)
+ goto fail;
+
+ /* Allocate memory for type name */
+ if ((type->name = _jc_cl_strdup(env, loader, cfile->name)) == NULL)
+ goto fail;
+
+ /*
+ * Create the java.lang.Class instance for this type, unless during
+ * initialization when java.lang.Class hasn't been loaded yet.
+ */
+ if ((vm->initialization == NULL || vm->initialization->create_class)
+ && _jc_create_class_instance(env, type) != JNI_OK)
+ goto fail;
+
+ /* Populate interface list */
+ type->num_interfaces = cfile->num_interfaces;
+ if (type->num_interfaces > 0
+ && (type->interfaces = _jc_cl_alloc(env, loader,
+ type->num_interfaces * sizeof(*type->interfaces))) == NULL)
+ goto fail;
+ for (i = 0; i < type->num_interfaces; i++)
+ *((_jc_type **)type->interfaces + i) = interfaces[i];
+
+ /* Derive fields */
+ if (_jc_derive_fields(env, type) != JNI_OK)
+ goto fail;
+
+ /* Derive methods */
+ if (_jc_derive_methods(env, type) != JNI_OK)
+ goto fail;
+
+ /* Compute field sizes and offsets */
+ ntype->num_virtual_refs = type->superclass != NULL ?
+ type->superclass->u.nonarray.num_virtual_refs : 0;
+ virtual_offset = type->superclass != NULL ?
+ (type->superclass->u.nonarray.instance_size
+ - ntype->num_virtual_refs * sizeof(void *)) : sizeof(_jc_object);
+ static_offset = 0;
+ for (i = 0; i < ntype->num_fields; i++) {
+ _jc_field *const field = ntype->fields[i];
+ const u_char ptype = _jc_sig_types[(u_char)*field->signature];
+ const int align = _jc_type_align[ptype];
+ const int size = _jc_type_sizes[ptype];
+
+ if (_JC_ACC_TEST(field, STATIC)) {
+ while (static_offset % align != 0)
+ static_offset++;
+ field->offset = static_offset;
+ static_offset += size;
+ } else {
+ _JC_ASSERT(!_JC_ACC_TEST(type, INTERFACE));
+ if (ptype == _JC_TYPE_REFERENCE) {
+ field->offset = -++ntype->num_virtual_refs
+ * sizeof(void *);
+ } else {
+ while (virtual_offset % align != 0)
+ virtual_offset++;
+ field->offset = virtual_offset;
+ virtual_offset += size;
+ }
+ }
+ }
+
+ /* Compute instance size */
+ if (!_JC_ACC_TEST(type, INTERFACE)) {
+ ntype->instance_size = virtual_offset
+ + ntype->num_virtual_refs * sizeof(void *);
+ }
+
+ /* Initialize heap block size index skip word flag */
+ if (!_JC_ACC_TEST(type, ABSTRACT))
+ _jc_initialize_bsi(vm, type);
+
+ /* Allocate memory for static fields, if any */
+ if (static_offset > 0
+ && (ntype->class_fields = _jc_cl_zalloc(env,
+ loader, static_offset)) == NULL)
+ goto fail;
+
+ /* Build trampolines */
+ for (i = 0; i < ntype->num_methods; i++) {
+ _jc_method *const method = ntype->methods[i];
+ u_char rtype = method->param_ptypes[method->num_parameters];
+ u_char *trampoline;
+ const void *func;
+ int len;
+
+ /* Skip interface methods */
+ if (_JC_ACC_TEST(type, INTERFACE)
+ && !_JC_ACC_TEST(method, STATIC))
+ continue;
+
+ /* Get the appropriate destination function */
+ func = _JC_ACC_TEST(method, NATIVE) ?
+ _jc_interp_native_funcs[rtype] : _jc_interp_funcs[rtype];
+
+ /* Create trampoline */
+ len = _jc_build_trampoline(NULL, method, func);
+ if ((trampoline = _jc_cl_alloc(env, loader, len)) == NULL)
+ goto fail;
+ _jc_build_trampoline(trampoline, method, func);
+ _jc_iflush(trampoline, len);
+ method->function = trampoline;
+ }
+
+ /* Skip vtable stuff for interfaces */
+ if (_JC_ACC_TEST(type, INTERFACE))
+ goto skip_vtable;
+
+ /*
+ * Fill in the vtable and mtable portions corresponding to this class.
+ * We fill in and override the superclass portions during resolution.
+ */
+ vtable_index = num_super_vmethods;
+ for (i = 0; i < ntype->num_methods; i++) {
+ _jc_method *const method = ntype->methods[i];
+
+ if (_JC_ACC_TEST(method, STATIC) || *method->name == '<')
+ continue;
+ method->vtable_index = vtable_index;
+ type->vtable[vtable_index] = method->function;
+ ntype->mtable[vtable_index] = method;
+ vtable_index++;
+ }
+
+ /* Sanity check */
+ _JC_ASSERT(vtable_index == num_vmethods);
+
+skip_vtable:
+ /*
+ * Find/create this class' class file node and add a reference to it.
+ * This also acts as an implicit dependency on the class file.
+ */
+ _JC_MUTEX_LOCK(env, vm->mutex);
+ if ((cnode = _jc_ref_class_node(env, type->name, ntype->hash,
+ loader != vm->boot.loader ? cbytes : NULL)) == NULL) {
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+ goto fail;
+ }
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+
+ /* Allocate and initialize type node */
+ if ((node = _jc_cl_zalloc(env, loader, sizeof(*node))) == NULL)
+ goto fail;
+ node->type = type;
+
+ /* Add node to the loader's initiated types tree */
+ _jc_splay_insert(&loader->initiated_types, node);
+
+ /* Add type to the loader's defined types tree */
+ _jc_splay_insert(&loader->defined_types, type);
+
+ /* Set type flags */
+ type->flags = _JC_TYPE_REFERENCE | _JC_TYPE_LOADED;
+
+ /* Done */
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+ return type;
+
+fail:
+ /* Give back class loader memory */
+ _jc_uni_reset(&loader->uni, mark);
+
+ /* Release class file reference */
+ if (cnode != NULL) {
+ _JC_MUTEX_LOCK(env, vm->mutex);
+ _jc_unref_class_node(vm, &cnode);
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+ }
+
+ /* Free parsed class file */
+ _jc_destroy_classfile(&cfile);
+
+ /* Unlock loader */
+ _JC_MUTEX_UNLOCK(env, loader->mutex);
+ return NULL;
+}
+
+/*
+ * Derive fields.
+ */
+static jint
+_jc_derive_fields(_jc_env *env, _jc_type *type)
+{
+ _jc_nonarray_type *const ntype = &type->u.nonarray;
+ _jc_classfile *const cfile = ntype->u.cfile;
+ int i;
+
+ /* Sanity check */
+ _JC_ASSERT(_JC_ACC_TEST(type, INTERP));
+ _JC_MUTEX_ASSERT(env, type->loader->mutex);
+
+ /* Allocate fields array */
+ ntype->num_fields = cfile->num_fields;
+ if (ntype->num_fields > 0
+ && (ntype->fields = _jc_cl_alloc(env, type->loader,
+ ntype->num_fields * sizeof(*ntype->fields))) == NULL)
+ return JNI_ERR;
+
+ /* Create field structures */
+ for (i = 0; i < cfile->num_fields; i++) {
+ _jc_cf_field *const cfield = &cfile->fields[i];
+ _jc_field *field;
+ size_t nlen;
+ size_t slen;
+
+ /* Allocate structure */
+ nlen = strlen(cfield->name) + 1;
+ slen = strlen(cfield->descriptor) + 1;
+ if ((field = _jc_cl_alloc(env, type->loader,
+ sizeof(*field) + nlen + slen)) == NULL)
+ return JNI_ERR;
+ ntype->fields[i] = field;
+
+ /* Initialize it */
+ memset(field, 0, sizeof(*field));
+ field->name = (char *)(field + 1);
+ memcpy((char *)field->name, cfield->name, nlen);
+ field->signature = field->name + nlen;
+ memcpy((char *)field->signature, cfield->descriptor, slen);
+ field->class = type;
+ field->access_flags = cfield->access_flags | _JC_ACC_INTERP;
+ }
+
+ /* Done */
+ return JNI_OK;
+}
+
+/*
+ * Derive methods.
+ */
+static jint
+_jc_derive_methods(_jc_env *env, _jc_type *type)
+{
+ _jc_nonarray_type *const ntype = &type->u.nonarray;
+ _jc_classfile *const cfile = ntype->u.cfile;
+ int i;
+
+ /* Sanity check */
+ _JC_ASSERT(_JC_ACC_TEST(type, INTERP));
+ _JC_MUTEX_ASSERT(env, type->loader->mutex);
+
+ /* Allocate methods array */
+ ntype->num_methods = cfile->num_methods;
+ if (ntype->num_methods > 0
+ && (ntype->methods = _jc_cl_alloc(env, type->loader,
+ ntype->num_methods * sizeof(*ntype->methods))) == NULL)
+ return JNI_ERR;
+
+ /* Create method structures */
+ for (i = 0; i < cfile->num_methods; i++) {
+ _jc_cf_method *const cmethod = &cfile->methods[i];
+ _jc_method *method;
+ size_t mem_size;
+ size_t nlen;
+ size_t slen;
+ int nparam;
+ void *mem;
+
+ /* Allocate structure */
+ nlen = strlen(cmethod->name) + 1;
+ slen = strlen(cmethod->descriptor) + 1;
+ if ((method = _jc_cl_alloc(env, type->loader,
+ sizeof(*method) + nlen + slen)) == NULL)
+ return JNI_ERR;
+ ntype->methods[i] = method;
+
+ /* Initialize it */
+ memset(method, 0, sizeof(*method));
+ method->name = (char *)(method + 1);
+ memcpy((char *)method->name, cmethod->name, nlen);
+ method->signature = method->name + nlen;
+ memcpy((char *)method->signature, cmethod->descriptor, slen);
+ method->class = type;
+ method->access_flags = cmethod->access_flags | _JC_ACC_INTERP;
+
+ /* Parse signature and count number of parameters */
+ if ((nparam = _jc_resolve_signature(env, method, NULL)) == -1)
+ return JNI_ERR;
+ method->num_parameters = nparam;
+ if (cmethod->exceptions != NULL) {
+ method->num_exceptions
+ = cmethod->exceptions->num_exceptions;
+ }
+
+ /* Allocate storage for stuff */
+ mem_size = (method->num_exceptions + method->num_parameters)
+ * sizeof(_jc_type *) + (method->num_parameters + 1);
+ if ((mem = _jc_cl_zalloc(env, type->loader, mem_size)) == NULL)
+ return JNI_ERR;
+
+ /* Initialize pointers */
+ if (method->num_parameters > 0)
+ method->param_types = mem;
+ if (method->num_exceptions > 0) {
+ method->exceptions = (_jc_type **)mem
+ + method->num_parameters;
+ }
+ method->param_ptypes = (u_char *)((_jc_type **)mem
+ + method->num_parameters + method->num_exceptions);
+
+ /* Get parameter ptypes */
+ _jc_resolve_signature(env, method, NULL);
+ }
+
+ /* Done */
+ return JNI_OK;
+}
+