You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ar...@apache.org on 2005/12/19 01:40:33 UTC

svn commit: r357585 [2/2] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm: etc/ libjc/ libjc/native/

Modified: 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=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/thread.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/thread.c Sun Dec 18 16:40:26 2005
@@ -69,8 +69,6 @@
  * 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)
@@ -111,8 +109,6 @@
 
 /*
  * Suspend the current thread.
- *
- * The caller must have clipped the top of the Java stack.
  */
 static void
 _jc_thread_suspend(_jc_env *env)
@@ -133,16 +129,29 @@
 	}
 
 	/* Exit Java mode */
-	_jc_stopping_java(env, "Suspended by Thread.suspend()");
+	_jc_stopping_java(env, NULL, "Suspended by Thread.suspend()");
 
-	/* Suspend while suspended */
+	/* Lock VM */
 	_JC_MUTEX_LOCK(env, vm->mutex);
+
+	/* Clip the C stack */
+	_jc_stack_clip(env);
+
+	/* Suspend while suspended */
 	while (env->suspended)
 		_JC_COND_WAIT(env, env->resumption, vm->mutex);
+
+#ifndef NDEBUG
+	/* Mark the C stack as not clipped */
+	if (env->c_stack != NULL)
+		env->c_stack->clipped = JNI_FALSE;
+#endif
+
+	/* Unock VM */
 	_JC_MUTEX_UNLOCK(env, vm->mutex);
 
 	/* Return to Java mode */
-	_jc_resuming_java(env);
+	_jc_resuming_java(env, NULL);
 }
 
 /*
@@ -258,10 +267,6 @@
 
 	/* 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;
@@ -271,13 +276,18 @@
 		if (--vm->pending_halt_count == 0)
 			_JC_COND_SIGNAL(vm->all_halted);
 
+		/* Clip the top of the C stack */
+		_jc_stack_clip(env);
+
 		/* 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);
+#ifndef NDEBUG
+		/* Mark the C stack not clipped */
+		if (env->c_stack != NULL)
+			env->c_stack->clipped = JNI_FALSE;
+#endif
 	}
 
 	/* Sanity check */
@@ -347,10 +357,19 @@
 		}
 	}
 
+	/* Clip the C stack */
+	_jc_stack_clip(env);
+
 	/* 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);
 
+#ifndef NDEBUG
+	/* Mark the C stack not clipped */
+	if (env->c_stack != NULL)
+		env->c_stack->clipped = JNI_FALSE;
+#endif
+
 	/* Update flags */
 	vm->world_stopped = JNI_TRUE;
 }
@@ -408,18 +427,27 @@
  * 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.
+ * There are two cases:
+ *
+ * 1. We are about to invoke some JNI/native code (cstack == NULL)
+ *
+ *    Clip the current C call stack so no references in registers
+ *    "leak" into the upcoming C stack frames, causing missed GC refs.
+ *
+ * 2. We are about to return to some JNI/native code (cstack != NULL)
+ *
+ *    _jc_resuming_java() was previously invoked with cstack.
+ *    Pop the cstack frame that we previously pushed.
  */
 void
-_jc_stopping_java(_jc_env *env, const char *fmt, ...)
+_jc_stopping_java(_jc_env *env, _jc_c_stack *cstack, 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->clipped);
+	_JC_ASSERT(env->c_stack == NULL || !env->c_stack->clipped);
 
 	/* Update debug status */
 	if (fmt == NULL) {
@@ -453,23 +481,37 @@
 		/* Unlock the VM */
 		_JC_MUTEX_UNLOCK(env, vm->mutex);
 	}
+
+	/* Pop C stack chunk if desired, else clip current C stack */
+	if (cstack != NULL) {
+		_JC_ASSERT(cstack == env->c_stack);
+		env->c_stack = cstack->next;
+	} else
+		_jc_stack_clip(env);
 }
 
 /*
  * 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.
+ * There are two cases:
+ *
+ * 1. We're about to invoke VM code from JNI/native code (cstack != NULL)
+ *
+ *    Start a new C stack chunk by pushing "cstack" onto the C call stack.
+ *
+ * 2. We're about to return from JNI/native to VM code (cstack == NULL)
+ *
+ *    Do nothing; the previous top of the C stack becomes "active" again.
  */
 void
-_jc_resuming_java(_jc_env *env)
+_jc_resuming_java(_jc_env *env, _jc_c_stack *cstack)
 {
 	_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->clipped);
 
 	/* Change this thread's status, but first halt if requested */
 	if (!_jc_compare_and_swap(&env->status,
@@ -481,6 +523,21 @@
 		env->status = _JC_THRDSTAT_RUNNING_NORMAL;
 		_JC_MUTEX_UNLOCK(env, vm->mutex);
 	}
+
+	/* Start a new C stack chunk if desired */
+	if (cstack != NULL) {
+		_JC_ASSERT(env->c_stack == NULL || env->c_stack->clipped);
+		cstack->next = env->c_stack;
+		env->c_stack = cstack;
+	} else {
+		_JC_ASSERT(env->c_stack != NULL);
+		_JC_ASSERT(env->c_stack->clipped);
+	}
+
+#ifndef NDEBUG
+	/* Mark the C stack as not clipped */
+	env->c_stack->clipped = JNI_FALSE;
+#endif
 }
 
 /*
@@ -567,6 +624,7 @@
 {
 	_jc_env *env = arg;
 	_jc_jvm *const vm = env->vm;
+	_jc_c_stack cstack;
 	_jc_object *vmt;
 
 	/* Sanity checks */
@@ -577,6 +635,10 @@
 	/* Set thread-local pointer to my thread structure */
 	_jc_set_current_env(vm, env);
 
+	/* Push first C stack chunk */
+	memset(&cstack, 0, sizeof(cstack));
+	env->c_stack = &cstack;
+
 	/* Grab pointer to the VMThread */
 	vmt = env->retval.l;
 	_JC_ASSERT(_jc_subclass_of(vmt, vm->boot.types.VMThread));
@@ -597,13 +659,14 @@
 
 /*
  * Create a thread structure and attach it to the currently running thread.
+ * If provided, use cstack as the first C stack chunk.
  *
  * 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_attach_thread(_jc_jvm *vm, _jc_ex_info *ex, _jc_c_stack *cstack)
 {
 	_jc_env temp_env;
 	_jc_env *env;
@@ -653,6 +716,12 @@
 
 	/* Sanity check */
 	_JC_ASSERT(env->status == _JC_THRDSTAT_RUNNING_NORMAL);
+	_JC_ASSERT(env->c_stack == NULL);
+
+	/* Push first C stack chunk */
+	_JC_ASSERT(cstack != NULL);
+	memset(cstack, 0, sizeof(*cstack));
+	env->c_stack = cstack;
 
 	/* Done */
 	return env;
@@ -688,6 +757,7 @@
 	_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());
+	_JC_ASSERT(env->c_stack != NULL);
 
 	/* Update thread's debugging status */
 	snprintf(env->text_status, sizeof(env->text_status), "detaching");
@@ -699,6 +769,10 @@
 	 */
 	_jc_halt_if_requested(env);
 
+	/* Pop off the last remaining C stack chunk */
+	env->c_stack = env->c_stack->next;
+	_JC_ASSERT(env->c_stack == NULL);
+
 	/* Invalidate current thread's reference to thread structure */
 	_jc_set_current_env(vm, NULL);
 
@@ -719,6 +793,7 @@
 {
 	_jc_env *env = *envp;
 	int last_report = -1;
+	_jc_c_stack cstack;
 	_jc_env *thread;
 	_jc_jvm *vm;
 
@@ -765,7 +840,7 @@
 	}
 
 	/* Re-attach this thread */
-	if ((env = _jc_attach_thread(vm, NULL)) == NULL)
+	if ((env = _jc_attach_thread(vm, NULL, &cstack)) == NULL)
 		_jc_fatal_error(vm, "can't reattach shutdown thread");
 
 	/* Stop the world */

Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/vm.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/vm.c?rev=357585&r1=357584&r2=357585&view=diff
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/vm.c (original)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/libjc/vm.c Sun Dec 18 16:40:26 2005
@@ -36,6 +36,7 @@
 	_jc_env *env = &temp_env;
 	_jc_jvm temp_vm;
 	_jc_jvm *vm = &temp_vm;
+	_jc_c_stack cstack;
 	jobject sref = NULL;
 	int i;
 
@@ -110,7 +111,7 @@
 
 	/* Create and attach a new thread structure to the current thread */
 	_JC_MUTEX_LOCK(NULL, vm->mutex);
-	if ((env = _jc_attach_thread(vm, &temp_env.ex)) == NULL) {
+	if ((env = _jc_attach_thread(vm, &temp_env.ex, &cstack)) == NULL) {
 		_JC_MUTEX_UNLOCK(NULL, vm->mutex);
 		env = &temp_env;
 		goto fail_info;
@@ -209,6 +210,9 @@
 	_JC_ASSERT(vm->initialization->ex.num == -1);
 	_JC_ASSERT(vm->initialization->frames == NULL);
 	vm->initialization = NULL;
+
+	/* Return to native code */
+	_jc_stopping_java(env, &cstack, NULL);
 
 	/* Done */
 	*vmp = vm;