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;
+}
+