harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arc...@apache.org
Subject svn commit: r357585 [1/2] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm: etc/ libjc/ libjc/native/
Date Mon, 19 Dec 2005 00:40:33 GMT
Author: archie
Date: Sun Dec 18 16:40:26 2005
New Revision: 357585

URL: http://svn.apache.org/viewcvs?rev=357585&view=rev
Log:
More simplification under the interpreter-only assumption, mainly of
code related to handling of the C and Java stacks:

- Separate C stack chunks from Java stack frames; keep them in separate
  linked lists. Eliminate overly-complex stack walking code in favor of
  a simple iteration over the Java stack frame linked list.
- It's no longer necessary to hold the VM mutex when walking the stack.
- Have C stack chunks include all C stack frames except for JNI frames and
  other "opaque" (i.e., non-JCNI) native code. This means we unnecessarily
  scan some parts of the C stack (e.g., _jc_interp() frames and signal frames)
  but results in much simpler code. Create a new C stack chunk each time
  we are invoked from native code.
- Only "clip" the C stack when necessary, i.e., when about to put a thread
  to sleep; push down "clip" operations as low as possible and eliminate
  all redundant "clips". Clarify the code and comments about "clipping".
- Remove env->jni_native field; instead, inspect the top Java stack frame.
- No longer assume JCNI native code synchronizes itself.
- Fix a bug in VMStackWalker.getClassContext().

Modified:
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/etc/gdb.userdef
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/class_loader.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_root.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_scan.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/interp.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/invoke.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_invoke.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_native.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/libjc.h
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/lock.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/gnu_classpath_VMStackWalker.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/java_lang_VMObject.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/reflect.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/signals.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/stack.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/structures.h
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/thread.c
    incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/vm.c

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/etc/gdb.userdef
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/etc/gdb.userdef?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/etc/gdb.userdef (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/etc/gdb.userdef Sun Dec 18 16:40:26 2005
@@ -73,15 +73,11 @@
 end
 
 define pstack
-  set $s = $env->java_stack
-  while $s != 0
-    set $s = (_jc_java_stack *)$s
-    if $s->interp
-      set $s = (_jc_interp_stack *)$s
-      set $method = $s->jstack.method
-      print_java_stack_frame $method *$s->pcp
-    end
-    set $s = ((_jc_java_stack *)$s)->next
+  set $jstack = $env->java_stack
+  while $jstack != 0
+    set $jip = $jstack->pcp != 0 ? *$jstack->pcp : -1
+    print_java_stack_frame $jstack->method $jip
+    set $jstack = $jstack->next
   end
 end
 

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/class_loader.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/class_loader.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/class_loader.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/class_loader.c Sun Dec 18 16:40:26 2005
@@ -109,9 +109,11 @@
 {
 	_jc_jvm *const vm = env->vm;
 
-	/* Use calling method's loader, if known */
-	if (env->jni_method != NULL)
-		return env->jni_method->class->loader;
+	/* Use current JNI method's loader, if known */
+	if (env->java_stack != NULL
+	    && _JC_ACC_TEST(env->java_stack->method, NATIVE)
+	    && !_JC_ACC_TEST(env->java_stack->method, JCNI))
+		return env->java_stack->method->class->loader;
 
 	/* Invoke ClassLoader.getSystemClassLoader() */
 	if (_jc_invoke_static(env,
@@ -250,7 +252,7 @@
 	_JC_MUTEX_ASSERT(env, loader->mutex);
 
 	/* Exit Java mode */
-	_jc_stopping_java(env, "waiting for class loader %p (%s)",
+	_jc_stopping_java(env, NULL, "waiting for class loader %p (%s)",
 	    loader, (loader->instance == NULL) ?
 	      "boot loader" : loader->instance->type->name);
 
@@ -261,7 +263,7 @@
 	_JC_COND_WAIT(env, loader->cond, loader->mutex);
 
 	/* Resume Java */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, NULL);
 }
 
 /*

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_root.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_root.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_root.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_root.c Sun Dec 18 16:40:26 2005
@@ -31,11 +31,10 @@
 				const _jc_word *info, _jc_object ***refsp);
 static int		_jc_root_walk_native_refs(_jc_native_frame_list *list,
 				_jc_object ***refsp);
-static int		_jc_scan_exec_stack(_jc_jvm *vm, _jc_exec_stack *stack,
+static int		_jc_scan_c_stack(_jc_jvm *vm, _jc_c_stack *cstack,
+				const _jc_word *info, _jc_object ***refsp);
+static int		_jc_scan_java_stack(_jc_jvm *vm, _jc_java_stack *jstack,
 				const _jc_word *info, _jc_object ***refsp);
-static int		_jc_scan_interp_stack(_jc_jvm *vm,
-				_jc_interp_stack *stack, const _jc_word *info,
-				_jc_object ***refsp);
 
 /* Internal variables */
 static const int	_jc_register_offs[] = _JC_REGISTER_OFFS;
@@ -236,32 +235,32 @@
 	_jc_jvm *const vm = thread->vm;
 	_jc_object **refs = *refsp;
 	_jc_java_stack *jstack;
-	_jc_stack_crawl crawl;
+	_jc_c_stack *cstack;
 	int count = 0;
 
-	/* Sanity check */
-	_JC_ASSERT(thread->java_stack == NULL
-	    || thread->java_stack->interp
-	    || thread->java_stack->clipped);
+	/* Scan each contiguous C stack chunk */
+	for (cstack = thread->c_stack; cstack != NULL; cstack = cstack->next) {
+
+		/* Sanity check */
+		_JC_ASSERT(cstack->clipped);
+
+		/* Scan references */
+		count += _jc_scan_c_stack(vm, cstack, info, &refs);
+	}
 
-	/* Scan each contiguous Java stack segment */
+	/*
+	 * Scan each Java stack frame. Also get implicit references
+	 * from Java methods to their classes.
+	 */
 	for (jstack = thread->java_stack;
 	    jstack != NULL; jstack = jstack->next) {
-		count += jstack->interp ?
-		    _jc_scan_interp_stack(vm,
-		      (_jc_interp_stack *)jstack, info, &refs) :
-		    _jc_scan_exec_stack(vm,
-		      (_jc_exec_stack *)jstack, info, &refs);
-	}
 
-	/* Get implicit references from Java methods to their classes */
-	for (_jc_stack_crawl_first(thread, &crawl);
-	    crawl.method != NULL; _jc_stack_crawl_next(vm, &crawl)) {
+		/* Scan the Java stack frame */
+		count += _jc_scan_java_stack(vm, jstack, info, &refs);
 
-		/* Add the Class instance */
-		_JC_ASSERT(crawl.method->class->instance != NULL);
+		/* Scan the Class instance */
 		if (refs != NULL)
-			*refs++ = crawl.method->class->instance;
+			*refs++ = jstack->method->class->instance;
 		count++;
 	}
 
@@ -298,10 +297,10 @@
  * Scan an interpreter stack frame.
  */
 static int
-_jc_scan_interp_stack(_jc_jvm *vm, _jc_interp_stack *stack,
+_jc_scan_java_stack(_jc_jvm *vm, _jc_java_stack *jstack,
 	const _jc_word *info, _jc_object ***refsp)
 {
-	_jc_method *const method = stack->jstack.method;
+	_jc_method *const method = jstack->method;
 	_jc_method_code *const code = &method->code;
 	_jc_object **refs = *refsp;
 	_jc_object *obj;
@@ -309,12 +308,12 @@
 	int i;
 
 	/* Any state in this method yet? */
-	if (stack->locals == NULL)
+	if (jstack->locals == NULL)
 		return 0;
 
 	/* Scan stack frame's locals and Java operand stack */
 	for (i = 0; i < code->max_locals + code->max_stack; i++) {
-		_jc_object *const ref = (_jc_object *)stack->locals[i];
+		_jc_object *const ref = (_jc_object *)jstack->locals[i];
 
 		/* Find object pointed to, if any */
 		if ((obj = _jc_locate_object(vm, info, ref)) == NULL)
@@ -335,7 +334,7 @@
  * Scan a contiguous executable stack chunk.
  */
 static int
-_jc_scan_exec_stack(_jc_jvm *vm, _jc_exec_stack *stack,
+_jc_scan_c_stack(_jc_jvm *vm, _jc_c_stack *cstack,
 	const _jc_word *info, _jc_object ***refsp)
 {
 	const size_t stack_step = (_JC_STACK_ALIGN < sizeof(void *)) ?
@@ -353,7 +352,7 @@
 
 		/* Find object pointed to by register, if any */
 		if ((obj = _jc_locate_object(vm, info,
-		    *(_jc_word **)((char *)&stack->regs
+		    *(_jc_word **)((char *)&cstack->regs
 		      + _jc_register_offs[regnum]))) == NULL)
 			continue;
 
@@ -363,11 +362,15 @@
 		count++;
 	}
 
-	/* Compute the top of this Java stack segment */
-	stack_top = _jc_mcontext_sp(&stack->regs);
+	/*
+	 * Find the bottom of this Java stack segment.
+	 *
+	 * Note: we assume 'cstack' is allocated at the bottom!
+	 */
+	stack_bot = (const char *)cstack;
 
-	/* Find the bottom of this Java stack segment */
-	stack_bot = stack->start_sp;
+	/* Find the top of this Java stack segment */
+	stack_top = _jc_mcontext_sp(&cstack->regs);
 
 	/* Sanity check stack alignment */
 	_JC_ASSERT(((_jc_word)stack_top & (_JC_STACK_ALIGN - 1)) == 0);

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_scan.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_scan.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_scan.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/gc_scan.c Sun Dec 18 16:40:26 2005
@@ -15,7 +15,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- * $Id: gc_scan.c,v 1.18 2005/11/09 18:14:22 archiecobbs Exp $
+ * $Id$
  */
 
 #include "libjc.h"
@@ -46,7 +46,6 @@
 {
 	_jc_jvm *const vm = env->vm;
 	_jc_heap *const heap = &vm->heap;
-	jboolean clipped_stack = JNI_FALSE;
 	_jc_object **root_set = NULL;
 	_jc_trace_info *trace = NULL;
 	struct timeval start_time;
@@ -123,8 +122,12 @@
 	LIST_FOREACH(loader, &vm->class_loaders, link)
 		loader->gc_mark = 0;
 
-	/* Clip the Java stack for the current thread */
-	clipped_stack = _jc_stack_clip(env);
+	/*
+	 * We must clip the C stack for the current thread. Otherwise,
+	 * references could "leak" into subsequent C stack frames and
+	 * we'd miss them when scanning this thread's C stack.
+	 */
+	_jc_stack_clip(env);
 
 	/* Compute the root set */
 	_JC_MUTEX_LOCK(env, vm->mutex);
@@ -464,10 +467,6 @@
 	_jc_heap_check(vm);
 #endif
 
-	/* Unclip Java stack */
-	if (clipped_stack)
-		_jc_stack_unclip(env);
-
 	/* Free root set memory */
 	_jc_vm_free(&root_set);
 
@@ -481,6 +480,10 @@
 		sched_yield();
 
 	/* Done */
+#ifndef NDEBUG
+	if (env->c_stack != NULL)
+		env->c_stack->clipped = JNI_FALSE;
+#endif
 	return status;
 
 fail:

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/interp.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/interp.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/interp.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/interp.c Sun Dec 18 16:40:26 2005
@@ -257,7 +257,7 @@
 	};
 	_jc_method_code *const code = &method->code;
 	int ticker = PERIODIC_CHECK_TICKS;
-	_jc_interp_stack state;
+	_jc_java_stack state;
 	_jc_object *lock = NULL;
 	_jc_word *sp;
 	int pc = 0;
@@ -290,11 +290,10 @@
 
 	/* Push Java stack frame */
 	memset(&state, 0, sizeof(state));
-	state.jstack.interp = JNI_TRUE;
-	state.jstack.next = env->java_stack;
-	state.jstack.method = method;
+	state.next = env->java_stack;
+	state.method = method;
 	state.pcp = &pc;
-	env->java_stack = &state.jstack;
+	env->java_stack = &state;
 
 	/* Allocate combined space for locals and stack */
 	if ((state.locals = _JC_STACK_ALLOC(env,
@@ -1580,7 +1579,7 @@
 	}
 
 	/* Pop Java stack frame */
-	env->java_stack = state.jstack.next;
+	env->java_stack = state.next;
 
 	/* Done */
 	return status;
@@ -1668,15 +1667,17 @@
 _JC_INTERP_ENTRY(v, interp_native, void, )
 
 /*
- * Entry point for interpreted methods when invoked from ELF methods.
+ * Entry point for interpreted methods when invoked from JCNI methods.
  * We get here by way of a trampoline set up by _jc_build_trampoline(),
  * which also sets env->interp to the method we are going to interpret.
  */
 static void
 _jc_vinterp(_jc_env *env, va_list args)
 {
+#ifndef NDEBUG
+	const jboolean was_interpreting = env->interpreting;
+#endif
 	_jc_method *const method = env->interp;
-	jboolean clipped_stack;
 	_jc_word *params;
 	_jc_object *this;
 	jint status;
@@ -1749,15 +1750,18 @@
 	}
 	_JC_ASSERT(pnum == method->code.num_params2);
 
-	/* Clip the current top of the Java stack */
-	clipped_stack = !env->java_stack->interp && _jc_stack_clip(env);
+#ifndef NDEBUG
+        /* Signals are not OK now */
+	env->interpreting = JNI_TRUE;
+#endif
 
 	/* Invoke method */
 	status = _jc_interp(env, method, this, params);
 
-	/* Unclip the current top of the Java stack */
-	if (clipped_stack)
-		_jc_stack_unclip(env);
+#ifndef NDEBUG
+        /* Restore debug flag */
+	env->interpreting = was_interpreting;
+#endif
 
 	/* Throw exception if any */
 	if (status != JNI_OK)

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/invoke.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/invoke.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/invoke.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/invoke.c Sun Dec 18 16:40:26 2005
@@ -574,10 +574,9 @@
 	const void *func, _jc_object *obj, _jc_word *params)
 {
 	JNIEnv *jenv = _JC_ENV2JNI(env);
-	_jc_method *previous_jni_method;
-	jboolean clipped_stack_top = JNI_FALSE;
 	jboolean pushed_frame = JNI_FALSE;
 	jboolean got_monitor = JNI_FALSE;
+	_jc_java_stack java_stack;
 	_jc_native_frame frame;
 	jint status = JNI_ERR;
 	int num_ref_params;
@@ -673,29 +672,24 @@
 		got_monitor = JNI_TRUE;
 	}
 
-	/* Keep track of the inner-most JNI method */
-	previous_jni_method = env->jni_method;
-	env->jni_method = method;
-
-	/* Clip the current top of the Java stack if not clipped already */
-	clipped_stack_top = _jc_stack_clip(env);
+	/* Add a Java stack frame */
+	memset(&java_stack, 0, sizeof(java_stack));
+	java_stack.next = env->java_stack;
+	java_stack.method = method;
+	env->java_stack = &java_stack;
 
 	/* Going native */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, NULL, NULL);
 
 	/* Invoke the method */
 	_jc_dynamic_invoke(func, JNI_FALSE, 2 + method->num_parameters,
 	    ptypes, nparams2, params2, &env->retval);
 
 	/* Returning from native */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, NULL);
 
-	/* Unclip stack */
-	if (clipped_stack_top)
-		_jc_stack_unclip(env);
-
-	/* Restore inner-most JNI method on the stack */
-	env->jni_method = previous_jni_method;
+	/* Pop Java stack */
+	env->java_stack = java_stack.next;
 
 	/* Return an error if an exception was posted */
 	status = (env->pending != NULL) ? JNI_ERR : JNI_OK;
@@ -840,20 +834,22 @@
  * If the method is static, 'obj' should be NULL and is not passed as a
  * parameter as JCNI does not pass the Class object to static methods.
  */
-
 jint
 _jc_invoke_jcni_a(_jc_env *env, _jc_method *method,
 	const void *func, _jc_object *volatile obj, _jc_word *volatile params)
 {
 	_jc_jvm *const vm = env->vm;
+#ifndef NDEBUG
+	const volatile jboolean was_interpreting = env->interpreting;
+#endif
 	volatile jboolean pushed_java_stack = JNI_FALSE;
 	volatile jboolean pushed_native_frame = JNI_FALSE;
 	volatile jboolean set_stack_limit = JNI_FALSE;
 	volatile jboolean got_monitor = JNI_FALSE;
-	volatile jboolean clipped_stack_top = JNI_FALSE;
 	volatile jint status = JNI_ERR;
+	_jc_c_stack *volatile saved_c_stack;
 	_jc_word *volatile params2 = NULL;		/* avoid gcc warning */
-	_jc_exec_stack java_stack;
+	_jc_java_stack java_stack;
 	_jc_native_frame frame;
 	_jc_catch_frame catch;
 	u_char *ptypes;
@@ -863,8 +859,11 @@
 	/* Catch exceptions here */
 	catch.next = env->catch_list;
 	env->catch_list = &catch;
-	if (sigsetjmp(catch.context, 0) != 0)
+	saved_c_stack = env->c_stack;
+	if (sigsetjmp(catch.context, 0) != 0) {
+		env->c_stack = saved_c_stack;	/* pop C stack chunks */
 		goto exception;
+	}
 
 	/* Sanity check */
 	_JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL
@@ -877,9 +876,6 @@
 	}
 	_JC_ASSERT(_JC_ACC_TEST(method, STATIC) == (obj == NULL));
 
-	/* Clip the current top of the Java stack if not clipped already */
-	clipped_stack_top = _jc_stack_clip(env);
-
 	/* Push a new local native reference frame (allocated on the stack) */
 	_jc_push_stack_local_native_frame(env, &frame);
 	pushed_native_frame = JNI_TRUE;
@@ -936,7 +932,7 @@
 
 	/* Synchronize native methods; non-native code synchronizes itself */
 	if (_JC_ACC_TEST(method, SYNCHRONIZED)
-	    && func == method->native_function) {
+	    && _JC_ACC_TEST(method, NATIVE)) {
 		if (_JC_ACC_TEST(method, STATIC))
 			obj = method->class->instance;
 		if (_jc_lock_object(env, obj) != JNI_OK)
@@ -944,14 +940,19 @@
 		got_monitor = JNI_TRUE;
 	}
 
-	/* Start a new contiguous executable Java stack frame sequence */
-	memset(&java_stack, 0, sizeof(java_stack));
-	java_stack.jstack.interp = JNI_FALSE;
-	java_stack.jstack.next = env->java_stack;
-	java_stack.jstack.method = method;
-	java_stack.start_sp = &java_stack;
-	env->java_stack = &java_stack.jstack;
-	pushed_java_stack = JNI_TRUE;
+	/* Add a Java stack frame for native methods */
+	if (_JC_ACC_TEST(method, NATIVE)) {
+		memset(&java_stack, 0, sizeof(java_stack));
+		java_stack.next = env->java_stack;
+		java_stack.method = method;
+		env->java_stack = &java_stack;
+		pushed_java_stack = JNI_TRUE;
+	}
+
+#ifndef NDEBUG
+	/* Signals are OK now */
+	env->interpreting = JNI_FALSE;
+#endif
 
 	/* Invoke the method */
 	_jc_dynamic_invoke(func, JNI_TRUE,
@@ -971,16 +972,12 @@
 done:
 	/* Pop local native reference frame and Java stack frame segment */
 	if (pushed_java_stack)
-		env->java_stack = java_stack.jstack.next;
+		env->java_stack = java_stack.next;
 	if (pushed_native_frame)
 		_jc_pop_local_native_frame(env, NULL);
 	if (set_stack_limit)
 		env->stack_limit = NULL;
 
-	/* Unclip stack */
-	if (clipped_stack_top)
-		_jc_stack_unclip(env);
-
 	/* Synchronized? */
 	if (got_monitor) {
 		_jc_value retval;
@@ -998,6 +995,11 @@
 
 	/* Unlink exception catcher */
 	env->catch_list = catch.next;
+
+#ifndef NDEBUG
+	/* Repair debug flag */
+	env->interpreting = was_interpreting;
+#endif
 
 	/* Done */
 	return status;

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_invoke.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_invoke.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_invoke.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_invoke.c Sun Dec 18 16:40:26 2005
@@ -15,7 +15,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- * $Id: jni_invoke.c,v 1.4 2005/03/16 15:31:12 archiecobbs Exp $
+ * $Id$
  */
 
 #include "libjc.h"
@@ -142,9 +142,6 @@
 	LIST_INSERT_HEAD(&_jc_vms_list, vm, link);
 	_JC_MUTEX_UNLOCK(NULL, _jc_vms_mutex);
 
-	/* Returning now to native code */
-	_jc_stopping_java(env, NULL);
-
 	/* Done */
 	*envp = _JC_ENV2JNI(env);
 	*jvmp = _JC_JVM2JNI(vm);
@@ -170,13 +167,14 @@
 {
 	_jc_jvm *vm = _JC_JNI2JVM(jvm);
 	_jc_env *env = _jc_get_current_env();
+	_jc_c_stack cstack;
 
 	/* This thread must be attached to the jvm */
 	if (env == NULL || env->vm != vm)
 		return JNI_ERR;
 
 	/* Enter java mode */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	VERBOSE(JNI, vm, "JNI_DestroyJavaVM invoked");
 
 	/* Kill all other threads */
@@ -227,6 +225,7 @@
 {
 	_jc_jvm *const vm = _JC_JNI2JVM(jvm);
 	JavaVMAttachArgs *const args = _args;
+	_jc_c_stack cstack;
 	_jc_ex_info einfo;
 	_jc_env *env;
 
@@ -242,7 +241,7 @@
 
 	/* Create and attach a new thread structure to the current thread */
 	_JC_MUTEX_LOCK(NULL, vm->mutex);
-	env = _jc_attach_thread(vm, &einfo);
+	env = _jc_attach_thread(vm, &einfo, &cstack);
 	_JC_MUTEX_UNLOCK(NULL, vm->mutex);
 	if (env == NULL) {
 		_jc_eprintf(vm, "%s: %s: %s\n", __FUNCTION__,
@@ -263,7 +262,7 @@
 		goto fail;
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	*envp = _JC_ENV2JNI(env);
@@ -285,13 +284,17 @@
 {
 	_jc_jvm *const vm = _JC_JNI2JVM(jvm);
 	_jc_env *env = _jc_get_current_env();
+	_jc_c_stack cstack;
 
 	/* This thread must be attached to the jvm */
 	if (env == NULL || env->vm != vm)
 		return JNI_ERR;
 
+	/* Sanity check */
+	_JC_ASSERT(env->c_stack == NULL);
+
 	/* Go un-native */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Grab global mutex */
 	_JC_MUTEX_LOCK(NULL, vm->mutex);

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_native.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_native.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_native.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/jni_native.c Sun Dec 18 16:40:26 2005
@@ -26,10 +26,11 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
 	_jc_object *fobj = NULL;
+	_jc_c_stack cstack;
 	jobject ref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -48,7 +49,7 @@
 done:
 	/* Returning to native code */
 	ref = _jc_pop_local_native_frame(env, fobj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -60,10 +61,11 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 	j ## _type value = 0;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Check for null */						\
@@ -82,7 +84,7 @@
 done:									\
 	/* Returning to native code */					\
 	_jc_pop_local_native_frame(env, NULL);				\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Done */							\
 	return value;							\
@@ -101,9 +103,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -124,7 +127,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 #define SetField(_type, Type)						\
@@ -134,9 +137,10 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Check for null */						\
@@ -155,7 +159,7 @@
 done:									\
 	/* Returning to native code */					\
 	_jc_pop_local_native_frame(env, NULL);				\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 }
 SetField(boolean, Boolean)
 SetField(byte, Byte)
@@ -171,11 +175,12 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_jvm *const vm = env->vm;
+	_jc_c_stack cstack;
 	_jc_type *type;
 	jobject ref = NULL;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Sanity check */
 	_JC_ASSERT((*class)->type == vm->boot.types.Class);
@@ -192,7 +197,7 @@
 	      + field->offset));
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -204,11 +209,12 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_jvm *const vm = env->vm;					\
+	_jc_c_stack cstack;						\
 	_jc_type *type;							\
 	j ## _type value;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 									\
 	/* Sanity check */						\
 	_JC_ASSERT((*class)->type == vm->boot.types.Class);		\
@@ -224,7 +230,7 @@
 	    + field->offset);						\
 									\
 	/* Returning to native code */					\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Done */							\
 	return value;							\
@@ -243,10 +249,11 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_jvm *const vm = env->vm;
+	_jc_c_stack cstack;
 	_jc_type *type;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Sanity check */
 	_JC_ASSERT((*class)->type == vm->boot.types.Class);
@@ -263,7 +270,7 @@
 	    + field->offset) = (value == NULL) ? NULL : *value;
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 #define SetStaticField(_type, Type)					\
@@ -273,10 +280,11 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_jvm *const vm = env->vm;					\
+	_jc_c_stack cstack;						\
 	_jc_type *type;							\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 									\
 	/* Sanity check */						\
 	_JC_ASSERT((*class)->type == vm->boot.types.Class);		\
@@ -292,7 +300,7 @@
 	    + field->offset) = value;					\
 									\
 	/* Returning to native code */					\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 }
 SetStaticField(boolean, Boolean)
 SetStaticField(byte, Byte)
@@ -320,9 +328,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Invoke method */
@@ -330,7 +339,7 @@
 
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static void
@@ -339,9 +348,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Invoke method */
@@ -349,7 +359,7 @@
 
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 #define CallNonvirtualMethod(_type, Type)				\
@@ -383,10 +393,11 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 	j ## _type result;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Invoke method */						\
@@ -396,7 +407,7 @@
 	expr1 _jc_pop_local_native_frame(env, expr2);			\
 									\
 	/* Returning to native code */					\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Done */							\
 	return result;							\
@@ -418,10 +429,11 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 	j ## _type result;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Invoke method */						\
@@ -431,7 +443,7 @@
 	expr1 _jc_pop_local_native_frame(env, expr2);			\
 									\
 	/* Returning to native code */					\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Done */							\
 	return result;							\
@@ -461,9 +473,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Invoke method */
@@ -471,7 +484,7 @@
 
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static void
@@ -479,9 +492,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Invoke method */
@@ -489,7 +503,7 @@
 
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 #define CallMethod(_type, Type)						\
@@ -523,10 +537,11 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 	j ## _type result;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Invoke method */						\
@@ -536,7 +551,7 @@
 	expr1 _jc_pop_local_native_frame(env, expr2);			\
 									\
 	/* Returning to native code */					\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Done */							\
 	return result;							\
@@ -558,10 +573,11 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 	j ## _type result;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Invoke method */						\
@@ -571,7 +587,7 @@
 	expr1 _jc_pop_local_native_frame(env, expr2);			\
 									\
 	/* Returning to native code */					\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Done */							\
 	return result;							\
@@ -602,9 +618,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Invoke method */
@@ -612,7 +629,7 @@
 
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static void
@@ -621,9 +638,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Invoke method */
@@ -631,7 +649,7 @@
 
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 #define CallStaticMethod(_type, Type)					\
@@ -665,10 +683,11 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 	j ## _type result;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Invoke method */						\
@@ -678,7 +697,7 @@
 	expr1 _jc_pop_local_native_frame(env, expr2);			\
 									\
 	/* Returning to native code */					\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Done */							\
 	return result;							\
@@ -700,10 +719,11 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 	j ## _type result;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Invoke method */						\
@@ -713,7 +733,7 @@
 	expr1 _jc_pop_local_native_frame(env, expr2);			\
 									\
 	/* Returning to native code */					\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Done */							\
 	return result;							\
@@ -736,10 +756,11 @@
 	_jc_jvm *const vm = env->vm;
 	_jc_field *field = NULL;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	_jc_type *type;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Get class info */
@@ -759,7 +780,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return field;
@@ -785,10 +806,11 @@
 	_jc_jvm *const vm = env->vm;
 	_jc_method *method = NULL;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	_jc_type *type;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Get class info */
@@ -815,7 +837,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return method;
@@ -840,10 +862,11 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_object *clobj = NULL;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jclass class;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -859,7 +882,7 @@
 done:
 	/* Returning to native code */
 	class = _jc_pop_local_native_frame(env, clobj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Return class */
 	return class;
@@ -873,10 +896,11 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_ ## _type ## _array *a;					\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 	jvalue *buf = NULL;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Check for null */						\
@@ -913,7 +937,7 @@
 done:									\
 	/* Returning to native code */					\
 	_jc_pop_local_native_frame(env, NULL);				\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Return elements */						\
 	return (j ## _type *)(buf != NULL ? buf + 1 : NULL);		\
@@ -935,9 +959,10 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	jvalue *buf = (jvalue *)elems - 1;				\
 	_jc_ ## _type ## _array *a;					\
+	_jc_c_stack cstack;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 									\
 	/* Sanity check */						\
 	_JC_ASSERT(elems != NULL && array != NULL && *array != NULL);	\
@@ -955,7 +980,7 @@
 	}								\
 									\
 	/* Returning to native code */					\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 }
 ReleaseArrayElements(boolean, Boolean)
 ReleaseArrayElements(byte, Byte)
@@ -972,10 +997,11 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_object *obj = NULL;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jobject ref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -997,7 +1023,7 @@
 done:
 	/* Returning to native code */
 	ref = _jc_pop_local_native_frame(env, obj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -1009,9 +1035,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -1034,7 +1061,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 #define GetArrayRegion(_type, Type)					\
@@ -1044,9 +1071,10 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Check for null */						\
@@ -1070,7 +1098,7 @@
 done:									\
 	/* Returning to native code */					\
 	_jc_pop_local_native_frame(env, NULL);				\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 }
 GetArrayRegion(boolean, Boolean)
 GetArrayRegion(byte, Byte)
@@ -1088,9 +1116,10 @@
 {									\
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Check for null */						\
@@ -1114,7 +1143,7 @@
 done:									\
 	/* Returning to native code */					\
 	_jc_pop_local_native_frame(env, NULL);				\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 }
 SetArrayRegion(boolean, Boolean)
 SetArrayRegion(byte, Byte)
@@ -1130,10 +1159,11 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	void *elems = NULL;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -1185,7 +1215,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return elems;
@@ -1234,16 +1264,17 @@
 ExceptionCheck(JNIEnv *jenv)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 	jboolean result;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Get result */
 	result = env->pending != NULL;
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return result;
@@ -1253,17 +1284,18 @@
 NewGlobalRef(JNIEnv *jenv, jobject obj)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 	jobject ref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Get new reference */
 	if ((ref = _jc_new_global_native_ref(env, *obj)) == NULL)
 		_jc_post_exception_info(env);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -1273,31 +1305,33 @@
 DeleteGlobalRef(JNIEnv *jenv, jobject obj)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Delete reference */
 	_jc_free_global_native_ref(&obj);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static jobject
 NewLocalRef(JNIEnv *jenv, jobject obj)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 	jobject ref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Get new reference */
 	ref = _jc_new_local_native_ref(env, *obj);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -1307,24 +1341,26 @@
 DeleteLocalRef(JNIEnv *jenv, jobject obj)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Delete reference */
 	_jc_free_local_native_ref(&obj);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static jweak
 NewWeakGlobalRef(JNIEnv *jenv, jobject obj)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	_jc_fatal_error(env->vm, "%s: unimplemented", __FUNCTION__);
 }
@@ -1333,9 +1369,10 @@
 DeleteWeakGlobalRef(JNIEnv *jenv, jweak obj)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	_jc_fatal_error(env->vm, "%s: unimplemented", __FUNCTION__);
 }
@@ -1344,10 +1381,11 @@
 EnsureLocalCapacity(JNIEnv *jenv, jint capacity)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 	jint status;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Extend capacity */
 	if (capacity < 0)
@@ -1358,7 +1396,7 @@
 		status =_jc_extend_local_native_frame(env, capacity);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return status;
@@ -1368,10 +1406,11 @@
 PushLocalFrame(JNIEnv *jenv, jint capacity)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 	jint status;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Push a local native referenc eframe */
 	if (capacity < 0)
@@ -1382,7 +1421,7 @@
 		status = _jc_push_local_native_frame(env, capacity);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return status;
@@ -1393,15 +1432,16 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_object *const obj = (ref != NULL) ? *ref : NULL;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Pop frame, but create a new reference for the object */
 	ref = _jc_pop_local_native_frame(env, obj);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -1420,12 +1460,13 @@
 	_jc_class_loader *loader;
 	_jc_object *clobj = NULL;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	_jc_type *type;
 	jobject clref;
 	jclass class;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Get the appropriate class loader to use */
@@ -1452,7 +1493,7 @@
 done:
 	/* Returning to native code */
 	class = _jc_pop_local_native_frame(env, clobj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return class;
@@ -1468,10 +1509,11 @@
 	_jc_object *clobj = NULL;
 	_jc_native_frame frame;
 	_jc_type *type = NULL;
+	_jc_c_stack cstack;
 	jclass cref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -1505,7 +1547,7 @@
 
 	/* Returning to native code */
 	cref = _jc_pop_local_native_frame(env, clobj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return cref;
@@ -1520,10 +1562,11 @@
 	_jc_object *clobj = NULL;
 	_jc_native_frame frame;
 	_jc_type *type = NULL;
+	_jc_c_stack cstack;
 	jclass cref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Sanity check */
@@ -1547,7 +1590,7 @@
 done:
 	/* Returning to native code */
 	cref = _jc_pop_local_native_frame(env, clobj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return cref;
@@ -1560,11 +1603,12 @@
 	_jc_jvm *const vm = env->vm;
 	jboolean result = JNI_FALSE;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	_jc_type *from_type;
 	_jc_type *to_type;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -1589,7 +1633,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return result;
@@ -1603,10 +1647,11 @@
 	_jc_object *const obj = (ref != NULL) ? *ref : NULL;
 	jboolean result = JNI_FALSE;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	_jc_type *type;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -1628,7 +1673,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return result;
@@ -1639,9 +1684,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Print stack trace */
@@ -1649,23 +1695,24 @@
 
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static jthrowable
 ExceptionOccurred(JNIEnv *jenv)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 	jthrowable ref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Get pending exception, if any */
 	ref = _jc_new_local_native_ref(env, env->pending);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -1676,9 +1723,10 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -1697,7 +1745,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return JNI_OK;
@@ -1707,24 +1755,26 @@
 ExceptionClear(JNIEnv *jenv)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Retrieve and clear pending exception, if any */
 	env->pending = NULL;
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static void
 FatalError(JNIEnv *jenv, const char *msg)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	_jc_fatal_error(env->vm, "JNI fatal error: %s", msg);
 }
@@ -1743,12 +1793,13 @@
 	_jc_jvm *const vm = env->vm;
 	_jc_object *const class_obj = *class;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	_jc_object *obj;
 	_jc_type *type;
 	jobject ref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Get class type */
@@ -1760,7 +1811,7 @@
 
 	/* Returning to native code */
 	ref = _jc_pop_local_native_frame(env, obj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -1868,11 +1919,12 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jchar *buf = NULL;
 	jint len;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -1897,7 +1949,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return buf;
@@ -1907,15 +1959,16 @@
 ReleaseStringChars(JNIEnv *jenv, jstring string, const jchar *chars)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Free buffer */
 	_jc_vm_free(&chars);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static void
@@ -1950,11 +2003,12 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	char *full_buf;
 	size_t full_len;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -1986,7 +2040,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static const jchar *
@@ -2006,10 +2060,11 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jint length = 0;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -2025,7 +2080,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return length;
@@ -2036,11 +2091,12 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	char *buf = NULL;
 	size_t len;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -2065,7 +2121,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return buf;
@@ -2075,15 +2131,16 @@
 ReleaseStringUTFChars(JNIEnv *jenv, jstring string, const char *utf)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Free buffer */
 	_jc_vm_free(&utf);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 }
 
 static jstring
@@ -2092,10 +2149,11 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
 	_jc_object *strobj;
+	_jc_c_stack cstack;
 	jobject string;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Create string */
@@ -2103,7 +2161,7 @@
 
 	/* Returning to native code */
 	string = _jc_pop_local_native_frame(env, strobj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return (jstring)string;
@@ -2117,6 +2175,7 @@
 	_jc_object_array *array = NULL;
 	_jc_object *const class_obj = *class;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jobject aref = NULL;
 	size_t name_len;
 	_jc_type *atype;
@@ -2124,7 +2183,7 @@
 	char *aname;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Sanity check */
@@ -2173,7 +2232,7 @@
 done:
 	/* Returning to native code */
 	aref = _jc_pop_local_native_frame(env, (_jc_object *)array);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return (jobjectArray)aref;
@@ -2186,11 +2245,12 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);				\
 	_jc_jvm *const vm = env->vm;					\
 	_jc_native_frame frame;						\
+	_jc_c_stack cstack;						\
 	_jc_array *array;						\
 	jobject ref;							\
 									\
 	/* Returning from native code */				\
-	_jc_resuming_java(env);						\
+	_jc_resuming_java(env, &cstack);				\
 	_jc_push_stack_local_native_frame(env, &frame);			\
 									\
 	/* Create array */						\
@@ -2199,7 +2259,7 @@
 									\
 	/* Returning to native code */					\
 	ref = _jc_pop_local_native_frame(env, (_jc_object *)array);	\
-	_jc_stopping_java(env, NULL);					\
+	_jc_stopping_java(env, &cstack, NULL);				\
 									\
 	/* Done */							\
 	return (j ## _type ## Array)ref;				\
@@ -2218,10 +2278,11 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jsize length = 0;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -2237,7 +2298,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return length;
@@ -2250,12 +2311,13 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_jvm *const vm = env->vm;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jint result = JNI_ERR;
 	_jc_type *type;
 	int i;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Get class info */
@@ -2299,7 +2361,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return result;
@@ -2310,11 +2372,12 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_jvm *const vm = env->vm;
+	_jc_c_stack cstack;
 	_jc_type *type;
 	int i;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Get class info */
 	type = *_JC_VMFIELD(vm, *class, Class, vmdata, _jc_type *);
@@ -2329,7 +2392,7 @@
 	}
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return JNI_OK;
@@ -2340,10 +2403,11 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jint status = JNI_ERR;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for NULL */
@@ -2359,7 +2423,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return status;
@@ -2370,10 +2434,11 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jint status = JNI_ERR;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for NULL */
@@ -2389,7 +2454,7 @@
 done:
 	/* Returning to native code */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return status;
@@ -2408,10 +2473,11 @@
 FromReflectedField(JNIEnv *jenv, jobject object)
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
+	_jc_c_stack cstack;
 	_jc_field *field;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Sanity check */
 	_JC_ASSERT(object != NULL && *object != NULL);
@@ -2421,7 +2487,7 @@
 	field = _jc_get_field(env, *object);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return field;
@@ -2432,10 +2498,11 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_jvm *const vm = env->vm;
+	_jc_c_stack cstack;
 	_jc_method *method;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 
 	/* Sanity check */
 	_JC_ASSERT(object != NULL && *object != NULL);
@@ -2447,7 +2514,7 @@
 	    _jc_get_method(env, *object) : _jc_get_constructor(env, *object);
 
 	/* Returning to native code */
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return method;
@@ -2458,11 +2525,12 @@
 {
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	_jc_object *obj;
 	jobject ref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Get reflected Field */
@@ -2470,7 +2538,7 @@
 
 	/* Returning to native code */
 	ref = _jc_pop_local_native_frame(env, obj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -2482,11 +2550,12 @@
 	const jboolean is_constructor = strcmp(method->name, "<init>") == 0;
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	_jc_object *obj;
 	jobject ref;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Get reflected Method or Constructor */
@@ -2496,7 +2565,7 @@
 
 	/* Returning to native code */
 	ref = _jc_pop_local_native_frame(env, obj);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	return ref;
@@ -2508,11 +2577,12 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_jvm *const vm = env->vm;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jobject data = NULL;
 	jobject buffer = NULL;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Create Pointer object */
@@ -2547,7 +2617,7 @@
 	_jc_free_local_native_ref(&data);
 	buffer = _jc_pop_local_native_frame(env,
 	    _jc_free_local_native_ref(&buffer));
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 	return buffer;
 }
 
@@ -2557,11 +2627,12 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_jvm *const vm = env->vm;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	_jc_object *data;
 	void *addr = NULL;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -2596,7 +2667,7 @@
 done:
 	/* Done */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 	return addr;
 }
 
@@ -2606,10 +2677,11 @@
 	_jc_env *const env = _JC_JNI2ENV(jenv);
 	_jc_jvm *const vm = env->vm;
 	_jc_native_frame frame;
+	_jc_c_stack cstack;
 	jlong capacity = 0;
 
 	/* Returning from native code */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, &cstack);
 	_jc_push_stack_local_native_frame(env, &frame);
 
 	/* Check for null */
@@ -2625,7 +2697,7 @@
 done:
 	/* Done */
 	_jc_pop_local_native_frame(env, NULL);
-	_jc_stopping_java(env, NULL);
+	_jc_stopping_java(env, &cstack, NULL);
 	return capacity;
 }
 

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/libjc.h
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/libjc.h?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/libjc.h (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/libjc.h Sun Dec 18 16:40:26 2005
@@ -456,12 +456,7 @@
 				int max, _jc_saved_frame *frames);
 extern void		_jc_print_stack_frames(_jc_env *env, FILE *fp,
 				int num_frames, _jc_saved_frame *frames);
-extern void		_jc_stack_crawl_first(_jc_env *env,
-				_jc_stack_crawl *crawl);
-extern void		_jc_stack_crawl_next(_jc_jvm *vm,
-				_jc_stack_crawl *crawl);
-extern jboolean		_jc_stack_clip(_jc_env *env);
-extern jboolean		_jc_stack_clip_ctx(_jc_env *env, const mcontext_t *ctx);
+extern void		_jc_stack_clip(_jc_env *env);
 extern void		_jc_stack_unclip(_jc_env *env);
 
 /* string.c */
@@ -480,7 +475,8 @@
 extern void		_jc_free_thread(_jc_env **envp, int cachable);
 extern void		_jc_free_thread_stacks(_jc_jvm *vm);
 extern void		_jc_destroy_thread(_jc_env **envp);
-extern _jc_env		*_jc_attach_thread(_jc_jvm *vm, _jc_ex_info *ex);
+extern _jc_env		*_jc_attach_thread(_jc_jvm *vm, _jc_ex_info *ex,
+				_jc_c_stack *cstack);
 extern void		_jc_detach_thread(_jc_env **envp);
 extern jint		_jc_thread_create_instance(_jc_env *env,
 				_jc_object *group, const char *name,
@@ -489,8 +485,9 @@
 extern void		_jc_stop_the_world(_jc_env *env);
 extern void		_jc_resume_the_world(_jc_env *env);
 extern void		_jc_halt_if_requested(_jc_env *env);
-extern void		_jc_stopping_java(_jc_env *env, const char *fmt, ...);
-extern void		_jc_resuming_java(_jc_env *env);
+extern void		_jc_stopping_java(_jc_env *env, _jc_c_stack *cstack,
+			    const char *fmt, ...);
+extern void		_jc_resuming_java(_jc_env *env, _jc_c_stack *cstack);
 extern void		*_jc_thread_start(void *arg);
 extern jobject		_jc_internal_thread(_jc_env *env, const char *class);
 extern jint		_jc_thread_check(_jc_env *env);

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/lock.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/lock.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/lock.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/lock.c Sun Dec 18 16:40:26 2005
@@ -15,7 +15,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- * $Id: lock.c,v 1.6 2005/03/19 19:40:45 archiecobbs Exp $
+ * $Id$
  */
 
 #include "libjc.h"
@@ -32,7 +32,6 @@
 _jc_lock_object(_jc_env *env, _jc_object *obj)
 {
 	_jc_jvm *const vm = env->vm;
-	jboolean clipped_stack_top;
 	_jc_word old_lockword;
 	_jc_fat_lock *lock;
 	jint status;
@@ -134,11 +133,8 @@
 		if (!notified)
 			goto retry;
 
-		/* Clip the current top of the Java stack if not already */
-		clipped_stack_top = _jc_stack_clip(env);
-
 		/* Enter non-Java mode */
-		_jc_stopping_java(env, "waiting for thinlock on %s@%p",
+		_jc_stopping_java(env, NULL, "waiting for thinlock on %s@%p",
 		    obj->type->name, obj);
 
 		/* Transition made; reacquire lock */
@@ -169,11 +165,7 @@
 		_JC_MUTEX_UNLOCK(env, owner->lock.owner.mutex);
 
 		/* Back to running normal Java */
-		_jc_resuming_java(env);
-
-		/* Unclip stack */
-		if (clipped_stack_top)
-			_jc_stack_unclip(env);
+		_jc_resuming_java(env, NULL);
 
 		/* Retry locking */
 		env->lock.waiter.object = NULL;
@@ -184,11 +176,8 @@
 	lock = vm->fat_locks.by_id[_JC_LW_EXTRACT(old_lockword, FAT_ID)];
 	_JC_ASSERT(lock != NULL);
 
-	/* Clip the current top of the Java stack if not already */
-	clipped_stack_top = _jc_stack_clip(env);
-
 	/* Enter non-Java mode */
-	_jc_stopping_java(env, "waiting for fatlock on %s@%p",
+	_jc_stopping_java(env, NULL, "waiting for fatlock on %s@%p",
 	    obj->type->name, obj);
 
 	/* Acquire mutex associated with the fat lock */
@@ -219,11 +208,7 @@
 	_JC_MUTEX_UNLOCK(env, lock->mutex);
 
 	/* Return to normal java */
-	_jc_resuming_java(env);
-
-	/* Unclip stack */
-	if (clipped_stack_top)
-		_jc_stack_unclip(env);
+	_jc_resuming_java(env, NULL);
 
 	/* Throw an error if recursion count overflowed */
 	if (status != JNI_OK) {

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/gnu_classpath_VMStackWalker.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/gnu_classpath_VMStackWalker.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/gnu_classpath_VMStackWalker.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/gnu_classpath_VMStackWalker.c Sun Dec 18 16:40:26 2005
@@ -15,7 +15,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- * $Id: gnu_classpath_VMStackWalker.c,v 1.5 2005/11/09 17:16:36 archiecobbs Exp $
+ * $Id$
  */
 
 #include "libjc.h"
@@ -28,7 +28,8 @@
 _jc_poppable_method(_jc_jvm *vm, _jc_method *method)
 {
 	/* Check for VMStackWalker methods */
-	if (method->class == vm->boot.types.VMStackWalker)
+	if (method->class == vm->boot.types.VMStackWalker
+	    && strcmp(method->name, "getClassContext") == 0)
 		return JNI_TRUE;
 
 	/* Check for Method.invoke() */
@@ -50,39 +51,26 @@
 {
 	_jc_jvm *const vm = env->vm;
 	_jc_object *result = NULL;
-	_jc_stack_crawl crawl;
+	_jc_java_stack *jstack;
 	jboolean top;
 
-	/* Lock VM */
-	_JC_MUTEX_LOCK(env, vm->mutex);
-
 	/* Crawl up the stack */
-	for (top = JNI_TRUE, _jc_stack_crawl_first(env, &crawl);
-	    crawl.method != NULL; _jc_stack_crawl_next(vm, &crawl)) {
-
-		/* Ignore non-Java stack frames */
-		if (crawl.method->class == NULL)
-			continue;
+	for (top = JNI_TRUE, jstack = env->java_stack;
+	    jstack != NULL; jstack = jstack->next) {
 
 		/* Ignore internal methods on top of stack */
-		if (top && _jc_poppable_method(vm, crawl.method))
+		if (top && _jc_poppable_method(vm, jstack->method))
 			continue;
 		top = JNI_FALSE;
 
 		/* Pop one additional frame */
-		do
-		    _jc_stack_crawl_next(vm, &crawl);
-		while (crawl.method != NULL && crawl.method->class == NULL);
+		jstack = jstack->next;
 
 		/* Done */
-		if (crawl.method != NULL && crawl.method->class != NULL)
-			result = crawl.method->class->instance;
+		result = jstack->method->class->instance;
 		break;
 	}
 
-	/* Unlock VM */
-	_JC_MUTEX_UNLOCK(env, vm->mutex);
-
 	/* Done */
 	return result;
 }
@@ -97,39 +85,26 @@
 {
 	_jc_jvm *const vm = env->vm;
 	_jc_object *result = NULL;
-	_jc_stack_crawl crawl;
+	_jc_java_stack *jstack;
 	jboolean top;
 
-	/* Lock VM */
-	_JC_MUTEX_LOCK(env, vm->mutex);
-
 	/* Crawl up the stack */
-	for (top = JNI_TRUE, _jc_stack_crawl_first(env, &crawl);
-	    crawl.method != NULL; _jc_stack_crawl_next(vm, &crawl)) {
-
-		/* Ignore non-Java stack frames */
-		if (crawl.method->class == NULL)
-			continue;
+	for (top = JNI_TRUE, jstack = env->java_stack;
+	    jstack != NULL; jstack = jstack->next) {
 
 		/* Ignore internal methods on top of stack */
-		if (top && _jc_poppable_method(vm, crawl.method))
+		if (top && _jc_poppable_method(vm, jstack->method))
 			continue;
 		top = JNI_FALSE;
 
 		/* Pop one additional frame */
-		do
-		    _jc_stack_crawl_next(vm, &crawl);
-		while (crawl.method != NULL && crawl.method->class == NULL);
+		jstack = jstack->next;
 
 		/* Done */
-		if (crawl.method != NULL && crawl.method->class != NULL)
-			result = crawl.method->class->loader->instance;
+		result = jstack->method->class->loader->instance;
 		break;
 	}
 
-	/* Unlock VM */
-	_JC_MUTEX_UNLOCK(env, vm->mutex);
-
 	/* Done */
 	return result;
 }
@@ -143,35 +118,25 @@
 {
 	_jc_jvm *const vm = env->vm;
 	_jc_object_array *array = NULL;
-	_jc_stack_crawl crawl;
+	_jc_java_stack *jstack;
 	jboolean top;
 	int num;
 
 again:
-	/* Lock VM */
-	_JC_MUTEX_LOCK(env, vm->mutex);
-
-	/* Crawl the Java stack and add Class objects for each method */
-	for (num = 0, top = JNI_TRUE, _jc_stack_crawl_first(env, &crawl);
-	    crawl.method != NULL; _jc_stack_crawl_next(vm, &crawl)) {
-
-		/* Ignore non-Java stack frames */
-		if (crawl.method->class == NULL)
-			continue;
+	/* Crawl up the stack */
+	for (num = 0, top = JNI_TRUE, jstack = env->java_stack;
+	    jstack != NULL; jstack = jstack->next) {
 
 		/* Ignore internal methods on top of stack */
-		if (top && _jc_poppable_method(vm, crawl.method))
+		if (top && _jc_poppable_method(vm, jstack->method))
 			continue;
 		top = JNI_FALSE;
 
 		/* Add method's class */
 		if (array != NULL)
-			array->elems[~num] = crawl.method->class->instance;
+			array->elems[~num] = jstack->method->class->instance;
 		num++;
 	}
-
-	/* Unlock VM */
-	_JC_MUTEX_UNLOCK(env, vm->mutex);
 
 	/* Create array and loop back */
 	if (array == NULL) {

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/java_lang_VMObject.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/java_lang_VMObject.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/java_lang_VMObject.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/native/java_lang_VMObject.c Sun Dec 18 16:40:26 2005
@@ -15,7 +15,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- * $Id: java_lang_VMObject.c,v 1.6 2005/05/15 21:41:01 archiecobbs Exp $
+ * $Id$
  */
 
 #include "libjc.h"
@@ -204,7 +204,6 @@
 {
 	_jc_jvm *const vm = env->vm;
 	const jboolean timed_wait = (millis != 0 || nanos != 0);
-	jboolean clipped_stack_top;
 	jboolean interrupted;
 	struct timespec wakeup;
 	jint recursion_count;
@@ -290,11 +289,8 @@
 		}
 	}
 
-	/* Clip the current top of the Java stack if not already */
-	clipped_stack_top = _jc_stack_clip(env);
-
 	/* Enter non-java mode */
-	_jc_stopping_java(env, "Object.wait() on %s@%p",
+	_jc_stopping_java(env, NULL, "Object.wait() on %s@%p",
 	    this->type->name, this);
 
 	/* Acquire the fat lock mutex */
@@ -404,7 +400,7 @@
 	_JC_MUTEX_UNLOCK(env, lock->mutex);
 
 	/* Back to running normal Java */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, NULL);
 
 	/* Check to see if we were interrupted */
 	interrupted = JNI_FALSE;
@@ -439,10 +435,6 @@
 		_jc_post_exception(env, _JC_InterruptedException);
 		_jc_throw_exception(env);
 	}
-
-	/* Unclip stack */
-	if (clipped_stack_top)
-		_jc_stack_unclip(env);
 }
 
 /*

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/reflect.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/reflect.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/reflect.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/reflect.c Sun Dec 18 16:40:26 2005
@@ -829,37 +829,28 @@
 _jc_reflect_accessible(_jc_env *env, _jc_type *member_class,
 	uint16_t access, _jc_type **calling_classp)
 {
-	_jc_jvm *const vm = env->vm;
 	_jc_type *calling_class = NULL;
-	_jc_stack_crawl crawl;
+	_jc_java_stack *jstack;
 	int rtn;
 
 	/* If member is public, we're done */
 	if ((access & _JC_ACC_PUBLIC) != 0)
 		return 1;
 
-	/* Lock VM */
-	_JC_MUTEX_LOCK(env, vm->mutex);
-
 	/* Crawl the stack until we see a non-bootstrap ClassLoader */
-	for (_jc_stack_crawl_first(env, &crawl);
-	    crawl.method != NULL; _jc_stack_crawl_next(vm, &crawl)) {
+	for (jstack = env->java_stack; jstack != NULL; jstack = jstack->next) {
 
-		/* Skip _jc_invoke_jcni_a() and java.lang.reflect methods */
-		if (crawl.method->class == NULL
-		    || strncmp(crawl.method->class->name, "java/lang/reflect/",
-		      sizeof("java/lang/reflect/") - 1) == 0)
+		/* Skip java.lang.reflect methods */
+		if (strncmp(jstack->method->class->name, "java/lang/reflect/",
+		    sizeof("java/lang/reflect/") - 1) == 0)
 			continue;
 
 		/* Found calling class */
-		calling_class = crawl.method->class;
+		calling_class = jstack->method->class;
 		*calling_classp = calling_class;
 		break;
 	}
 
-	/* Unlock VM */
-	_JC_MUTEX_UNLOCK(env, vm->mutex);
-
 	/* Sanity check */
 	_JC_ASSERT(calling_class != NULL);
 
@@ -879,11 +870,11 @@
 		int member_plen = 0;
 		const char *s;
 
-		/*
-		 * Check for same package.
-		 * XXX We should not say classes loaded by different
-		 * XXX class loaders are in the same package.
-		 */
+		/* Check for same class loader */
+		if (member_class->loader != calling_class->loader)
+			return JNI_FALSE;
+
+		/* Check for same package */
 		if ((s = strrchr(member_class->name, '/')) != NULL)
 			member_plen = s - member_class->name;
 		if ((s = strrchr(calling_class->name, '/')) != NULL)

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/signals.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/signals.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/signals.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/signals.c Sun Dec 18 16:40:26 2005
@@ -103,7 +103,6 @@
 _jc_signal_action(int sig_num, siginfo_t *info, ucontext_t *uctx)
 {
 	_jc_env *const env = _jc_get_current_env();
-	_jc_exec_stack *estack;
 	_jc_jvm *vm = NULL;
 	int sig_index;
 
@@ -161,23 +160,24 @@
 	}
 
 	/*
-	 * If this signal occured while there is no Java stack, then 
-	 * then it didn't occur in Java code and so was unexpected.
+	 * If this signal occured while there is no Java or C stack, then 
+	 * then it didn't occur in JCNI code and so was unexpected.
 	 */
-	if (env->java_stack == NULL)
+	if (env->java_stack == NULL || env->c_stack == NULL)
 		goto unexpected;
 
+#ifndef NDEBUG
 	/* If the signal occurred while interpeting, it was unexpected */
-	if (env->java_stack->interp)
+	if (env->interpreting)
 		goto unexpected;
-	estack = (_jc_exec_stack *)env->java_stack;
 
 	/*
 	 * If the signal occurred while the Java stack was clipped,
-	 * then it didn't occur in Java code and so was unexpected.
+	 * then occurred in JNI or native code and so was unexpected.
 	 */
-	if (estack->jstack.clipped)
-		goto unexpected;
+	if (env->c_stack->clipped)
+	       goto unexpected;
+#endif
 
 #if !HAVE_GETCONTEXT
 	/* Poor man's getcontext() using signals */
@@ -187,13 +187,6 @@
 		return;
 	}
 #endif
-
-	/*
-	 * Clip the top of the Java stack. We must do this here because it's
-	 * not possible to follow saved frame pointers across a signal frame.
-	 * That is, any signal creates a new contiguous Java stack region.
-	 */
-	_jc_stack_clip_ctx(env, &uctx->uc_mcontext);
 
 	/* Take the appropriate action */
 	switch (sig_index) {

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/stack.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/stack.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/stack.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/stack.c Sun Dec 18 16:40:26 2005
@@ -21,45 +21,23 @@
 #include "libjc.h"
 
 /*
- * Clip the current top of the Java stack. A thread's Java stack is
+ * Clip the current top C stack chunk. A thread's C stack is
  * a sequence of disconnected chunks of contiguous C stack frames
- * intersperced with non-crawlable stuff like native stack frames
- * and signal frames. Each chunk also contains a set of saved registers
- * which are scanned conservatively during garbage collection.
- *
- * This sets the top frame to be the calling function's calling function.
- * See also _jc_invoke_jcni_a().
- *
- * Returns JNI_TRUE if the stack was clipped, otherwise JNI_FALSE
- * (i.e., the stack was already clipped so we didn't clip it again).
- *
- * NOTE: If this function returns JNI_TRUE, the function calling this
- * function must call _jc_stack_unclip() before returning or else throw
- * (not just post) an exception.
+ * intersperced with uninteresting stuff like JNI native stack frames
+ * and signal frames. Each other than the top chunk also contains
+ * a set of saved registers which are scanned conservatively during
+ * garbage collection. Saving these registers is called "clipping"
+ * and it prevents references from "leaking" across chunk boundaries.
  */
-jboolean
+void
 _jc_stack_clip(_jc_env *env)
 {
-	_jc_java_stack *const stack = env->java_stack;
-	_jc_exec_stack *estack;
+	_jc_c_stack *const cstack = env->c_stack;
 
 	/* Sanity check */
 	_JC_ASSERT(env == _jc_get_current_env());
-
-	/* If no Java call stack yet, nothing to do */
-	if (stack == NULL)
-		return JNI_FALSE;
-
-	/* If already clipped, do nothing */
-	if (stack->clipped)
-		return JNI_FALSE;
-
-	/* If interpreting, just set the flag */
-	if (stack->interp)
-		goto done;
-
-	/* We are running executable Java */
-	estack = (_jc_exec_stack *)stack;
+	_JC_ASSERT(cstack != NULL);
+	_JC_ASSERT(!cstack->clipped);
 
 	/* Grab the current context and clip the Java stack with it */
 #if HAVE_GETCONTEXT
@@ -67,7 +45,7 @@
 	ucontext_t ctx;
 
 	getcontext(&ctx);
-	_jc_stack_clip_ctx(env, &ctx.uc_mcontext);
+	cstack->regs = ctx.uc_mcontext;
     }
 #else
     {
@@ -98,66 +76,14 @@
 #endif
 
 	/* Use it to clip Java stack */
-	_jc_stack_clip_ctx(env, &ctx);
+	cstack->regs = ctx.uc_mcontext;
     }
 #endif
 
-done:
-	/* Done */
-	stack->clipped = JNI_TRUE;
-	return JNI_TRUE;
-}
-
-/*
- * Clip the top of the Java stack using the supplied machine context,
- * which must be created either from getcontext() or by a signal.
- * The stack must not already be clipped.
- *
- * This sets the top of the Java stack to be the function in which
- * the context was created.
- *
- * Returns JNI_TRUE if the stack was clipped, otherwise JNI_FALSE
- */
-jboolean
-_jc_stack_clip_ctx(_jc_env *env, const mcontext_t *ctx)
-{
-	_jc_java_stack *const stack = env->java_stack;
-	_jc_exec_stack *estack;
-
-	/* Sanity check */
-	_JC_ASSERT(env == _jc_get_current_env());
-
-	/* If there's no Java call stack yet, nothing to do */
-	if (stack == NULL)
-		return JNI_FALSE;
-
-	/* Sanity check */
-	_JC_ASSERT(!stack->interp);
-	estack = (_jc_exec_stack *)stack;
-
-	/* Save machine registers */
-	estack->regs = *ctx;
-
-	/* Done */
-	return JNI_TRUE;
-}
-
-/*
- * Un-do the effects of _jc_stack_clip().
- */
-void
-_jc_stack_unclip(_jc_env *env)
-{
-	_jc_java_stack *const stack = env->java_stack;
-
-	/* Sanity check */
-	_JC_ASSERT(stack != NULL);
-	_JC_ASSERT(env == _jc_get_current_env());
-	_JC_ASSERT(stack->clipped);
-
-	/* Mark it unclipped */
-	stack->clipped = JNI_FALSE;
-	return;
+#ifndef NDEBUG
+	/* Mark stack as clipped */
+	cstack->clipped = JNI_TRUE;
+#endif
 }
 
 /*
@@ -266,7 +192,7 @@
  *
  * If 'thread' doesn't correspond to the current thread, then the
  * target thread must be running in non-java mode or halted
- * (so that it's top Java stack frame is already clipped).
+ * (so that it's top C stack frame is already clipped).
  *
  * The array is stored in the area pointed to by 'frames' (if not NULL).
  * At most 'max' frames are stored.
@@ -277,98 +203,26 @@
 _jc_save_stack_frames(_jc_env *env, _jc_env *thread,
 	int max, _jc_saved_frame *frames)
 {
-	_jc_jvm *const vm = env->vm;
-	_jc_stack_crawl crawl;
+	_jc_java_stack *jstack;
 	int i;
 
-	/* Lock VM */
-	_JC_MUTEX_LOCK(env, vm->mutex);
-
 	/* Crawl the stack */
-	for (i = 0, _jc_stack_crawl_first(thread, &crawl);
-	    crawl.method != NULL; _jc_stack_crawl_next(vm, &crawl)) {
+	for (i = 0, jstack = env->java_stack;
+	    jstack != NULL; jstack = jstack->next) {
 		_jc_saved_frame *const frame = &frames[i];
 
 		/* Sanity check */
-		_JC_ASSERT(crawl.method->class != NULL);
+		_JC_ASSERT(jstack->method->class != NULL);
 
 		/* Save this one */
 		if (i < max) {
-			frame->method = crawl.method;
-			if (crawl.stack->interp) {
-				_jc_interp_stack *const istack
-				    = (_jc_interp_stack *)crawl.stack;
-
-				frame->ipc = *istack->pcp;
-			} else
-				frame->ipc = -1;
+			frame->method = jstack->method;
+			frame->ipc = jstack->pcp != NULL ? *jstack->pcp : -1;
 		}
 		i++;
 	}
 
-	/* Unlock VM */
-	_JC_MUTEX_UNLOCK(env, vm->mutex);
-
 	/* Done */
 	return i;
-}
-
-/*
- * Initialize a Java stack crawl.
- *
- * If 'thread' doesn't correspond to the current thread, then the
- * target thread must be running in non-java mode or halted
- * (so that it's top Java stack frame is already clipped).
- *
- * NOTE: caller must acquire the VM lock before calling this function.
- */
-void
-_jc_stack_crawl_first(_jc_env *thread, _jc_stack_crawl *crawl)
-{
-	_jc_java_stack *const stack = thread->java_stack;
-
-	/* Initialize */
-	memset(crawl, 0, sizeof(*crawl));
-
-	/* If there's no Java call stack yet, return end of stack */
-	if (stack == NULL)
-		return;
-
-	/* Sanity check */
-	_JC_ASSERT(thread == _jc_get_current_env()
-	    || (stack->clipped
-	      && (thread->status == _JC_THRDSTAT_HALTING_NONJAVA
-	       || thread->status == _JC_THRDSTAT_HALTED)));
-
-	/* Start with top of stack */
-	crawl->stack = stack;
-	crawl->method = stack->method;
-}
-
-/*
- * Get the next registered Java method (or _jc_invoke_jcni_a()) in a stack
- * crawl. The 'thread' parameter does not have to be the current thread.
- *
- * If the bottom of the stack is reached, crawl->method is set to NULL.
- *
- * NOTE: caller must acquire the VM lock before calling this function.
- */
-void
-_jc_stack_crawl_next(_jc_jvm *vm, _jc_stack_crawl *crawl)
-{
-	/* Sanity check */
-	_JC_ASSERT(crawl->method != NULL);
-
-	/* Advance to the next deeper stack chunk */
-	crawl->stack = crawl->stack->next;
-
-	/* Did we reach the end of the Java stack? */
-	if (crawl->stack == NULL) {
-		memset(crawl, 0, sizeof(*crawl));
-		return;
-	}
-
-	/* Set method and return */
-	crawl->method = crawl->stack->method;
 }
 

Modified: 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=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/structures.h (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/structures.h Sun Dec 18 16:40:26 2005
@@ -34,18 +34,17 @@
 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_c_stack _jc_c_stack;
 typedef struct _jc_class_ref _jc_class_ref;
 typedef struct _jc_classbytes _jc_classbytes;
 typedef struct _jc_cpath_entry _jc_cpath_entry;
 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_native_frame _jc_native_frame;
@@ -59,7 +58,6 @@
 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;
@@ -167,37 +165,31 @@
 };
 
 /*
- * Common information that lives at the beginning of
- * _jc_exec_stack and _jc_interp_stack.
+ * Represents one chunk of scannable C call stack.
  *
  * 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_java_stack {
-	jboolean			interp;
-	jboolean			clipped;
-	_jc_method			*method;
-	_jc_java_stack			*next;
-};
-
-/*
- * Represents one native method stack frame. "regs" hold a copy
+ *
+ * All but the current chunk are "clipped", meaning "regs" hold a copy
  * of all machine registers, so that all references are captured
  * and don't leak into unscanned regions of the C call stack.
  */
-struct _jc_exec_stack {
-	_jc_java_stack			jstack;
-	void				*start_sp;
+struct _jc_c_stack {
+	_jc_c_stack			*next;
 	mcontext_t			regs;
+#ifndef NDEBUG
+	jboolean			clipped;
+#endif
 };
 
 /*
- * Represents one interpreted Java method stack frame.
+ * Represents one interpreted Java method in the Java call stack.
  */
-struct _jc_interp_stack {
-	_jc_java_stack			jstack;
+struct _jc_java_stack {
+	_jc_java_stack			*next;
+	_jc_method			*method;
 	_jc_word			*locals;
 	const int			*pcp;
 };
@@ -210,7 +202,7 @@
  * If/when Throwable.getStackTrace() is called later, this
  * information gets converted into a StackTraceElement[] array.
  *
- * 'ipc' is the (int) instruction index.
+ * 'ipc' is the (int) instruction index, or -1 if unknown.
  */
 struct _jc_saved_frame {
 	_jc_method			*method;
@@ -218,15 +210,6 @@
 };
 
 /*
- * 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 */
-};
-
-/*
  * Exception info stored for future posting.
  */
 struct _jc_ex_info {
@@ -248,12 +231,14 @@
 	/* Interpreter trampoline info */
 	_jc_method			*interp;	/* interpret method */
 
-	/* Stack info */
-	void				*stack;		/* thread's stack */
+	/* C stack info */
+	void				*stack;		/* c stack memory */
 	size_t				stack_size;	/* size of stack */
-	char				*stack_limit;	/* for stack overflow */
+	char				*stack_limit;	/* c stack limit */
+	_jc_c_stack			*c_stack;	/* c stack chunks */
+
+	/* Java stack info */
 	_jc_java_stack			*java_stack;	/* java stack info */
-	_jc_method			*jni_method;	/* innermost JNI meth */
 	_jc_value			retval;		/* invoke rtn value */
 
 	/* Thread info */
@@ -304,6 +289,9 @@
 	/* Thread flags */
 	jboolean			out_of_memory;
 	jboolean			handling_signal;
+#ifndef NDEBUG
+	jboolean			interpreting;
+#endif
 
 	/*
 	 * Support for Thread.interrupt() and suspend/resume.



Mime
View raw message