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 [23/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/structures.h
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/structures.h?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/structures.h (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/structures.h Tue Oct 4 19:19:16 2005
@@ -0,0 +1,1036 @@
+
+/*
+ * 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: structures.h,v 1.36 2005/05/24 01:09:38 archiecobbs Exp $
+ */
+
+#ifndef _STRUCTURES_H_
+#define _STRUCTURES_H_
+
+/************************************************************************
+ * Definitions *
+ ************************************************************************/
+
+/*
+ * Forward structure declarations and typedef's
+ */
+typedef struct _jc_boot _jc_boot;
+typedef struct _jc_boot_array _jc_boot_array;
+typedef struct _jc_boot_fields _jc_boot_fields;
+typedef struct _jc_boot_methods _jc_boot_methods;
+typedef struct _jc_boot_objects _jc_boot_objects;
+typedef struct _jc_boot_types _jc_boot_types;
+typedef struct _jc_class_node _jc_class_node;
+typedef struct _jc_class_ref _jc_class_ref;
+typedef struct _jc_class_save _jc_class_save;
+typedef struct _jc_classbytes _jc_classbytes;
+typedef struct _jc_cpath_entry _jc_cpath_entry;
+typedef struct _jc_dwarf2_line_hdr _jc_dwarf2_line_hdr;
+typedef struct _jc_elf_debug_lines _jc_elf_debug_lines;
+typedef struct _jc_elf_info _jc_elf_info;
+typedef struct _jc_elf_loadable _jc_elf_loadable;
+typedef struct _jc_ex_info _jc_ex_info;
+typedef struct _jc_exec_stack _jc_exec_stack;
+typedef struct _jc_fat_lock _jc_fat_lock;
+typedef struct _jc_fat_locks _jc_fat_locks;
+typedef struct _jc_heap _jc_heap;
+typedef struct _jc_heap_size _jc_heap_size;
+typedef struct _jc_heap_sweep _jc_heap_sweep;
+typedef struct _jc_initialization _jc_initialization;
+typedef struct _jc_interp_stack _jc_interp_stack;
+typedef struct _jc_java_stack _jc_java_stack;
+typedef struct _jc_jvm _jc_jvm;
+typedef struct _jc_map_state _jc_map_state;
+typedef struct _jc_method_node _jc_method_node;
+typedef struct _jc_native_frame _jc_native_frame;
+typedef struct _jc_native_frame_list _jc_native_frame_list;
+typedef struct _jc_native_lib _jc_native_lib;
+typedef struct _jc_objpath_entry _jc_objpath_entry;
+typedef struct _jc_properties _jc_properties;
+typedef struct _jc_property _jc_property;
+typedef struct _jc_resolve_info _jc_resolve_info;
+typedef struct _jc_saved_frame _jc_saved_frame;
+typedef struct _jc_scan_frame _jc_scan_frame;
+typedef struct _jc_scan_list _jc_scan_list;
+typedef struct _jc_splay_tree _jc_splay_tree;
+typedef struct _jc_stab _jc_stab;
+typedef struct _jc_stack_crawl _jc_stack_crawl;
+typedef struct _jc_threads _jc_threads;
+typedef struct _jc_trace_info _jc_trace_info;
+typedef struct _jc_type_node _jc_type_node;
+typedef struct _jc_uni_mem _jc_uni_mem;
+typedef struct _jc_uni_page_list _jc_uni_page_list;
+typedef struct _jc_uni_pages _jc_uni_pages;
+
+TAILQ_HEAD(_jc_uni_page_list, _jc_uni_pages);
+SLIST_HEAD(_jc_native_frame_list, _jc_native_frame);
+
+#include "cf_parse.h"
+#include "zip.h"
+
+/************************************************************************
+ * Splay trees *
+ ************************************************************************/
+
+/* One splay tree */
+struct _jc_splay_tree {
+ size_t offset; /* offset of node in an item */
+ int size; /* number of nodes in tree */
+ _jc_splay_node *root; /* root of the tree */
+ _jc_splay_cmp_t *compare; /* item comparision function */
+};
+
+/************************************************************************
+ * ELF file structures *
+ ************************************************************************/
+
+/* This describes a loadable section within an ELF object */
+struct _jc_elf_loadable {
+ const char *name; /* name of section */
+ const Elf_Shdr *shdr; /* section header */
+ const Elf_Shdr *rel; /* normal relocations section */
+ const Elf_Shdr *rela; /* addend relocations section */
+ const char *bytes; /* start of section in file */
+ char *vaddr; /* start of loaded section */
+ Elf_Off offset; /* offset of loaded section */
+};
+
+/* This describes the ELF debug section containing line number info */
+struct _jc_elf_debug_lines {
+ u_char type; /* _JC_LINE_DEBUG_* */
+ const char *strings; /* associated string section */
+ _jc_elf_loadable loadable; /* loading info */
+};
+
+/*
+ * Linking and symbol information associated with an ELF object.
+ * This information is only needed for loading and linking.
+ */
+struct _jc_elf_info {
+ char *map_base; /* base of mmap() region */
+ size_t map_size; /* size of mmap() region */
+ const Elf_Ehdr *ehdr; /* ELF header (=map_base) */
+ const Elf_Shdr *shdrs; /* section headers */
+ int num_symbols; /* number of symbols */
+ const Elf_Sym *symbols; /* symbols */
+ int num_loadables; /* number loadable sections */
+ _jc_elf_loadable *loadables; /* loadable sections */
+ _jc_elf_loadable **shdr2section; /* maps shdr index -> section */
+ const char *strings; /* strings in string table */
+ _jc_env *resolver; /* currently resolving thread */
+ _jc_elf_debug_lines debug_lines; /* ELF debug line info */
+};
+
+/*
+ * Information associated with a loaded ELF object.
+ */
+struct _jc_elf {
+ _jc_elf_info *info; /* transient linking info */
+ _jc_class_loader *loader; /* loader who loaded me */
+ char *vaddr; /* load address of object */
+ Elf_Off vsize; /* size of loaded object */
+ _jc_splay_tree types; /* types defined in file */
+ volatile _jc_word refs; /* number of references */
+ char pathname[0]; /* original file pathname */
+};
+
+/* One entry in the object file search path */
+struct _jc_objpath_entry {
+ int type; /* _JC_OBJPATH_* */
+ char *pathname;
+};
+
+/* Information about a method function during ELF file processing */
+struct _jc_method_node {
+ const char *cname; /* encoded class name */
+ int clen; /* length of 'cname' */
+ const char *mname; /* encoded method name */
+ int mlen; /* length of 'mname' */
+ size_t size; /* size of function body */
+ _jc_method *method; /* associated _jc_method */
+ _jc_splay_node node; /* node in temporary tree */
+};
+
+/* Information maintained when resolving classes */
+struct _jc_resolve_info {
+ _jc_type *type;
+ _jc_class_loader *loader;
+ _jc_object **implicit_refs;
+ int num_implicit_refs;
+ int num_implicit_alloc;
+};
+
+/* Superclass and superinterfaces for an unresolved ELF type */
+struct _jc_super_info {
+ _jc_type *superclass;
+ _jc_type *interfaces[0];
+};
+
+/************************************************************************
+ * Line Number Information *
+ ************************************************************************/
+
+/* One entry in a method's [PC -> Java line number table] map */
+struct _jc_pc_map {
+ const void *pc;
+ uint16_t jline;
+};
+
+/* Transient state used when building a PC map */
+struct _jc_map_state {
+ int map_alloc;
+ int last_linenum;
+ int last_map;
+ _jc_linenum_info linenum;
+ _jc_pc_map_info pc_map;
+};
+
+/* ELF stabs entry format */
+struct _jc_stab {
+ uint32_t sindex;
+ u_char type;
+ u_char misc;
+ uint16_t desc;
+ Elf_Addr value;
+};
+
+/* DWARF line program header */
+struct _jc_dwarf2_line_hdr {
+ unsigned char minimum_instruction_length;
+ unsigned char default_is_stmt;
+ signed char line_base;
+ unsigned char line_range;
+ unsigned char opcode_base;
+ unsigned char standard_opcode_lengths[0];
+};
+
+/* Class bytes: in-memory copy of a class file byte[] array */
+struct _jc_classbytes {
+ u_char *bytes;
+ size_t length;
+ jlong hash;
+ volatile _jc_word refs;
+ void (*freer)(_jc_classbytes *);
+};
+
+/*
+ * VM meta-information about a class file, stored in the vm->classfiles tree.
+ *
+ * The 'bytes' field is non-NULL only if (a) the class was first loaded by
+ * a non-bootstrap class loader, and (b) object file generation is enabled.
+ *
+ * Otherwise, we don't need it (not (b)) or we can get it by searching the
+ * boot loader classpath (not (a)).
+ *
+ * Each loaded type holds one reference for its own class and one for
+ * each class listed in its dependency list.
+ */
+struct _jc_class_node {
+ const char *name; /* name of class */
+ jint refs; /* number of references */
+ jlong hash; /* hash of class file bytes */
+ _jc_classbytes *bytes; /* saved bytes for code gen */
+ _jc_splay_node node; /* in vm->classfiles */
+};
+
+/* A reference to one class from another class */
+struct _jc_class_ref {
+ const char *name; /* NOTE: not nul-terminated */
+ size_t len;
+};
+
+/************************************************************************
+ * Uni-allocator memory *
+ ************************************************************************/
+
+/*
+ * This structure lives at the beginning of each string of pages
+ * allocated by a uni-allocator.
+ */
+struct _jc_uni_pages {
+ TAILQ_ENTRY(_jc_uni_pages) link;
+ int num_pages;
+ size_t offset;
+};
+
+/*
+ * This describes one uni-allocator.
+ */
+struct _jc_uni_mem {
+ _jc_uni_page_list pages;
+ int min_pages;
+ volatile _jc_word *avail_pages;
+};
+
+/************************************************************************
+ * Thread related structures *
+ ************************************************************************/
+
+/*
+ * Native reference frame, containing explicit references to objects that
+ * are held by e.g. JNI code. These must be explicitly accounted for
+ * because we are not able to reliably scan a native call frame for
+ * object references directly. Same applies to libjc internal code.
+ */
+struct _jc_native_frame {
+ SLIST_ENTRY(_jc_native_frame) link;
+ _jc_word flags;
+ _jc_object *refs[_JC_NATIVE_REFS_PER_FRAME];
+};
+
+/*
+ * Common information that lives at the beginning of
+ * _jc_exec_stack and _jc_interp_stack.
+ */
+struct _jc_java_stack {
+ jboolean interp;
+ _jc_java_stack *next;
+};
+
+/*
+ * Structure representing a contiguous portion of the C call stack
+ * (some functions within which may be Java method C functions).
+ * The "frame" and "pc" fields define the top of a C stack fragment
+ * (or, in the case of the current thread, they may be NULL to indicate
+ * that the top of the stack is the top of the real C stack and has not
+ * yet been "marked"). The bottom of the fragment is always a stack
+ * frame for _jc_invoke_jcni_a(). The next deeper contiguous stack frame
+ * fragment is pointed to by the "next" field.
+ *
+ * The "next" field is needed is so we can "skip over" stack frames
+ * associated with native code, signal frames, etc. This is because
+ * we can't reliabily follow the chain of frame pointers through
+ * those frames (especially signal frames).
+ */
+struct _jc_exec_stack {
+ _jc_java_stack jstack;
+ _jc_stack_frame frame;
+ const void *pc;
+ mcontext_t regs;
+};
+
+/*
+ * Represents one interpreted Java method stack frame.
+ */
+struct _jc_interp_stack {
+ _jc_java_stack jstack;
+ _jc_method *method;
+ _jc_word *locals;
+ const int *pcp;
+ jboolean clipped;
+};
+
+/*
+ * Structure used to save an exception Java stack trace. When the
+ * VMThrowable.fillInStackTrace() is called, what gets saved in the
+ * "vmdata" field of the VMThrowable object is an array of these.
+ *
+ * If/when Throwable.getStackTrace() is called later, this
+ * information gets converted into a StackTraceElement[] array.
+ *
+ * For exec methods, 'pc' is the actual CPU program counter.
+ * For interp methods, 'pc' points to the (int) instruction index.
+ */
+struct _jc_saved_frame {
+ _jc_method *method;
+ union {
+ const void *pc; /* executable */
+ int ipc; /* interpreted */
+ } u;
+};
+
+/*
+ * Structure used when crawling the stack looking for Java methods.
+ * See _jc_stack_crawl_first() and _jc_stack_crawl_next().
+ */
+struct _jc_stack_crawl {
+ _jc_method *method; /* current method */
+ _jc_java_stack *stack; /* current chunk */
+ _jc_stack_frame frame; /* exec only */
+ const void *pc; /* exec only */
+};
+
+/*
+ * Thread-private structure used when trying to find class files.
+ * See _jc_get_class_node().
+ */
+struct _jc_class_save {
+ const char *name; /* name of class */
+ _jc_classbytes *bytes; /* class file bytes */
+ _jc_class_save *next; /* next in list */
+};
+
+/*
+ * Exception info stored for future posting.
+ */
+struct _jc_ex_info {
+ jshort num;
+ char msg[200];
+};
+
+/*
+ * The JC internal structure that corresponds to a Java thread.
+ */
+struct _jc_env {
+ _jc_env_head head; /* must be first */
+ _jc_jvm *vm; /* vm that owns me */
+
+ /* Interpreter trampoline info */
+ _jc_method *interp; /* interpret method */
+
+ /* Stack info */
+ void *stack; /* thread's stack */
+ size_t stack_size; /* size of stack */
+ char *stack_limit; /* for stack overflow */
+ _jc_java_stack *java_stack; /* java stack info */
+ _jc_method *jni_method; /* innermost JNI meth */
+ _jc_value retval; /* invoke rtn value */
+
+ /* Thread info */
+ volatile _jc_word status; /* JC_THRDSTAT_* */
+ jint thread_id; /* unique thread id */
+ _jc_object *instance; /* java.lang.Thread */
+ char text_status[_JC_MAX_TEXT_STATUS];
+
+ /* Lock info */
+ _jc_word thinlock_id;
+ struct {
+
+ /* Information about other threads waiting on this one */
+ struct {
+ pthread_mutex_t mutex; /* protects struct */
+#ifndef NDEBUG
+ _jc_env *mutex_owner; /* current owner */
+#endif
+ volatile _jc_word contention; /* contention flag */
+ SLIST_HEAD(, _jc_env) waiters; /* waiting on me */
+ } owner;
+
+ /* Information about the other thread this one is waiting on */
+ struct {
+ _jc_object *object; /* contended object */
+ pthread_cond_t cond; /* try again signal */
+ SLIST_ENTRY(_jc_env) link; /* link in 'waiters' */
+ } waiter;
+ } lock;
+
+ /* Local native reference frames */
+ _jc_native_frame_list native_locals;
+
+ /* JNI native interface */
+ const struct JNINativeInterface *jni_interface;
+
+ /* Recursive exception detector */
+ jlong in_vmex; /* JC_VMEX_* bits */
+
+ /* Exception information filled in by some functions on error */
+ _jc_ex_info ex;
+
+#if !HAVE_GETCONTEXT
+ /* For our poor man's getcontext() using signals */
+ mcontext_t *ctx;
+#endif
+
+ /* Thread flags */
+ const char *generating;
+ jboolean out_of_memory;
+ jboolean handling_signal;
+
+ /*
+ * Support for Thread.interrupt() and suspend/resume.
+ * Note the VM global mutex protects the suspend/resume fields.
+ */
+ jboolean suspended;
+ jboolean resumption_initialized;
+ pthread_cond_t resumption;
+ volatile _jc_word interrupt_status;
+ _jc_fat_lock *interruptible_lock;
+
+ /* Used by _jc_get_class_node() */
+ _jc_class_save *class_save;
+
+ /* Support for threads throwing exceptions in other threads */
+ _jc_object *volatile cross_exception;
+
+ /* Link in VM list */
+ LIST_ENTRY(_jc_env) link; /* entry in vm list */
+};
+
+/************************************************************************
+ * Class loader information *
+ ************************************************************************/
+
+/*
+ * An entry in a class loader's initialized or partially derived types tree.
+ *
+ * In the case of the partially derived tree, the structure pointed to by
+ * the "type" field is not complete; only type->name can be used.
+ */
+struct _jc_type_node {
+ _jc_type *type; /* corresponding type */
+ _jc_splay_node node; /* initiat*, deriving trees */
+ _jc_env *thread; /* thread loading type */
+};
+
+/*
+ * Information about a native library.
+ */
+struct _jc_native_lib {
+ char *name;
+ void *handle;
+ STAILQ_ENTRY(_jc_native_lib) link;
+};
+
+/*
+ * Information associated with a class loader.
+ *
+ * All fields are protected by the mutex.
+ */
+struct _jc_class_loader {
+ _jc_object *instance;
+ pthread_mutex_t mutex;
+#ifndef NDEBUG
+ _jc_env *mutex_owner;
+#endif
+ pthread_cond_t cond;
+ _jc_uni_mem uni;
+ _jc_splay_tree initiated_types;/* _jc_type_node's */
+ _jc_splay_tree deriving_types; /* _jc_type_node's */
+ _jc_splay_tree defined_types; /* _jc_type's */
+ int num_implicit_refs;
+ _jc_object **implicit_refs;
+ jboolean *objects_loaded;
+ jboolean gc_mark;
+ jboolean waiters;
+ STAILQ_HEAD(, _jc_native_lib) native_libs;
+ LIST_ENTRY(_jc_class_loader) link;
+};
+
+/************************************************************************
+ * Bootstrap class loader information *
+ ************************************************************************/
+
+/*
+ * Classes that are specially resolved at bootstrap time.
+ */
+struct _jc_boot_types {
+
+ /* Normal class types */
+ _jc_type *AccessibleObject;
+ _jc_type *Buffer;
+ _jc_type *Class;
+ _jc_type *ClassLoader;
+ _jc_type *Cloneable;
+ _jc_type *Constructor;
+ _jc_type *DirectByteBufferImpl;
+ _jc_type *Error;
+ _jc_type *Field;
+ _jc_type *Generate;
+ _jc_type *Method;
+ _jc_type *Object;
+ _jc_type *PhantomReference;
+ _jc_type *RawData;
+ _jc_type *Reference;
+ _jc_type *Serializable;
+ _jc_type *SoftReference;
+ _jc_type *StackTraceElement;
+ _jc_type *String;
+ _jc_type *System;
+ _jc_type *Thread;
+ _jc_type *ThreadGroup;
+ _jc_type *Throwable;
+ _jc_type *VMStackWalker;
+ _jc_type *VMThread;
+ _jc_type *VMThrowable;
+ _jc_type *WeakReference;
+
+ /* Primitive types */
+ _jc_type *prim[_JC_TYPE_MAX];
+
+ /* Primitive array types */
+ _jc_type *prim_array[_JC_TYPE_MAX];
+
+ /* Primitive wrapper types */
+ _jc_type *prim_wrapper[_JC_TYPE_MAX];
+
+ /* Exception and Error classes */
+ _jc_type *vmex[_JC_VMEXCEPTION_MAX];
+
+ /* Object array types */
+ _jc_type *Class_array;
+ _jc_type *Constructor_array;
+ _jc_type *Field_array;
+ _jc_type *Method_array;
+ _jc_type *StackTraceElement_array;
+};
+
+/*
+ * Methods that are specially resolved at bootstrap time.
+ */
+struct _jc_boot_methods {
+ struct {
+ _jc_method *isAccessible;
+ } AccessibleObject;
+ struct {
+ _jc_method *loadClass;
+ _jc_method *getSystemClassLoader;
+ } ClassLoader;
+ struct {
+ _jc_method *init;
+ } Constructor;
+ struct {
+ _jc_method *init;
+ } DirectByteBufferImpl;
+ struct {
+ _jc_method *init;
+ } Field;
+ struct {
+ _jc_method *v;
+ _jc_method *generateObject;
+ } Generate;
+ struct {
+ _jc_method *init;
+ _jc_method *invoke;
+ } Method;
+ struct {
+ _jc_method *finalize;
+ _jc_method *notifyAll;
+ _jc_method *toString;
+ _jc_method *wait;
+ } Object;
+ struct {
+ _jc_method *enqueue;
+ } Reference;
+ struct {
+ _jc_method *init;
+ } StackTraceElement;
+ struct {
+ _jc_method *init;
+ _jc_method *intern;
+ } String;
+ struct {
+ _jc_method *init;
+ _jc_method *stop;
+ } Thread;
+ struct {
+ _jc_method *addThread;
+ _jc_method *init;
+ _jc_method *uncaughtException;
+ } ThreadGroup;
+ struct {
+ _jc_method *init;
+ _jc_method *run;
+ } VMThread;
+ struct {
+ _jc_method *value;
+ _jc_method *init;
+ } prim_wrapper[_JC_TYPE_MAX];
+ struct {
+ _jc_method *init;
+ } vmex[_JC_VMEXCEPTION_MAX];
+};
+
+/*
+ * Fields that are specially resolved at bootstrap time.
+ */
+struct _jc_boot_fields {
+ struct {
+ _jc_field *cap;
+ _jc_field *address;
+ } Buffer;
+ struct {
+ _jc_field *pd;
+ _jc_field *vmdata;
+ } Class;
+ struct {
+ _jc_field *parent;
+ _jc_field *vmdata;
+ } ClassLoader;
+ struct {
+ _jc_field *clazz;
+ _jc_field *slot;
+ } Constructor;
+ struct {
+ _jc_field *declaringClass;
+ _jc_field *slot;
+ } Field;
+ struct {
+ _jc_field *declaringClass;
+ _jc_field *slot;
+ } Method;
+ struct {
+ _jc_field *data;
+ } RawData;
+ struct {
+ _jc_field *queue;
+ _jc_field *referent;
+ } Reference;
+ struct {
+ _jc_field *value;
+ _jc_field *offset;
+ _jc_field *count;
+ } String;
+ struct {
+ _jc_field *in;
+ _jc_field *out;
+ _jc_field *err;
+ } System;
+ struct {
+ _jc_field *daemon;
+ _jc_field *group;
+ _jc_field *name;
+ _jc_field *priority;
+ _jc_field *vmThread;
+ } Thread;
+ struct {
+ _jc_field *root;
+ } ThreadGroup;
+ struct {
+ _jc_field *cause;
+ _jc_field *detailMessage;
+ _jc_field *vmState;
+ } Throwable;
+ struct {
+ _jc_field *thread;
+ _jc_field *vmdata;
+ } VMThread;
+ struct {
+ _jc_field *vmdata;
+ } VMThrowable;
+};
+
+/*
+ * Objects that are specially instantiated at bootstrap time.
+ */
+struct _jc_boot_objects {
+ _jc_object *vmex[_JC_VMEXCEPTION_MAX];
+ _jc_object *systemThreadGroup;
+};
+
+/*
+ * Bootstrap class loader info for deriving array types.
+ */
+struct _jc_boot_array {
+ int num_interfaces;
+ _jc_type **interfaces;
+ _jc_method ***imethod_hash_table;
+ const void **imethod_quick_table;
+};
+
+/* One entry in a classpath style search path */
+struct _jc_cpath_entry {
+ int type; /* _JC_CPATH_* */
+ char *pathname;
+ _jc_zip *zip;
+};
+
+/*
+ * Boot class loader info. All fields are read only after VM creation
+ * except *loader and "loading_types", which are protected by loader->mutex.
+ */
+struct _jc_boot {
+ int class_path_len;
+ _jc_cpath_entry *class_path;
+ _jc_boot_array array;
+ _jc_boot_types types;
+ _jc_boot_methods methods;
+ _jc_boot_fields fields;
+ _jc_boot_objects objects;
+ _jc_class_loader *loader;
+ _jc_splay_tree loading_types; /* _jc_type_node's */
+};
+
+/************************************************************************
+ * Java heap and garbage collection *
+ ************************************************************************/
+
+/*
+ * Heap info.
+ *
+ * All info in this structure is either read-only or accessed using
+ * atomic operations (except during garbage collection when the world
+ * is stopped).
+ */
+struct _jc_heap {
+ int num_pages;
+ void *volatile pages;
+ int num_sizes;
+ _jc_heap_size *sizes;
+ volatile int next_page;
+ void *mem;
+ size_t size;
+ int granularity;
+ int max_pages;
+};
+
+/*
+ * Descriptor for each heap block size.
+ */
+struct _jc_heap_size {
+ _jc_word *volatile pages; /* list of pages this size */
+ _jc_word *volatile hint; /* next free (?) block to try */
+ int size; /* size of each block */
+ int num_blocks; /* number blocks per page */
+};
+
+/*
+ * State maintained when visiting all objects in the heap.
+ */
+struct _jc_heap_sweep {
+ char *page;
+ char *end;
+ char *block;
+ _jc_heap_size *size;
+ int bsi;
+ int block_size;
+ int blocks_left;
+ int blocks_live;
+ int npages;
+ _jc_heap *heap;
+};
+
+/*
+ * GC trace reference list structure. Points to a list of object
+ * references to scan during garbage collection.
+ */
+struct _jc_scan_list {
+ _jc_object **start;
+ _jc_object **end;
+};
+
+/*
+ * One frame in the stack of reference pointers we keep while tracing
+ * objects during GC. Each frame holds a fixed number of _jc_scan_list's.
+ * We aggregate them into larger frames to decrease the number of
+ * allocation operations required.
+ */
+struct _jc_scan_frame {
+ int posn; /* current position in this frame */
+ _jc_scan_frame *prev; /* previous reference stack frame */
+ _jc_scan_frame *next; /* next reference stack frame */
+ _jc_scan_list lists[64]; /* reference lists */
+};
+
+/*
+ * Garbage collection state and statistics.
+ */
+struct _jc_trace_info {
+ _jc_heap *heap;
+ jboolean follow_soft;
+ jboolean wakeup_finalizer;
+ _jc_word mark_bits;
+ _jc_word gc_stack_visited;
+ _jc_scan_frame bottom_frame;
+ int num_finalizable;
+ int num_refs_cleared;
+ int num_recycled_pages;
+ int num_large_pages;
+ int num_small_pages;
+ int num_recycled_objects;
+ int num_fat_locks_recycled;
+ int num_large_objects;
+ int num_small_objects[0];
+};
+
+/************************************************************************
+ * Java virtual machine information *
+ ************************************************************************/
+
+/*
+ * Structure used only during initialization.
+ */
+struct _jc_initialization {
+ jboolean may_execute; /* ok to run java code */
+ jboolean create_class; /* ok to create Class objects */
+ _jc_ex_info ex; /* exception info */
+ _jc_saved_frame *frames; /* exception stack frames */
+ int num_frames;
+};
+
+/*
+ * One system property.
+ */
+struct _jc_property {
+ const char *name; /* propery name */
+ const char *value; /* propery value */
+};
+
+/*
+ * System properties, stored as a sorted array.
+ */
+struct _jc_properties {
+ int allocated; /* number of allocated properties */
+ int length; /* actual number of properties */
+ _jc_property *elems; /* properties */
+};
+
+/*
+ * An expanded, or 'fat lock', object monitor.
+ */
+struct _jc_fat_lock {
+ _jc_word id;
+ jint recursion_count;
+ jchar notify_count;
+ jbyte notify_wakeup;
+ pthread_mutex_t mutex;
+#ifndef NDEBUG
+ _jc_env *mutex_owner;
+#endif
+ pthread_cond_t cond;
+ pthread_cond_t notify;
+ union {
+ _jc_env *owner;
+ SLIST_ENTRY(_jc_fat_lock) link;
+ } u;
+};
+
+/*
+ * Fat locks.
+ */
+struct _jc_fat_locks {
+ _jc_fat_lock **by_id; /* indexed by id */
+ jint next_id; /* next fat lock id */
+ SLIST_HEAD(, _jc_fat_lock) free_list;
+};
+
+/*
+ * Information about threads associated with a VM instance.
+ * All of this structure is protected by the VM mutex.
+ *
+ * Note: the free entries in the 'by_id' array form a linked list of
+ * free thread IDs, starting with the slot indexed by 'free_id_list'.
+ */
+struct _jc_threads {
+ _jc_env **by_id; /* threads indexed by id */
+ jint next_free_id; /* free thread id list */
+ LIST_HEAD(, _jc_env) alive_list; /* list of alive threads */
+ LIST_HEAD(, _jc_env) free_list; /* free thread structures */
+ int num_free; /* length of free list */
+
+ /* Stack size parameters */
+ size_t stack_minimum;
+ size_t stack_maximum;
+ size_t stack_default;
+
+ /* Priority parameters */
+ int prio_min; /* min scheduling priority */
+ int prio_max; /* max scheduling priority */
+ jint java_prio_min; /* Thread.MIN_PRIORITY */
+ jint java_prio_max; /* Thread.MAX_PRIORITY */
+ jint java_prio_norm; /* Thread.NORM_PRIORITY */
+};
+
+/*
+ * Virtual machine info.
+ *
+ * All information in this structure are protected by vm->mutex, with a
+ * few exceptions. Access to fields which are read-only after VM creation,
+ * or which are accessed with atomic operations, does not require the
+ * mutex of course.
+ */
+struct _jc_jvm {
+ _jc_fat_locks fat_locks;
+ LIST_ENTRY(_jc_jvm) link;
+ pthread_mutex_t mutex;
+#ifndef NDEBUG
+ _jc_env *mutex_owner;
+#endif
+ _jc_threads threads;
+ _jc_native_frame_list native_globals;
+ _jc_heap heap;
+
+ /*
+ * Properties and variables derived from them.
+ */
+ _jc_properties system_properties;
+ jboolean generation_enabled;
+ jboolean line_numbers;
+ jboolean resolve_native_directly;
+ jboolean without_classfiles;
+ jboolean loader_enabled;
+ jboolean ignore_resolution_failures;
+ jboolean compiler_disabled;
+ char **source_path;
+ _jc_objpath_entry *object_path;
+ int object_path_len;
+ int max_loader_pages;
+
+ /*
+ * This is non-NULL during bootstrap only.
+ */
+ _jc_initialization *initialization;
+
+ /*
+ * JNI invoke interface.
+ */
+ const struct JNIInvokeInterface *jni_interface;
+
+ /*
+ * Function pointers received from JNI.
+ */
+ int (*vfprintf)(FILE *,
+ const char *, va_list);
+ void (*exit)(int)
+ __attribute__ ((noreturn));
+ void (*abort)(void)
+ __attribute__ ((noreturn));
+
+ /*
+ * Class loading info.
+ */
+ _jc_boot boot;
+ LIST_HEAD(, _jc_class_loader) class_loaders;
+
+ /*
+ * Tree of known class files and their hash values.
+ */
+ _jc_splay_tree classfiles; /* _jc_cfile_node's */
+
+ /*
+ * Tree mapping stack PC values to Java methods (or C functions).
+ */
+ _jc_splay_tree method_tree; /* _jc_method's */
+ _jc_method invoke_method; /* _jc_invoke_jcni_a()*/
+
+ /*
+ * Used for 'stop the world' operations, suspend/resume, shutdown
+ */
+ int pending_halt_count;
+ jboolean world_stopped;
+ jboolean world_ending;
+ pthread_cond_t all_halted;
+ pthread_cond_t world_restarted;
+ pthread_cond_t vm_destruction;
+ char *check_address;
+
+ /*
+ * VM internal threads
+ */
+ jobject debug_thread;
+ jobject finalizer_thread;
+
+ /*
+ * Misc global parameters.
+ */
+ jint verbose_flags;
+ jint gc_cycles;
+ volatile _jc_word avail_loader_pages;
+ _jc_word gc_stack_visited;
+ FILE *object_list;
+};
+
+#endif /* _STRUCTURES_H_ */
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/tables.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/tables.c?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/tables.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/tables.c Tue Oct 4 19:19:16 2005
@@ -0,0 +1,476 @@
+
+/*
+ * 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: tables.c,v 1.11 2005/07/10 21:03:54 archiecobbs Exp $
+ */
+
+#include "libjc.h"
+
+/*
+ * Mapping from Java type to Java type signature letter.
+ */
+const char _jc_prim_chars[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= 'Z',
+ [_JC_TYPE_BYTE]= 'B',
+ [_JC_TYPE_CHAR]= 'C',
+ [_JC_TYPE_SHORT]= 'S',
+ [_JC_TYPE_INT]= 'I',
+ [_JC_TYPE_LONG]= 'J',
+ [_JC_TYPE_FLOAT]= 'F',
+ [_JC_TYPE_DOUBLE]= 'D',
+ [_JC_TYPE_VOID]= 'V',
+ [_JC_TYPE_REFERENCE]= 'L',
+};
+
+/*
+ * Mapping from Java type signature letter to Java type.
+ */
+const u_char _jc_sig_types[0x100] = {
+ ['Z']= _JC_TYPE_BOOLEAN,
+ ['B']= _JC_TYPE_BYTE,
+ ['C']= _JC_TYPE_CHAR,
+ ['S']= _JC_TYPE_SHORT,
+ ['I']= _JC_TYPE_INT,
+ ['J']= _JC_TYPE_LONG,
+ ['F']= _JC_TYPE_FLOAT,
+ ['D']= _JC_TYPE_DOUBLE,
+ ['V']= _JC_TYPE_VOID,
+ ['L']= _JC_TYPE_REFERENCE,
+ ['[']= _JC_TYPE_REFERENCE
+};
+
+/*
+ * Size of various Java types.
+ */
+const size_t _jc_type_sizes[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= sizeof(jboolean),
+ [_JC_TYPE_BYTE]= sizeof(jbyte),
+ [_JC_TYPE_CHAR]= sizeof(jchar),
+ [_JC_TYPE_SHORT]= sizeof(jshort),
+ [_JC_TYPE_INT]= sizeof(jint),
+ [_JC_TYPE_LONG]= sizeof(jlong),
+ [_JC_TYPE_FLOAT]= sizeof(jfloat),
+ [_JC_TYPE_DOUBLE]= sizeof(jdouble),
+ [_JC_TYPE_REFERENCE]= sizeof(void *)
+};
+
+/*
+ * Alignment requirements of various Java types.
+ */
+const size_t _jc_type_align[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= __alignof__(jboolean),
+ [_JC_TYPE_BYTE]= __alignof__(jbyte),
+ [_JC_TYPE_CHAR]= __alignof__(jchar),
+ [_JC_TYPE_SHORT]= __alignof__(jshort),
+ [_JC_TYPE_INT]= __alignof__(jint),
+ [_JC_TYPE_LONG]= __alignof__(jlong),
+ [_JC_TYPE_FLOAT]= __alignof__(jfloat),
+ [_JC_TYPE_DOUBLE]= __alignof__(jdouble),
+ [_JC_TYPE_REFERENCE]= __alignof__(void *),
+};
+
+/*
+ * Whether each Java type requires one or two Java stack words.
+ */
+const u_char _jc_dword_type[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= JNI_FALSE,
+ [_JC_TYPE_BYTE]= JNI_FALSE,
+ [_JC_TYPE_CHAR]= JNI_FALSE,
+ [_JC_TYPE_SHORT]= JNI_FALSE,
+ [_JC_TYPE_INT]= JNI_FALSE,
+ [_JC_TYPE_LONG]= JNI_TRUE,
+ [_JC_TYPE_FLOAT]= JNI_FALSE,
+ [_JC_TYPE_DOUBLE]= JNI_TRUE,
+ [_JC_TYPE_REFERENCE]= JNI_FALSE,
+};
+
+/*
+ * Size of the head part in the various array object types.
+ */
+const size_t _jc_array_head_sizes[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= _JC_OFFSETOF(_jc_boolean_array, elems),
+ [_JC_TYPE_BYTE]= _JC_OFFSETOF(_jc_byte_array, elems),
+ [_JC_TYPE_CHAR]= _JC_OFFSETOF(_jc_char_array, elems),
+ [_JC_TYPE_SHORT]= _JC_OFFSETOF(_jc_short_array, elems),
+ [_JC_TYPE_INT]= _JC_OFFSETOF(_jc_int_array, elems),
+ [_JC_TYPE_LONG]= _JC_OFFSETOF(_jc_long_array, elems),
+ [_JC_TYPE_FLOAT]= _JC_OFFSETOF(_jc_float_array, elems),
+ [_JC_TYPE_DOUBLE]= _JC_OFFSETOF(_jc_double_array, elems),
+ [_JC_TYPE_REFERENCE]= sizeof(_jc_object_array),
+};
+
+/*
+ * Names of various primitive types.
+ */
+const char *const _jc_prim_names[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= "boolean",
+ [_JC_TYPE_BYTE]= "byte",
+ [_JC_TYPE_CHAR]= "char",
+ [_JC_TYPE_SHORT]= "short",
+ [_JC_TYPE_INT]= "int",
+ [_JC_TYPE_LONG]= "long",
+ [_JC_TYPE_FLOAT]= "float",
+ [_JC_TYPE_DOUBLE]= "double",
+ [_JC_TYPE_VOID]= "void",
+ [_JC_TYPE_REFERENCE]= "object"
+};
+
+/*
+ * Method intepreter gateway functions.
+ */
+const void *const _jc_interp_funcs[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= _jc_interp_z,
+ [_JC_TYPE_BYTE]= _jc_interp_b,
+ [_JC_TYPE_CHAR]= _jc_interp_c,
+ [_JC_TYPE_SHORT]= _jc_interp_s,
+ [_JC_TYPE_INT]= _jc_interp_i,
+ [_JC_TYPE_LONG]= _jc_interp_j,
+ [_JC_TYPE_FLOAT]= _jc_interp_f,
+ [_JC_TYPE_DOUBLE]= _jc_interp_d,
+ [_JC_TYPE_VOID]= _jc_interp_v,
+ [_JC_TYPE_REFERENCE]= _jc_interp_l,
+};
+const void *const _jc_interp_native_funcs[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= _jc_interp_native_z,
+ [_JC_TYPE_BYTE]= _jc_interp_native_b,
+ [_JC_TYPE_CHAR]= _jc_interp_native_c,
+ [_JC_TYPE_SHORT]= _jc_interp_native_s,
+ [_JC_TYPE_INT]= _jc_interp_native_i,
+ [_JC_TYPE_LONG]= _jc_interp_native_j,
+ [_JC_TYPE_FLOAT]= _jc_interp_native_f,
+ [_JC_TYPE_DOUBLE]= _jc_interp_native_d,
+ [_JC_TYPE_VOID]= _jc_interp_native_v,
+ [_JC_TYPE_REFERENCE]= _jc_interp_native_l,
+};
+
+/*
+ * Mapping from Java primitive type to Java wrapper class name.
+ */
+const char *const _jc_prim_wrapper_class[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= "java/lang/Boolean",
+ [_JC_TYPE_BYTE]= "java/lang/Byte",
+ [_JC_TYPE_CHAR]= "java/lang/Character",
+ [_JC_TYPE_SHORT]= "java/lang/Short",
+ [_JC_TYPE_INT]= "java/lang/Integer",
+ [_JC_TYPE_LONG]= "java/lang/Long",
+ [_JC_TYPE_FLOAT]= "java/lang/Float",
+ [_JC_TYPE_DOUBLE]= "java/lang/Double",
+ [_JC_TYPE_VOID]= "java/lang/Void"
+};
+
+/*
+ * Maximum allowable array length for the various Java types.
+ * Any longer and the total object size would overflow 'size_t'.
+ */
+const jlong _jc_type_max_array_length[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= (jlong)SIZE_T_MAX / sizeof(jboolean),
+ [_JC_TYPE_BYTE]= (jlong)SIZE_T_MAX / sizeof(jbyte),
+ [_JC_TYPE_CHAR]= (jlong)SIZE_T_MAX / sizeof(jchar),
+ [_JC_TYPE_SHORT]= (jlong)SIZE_T_MAX / sizeof(jshort),
+ [_JC_TYPE_INT]= (jlong)SIZE_T_MAX / sizeof(jint),
+ [_JC_TYPE_LONG]= (jlong)SIZE_T_MAX / sizeof(jlong),
+ [_JC_TYPE_FLOAT]= (jlong)SIZE_T_MAX / sizeof(jfloat),
+ [_JC_TYPE_DOUBLE]= (jlong)SIZE_T_MAX / sizeof(jdouble),
+ [_JC_TYPE_REFERENCE]= (jlong)SIZE_T_MAX / sizeof(void *)
+};
+
+/*
+ * Field sorting order.
+ *
+ * This must sort the same as org.dellroad.jc.cgen.Util.OrderTypeSwitch.
+ */
+const int _jc_field_type_sort[_JC_TYPE_MAX] = {
+ [_JC_TYPE_BOOLEAN]= 4,
+ [_JC_TYPE_BYTE]= 4,
+ [_JC_TYPE_CHAR]= 3,
+ [_JC_TYPE_SHORT]= 3,
+ [_JC_TYPE_INT]= 2,
+ [_JC_TYPE_FLOAT]= 2,
+ [_JC_TYPE_LONG]= 1,
+ [_JC_TYPE_DOUBLE]= 1,
+ [_JC_TYPE_REFERENCE]= 0,
+};
+
+/*
+ * Names of VM exceptions.
+ */
+#define VMEX_ENTRY(name) [_JC_ ## name]= "java/lang/" #name
+const char *const _jc_vmex_names[_JC_VMEXCEPTION_MAX] = {
+ VMEX_ENTRY(AbstractMethodError),
+ VMEX_ENTRY(ArithmeticException),
+ VMEX_ENTRY(ArrayIndexOutOfBoundsException),
+ VMEX_ENTRY(ArrayStoreException),
+ VMEX_ENTRY(ClassCastException),
+ VMEX_ENTRY(ClassCircularityError),
+ VMEX_ENTRY(ClassFormatError),
+ VMEX_ENTRY(ClassNotFoundException),
+ VMEX_ENTRY(CloneNotSupportedException),
+ VMEX_ENTRY(ExceptionInInitializerError),
+ [_JC_IOException] = "java/io/IOException",
+ VMEX_ENTRY(IllegalAccessError),
+ VMEX_ENTRY(IllegalAccessException),
+ VMEX_ENTRY(IllegalArgumentException),
+ VMEX_ENTRY(IllegalMonitorStateException),
+ VMEX_ENTRY(IllegalThreadStateException),
+ VMEX_ENTRY(IncompatibleClassChangeError),
+ VMEX_ENTRY(InstantiationError),
+ VMEX_ENTRY(InstantiationException),
+ VMEX_ENTRY(InternalError),
+ VMEX_ENTRY(InterruptedException),
+ [_JC_InvocationTargetException]
+ = "java/lang/reflect/InvocationTargetException",
+ VMEX_ENTRY(LinkageError),
+ VMEX_ENTRY(NegativeArraySizeException),
+ VMEX_ENTRY(NoClassDefFoundError),
+ VMEX_ENTRY(NoSuchFieldError),
+ VMEX_ENTRY(NoSuchMethodError),
+ VMEX_ENTRY(NullPointerException),
+ VMEX_ENTRY(OutOfMemoryError),
+ VMEX_ENTRY(StackOverflowError),
+ VMEX_ENTRY(ThreadDeath),
+ VMEX_ENTRY(UnsatisfiedLinkError),
+ VMEX_ENTRY(UnsupportedClassVersionError),
+};
+
+/*
+ * Hex chars.
+ */
+const char _jc_hex_chars[16] = "0123456789abcdef";
+
+/*
+ * Printable names of the verbosity flags.
+ */
+const char *const _jc_verbose_names[_JC_VERBOSE_MAX] = {
+ [_JC_VERBOSE_CLASS]= "class",
+ [_JC_VERBOSE_GC]= "gc",
+ [_JC_VERBOSE_JNI]= "jni",
+ [_JC_VERBOSE_EXCEPTIONS]= "exceptions",
+ [_JC_VERBOSE_RESOLUTION]= "resolution",
+ [_JC_VERBOSE_INIT]= "init",
+ [_JC_VERBOSE_GEN]= "gen",
+ [_JC_VERBOSE_JNI_INVOKE]= "jni-invoke",
+ [_JC_VERBOSE_OBJ]= "obj",
+};
+
+/*
+ * Bytecode names.
+ */
+#define BYTECODE(name) [_JC_ ## name]= #name
+const char *const _jc_bytecode_names[0x100] = {
+ BYTECODE(aaload),
+ BYTECODE(aastore),
+ BYTECODE(aconst_null),
+ BYTECODE(aload),
+ BYTECODE(aload_0),
+ BYTECODE(aload_1),
+ BYTECODE(aload_2),
+ BYTECODE(aload_3),
+ BYTECODE(anewarray),
+ BYTECODE(areturn),
+ BYTECODE(arraylength),
+ BYTECODE(astore),
+ BYTECODE(astore_0),
+ BYTECODE(astore_1),
+ BYTECODE(astore_2),
+ BYTECODE(astore_3),
+ BYTECODE(athrow),
+ BYTECODE(baload),
+ BYTECODE(bastore),
+ BYTECODE(bipush),
+ BYTECODE(caload),
+ BYTECODE(castore),
+ BYTECODE(checkcast),
+ BYTECODE(d2f),
+ BYTECODE(d2i),
+ BYTECODE(d2l),
+ BYTECODE(dadd),
+ BYTECODE(daload),
+ BYTECODE(dastore),
+ BYTECODE(dcmpg),
+ BYTECODE(dcmpl),
+ BYTECODE(dconst_0),
+ BYTECODE(dconst_1),
+ BYTECODE(ddiv),
+ BYTECODE(dload),
+ BYTECODE(dload_0),
+ BYTECODE(dload_1),
+ BYTECODE(dload_2),
+ BYTECODE(dload_3),
+ BYTECODE(dmul),
+ BYTECODE(dneg),
+ BYTECODE(drem),
+ BYTECODE(dreturn),
+ BYTECODE(dstore),
+ BYTECODE(dstore_0),
+ BYTECODE(dstore_1),
+ BYTECODE(dstore_2),
+ BYTECODE(dstore_3),
+ BYTECODE(dsub),
+ BYTECODE(dup),
+ BYTECODE(dup_x1),
+ BYTECODE(dup_x2),
+ BYTECODE(dup2),
+ BYTECODE(dup2_x1),
+ BYTECODE(dup2_x2),
+ BYTECODE(f2d),
+ BYTECODE(f2i),
+ BYTECODE(f2l),
+ BYTECODE(fadd),
+ BYTECODE(faload),
+ BYTECODE(fastore),
+ BYTECODE(fcmpg),
+ BYTECODE(fcmpl),
+ BYTECODE(fconst_0),
+ BYTECODE(fconst_1),
+ BYTECODE(fconst_2),
+ BYTECODE(fdiv),
+ BYTECODE(fload),
+ BYTECODE(fload_0),
+ BYTECODE(fload_1),
+ BYTECODE(fload_2),
+ BYTECODE(fload_3),
+ BYTECODE(fmul),
+ BYTECODE(fneg),
+ BYTECODE(frem),
+ BYTECODE(freturn),
+ BYTECODE(fstore),
+ BYTECODE(fstore_0),
+ BYTECODE(fstore_1),
+ BYTECODE(fstore_2),
+ BYTECODE(fstore_3),
+ BYTECODE(fsub),
+ BYTECODE(getfield),
+ BYTECODE(getstatic),
+ BYTECODE(goto),
+ BYTECODE(goto_w),
+ BYTECODE(i2b),
+ BYTECODE(i2c),
+ BYTECODE(i2d),
+ BYTECODE(i2f),
+ BYTECODE(i2l),
+ BYTECODE(i2s),
+ BYTECODE(iadd),
+ BYTECODE(iaload),
+ BYTECODE(iand),
+ BYTECODE(iastore),
+ BYTECODE(iconst_m1),
+ BYTECODE(iconst_0),
+ BYTECODE(iconst_1),
+ BYTECODE(iconst_2),
+ BYTECODE(iconst_3),
+ BYTECODE(iconst_4),
+ BYTECODE(iconst_5),
+ BYTECODE(idiv),
+ BYTECODE(if_acmpeq),
+ BYTECODE(if_acmpne),
+ BYTECODE(if_icmpeq),
+ BYTECODE(if_icmpne),
+ BYTECODE(if_icmplt),
+ BYTECODE(if_icmpge),
+ BYTECODE(if_icmpgt),
+ BYTECODE(if_icmple),
+ BYTECODE(ifeq),
+ BYTECODE(ifne),
+ BYTECODE(iflt),
+ BYTECODE(ifge),
+ BYTECODE(ifgt),
+ BYTECODE(ifle),
+ BYTECODE(ifnonnull),
+ BYTECODE(ifnull),
+ BYTECODE(iinc),
+ BYTECODE(iload),
+ BYTECODE(iload_0),
+ BYTECODE(iload_1),
+ BYTECODE(iload_2),
+ BYTECODE(iload_3),
+ BYTECODE(imul),
+ BYTECODE(ineg),
+ BYTECODE(instanceof),
+ BYTECODE(invokeinterface),
+ BYTECODE(invokespecial),
+ BYTECODE(invokestatic),
+ BYTECODE(invokevirtual),
+ BYTECODE(ior),
+ BYTECODE(irem),
+ BYTECODE(ireturn),
+ BYTECODE(ishl),
+ BYTECODE(ishr),
+ BYTECODE(istore),
+ BYTECODE(istore_0),
+ BYTECODE(istore_1),
+ BYTECODE(istore_2),
+ BYTECODE(istore_3),
+ BYTECODE(isub),
+ BYTECODE(iushr),
+ BYTECODE(ixor),
+ BYTECODE(jsr),
+ BYTECODE(jsr_w),
+ BYTECODE(l2d),
+ BYTECODE(l2f),
+ BYTECODE(l2i),
+ BYTECODE(ladd),
+ BYTECODE(laload),
+ BYTECODE(land),
+ BYTECODE(lastore),
+ BYTECODE(lcmp),
+ BYTECODE(lconst_0),
+ BYTECODE(lconst_1),
+ BYTECODE(ldc),
+ BYTECODE(ldc_w),
+ BYTECODE(ldc_string),
+ BYTECODE(ldc2_w),
+ BYTECODE(ldiv),
+ BYTECODE(lload),
+ BYTECODE(lload_0),
+ BYTECODE(lload_1),
+ BYTECODE(lload_2),
+ BYTECODE(lload_3),
+ BYTECODE(lmul),
+ BYTECODE(lneg),
+ BYTECODE(lookupswitch),
+ BYTECODE(lor),
+ BYTECODE(lrem),
+ BYTECODE(lreturn),
+ BYTECODE(lshl),
+ BYTECODE(lshr),
+ BYTECODE(lstore),
+ BYTECODE(lstore_0),
+ BYTECODE(lstore_1),
+ BYTECODE(lstore_2),
+ BYTECODE(lstore_3),
+ BYTECODE(lsub),
+ BYTECODE(lushr),
+ BYTECODE(lxor),
+ BYTECODE(monitorenter),
+ BYTECODE(monitorexit),
+ BYTECODE(multianewarray),
+ BYTECODE(new),
+ BYTECODE(newarray),
+ BYTECODE(nop),
+ BYTECODE(pop),
+ BYTECODE(pop2),
+ BYTECODE(putfield),
+ BYTECODE(putstatic),
+ BYTECODE(ret),
+ BYTECODE(return),
+ BYTECODE(saload),
+ BYTECODE(sastore),
+ BYTECODE(sipush),
+ BYTECODE(swap),
+ BYTECODE(tableswitch),
+ BYTECODE(wide),
+};
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/thread.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/thread.c?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/thread.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/thread.c Tue Oct 4 19:19:16 2005
@@ -0,0 +1,1121 @@
+
+/*
+ * 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: thread.c,v 1.14 2005/03/18 04:17:48 archiecobbs Exp $
+ */
+
+#include "libjc.h"
+
+/* Internal variables */
+static pthread_key_t _jc_env_key;
+
+/* Internal functions */
+static void _jc_set_current_env(_jc_jvm *vm, _jc_env *env);
+static void _jc_thread_suspend(_jc_env *env);
+
+#ifdef __linux__
+static void _jc_touch_stack(const char *start, const char *current);
+#endif
+
+/*
+ * Initialize threading.
+ */
+jint
+_jc_thread_init(void)
+{
+ if ((errno = pthread_key_create(&_jc_env_key, NULL)) != 0) {
+ fprintf(stderr, "jc: %s: %s",
+ "pthread_key_create", strerror(errno));
+ return JNI_ERR;
+ }
+ return JNI_OK;
+}
+
+/*
+ * Get the _jc_env corresponding to the current thread.
+ */
+_jc_env *
+_jc_get_current_env(void)
+{
+ return (_jc_env *)pthread_getspecific(_jc_env_key);
+}
+
+/*
+ * Set the _jc_env corresponding to the current thread.
+ */
+static void
+_jc_set_current_env(_jc_jvm *vm, _jc_env *env)
+{
+ int error;
+
+ if ((error = pthread_setspecific(_jc_env_key, env)) != 0) {
+ _jc_fatal_error(vm, "%s: %s\n",
+ "pthread_setspecific", strerror(error));
+ }
+}
+
+/*
+ * Check whether another thread has notified us to take some action.
+ * There must not be any currently posted exception.
+ *
+ * Returns JNI_ERR if there was a cross-posted exception.
+ *
+ * The caller must have clipped the top of the Java stack.
+ */
+jint
+_jc_thread_check(_jc_env *env)
+{
+ _jc_jvm *const vm = env->vm;
+ jint status = JNI_OK;
+ _jc_object *ex;
+
+ /* Sanity check */
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL
+ || env->status == _JC_THRDSTAT_HALTING_NORMAL);
+ _JC_ASSERT(env->head.pending == NULL);
+
+ /* Check for halt requested */
+ if (env->status == _JC_THRDSTAT_HALTING_NORMAL) {
+ _JC_MUTEX_LOCK(env, vm->mutex);
+ snprintf(env->text_status, sizeof(env->text_status),
+ "executing Java code");
+ _jc_halt_if_requested(env);
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+ }
+
+ /* Check for being suspended */
+ if (env->suspended)
+ _jc_thread_suspend(env);
+
+ /* Check for an exception posted by another thread */
+ if ((ex = _jc_retrieve_cross_exception(env)) != NULL) {
+ VERBOSE(EXCEPTIONS, vm, "cross-posting `%s' in thread %p",
+ ex->type->name, env);
+ env->head.pending = ex;
+ status = JNI_ERR;
+ }
+
+ /* Done */
+ return status;
+}
+
+/*
+ * Suspend the current thread.
+ *
+ * The caller must have clipped the top of the Java stack.
+ */
+static void
+_jc_thread_suspend(_jc_env *env)
+{
+ _jc_jvm *const vm = env->vm;
+
+ /* Sanity check */
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL
+ || env->status == _JC_THRDSTAT_HALTING_NORMAL);
+
+ /* Initialize resume condition variable if not already done */
+ if (!env->resumption_initialized) {
+ if (_jc_cond_init(env, &env->resumption) != JNI_OK) {
+ _jc_post_exception_info(env);
+ _jc_throw_exception(env);
+ }
+ env->resumption_initialized = JNI_TRUE;
+ }
+
+ /* Exit Java mode */
+ _jc_stopping_java(env, "Suspended by Thread.suspend()");
+
+ /* Suspend while suspended */
+ _JC_MUTEX_LOCK(env, vm->mutex);
+ while (env->suspended)
+ _JC_COND_WAIT(env, env->resumption, vm->mutex);
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+
+ /* Return to Java mode */
+ _jc_resuming_java(env);
+}
+
+/*
+ * Interrupt another thread given its Thread instance.
+ *
+ * This method may be called by a thread running in non-Java mode.
+ */
+void
+_jc_thread_interrupt_instance(_jc_jvm *vm, _jc_object *instance)
+{
+ _jc_env *thread;
+ _jc_object *vmt;
+
+ /* Sanity check */
+ _JC_ASSERT(_jc_subclass_of(instance, vm->boot.types.Thread));
+
+ /* Lock VM to keep thread from disappearing */
+ _JC_MUTEX_LOCK(_jc_get_current_env(), vm->mutex);
+
+ /* Get VMThread */
+ vmt = *_JC_VMFIELD(vm, instance, Thread, vmThread, _jc_object *);
+ if (vmt == NULL)
+ goto done;
+
+ /* Get internal thread structure */
+ thread = _jc_get_vm_pointer(vmt, vm->boot.fields.VMThread.vmdata);
+ if (thread == NULL)
+ goto done;
+
+ /* Interrupt thread */
+ _jc_thread_interrupt(vm, thread);
+
+done:
+ /* Unlock VM */
+ _JC_MUTEX_UNLOCK(_jc_get_current_env(), vm->mutex);
+}
+
+/*
+ * Interrupt another thread.
+ *
+ * This method may be called by a thread running in non-Java mode.
+ *
+ * NOTE: The caller must have acquire the VM mutex.
+ */
+void
+_jc_thread_interrupt(_jc_jvm *vm, _jc_env *thread)
+{
+ /* Sanity check */
+ _JC_MUTEX_ASSERT(_jc_get_current_env(), vm->mutex);
+
+ /*
+ * Atomically set other thread's interrupted flag. If
+ * the thread is in interruptible sleep, wake it up.
+ */
+ while (JNI_TRUE) {
+ _jc_word old_status;
+
+ switch ((old_status = thread->interrupt_status)) {
+ case _JC_INTERRUPT_CLEAR:
+ if (_jc_compare_and_swap(&thread->interrupt_status,
+ old_status, _JC_INTERRUPT_SET))
+ return;
+ break;
+ case _JC_INTERRUPT_INTERRUPTIBLE:
+ {
+ _jc_fat_lock *lock;
+
+ /* Change state to interrupted */
+ if (!_jc_compare_and_swap(
+ &thread->interrupt_status,
+ old_status, _JC_INTERRUPT_INTERRUPTED))
+ break;
+
+ /*
+ * Wake up the other thread. If the lock is NULL then
+ * thread has already woken up and left. Otherwise,
+ * we must grab the mutex to ensure the thread has
+ * started sleeping on the condition variable.
+ */
+ if ((lock = thread->interruptible_lock) != NULL) {
+ _JC_MUTEX_LOCK(_jc_get_current_env(),
+ lock->mutex);
+ _JC_COND_BROADCAST(lock->notify);
+ _JC_MUTEX_UNLOCK(_jc_get_current_env(),
+ lock->mutex);
+ }
+ return;
+ }
+ case _JC_INTERRUPT_SET:
+ case _JC_INTERRUPT_INTERRUPTED:
+ return;
+ default:
+ _JC_ASSERT(JNI_FALSE);
+ }
+ }
+}
+
+/*
+ * Check if another thread has requested that this thread halt.
+ *
+ * NOTE: The calling thread must ensure vm->mutex is acquired
+ * and update env->text_status with the thread's status.
+ */
+void
+_jc_halt_if_requested(_jc_env *env)
+{
+ _jc_jvm *const vm = env->vm;
+
+ /* Sanity check */
+ _JC_MUTEX_ASSERT(env, vm->mutex);
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL
+ || env->status == _JC_THRDSTAT_HALTING_NORMAL);
+
+ /* Stop while requested to */
+ while (env->status == _JC_THRDSTAT_HALTING_NORMAL) {
+ jboolean clipped_stack_top;
+
+ /* Clip the current top of the Java stack if not already */
+ clipped_stack_top = _jc_stack_clip(env);
+
+ /* Update status */
+ env->status = _JC_THRDSTAT_HALTED;
+
+ /* The last thread to halt wakes up the requesting thread */
+ _JC_ASSERT(vm->pending_halt_count > 0);
+ if (--vm->pending_halt_count == 0)
+ _JC_COND_SIGNAL(vm->all_halted);
+
+ /* Wait for the thread requesting the halt to finish */
+ while (env->status == _JC_THRDSTAT_HALTED)
+ _JC_COND_WAIT(env, vm->world_restarted, vm->mutex);
+
+ /* Unclip stack */
+ if (clipped_stack_top)
+ _jc_stack_unclip(env);
+ }
+
+ /* Sanity check */
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL);
+}
+
+/*
+ * Stop all other threads except this one.
+ *
+ * NOTE: The calling thread should acquire vm->mutex. Once the world
+ * is stopped, the calling thread should release the lock until just
+ * prior to the call to calling _jc_resume_the_world().
+ */
+void
+_jc_stop_the_world(_jc_env *env)
+{
+ _jc_jvm *const vm = env->vm;
+ _jc_env *thread;
+
+ /* Sanity check */
+ _JC_MUTEX_ASSERT(env, vm->mutex);
+ _JC_ASSERT(!vm->world_stopped);
+
+ /* Update thread's debugging status */
+ snprintf(env->text_status, sizeof(env->text_status),
+ "trying to stop the world");
+
+ /* If another thread beat us to it, halt for it first */
+ _jc_halt_if_requested(env);
+
+ /* Sanity checks */
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL);
+ _JC_ASSERT(vm->pending_halt_count == 0);
+
+ /*
+ * Put all other threads in 'halting' mode.
+ * They will halt at the next available opportunity.
+ */
+ LIST_FOREACH(thread, &vm->threads.alive_list, link) {
+ jboolean succeeded;
+
+ /* Skip the current thread */
+ if (thread == env)
+ continue;
+
+ /* Set thread's status to halting */
+ for (succeeded = JNI_FALSE; !succeeded; ) {
+ switch (thread->status) {
+ case _JC_THRDSTAT_RUNNING_NORMAL:
+ succeeded = _jc_compare_and_swap(
+ &thread->status,
+ _JC_THRDSTAT_RUNNING_NORMAL,
+ _JC_THRDSTAT_HALTING_NORMAL);
+ if (succeeded)
+ vm->pending_halt_count++;
+ break;
+ case _JC_THRDSTAT_RUNNING_NONJAVA:
+ succeeded = _jc_compare_and_swap(
+ &thread->status,
+ _JC_THRDSTAT_RUNNING_NONJAVA,
+ _JC_THRDSTAT_HALTING_NONJAVA);
+ break;
+ default:
+ _JC_ASSERT(JNI_FALSE);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Unmap the check address page so all threads executing Java code
+ * will receive a SEGV signal, which will cause them to invoke
+ * _jc_thread_check() and notice that they need to halt.
+ */
+ if (mprotect(vm->check_address, _JC_PAGE_SIZE, PROT_NONE) == -1)
+ _jc_fatal_error(vm, "mprotect: %s", strerror(errno));
+
+ /* Now wait for the threads running in Java mode to actually halt */
+ while (vm->pending_halt_count > 0)
+ _JC_COND_WAIT(env, vm->all_halted, vm->mutex);
+
+ /* Re-map the check address page */
+ if (mprotect(vm->check_address, _JC_PAGE_SIZE, PROT_READ) == -1)
+ _jc_fatal_error(vm, "mprotect: %s", strerror(errno));
+
+ /* Update flags */
+ vm->world_stopped = JNI_TRUE;
+}
+
+/*
+ * Wake up other threads previously halted by _jc_stop_the_world().
+ *
+ * NOTE: The calling thread should acquire vm->mutex before
+ * calling this function. Of course, _jc_stop_the_world()
+ * must have been called previously by this thread as well.
+ */
+void
+_jc_resume_the_world(_jc_env *env)
+{
+ _jc_jvm *const vm = env->vm;
+ _jc_env *thread;
+
+ /* Sanity check */
+ _JC_MUTEX_ASSERT(env, vm->mutex);
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL);
+ _JC_ASSERT(vm->pending_halt_count == 0);
+ _JC_ASSERT(vm->world_stopped);
+
+ /*
+ * Wake up all other threads previously halted by us.
+ */
+ LIST_FOREACH(thread, &vm->threads.alive_list, link) {
+
+ /* Skip the current thread */
+ if (thread == env)
+ continue;
+
+ /* Mark thread as running */
+ switch (thread->status) {
+ case _JC_THRDSTAT_HALTED:
+ thread->status = _JC_THRDSTAT_RUNNING_NORMAL;
+ break;
+ case _JC_THRDSTAT_HALTING_NONJAVA:
+ thread->status = _JC_THRDSTAT_RUNNING_NONJAVA;
+ break;
+ default:
+ _JC_ASSERT(JNI_FALSE);
+ break;
+ }
+ }
+
+ /* Wake all halted threads */
+ _JC_COND_BROADCAST(vm->world_restarted);
+
+ /* Update flag */
+ vm->world_stopped = JNI_FALSE;
+}
+
+/*
+ * Transition from Java code to non-Java code.
+ * Halt if requested to do so by another thread.
+ *
+ * NOTE: If this is called because we're about to invoke a non-Java
+ * function, then the top of the Java stack must be clipped first.
+ */
+void
+_jc_stopping_java(_jc_env *env, const char *fmt, ...)
+{
+ _jc_jvm *const vm = env->vm;
+
+ /* Sanity check */
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL
+ || env->status == _JC_THRDSTAT_HALTING_NORMAL);
+ _JC_ASSERT(env->java_stack == NULL
+ || ((!env->java_stack->interp
+ && ((_jc_exec_stack *)env->java_stack)->pc != NULL)
+ || (env->java_stack->interp
+ && ((_jc_interp_stack *)env->java_stack)->clipped)));
+
+ /* Update debug status */
+ if (fmt == NULL) {
+ snprintf(env->text_status, sizeof(env->text_status),
+ "running native code");
+ } else {
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(env->text_status, sizeof(env->text_status),
+ fmt, args);
+ va_end(args);
+ }
+
+ /* Change this thread's status, but first halt if requested */
+ if (!_jc_compare_and_swap(&env->status,
+ _JC_THRDSTAT_RUNNING_NORMAL, _JC_THRDSTAT_RUNNING_NONJAVA)) {
+
+ /* Lock the VM */
+ _JC_MUTEX_LOCK(env, vm->mutex);
+
+ /* Halt if requested */
+ _jc_halt_if_requested(env);
+
+ /* Sanity check */
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL);
+
+ /* Update status */
+ env->status = _JC_THRDSTAT_RUNNING_NONJAVA;
+
+ /* Unlock the VM */
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+ }
+}
+
+/*
+ * Transition from non-Java code to Java code.
+ * Halt if requested to do so by another thread.
+ *
+ * The top of the Java stack must have been clipped already.
+ */
+void
+_jc_resuming_java(_jc_env *env)
+{
+ _jc_jvm *const vm = env->vm;
+
+ /* Sanity check */
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NONJAVA
+ || env->status == _JC_THRDSTAT_HALTING_NONJAVA);
+ _JC_ASSERT(env->java_stack == NULL
+ || ((!env->java_stack->interp
+ && ((_jc_exec_stack *)env->java_stack)->pc != NULL)
+ || (env->java_stack->interp
+ && ((_jc_interp_stack *)env->java_stack)->clipped)));
+
+ /* Change this thread's status, but first halt if requested */
+ if (!_jc_compare_and_swap(&env->status,
+ _JC_THRDSTAT_RUNNING_NONJAVA, _JC_THRDSTAT_RUNNING_NORMAL)) {
+ _JC_MUTEX_LOCK(env, vm->mutex);
+ while (env->status == _JC_THRDSTAT_HALTING_NONJAVA)
+ _JC_COND_WAIT(env, vm->world_restarted, vm->mutex);
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NONJAVA);
+ env->status = _JC_THRDSTAT_RUNNING_NORMAL;
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+ }
+}
+
+/*
+ * Create the java.lang.Thread instance associated with a native thread.
+ */
+jint
+_jc_thread_create_instance(_jc_env *env, _jc_object *group,
+ const char *name, jint priority, jboolean daemon)
+{
+ _jc_jvm *const vm = env->vm;
+ jobject sref = NULL;
+ jobject vtref = NULL;
+
+ /* Sanity check */
+ _JC_ASSERT(group != NULL);
+ _JC_ASSERT(env->instance == NULL);
+
+ /* Create String from supplied name, if any */
+ if (name != NULL
+ && (sref = _jc_new_local_native_ref(env,
+ _jc_new_string(env, name, strlen(name)))) == NULL)
+ goto fail;
+
+ /* Create new Thread object for this thread */
+ if ((env->instance = _jc_new_object(env,
+ vm->boot.types.Thread)) == NULL)
+ goto fail;
+
+ /* Create new VMThread object for this thread */
+ if ((vtref = _jc_new_local_native_ref(env,
+ _jc_new_object(env, vm->boot.types.VMThread))) == NULL)
+ goto fail;
+
+ /* Set VMThread private data */
+ _jc_set_vm_pointer(*vtref, vm->boot.fields.VMThread.vmdata, env);
+
+ /* Invoke VMThread constructor */
+ if (_jc_invoke_nonvirtual(env, vm->boot.methods.VMThread.init,
+ *vtref, env->instance) != JNI_OK) {
+ _jc_print_stack_trace(env, stderr);
+ goto fail;
+ }
+
+ /* Invoke the Thread() constructor used for native threads */
+ if (_jc_invoke_nonvirtual(env, vm->boot.methods.Thread.init,
+ env->instance, *vtref, (sref != NULL) ? *sref : NULL,
+ priority, daemon) != JNI_OK) {
+ _jc_print_stack_trace(env, stderr);
+ goto fail;
+ }
+
+ /* Add thread to the group */
+ *_JC_VMFIELD(vm, env->instance, Thread, group, _jc_object *) = group;
+ if (_jc_invoke_virtual(env, vm->boot.methods.ThreadGroup.addThread,
+ group, env->instance) != JNI_OK)
+ goto fail;
+
+ /* XXX FIXME do InheritableThreadLocal */
+
+ /* Done */
+ _jc_free_local_native_ref(&sref);
+ _jc_free_local_native_ref(&vtref);
+ return JNI_OK;
+
+fail:
+ /* Clean up after failure */
+ _jc_free_local_native_ref(&sref);
+ _jc_free_local_native_ref(&vtref);
+ env->instance = NULL;
+ return JNI_ERR;
+}
+
+/*
+ * Entry point for new java.lang.Thread threads.
+ *
+ * This function marks the bottom of the call stack of threads created
+ * via Thread.start(). Threads attached to the VM using the JNI invocation
+ * API do not go through this function.
+ */
+void *
+_jc_thread_start(void *arg)
+{
+ _jc_env *env = arg;
+ _jc_jvm *const vm = env->vm;
+ _jc_object *vmt;
+
+ /* Sanity checks */
+ _JC_ASSERT(env->instance != NULL);
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL
+ || env->status == _JC_THRDSTAT_HALTING_NORMAL);
+
+ /* Set thread-local pointer to my thread structure */
+ _jc_set_current_env(vm, env);
+
+ /* Grab pointer to the VMThread */
+ vmt = env->retval.l;
+ _JC_ASSERT(_jc_subclass_of(vmt, vm->boot.types.VMThread));
+
+ /* Invoke VMThread.run() */
+ if (_jc_invoke_virtual(env,
+ vm->boot.methods.VMThread.run, vmt) != JNI_OK)
+ (void)_jc_retrieve_exception(env, NULL);
+
+ /* Detach thread */
+ _JC_MUTEX_LOCK(env, vm->mutex);
+ _jc_detach_thread(&env);
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+
+ /* Okaybye */
+ return NULL;
+}
+
+/*
+ * Create a thread structure and attach it to the currently running thread.
+ *
+ * If unsuccessful an exception is stored in the supplied pointers.
+ *
+ * NOTE: This assumes the VM global mutex is held.
+ */
+_jc_env *
+_jc_attach_thread(_jc_jvm *vm, _jc_ex_info *ex)
+{
+ _jc_env temp_env;
+ _jc_env *env;
+
+ /* Initialize phoney current thread structure */
+ memset(&temp_env, 0, sizeof(temp_env));
+ temp_env.ex.num = -1;
+ temp_env.vm = vm;
+
+ /* Ensure this thread isn't already attached to a VM */
+ if (_jc_get_current_env() != NULL) {
+ _JC_EX_STORE(&temp_env, InternalError,
+ "current thread is already attached");
+ goto fail;
+ }
+
+ /* Sanity check */
+ _JC_MUTEX_ASSERT(NULL, vm->mutex);
+#ifndef NDEBUG
+ vm->mutex_owner = &temp_env;
+#endif
+
+ /* Get a new thread structure */
+ if ((env = _jc_allocate_thread(&temp_env)) == NULL)
+ goto fail;
+
+#ifdef __linux__
+ /* Make sure the stack is really there */
+ _jc_touch_stack((const char *)&vm, (const char *)&vm);
+#endif
+
+ /* Remember that this thread structure goes with the current thread */
+ _jc_set_current_env(vm, env);
+
+#ifndef NDEBUG
+ /* Update mutex owner */
+ vm->mutex_owner = env;
+#endif
+
+ /* If the world is stopping or stopped, we wait for it to restart */
+ if (vm->world_stopped || vm->pending_halt_count > 0) {
+
+ /* Mark this thread as halted */
+ env->status = _JC_THRDSTAT_HALTED;
+ snprintf(env->text_status, sizeof(env->text_status),
+ "newly attached thread");
+
+ /* Wait for other thread to wake me back up */
+ while (env->status == _JC_THRDSTAT_HALTED)
+ _JC_COND_WAIT(env, vm->world_restarted, vm->mutex);
+ }
+
+ /* Sanity check */
+ _JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL);
+
+ /* Done */
+ return env;
+
+fail:
+ /* Failed, copy stored exception */
+ if (ex != NULL)
+ *ex = temp_env.ex;
+#ifndef NDEBUG
+ vm->mutex_owner = NULL;
+#endif
+ return NULL;
+}
+
+/*
+ * Detach a thread structure from the currently running thread and free it.
+ * It must be attached and correspond to the currently running thread.
+ *
+ * NOTE: This assumes the VM global mutex is held.
+ */
+void
+_jc_detach_thread(_jc_env **envp)
+{
+ _jc_env *env = *envp;
+ _jc_jvm *const vm = env->vm;
+
+ /* Sanity check */
+ if (env == NULL)
+ return;
+ *envp = NULL;
+
+ /* Sanity check */
+ _JC_MUTEX_ASSERT(_jc_get_current_env(), vm->mutex);
+ _JC_ASSERT(env == vm->threads.by_id[env->thread_id]);
+ _JC_ASSERT(env == _jc_get_current_env());
+
+ /* Update thread's debugging status */
+ snprintf(env->text_status, sizeof(env->text_status), "detaching");
+
+ /*
+ * Check one last time (while mutex held) for halt. This is necessary
+ * because of the use of 'pending_halt_count'. If we didn't check
+ * here, we might leave without being counted as having halted.
+ */
+ _jc_halt_if_requested(env);
+
+ /* Invalidate current thread's reference to thread structure */
+ _jc_set_current_env(vm, NULL);
+
+#ifndef NDEBUG
+ /* Update mutex owner */
+ vm->mutex_owner = NULL;
+#endif
+
+ /* Free the thread structure */
+ _jc_free_thread(&env, JNI_TRUE);
+}
+
+/*
+ * Kill all other threads in the VM. This is used during VM shutdown.
+ */
+void
+_jc_thread_shutdown(_jc_env **envp)
+{
+ _jc_env *env = *envp;
+ int last_report = -1;
+ _jc_env *thread;
+ _jc_jvm *vm;
+
+ /* Sanity check */
+ if (env == NULL)
+ return;
+ *envp = NULL;
+ vm = env->vm;
+
+ /* Grab VM global mutex */
+ _JC_MUTEX_LOCK(env, vm->mutex);
+
+ /* Detach this thread */
+ _jc_detach_thread(&env);
+
+ /* Wait for all non-daemon threads to exit */
+ while (JNI_TRUE) {
+ int user_thread_count;
+
+ /* Search for remaining non-daemon threads */
+ user_thread_count = 0;
+ LIST_FOREACH(thread, &vm->threads.alive_list, link) {
+
+ /* Check whether it's a daemon thread */
+ _JC_ASSERT(thread->instance != NULL);
+ if (!*_JC_VMFIELD(vm, thread->instance,
+ Thread, daemon, jboolean))
+ user_thread_count++;
+ }
+
+ /* No more user threads? Then stop waiting */
+ if (user_thread_count == 0)
+ break;
+
+ /* Log progress */
+ if (user_thread_count != last_report) {
+ VERBOSE(JNI, vm, "JNI_DestroyJavaVM: waiting for %d"
+ " user threads to exit", user_thread_count);
+ last_report = user_thread_count;
+ }
+
+ /* Wait for the next thread to exit */
+ _JC_COND_WAIT(env, vm->vm_destruction, vm->mutex);
+ }
+
+ /* Re-attach this thread */
+ if ((env = _jc_attach_thread(vm, NULL)) == NULL)
+ _jc_fatal_error(vm, "can't reattach shutdown thread");
+
+ /* Stop the world */
+ _jc_stop_the_world(env);
+
+ /* Disable uncaught exception handling */
+ vm->world_ending = JNI_TRUE;
+
+ /* Post a ThreadDeath in all remaining threads */
+ LIST_FOREACH(thread, &vm->threads.alive_list, link) {
+ _jc_object *const tdeath
+ = vm->boot.objects.vmex[_JC_ThreadDeath];
+
+ if (thread == env)
+ continue;
+ _JC_ASSERT(tdeath != NULL);
+ thread->cross_exception = tdeath;
+ _jc_thread_interrupt(vm, thread);
+ }
+
+ /* Resume the world */
+ _jc_resume_the_world(env);
+
+ /* Detach this thread */
+ _jc_detach_thread(&env);
+
+ /* Wait for all other threads to die */
+ while (!LIST_EMPTY(&vm->threads.alive_list))
+ _JC_COND_WAIT(env, vm->vm_destruction, vm->mutex);
+
+ /* Unlock VM global mutex */
+ _JC_MUTEX_UNLOCK(env, vm->mutex);
+}
+
+/*
+ * Allocate a new thread structure. The 'env' pointer may be NULL
+ * if the current thread is not attached to any VM.
+ *
+ * This assumes the VM global mutex is held.
+ *
+ * If unsuccessful an exception is stored.
+ */
+_jc_env *
+_jc_allocate_thread(_jc_env *env)
+{
+ _jc_jvm *const vm = env->vm;
+ _jc_env *new_env;
+
+ /* Sanity check */
+ _JC_MUTEX_ASSERT(env, vm->mutex);
+
+ /* Free thread stacks */
+ _jc_free_thread_stacks(vm);
+
+ /* Check for too many threads */
+ if (vm->threads.next_free_id == 0) {
+ _JC_EX_STORE(env, InternalError,
+ "max number of threads (%d) exceeded", _JC_MAX_THREADS - 1);
+ return NULL;
+ }
+
+ /* Reuse a free thread structure off the free list, if any */
+ if ((new_env = LIST_FIRST(&vm->threads.free_list)) != NULL) {
+ _JC_ASSERT(vm->threads.num_free > 0);
+ LIST_REMOVE(new_env, link);
+ vm->threads.num_free--;
+ goto set_id;
+ }
+
+ /* Allocate and initialize new '_jc_env' struct for this thread */
+ if ((new_env = _jc_vm_zalloc(env, sizeof(*new_env))) == NULL)
+ return NULL;
+ new_env->vm = vm;
+ new_env->jni_interface = &_jc_native_interface;
+ new_env->status = _JC_THRDSTAT_RUNNING_NORMAL;
+ new_env->ex.num = -1;
+
+ /* Create the first local native reference frame */
+ SLIST_INIT(&new_env->native_locals);
+ if (_jc_add_native_frame(new_env, &new_env->native_locals) == NULL) {
+ _jc_vm_free(&new_env);
+ return NULL;
+ }
+
+ /* Initialize contention state for this thread */
+ if (_jc_mutex_init(env, &new_env->lock.owner.mutex) != JNI_OK) {
+ _jc_free_all_native_local_refs(new_env);
+ _jc_vm_free(&new_env);
+ return NULL;
+ }
+ if (_jc_cond_init(env, &new_env->lock.waiter.cond) != JNI_OK) {
+ _jc_mutex_destroy(&new_env->lock.owner.mutex);
+ _jc_free_all_native_local_refs(new_env);
+ _jc_vm_free(&new_env);
+ return NULL;
+ }
+ SLIST_INIT(&new_env->lock.owner.waiters);
+
+set_id:
+ /* Sanity check */
+ _JC_ASSERT(new_env->thread_id == 0);
+ _JC_ASSERT(!new_env->suspended);
+ _JC_ASSERT(!new_env->resumption_initialized);
+ _JC_ASSERT(vm->threads.next_free_id > 0
+ && vm->threads.next_free_id < _JC_MAX_THREADS);
+
+ /* Assign next free thread ID to the thread */
+ new_env->thread_id = vm->threads.next_free_id;
+ vm->threads.next_free_id = (jint)vm->threads.by_id[new_env->thread_id];
+ vm->threads.by_id[new_env->thread_id] = new_env;
+
+ /* Initialize thread's thinlock ID */
+ new_env->thinlock_id = new_env->thread_id << _JC_LW_THIN_TID_SHIFT;
+
+ /* Add this thread to the VM 'alive' thread list */
+ LIST_INSERT_HEAD(&vm->threads.alive_list, new_env, link);
+
+ /* Done */
+ return new_env;
+}
+
+/*
+ * Release a thread structure.
+ *
+ * This does not free the thread's stack, because we might be running
+ * on that stack.
+ *
+ * NOTE: This assumes the VM global mutex is held.
+ */
+void
+_jc_free_thread(_jc_env **envp, int cachable)
+{
+ _jc_env *env = *envp;
+ _jc_jvm *const vm = env->vm;
+
+ /* Invalidate caller's pointer */
+ if (env == NULL)
+ return;
+ *envp = NULL;
+
+ /* Sanity check */
+ _JC_MUTEX_ASSERT(_jc_get_current_env(), vm->mutex);
+ _JC_ASSERT(env->thread_id > 0 && env->thread_id < _JC_MAX_THREADS);
+ _JC_ASSERT(vm->threads.by_id[env->thread_id] == env);
+
+ /* Invalidate the reference from the VMThread object, if any */
+ if (env->instance != NULL) {
+ _jc_object *vmt;
+
+ vmt = *_JC_VMFIELD(vm, env->instance,
+ Thread, vmThread, _jc_object *);
+ if (vmt != NULL) {
+ _jc_set_vm_pointer(vmt,
+ vm->boot.fields.VMThread.vmdata, NULL);
+ }
+ }
+
+ /* Remove this thread from the alive thread list */
+ LIST_REMOVE(env, link);
+
+ /* Free native local refs */
+ _jc_free_all_native_local_refs(env);
+
+ /* Push threads' ID back on the thread ID free list */
+ vm->threads.by_id[env->thread_id] = (_jc_env *)vm->threads.next_free_id;
+ vm->threads.next_free_id = env->thread_id;
+ env->thread_id = 0;
+
+ /* Free suspend/notify condition variable, if any */
+ if (env->resumption_initialized) {
+ _jc_cond_destroy(&env->resumption);
+ env->resumption_initialized = JNI_FALSE;
+ }
+
+ /* Notify any threads waiting for this thread to die */
+ _JC_COND_SIGNAL(vm->vm_destruction);
+
+ /* Put thread structure on the free list if possible or required */
+ if ((cachable && vm->threads.num_free < _JC_MAX_FREE_THREADS)
+ || env->stack != NULL) {
+ _jc_free_thread_stacks(vm);
+ LIST_INSERT_HEAD(&vm->threads.free_list, env, link);
+ vm->threads.num_free++;
+ return;
+ }
+
+ /* Destroy thread structure */
+ _jc_destroy_thread(&env);
+}
+
+/*
+ * Free stacks associated with free'd threads.
+ *
+ * We maintain the invariant that free'd threads whose stacks still
+ * need to be free'd are all at the front of the thread free list.
+ *
+ * NOTE: This assumes the VM global mutex is held.
+ */
+void
+_jc_free_thread_stacks(_jc_jvm *vm)
+{
+ _jc_env *env;
+
+ /* Free thread stack */
+ LIST_FOREACH(env, &vm->threads.free_list, link) {
+ if (env->stack == NULL)
+ return;
+ munmap(env->stack, env->stack_size);
+ env->stack_size = 0;
+ env->stack = NULL;
+ }
+}
+
+/*
+ * Destroy a thread structure.
+ */
+void
+_jc_destroy_thread(_jc_env **envp)
+{
+ _jc_env *env = *envp;
+
+ /* Invalidate caller's pointer */
+ if (env == NULL)
+ return;
+ *envp = NULL;
+
+ /* Stack must be freed already */
+ _JC_ASSERT(env->stack == NULL);
+
+ /* Destroy thread structure */
+ _jc_cond_destroy(&env->lock.waiter.cond);
+ _jc_mutex_destroy(&env->lock.owner.mutex);
+ _jc_vm_free(&env);
+}
+
+/*
+ * Fire up an internal VM daemon thread.
+ */
+jobject
+_jc_internal_thread(_jc_env *env, const char *class)
+{
+ _jc_jvm *const vm = env->vm;
+ _jc_method *constructor;
+ _jc_method *start;
+ jobject ref = NULL;
+ _jc_type *type;
+
+ /* Get the class' type */
+ if ((type = _jc_load_type(env, vm->boot.loader, class)) == NULL)
+ goto fail;
+
+ /* Find no-arg constructor */
+ if ((constructor = _jc_get_declared_method(env, type,
+ "<init>", "()V", _JC_ACC_STATIC, 0)) == NULL) {
+ _jc_post_exception_info(env);
+ goto fail;
+ }
+
+ /* Instantiate one and wrap in a global native reference */
+ if ((ref = _jc_new_global_native_ref(env,
+ _jc_new_object(env, type))) == NULL) {
+ _jc_post_exception_info(env);
+ goto fail;
+ }
+
+ /* Sanity check */
+ _JC_ASSERT(_jc_subclass_of(*ref, vm->boot.types.Thread));
+
+ /* Invoke constructor */
+ if (_jc_invoke_nonvirtual(env, constructor, *ref) != JNI_OK)
+ goto fail;
+
+ /* Make it a daemon thread */
+ *_JC_VMFIELD(vm, *ref, Thread, daemon, jboolean) = JNI_TRUE;
+
+ /* Find Thread.start() */
+ if ((start = _jc_get_declared_method(env, vm->boot.types.Thread,
+ "start", "()V", _JC_ACC_STATIC, 0)) == NULL) {
+ _jc_post_exception_info(env);
+ goto fail;
+ }
+
+ /* Invoke Thread.start() */
+ if (_jc_invoke_virtual(env, start, *ref) != JNI_OK)
+ goto fail;
+
+ /* Done */
+ return ref;
+
+fail:
+ /* Clean up after failure */
+ _jc_free_global_native_ref(&ref);
+ return NULL;
+}
+
+#ifdef __linux__
+
+/*
+ * Linux has an (arguable) bug whereby you get a segfault if you touch
+ * otherwise valid stack memory that is too far past the current stack
+ * pointer if those pages are not yet faulted into memory. This causes
+ * our _JC_STACK_OVERFLOW_CHECK() macro to segfault way too early.
+ * So for threads attached natively, we touch all pages in the expected
+ * stack usage range to avoid this problem.
+ */
+static void
+_jc_touch_stack(const char *const start, const char *current)
+{
+ const size_t max = strtoul(_JC_STACK_DEFAULT, NULL, 10);
+ char buf[1024]; /* surely smaller than one page */
+ size_t diff;
+
+ /* Get current stack depth */
+#if _JC_DOWNWARD_STACK
+ diff = start - current;
+#else
+ diff = current - start;
+#endif
+
+ /* Continue until we touch all of it */
+ if (diff < max - 1024)
+ _jc_touch_stack(start, buf);
+}
+
+#endif
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/utf.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/utf.c?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/utf.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/utf.c Tue Oct 4 19:19:16 2005
@@ -0,0 +1,109 @@
+
+/*
+ * 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: utf.c,v 1.2 2004/07/18 02:19:12 archiecobbs Exp $
+ */
+
+#include "libjc.h"
+
+/*
+ * Decode a UTF-8 byte array. If 'buf' is not NULL, write the decoded
+ * characters into the buffer, which must be large enough.
+ *
+ * Returns the length in characters of the decoded string, or -1 if
+ * the UTF-8 bytes are not valid.
+ */
+jint
+_jc_utf_decode(const u_char *utf, jint ulen, jchar *buf)
+{
+ jint clen;
+ jint i;
+
+ for (clen = i = 0; i < ulen; clen++) {
+ if ((utf[i] & 0x80) == 0) {
+ if (utf[i] == 0)
+ return -1;
+ if (buf != NULL)
+ buf[clen] = utf[i];
+ i++;
+ } else if ((utf[i] & 0xe0) == 0xc0) {
+ if (i + 1 >= ulen)
+ return -1;
+ if ((utf[i + 1] & 0xc0) != 0x80)
+ return -1;
+ if (buf != NULL) {
+ buf[clen] = ((utf[i] & 0x1f) << 6)
+ | (utf[i + 1] & 0x3f);
+ }
+ i += 2;
+ } else if ((utf[i] & 0xf0) == 0xe0) {
+ if (i + 2 >= ulen)
+ return -1;
+ if ((utf[i + 1] & 0xc0) != 0x80)
+ return -1;
+ if ((utf[i + 2] & 0xc0) != 0x80)
+ return -1;
+ if (buf != NULL) {
+ buf[clen] = ((utf[i] & 0x0f) << 12)
+ | ((utf[i + 1] & 0x3f) << 6)
+ | (utf[i + 2] & 0x3f);
+ }
+ i += 3;
+ } else
+ return -1;
+ }
+ return clen;
+}
+
+/*
+ * Encode a character array into UTF-8. If 'buf' is not NULL, write
+ * the encoded bytes into the buffer, which must be large enough.
+ * The buffer is not NUL terminated.
+ *
+ * Returns the length in bytes of the encoded string.
+ */
+size_t
+_jc_utf_encode(const jchar *chars, jint clen, u_char *buf)
+{
+ size_t blen;
+ jint i;
+
+ for (blen = i = 0; i < clen; i++) {
+ const jchar ch = chars[i];
+
+ if (ch >= 0x01 && ch <= 0x7f) {
+ if (buf != NULL)
+ buf[blen] = (u_char)ch;
+ blen++;
+ } else if ((ch & 0xf800) == 0) {
+ if (buf != NULL) {
+ buf[blen] = 0xc0 | ((ch >> 6) & 0x1f);
+ buf[blen + 1] = 0x80 | (ch & 0x3f);
+ }
+ blen += 2;
+ } else {
+ if (buf != NULL) {
+ buf[blen] = 0xe0 | ((ch >> 12) & 0x0f);
+ buf[blen + 1] = 0x80 | ((ch >> 6) & 0x3f);
+ buf[blen + 2] = 0x80 | (ch & 0x3f);
+ }
+ blen += 3;
+ }
+ }
+ return blen;
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/verify.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/verify.c?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/verify.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/verify.c Tue Oct 4 19:19:16 2005
@@ -0,0 +1,50 @@
+
+/*
+ * 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: verify.c,v 1.3 2005/02/27 04:52:59 archiecobbs Exp $
+ */
+
+#include "libjc.h"
+
+/*
+ * Verify a type.
+ *
+ * We don't verify yet. But note: this could be implemented in Java.
+ *
+ * NOTE: This assumes the caller is handling synchronization issues.
+ */
+jint
+_jc_verify_type(_jc_env *env, _jc_type *type)
+{
+ /* Already verified? */
+ if (_JC_FLG_TEST(type, VERIFIED)) {
+ _JC_ASSERT(_JC_FLG_TEST(type, LOADED));
+ return JNI_OK;
+ }
+
+ /* Sanity check */
+ _JC_ASSERT(!_JC_FLG_TEST(type, ARRAY));
+
+ /* XXX verify class here */
+
+ /* Mark type as verified */
+ type->flags |= _JC_TYPE_VERIFIED;
+
+ /* Done */
+ return JNI_OK;
+}
+