harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From var...@apache.org
Subject svn commit: r487483 [1/4] - in /harmony/enhanced/drlvm/trunk: build/make/targets/ vm/interpreter/src/ vm/jitrino/src/jet/ vm/port/src/lil/em64t/pim/ vm/port/src/lil/ia32/pim/ vm/port/src/lil/ipf/pim/ vm/tests/smoke/shutdown/ vm/vmcore/include/ vm/vmcor...
Date Fri, 15 Dec 2006 08:33:23 GMT
Author: varlax
Date: Fri Dec 15 00:33:21 2006
New Revision: 487483

URL: http://svn.apache.org/viewvc?view=rev&rev=487483
Log:
Applied HARMONY-2391 [drlvm] The VM doesn't cleanup resources if there are running daemon threads.
Tested on SUSE9@ia32 SUSE9@x64 Win2003@ia32.

Added:
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.c   (with props)
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.h   (with props)
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.java
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.c   (with props)
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.h   (with props)
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.java
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestLock.java
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.c   (with props)
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.h   (with props)
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.java
    harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestWaitSet.java
Modified:
    harmony/enhanced/drlvm/trunk/build/make/targets/smoke.test.xml
    harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/m2n_em64t.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/m2n_ia32.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/init.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/stack_trace.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_impl.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/finalize.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_properties.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_shutdown.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_field.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_method.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_trace.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_manager.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/em64t/base/compile_em64t.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_em64t.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/nt_platform_utils.cpp

Modified: harmony/enhanced/drlvm/trunk/build/make/targets/smoke.test.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/build/make/targets/smoke.test.xml?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/build/make/targets/smoke.test.xml (original)
+++ harmony/enhanced/drlvm/trunk/build/make/targets/smoke.test.xml Fri Dec 15 00:33:21 2006
@@ -19,7 +19,10 @@
 Version: $Revision: 1.4.2.11 $
 -->
 <project name="SMOKE TESTS">
-    <property name="smoke.test.javasrc" location="${build.VM.home}/tests/smoke" />
+    <property name="smoke.test.src" location="${build.VM.home}/tests/smoke" />
+    <property name="smoke.test.class.path" location="${build.dir}/_smoke.tests/classes" />
+    <property name="smoke.test.native.path" location="${build.dir}/_smoke.tests/natives" />
+
     <patternset id="smoke.test.java.pattern">
         <include name="**/*.java"/>
         <exclude name="**/Logger.java"/>
@@ -29,11 +32,24 @@
         <exclude name="**/*$*.class"/>
     </patternset>
 
-    <target name="smoke.test" depends="compile.smoke.tests, java_test_smoke" />
-    <target name="compile.smoke.tests" depends="init_component">
-        <mkdir dir="${build.dir}/_smoke.tests/classes" />
-        <javac includeJavaRuntime="yes" srcdir="${smoke.test.javasrc}" 
-                destdir="${build.dir}/_smoke.tests/classes" 
+    <target name="smoke.test.native.init">
+        <fileset id="smoke.test.native.refid"
+                dir="${smoke.test.src}">
+            <include name="**/*.c"/>
+        </fileset>
+        <pathconvert property="smoke.test.native.list"
+                     refid="smoke.test.native.refid" pathsep="," />
+
+    </target>
+
+    <target name="smoke.test" depends="compile.smoke.test, java_test_smoke" />
+
+    <target name="compile.smoke.test" depends="compile.smoke.test.java, compile.smoke.test.native" />
+
+    <target name="compile.smoke.test.java" depends="init_component">
+        <mkdir dir="${smoke.test.class.path}" />
+        <javac includeJavaRuntime="yes" srcdir="${smoke.test.src}" 
+                destdir="${smoke.test.class.path}" 
                 target="${javac.target}" debug="${java.debug.option}">
             <patternset refid="smoke.test.java.pattern" />
             <bootclasspath>
@@ -41,15 +57,48 @@
             </bootclasspath>
         </javac>
     </target>
-    <target name="jar.smoke.tests" depends="compile.smoke.tests">
+
+
+    <target name="compile.smoke.test.native" depends="init_component, smoke.test.native.init">
+        <mkdir dir="${smoke.test.native.path}" />
+
+        <for list="${smoke.test.native.list}" param="full.file.path" delimiter=",">
+            <sequential>
+                <var name="outputdir" unset="true" />
+                <var name="tmp.outputdir" unset="true" />
+                <var name="outputfile" unset="true" />
+
+                <basename property="outputfile" file="@{full.file.path}" suffix=".c"/>
+                <dirname property="tmp.outputdir" file="@{full.file.path}" />
+                <basename property="outputdir" file="${tmp.outputdir}" />
+
+                <mkdir dir="${smoke.test.native.path}/${outputdir}" />
+
+                <cc name="${build.cxx}"
+                    debug="true"
+                    runtime="dynamic"
+                    multithreaded="true"
+                    link="shared"
+                    outfile="${smoke.test.native.path}/${outputdir}/${outputfile}">
+                    <includepath path="${build.deploy.dir}/jdk/include" />
+                    <select os="lnx">
+                        <linkerarg value="-lstdc++" />
+                    </select>
+                    <fileset file="@{full.file.path}" />                    
+                </cc>
+            </sequential>
+        </for>
+    </target>
+
+    <target name="jar.smoke.tests" depends="compile.smoke.test">
         <jar jarfile="${build.dir}/_smoke.tests/">
-            <fileset dir="${build.dir}/_smoke.tests/classes" includes="**/*.class" />
+            <fileset dir="${smoke.test.class.path}" includes="**/*.class" />
         </jar>
     </target>
     <target name="java_test_smoke">
         <mkdir dir="${build.dir}/_smoke.tests/reports" />
         <path id="java.class.path">
-            <pathelement location="${build.dir}/_smoke.tests/classes" />
+            <pathelement location="${smoke.test.class.path}" />
             <fileset dir="${build.deploy.dir}/jdk/jre/lib" includes="*.jar" />
         </path>
         <select arch="ia32,em64t">
@@ -67,7 +116,7 @@
         </condition>
         <property name="using.jit.or.jitrino" value="Using jitrino" />
         <echo message="${using.jit.or.jitrino}" />
-        <property name="classes.location" location="${smoke.test.javasrc}" />
+        <property name="classes.location" location="${smoke.test.src}" />
         <pathconvert property="java.path.property" refid="java.class.path" />
         <condition property="int.or.jit.exclude" value="X_int,X_interpreter">
             <contains string="${jit.or.interpreter}" substring="int" />
@@ -94,7 +143,7 @@
 ------------------------------------------------
         </echo>
         <for param="test">
-            <fileset dir="${smoke.test.javasrc}">
+            <fileset dir="${smoke.test.src}">
                <!--  <patternset refid="smoke.test.java.pattern" /> -->
                 <include name="**/*.java"/>
                 <!-- <exclude name="**/Logger.java"/> -->
@@ -102,6 +151,9 @@
 
             </fileset>
             <sequential>
+                <var name="outdir" unset="true" />
+                <var name="tmp.outdir" unset="true" />
+
                 <basename property="filename.@{test}" file="@{test}" />
                 <propertycopy name="fname" override="true" from="filename.@{test}" />
                 <propertyregex property="classes.location1" override="true" input="${classes.location}" regexp="\\" replace="/" global="true" defaultValue="${classes.location}" />
@@ -112,6 +164,9 @@
                 <propertycopy name="src.file" override="true" from="@{test}.src.file" />
                 <propertyregex property="@{test}.keywords" input="${src.file}" regexp="(?m)@keyword(.*)" select="\1" defaultValue="" />
                 <propertycopy name="file.keywords" override="true" from="@{test}.keywords" />
+                <dirname property="tmp.outdir" file="@{test}" />
+                <basename property="outdir" file="${tmp.outdir}" />
+
                 <for param="keyword" list="${EXCLUDE_KEYWORDS}" delimiter=",">
                     <sequential>
                         <condition property="@{test}.is.excluded" value="@{keyword}">
@@ -139,20 +194,23 @@
                                 <equals arg1="${int.or.jit.arg}" arg2="" />
                             </not>
                             <then>
-                                <java newenvironment="yes" output="${build.dir}/_smoke.tests/reports/${class.name}_${jit.or.interpreter}.out" classname="${class.name}" fork="true" jvm="${build.deploy.dir}/jdk/jre/bin/java${executable.postfix}" error="${build.dir}/_smoke.tests/reports/${class.name}_${jit.or.interpreter}.out.err">
+                                <java newenvironment="yes" dir="${build.deploy.dir}/jdk/jre/bin" output="${build.dir}/_smoke.tests/reports/${class.name}_${jit.or.interpreter}.out" classname="${class.name}" fork="true" jvm="${build.deploy.dir}/jdk/jre/bin/java${executable.postfix}" error="${build.dir}/_smoke.tests/reports/${class.name}_${jit.or.interpreter}.out.err">
                                     <jvmarg value="-Dvm.assert_dialog=0" />
+                                    <jvmarg value="-Djava.library.path=${smoke.test.native.path}/${outdir}" />
                                     <jvmarg value="${int.or.jit.arg}" />
                                     <jvmarg value="-classpath" />
-                                    <jvmarg value="${build.dir}/_smoke.tests/classes" />
+                                    <jvmarg value="${smoke.test.class.path}" />
                                     <env key="JAVA_HOME" value="${build.deploy.dir}/jdk/jre" />
                                     <env key="LD_LIBRARY_PATH" value="${build.deploy.dir}/jdk/jre/bin:${env.LD_LIBRARY_PATH}" />
                                 </java>
                             </then>
                             <else>
-                                <java newenvironment="yes" output="${build.dir}/_smoke.tests/reports/${class.name}_${jit.or.interpreter}.out" classname="${class.name}" fork="true" jvm="${build.deploy.dir}/jdk/jre/bin/java${executable.postfix}" error="${build.dir}/_smoke.tests/reports/${class.name}_${jit.or.interpreter}.out.err">
+                                <java newenvironment="yes" dir="${build.deploy.dir}/jdk/jre/bin" output="${build.dir}/_smoke.tests/reports/${class.name}_${jit.or.interpreter}.out" classname="${class.name}" fork="true" jvm="${build.deploy.dir}/jdk/jre/bin/java${executable.postfix}" error="${build.dir}/_smoke.tests/reports/${class.name}_${jit.or.interpreter}.out.err">
                                     <jvmarg value="-Dvm.assert_dialog=0" />
+                                    <jvmarg value="-Djava.library.path=${smoke.test.native.path}/${outdir}" />
                                     <jvmarg value="-classpath" />
-                                    <jvmarg value="${build.dir}/_smoke.tests/classes" />
+                                    <jvmarg value="${smoke.test.class.path}" />
+
                                     <env key="JAVA_HOME" value="${build.deploy.dir}/jdk/jre" />
                                     <env key="LD_LIBRARY_PATH" value="${build.deploy.dir}/jdk/jre/bin:${env.LD_LIBRARY_PATH}" />
                                 </java>

Modified: harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp Fri Dec 15 00:33:21 2006
@@ -2392,11 +2392,10 @@
 
 
 static inline void
-stackDump(StackFrame& frame) {
+stackDump(FILE * file, StackFrame& frame) {
 
     StackFrame *f = &frame;
 
-    ECHO("****** STACK DUMP: ************");
     while(f) {
         Method *m = f->method;
         Class *c = m->get_class();
@@ -2406,35 +2405,21 @@
             line = m->get_line_number((uint16)ip);
         }
 #ifdef INTERPRETER_DEEP_DEBUG
-        ECHO(c->name->bytes << "."
-                << m->get_name()->bytes
-                << m->get_descriptor()->bytes << " ("
-                << class_get_source_file_name(c) << ":"
-                << line << ")"
-                << " last bcs: (8 of " << f->n_last_bytecode << "): "
-                << opcodeNames[f->last_bytecodes[
-                        (f->n_last_bytecode-1)&7]] << " "
-                << opcodeNames[f->last_bytecodes[
-                        (f->n_last_bytecode-2)&7]] << " "
-                << opcodeNames[f->last_bytecodes[
-                        (f->n_last_bytecode-3)&7]] << " "
-                << opcodeNames[f->last_bytecodes[
-                        (f->n_last_bytecode-4)&7]] << " "
-                << opcodeNames[f->last_bytecodes[
-                        (f->n_last_bytecode-5)&7]] << " "
-                << opcodeNames[f->last_bytecodes[
-                        (f->n_last_bytecode-6)&7]] << " "
-                << opcodeNames[f->last_bytecodes[
-                        (f->n_last_bytecode-7)&7]] << " "
-                << opcodeNames[f->last_bytecodes[
-                        (f->n_last_bytecode-8)&7]]);
+        fprintf(file, "%s.%s%s (%s:%i) last bcs: (8 of %i): %s %s %s %s %s %s %s %s",
+            c->name->bytes, m->get_name()->bytes, m->get_descriptor()->bytes,
+            class_get_source_file_name(c), line, f->n_last_bytecode,
+            opcodeNames[f->last_bytecodes[(f->n_last_bytecode-1)&7]],
+            opcodeNames[f->last_bytecodes[(f->n_last_bytecode-2)&7]],
+            opcodeNames[f->last_bytecodes[(f->n_last_bytecode-3)&7]],
+            opcodeNames[f->last_bytecodes[(f->n_last_bytecode-4)&7]],
+            opcodeNames[f->last_bytecodes[(f->n_last_bytecode-5)&7]],
+            opcodeNames[f->last_bytecodes[(f->n_last_bytecode-6)&7]],
+            opcodeNames[f->last_bytecodes[(f->n_last_bytecode-7)&7]],
+            opcodeNames[f->last_bytecodes[(f->n_last_bytecode-8)&7]]);
 #else
     const char *filename = class_get_source_file_name(c);
-    ECHO(class_get_name(c) << "."
-        << m->get_name()->bytes
-        << m->get_descriptor()->bytes << " ("
-        << (filename != NULL ? filename : "NULL") << ":"
-        << line << ")");
+    fprintf(file, "  %s.%s%s (%s:%i)\n", class_get_name(c), m->get_name()->bytes,
+        m->get_descriptor()->bytes, (filename != NULL ? filename : "NULL"), line);
 #endif
         f = f->prev;
     }
@@ -2442,15 +2427,14 @@
 
 void stack_dump(VM_thread *thread) {
     StackFrame *frame = getLastStackFrame(thread);
-    stackDump(*frame);
+    stackDump(stdout, *frame);
 }
 
 void stack_dump() {
     StackFrame *frame = getLastStackFrame();
-    stackDump(*frame);
+    stackDump(stdout, *frame);
 }
 
-
 static inline
 void UNUSED dump_all_java_stacks() {
     hythread_iterator_t  iterator;
@@ -2973,14 +2957,14 @@
                     case OPCODE_RET: Opcode_WIDE_RET(frame); break;
                     default:
                      DEBUG2("wide bytecode 0x" << hex << (int)*ip1 << " not implemented\n");
-                     stackDump(frame);
+                     stackDump(stdout, frame);
                      ABORT("Unexpected wide bytecode");
                 }
                 break;
             }
 
             default: DEBUG2("bytecode 0x" << hex << (int)ip0 << " not implemented\n");
-                     stackDump(frame);
+                     stackDump(stdout, frame);
                      ABORT("Unexpected bytecode");
         }
         assert(&frame == getLastStackFrame());
@@ -2991,6 +2975,20 @@
         if (frame.exc == 0) continue;
 got_exception:
         assert(&frame == getLastStackFrame());
+
+        if (VM_Global_State::loader_env->IsVmShutdowning()) {
+            assert(!hythread_is_suspend_enabled());
+            assert(exn_raised());
+            if (frame.locked_monitors) {
+                M2N_ALLOC_MACRO;
+                vm_monitor_exit_wrapper(frame.locked_monitors->monitor);
+                M2N_FREE_MACRO;
+                assert(!frame.locked_monitors->next);
+            }
+            M2N_FREE_MACRO;
+            return;
+        }
+
         clear_current_thread_exception();
 
         if (interpreter_ti_notification_mode) {

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp Fri Dec 15 00:33:21 2006
@@ -283,7 +283,6 @@
 {"stats", 
  "type: bool; default: off; scope: global                               \n"
  "Collects and shows various statistics about compiled methods.         \n"
- "Note: you may need to pass -XcleanupOnExit to VM to view the stats.   \n"
 },
 #endif  // ~JIT_STATS
 

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/m2n_em64t.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/m2n_em64t.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/m2n_em64t.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/m2n_em64t.cpp Fri Dec 15 00:33:21 2006
@@ -25,6 +25,7 @@
 #include "open/types.h"
 #include "port_malloc.h"
 #include "vm_threads.h"
+#include "exceptions.h"
 
 #include "m2n.h"
 #include "encoder.h"
@@ -313,35 +314,56 @@
     return buf;
 }
 
+static void m2n_pop_local_handles() {
+    assert(!hythread_is_suspend_enabled());
+    
+    if (exn_raised()) {
+        exn_rethrow();
+    }
+    
+    M2nFrame * m2n = m2n_get_last_frame();
+    free_local_object_handles2(m2n->local_object_handles);
+}
+
+static void m2n_free_local_handles() {
+    assert(!hythread_is_suspend_enabled());
+
+    if (exn_raised()) {
+        exn_rethrow();
+    }
+
+    M2nFrame * m2n = m2n_get_last_frame();
+    free_local_object_handles3(m2n->local_object_handles);
+}
+
 char * m2n_gen_pop_m2n(char * buf, bool handles, unsigned num_callee_saves,
                       int32 bytes_to_m2n_bottom, unsigned num_preserve_ret) {
-    assert (num_preserve_ret <= 2);    
-    unsigned handles_offset = 2 * LcgEM64TContext::GR_SIZE + bytes_to_m2n_bottom;
+    assert (num_preserve_ret <= 2);
+    assert(LcgEM64TContext::GR_SIZE == 8);
+
+    if (num_preserve_ret > 0) {
+        // Save return value
+        // NOTE: don't break stack allignment by pushing only one register.
+        buf = push(buf,  rax_opnd, size_64);
+        buf = push(buf,  rdx_opnd, size_64);
+    }
+
     if (handles) {
-        if (num_preserve_ret > 0) {
-            // Save return value
-            assert(LcgEM64TContext::GR_SIZE == 8);
-            handles_offset += LcgEM64TContext::GR_SIZE;
-            buf = push(buf,  rax_opnd, size_64);
-            if (num_preserve_ret > 1) {
-                handles_offset += LcgEM64TContext::GR_SIZE;
-                buf = push(buf,  rdx_opnd, size_64);
-            }
-        }
+        // There are handles located on the stack
+        buf = mov(buf, rax_opnd, Imm_Opnd(size_64, (uint64)m2n_pop_local_handles), size_64);
+    } else {
+        buf = mov(buf, rax_opnd, Imm_Opnd(size_64, (uint64)m2n_free_local_handles), size_64);
+    }
+    
+    // NOTE: the following should be true before the call ($rsp % 8 == 0 && $rsp % 16 != 0)!
 
-        // Must free the handles
-        M_Base_Opnd m(rsp_reg, handles_offset);
-        buf = mov(buf,  rdi_opnd, m, size_64);
-        buf = mov(buf, rax_opnd, Imm_Opnd(size_64, (uint64)free_local_object_handles2), size_64);
-        buf = call(buf, rax_opnd, size_64);
-
-        if (num_preserve_ret > 0) {
-            // Restore return value
-            if (num_preserve_ret > 1) {
-                buf = pop(buf,  rdx_opnd, size_64);
-            }
-            buf = pop(buf,  rax_opnd, size_64);
-        }
+    // Call m2n_pop_local_handles or m2n_free_local_handles
+    buf = call(buf, rax_opnd, size_64);
+    
+    if (num_preserve_ret > 0) {
+        // Restore return value
+        buf = pop(buf,  rdx_opnd, size_64);
+        buf = pop(buf,  rax_opnd, size_64);
     }
 
     // pop prev_m2nf

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/m2n_ia32.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/m2n_ia32.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/m2n_ia32.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/m2n_ia32.cpp Fri Dec 15 00:33:21 2006
@@ -19,15 +19,17 @@
  * @version $Revision: 1.1.2.1.4.4 $
  */  
 
+#include "open/types.h"
+#include "open/hythread.h"
 
-#include "port_malloc.h"
 #include "m2n.h"
 #include "m2n_ia32_internal.h"
+#include "port_malloc.h"
 #include "object_handles.h"
 #include "vm_threads.h"
-#include "open/types.h"
 #include "encoder.h"
 #include "interpreter.h" // for asserts only
+#include "exceptions.h"
 
 
 //////////////////////////////////////////////////////////////////////////
@@ -234,8 +236,6 @@
     return buf;
 }
 
-void free_local_object_handles2(ObjectHandles*);
-
 unsigned m2n_pop_m2n_size(bool handles, unsigned num_callee_saves, unsigned extra_on_stack, unsigned preserve_ret)
 {
     unsigned size = 7+(4-num_callee_saves);
@@ -245,54 +245,69 @@
     return size + 128;
 }
 
-void m2n_pop_local_handles() {
-    M2nFrame *m2n = m2n_get_last_frame();
+static void m2n_pop_local_handles() {
+    assert(!hythread_is_suspend_enabled());
+    
+    if (exn_raised()) {
+        exn_rethrow();
+    }
+    
+    M2nFrame * m2n = m2n_get_last_frame();
+    free_local_object_handles2(m2n->local_object_handles);
+}
+
+static void m2n_free_local_handles() {
+    assert(!hythread_is_suspend_enabled());
+
+    if (exn_raised()) {
+        exn_rethrow();
+    }
+
+    M2nFrame * m2n = m2n_get_last_frame();
     free_local_object_handles3(m2n->local_object_handles);
 }
 
 char* m2n_gen_pop_m2n(char* buf, bool handles, unsigned num_callee_saves, unsigned extra_on_stack, unsigned preserve_ret)
 {
-    if (handles) {
-        // Must free the handles
-        unsigned handles_off = 8+extra_on_stack;
-        if (preserve_ret>0) {
-            // Save return value
-            handles_off += 4;
-            buf = push(buf,  eax_opnd);
-            if (preserve_ret>1) {
-                handles_off += 4;
-                buf = push(buf,  edx_opnd);
-            }
-        }
-        M_Base_Opnd m(esp_reg, handles_off);
-        buf = push(buf,  m);
-        buf = call(buf, (char*)free_local_object_handles2);
-        Imm_Opnd imm(4);
-        buf = alu(buf, add_opc,  esp_opnd,  imm);
-        if (preserve_ret>0) {
-            // Restore return value
-            if (preserve_ret>1) buf = pop(buf,  edx_opnd);
-            buf = pop(buf,  eax_opnd);
+    if (preserve_ret > 0) {
+        // Save return value
+        buf = push(buf,  eax_opnd);
+        if (preserve_ret > 1) {
+            buf = push(buf,  edx_opnd);
         }
-    } else {
-        buf = push(buf, eax_opnd);
-        buf = push(buf, ecx_opnd);
-        buf = push(buf, edx_opnd);
+    }
+    
+    if (handles) {
+        // There are handles located on the stack
         buf = call(buf, (char*)m2n_pop_local_handles);
-        buf = pop(buf, edx_opnd);
-        buf = pop(buf, ecx_opnd);
-        buf = pop(buf, eax_opnd);
+    } else {
+        buf = call(buf, (char*)m2n_free_local_handles);
     }
     
+    if (preserve_ret > 0) {
+        // Restore return value
+        if (preserve_ret > 1) {
+            buf = pop(buf,  edx_opnd);
+        }
+        buf = pop(buf,  eax_opnd);
+    }
+    
+    // pop "garbage" from the stack
     if (extra_on_stack) {
         Imm_Opnd imm(extra_on_stack);
         buf = alu(buf, add_opc,  esp_opnd,  imm);
     }
+    
+    // Unlink the M2nFrame from the list of the current thread
     buf = pop(buf,  esi_opnd);
     buf = pop(buf,  ebx_opnd);
     buf = mov(buf,  M_Base_Opnd(ebx_reg, +0),  esi_opnd);
     buf = alu(buf, add_opc,  esp_opnd,  Imm_Opnd(+16));
-
+    
+    // TODO: check if there is no need to restore callee saved registers
+    // JUSTIFICATION: m2n frame is popped as a result of "normal"
+    //                (opposite to destuctive) stack unwinding
+    // Restore callee saved general registers
     if (num_callee_saves<4) buf = pop(buf,  edi_opnd);
     if (num_callee_saves<3) buf = pop(buf,  esi_opnd);
     if (num_callee_saves<2) buf = pop(buf,  ebx_opnd);

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf.cpp Fri Dec 15 00:33:21 2006
@@ -33,6 +33,7 @@
 #include "open/vm_util.h"
 #include "stub_code_utils.h"
 #include "interpreter.h"
+#include "exceptions.h"
 
 
 //////////////////////////////////////////////////////////////////////////
@@ -243,14 +244,33 @@
     emitter->ipf_movi(M2N_OBJECT_HANDLES, (int)imm_val);
 }
 
-void free_local_object_handles2(ObjectHandles* head);
-
 void m2n_pop_local_handles() {
     assert(!hythread_is_suspend_enabled());
     M2nFrame *m2n = m2n_get_last_frame();
     free_local_object_handles3(m2n_get_local_handles(m2n));
 }
 
+static void m2n_pop_local_handles() {
+    assert(!hythread_is_suspend_enabled());
+    
+    if (exn_raised()) {
+        exn_rethrow();
+    }
+    
+    M2nFrame * m2n = m2n_get_last_frame();
+    free_local_object_handles2(m2n->local_object_handles);
+}
+
+static void m2n_free_local_handles() {
+    assert(!hythread_is_suspend_enabled());
+
+    if (exn_raised()) {
+        exn_rethrow();
+    }
+
+    M2nFrame * m2n = m2n_get_last_frame();
+    free_local_object_handles3(m2n->local_object_handles);
+}
 
 void m2n_gen_pop_m2n(Merced_Code_Emitter* emitter, bool handles, M2nPreserveRet preserve_ret, bool do_alloc, unsigned out_reg, int target)
 {
@@ -260,38 +280,31 @@
         unsigned free_target = (unsigned) target;
         emitter->ipf_cmp(icmp_eq, cmp_none, SCRATCH_PRED_REG, SCRATCH_PRED_REG2, M2N_OBJECT_HANDLES, 0);
         emitter->ipf_br(br_cond, br_many, br_spnt, br_none, free_target, SCRATCH_PRED_REG);
-        // Yes, save return register
-        if (preserve_ret==MPR_Gr)
-            emitter->ipf_add(6, RETURN_VALUE_REG, 0);
-        else if (preserve_ret==MPR_Fr)
-            emitter->ipf_stf_inc_imm(float_mem_size_e, mem_st_spill, mem_none, SP_REG, RETURN_VALUE_REG, unsigned(-16));
-        // Do free
-        if (!out_reg) out_reg = 32+8+M2N_NUMBER_LOCALS;
-        emitter->ipf_add(out_reg, M2N_OBJECT_HANDLES, 0);
-        emit_call_with_gp(*emitter, (void**)free_local_object_handles2);
-        // Restore return register
-        if (preserve_ret==MPR_Gr) {
-            emitter->ipf_add(RETURN_VALUE_REG, 6, 0);
-        } else if (preserve_ret==MPR_Fr) {
-            emitter->ipf_adds(SP_REG, 16, SP_REG);
-            emitter->ipf_ldf(float_mem_size_e, mem_ld_fill, mem_none, RETURN_VALUE_REG, SP_REG);
-        }
-        emitter->set_target(free_target);
-    } else {
-        // Yes, save return register
-        if (preserve_ret==MPR_Gr)
-            emitter->ipf_add(6, RETURN_VALUE_REG, 0);
-        else if (preserve_ret==MPR_Fr)
-            emitter->ipf_stf_inc_imm(float_mem_size_e, mem_st_spill, mem_none, SP_REG, RETURN_VALUE_REG, unsigned(-16));
-        // Do free
+    }
+    // Yes, save return register
+    if (preserve_ret == MPR_Gr) {
+        emitter->ipf_add(6, RETURN_VALUE_REG, 0);
+    } else if (preserve_ret == MPR_Fr) {
+        emitter->ipf_stf_inc_imm(float_mem_size_e, mem_st_spill, mem_none, SP_REG, RETURN_VALUE_REG, unsigned(-16));
+    }
+
+    if (handles) {
         emit_call_with_gp(*emitter, (void**)m2n_pop_local_handles);
-        // Restore return register
-        if (preserve_ret==MPR_Gr) {
-            emitter->ipf_add(RETURN_VALUE_REG, 6, 0);
-        } else if (preserve_ret==MPR_Fr) {
-            emitter->ipf_adds(SP_REG, 16, SP_REG);
-            emitter->ipf_ldf(float_mem_size_e, mem_ld_fill, mem_none, RETURN_VALUE_REG, SP_REG);
-        }
+    } else {
+        emit_call_with_gp(*emitter, (void**)m2n_free_local_handles);
+    }
+    
+    // Restore return register
+    if (preserve_ret == MPR_Gr) {
+        emitter->ipf_add(RETURN_VALUE_REG, 6, 0);
+    } else if (preserve_ret == MPR_Fr) {
+        emitter->ipf_adds(SP_REG, 16, SP_REG);
+        emitter->ipf_ldf(float_mem_size_e, mem_ld_fill, mem_none, RETURN_VALUE_REG, SP_REG);
+    }
+
+
+    if (handles) {
+        emitter->set_target(free_target);
     }
 
     // Unlink the M2nFrame from the list of the current thread

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.c?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.c (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.c Fri Dec 15 00:33:21 2006
@@ -0,0 +1,7 @@
+#include "TestFatalError.h"
+
+JNIEXPORT void JNICALL Java_shutdown_TestFatalError_sendFatalError
+  (JNIEnv * jni_env, jclass clazz)
+{
+    (*jni_env)->FatalError(jni_env, "PASSED");
+}
\ No newline at end of file

Propchange: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.h?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.h Fri Dec 15 00:33:21 2006
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class shutdown_TestFatalError */
+
+#ifndef _Included_shutdown_TestFatalError
+#define _Included_shutdown_TestFatalError
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     shutdown_TestFatalError
+ * Method:    sendFatalError
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_shutdown_TestFatalError_sendFatalError
+  (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

Propchange: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.java?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.java (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestFatalError.java Fri Dec 15 00:33:21 2006
@@ -0,0 +1,37 @@
+package shutdown;
+
+public class TestFatalError {
+    private static Object sync = new Object();
+
+    static {
+        System.loadLibrary("TestFatalError");
+    }
+
+    public static native void sendFatalError();
+
+    public static void main(String[] args) {
+        synchronized (sync) {
+            Thread permanentThread = new PermanentThread();
+            permanentThread.start();
+            Thread hook = new HookThread();
+            Runtime.getRuntime().addShutdownHook(hook);
+            sendFatalError();
+            System.out.println("FAILED");
+        }
+    }
+
+    static class PermanentThread extends Thread {
+        public void run() {
+            synchronized (sync) {
+                System.out.println("FAILED");
+            }                
+        }
+        
+    }
+
+    static class HookThread extends Thread {
+        public void run() {
+           System.out.println("FAILED");
+        }
+    }
+}
\ No newline at end of file

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.c?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.c (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.c Fri Dec 15 00:33:21 2006
@@ -0,0 +1,24 @@
+#include "TestInterrupt.h"
+
+#if defined (_WIN32) || defined (__WIN32__) || defined (WIN32)
+#include <windows.h>
+
+JNIEXPORT void JNICALL Java_shutdown_TestInterrupt_sendInterrupt
+  (JNIEnv * jni_env, jclass clazz)
+{
+    printf("HAH Signalling....");
+    GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
+}
+
+#else
+
+#include <signal.h>
+
+JNIEXPORT void JNICALL Java_shutdown_TestInterrupt_sendInterrupt
+  (JNIEnv * jni_env, jclass clazz)
+{
+    printf("Signalling....");
+    raise(SIGINT);
+}
+
+#endif
\ No newline at end of file

Propchange: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.h?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.h Fri Dec 15 00:33:21 2006
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class shutdown_TestInterrupt */
+
+#ifndef _Included_shutdown_TestInterrupt
+#define _Included_shutdown_TestInterrupt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     shutdown_TestInterrupt
+ * Method:    sendInterrupt
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_shutdown_TestInterrupt_sendInterrupt
+  (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

Propchange: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.java?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.java (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestInterrupt.java Fri Dec 15 00:33:21 2006
@@ -0,0 +1,35 @@
+package shutdown;
+
+public class TestInterrupt {
+    private static Object sync = new Object();
+
+    static {
+        System.loadLibrary("TestInterrupt");
+    }
+
+    public static native void sendInterrupt();
+
+    public static void main(String[] args) {
+        synchronized (sync) {
+            try {
+                Thread hook = new HookThread();
+                Runtime.getRuntime().addShutdownHook(hook);
+                sendInterrupt();
+                sync.wait();                 
+                sync.wait();                 
+            } catch (InterruptedException e) {
+                System.out.println("FAILED");
+            }
+        }
+        System.out.println("FAILED");
+    }
+
+    static class HookThread extends Thread {
+        public void run() {
+            synchronized (sync) {
+                sync.notify();
+            }
+            System.out.println("PASSED");
+        }
+    }
+}
\ No newline at end of file

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestLock.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestLock.java?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestLock.java (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestLock.java Fri Dec 15 00:33:21 2006
@@ -0,0 +1,50 @@
+package shutdown;
+
+public class TestLock {
+    private static Object start = new Object();
+    private static Object sync = new Object();
+
+    public static void main(String[] args) {
+        synchronized (start) {
+            try {
+                Thread worker = new WorkerThread();
+                worker.setDaemon(true);
+                worker.start();
+                start.wait();
+                Thread locked = new LockedThread();
+                locked.setDaemon(true);
+                locked.start();
+                start.wait();
+            } catch (InterruptedException e) {
+                System.out.println("FAILED");
+            }
+        }
+        System.out.println("PASSED");
+    }
+
+    static class WorkerThread extends Thread {
+        public void run() {
+            synchronized (sync) {
+                synchronized (start) {
+                    start.notify();
+                }
+                while (true) {
+                    Thread.yield();
+                }
+            }
+        }
+    }
+
+    static class LockedThread extends Thread {
+        public void run() {
+            synchronized (start) {
+                start.notify();
+            }
+            synchronized (sync) {
+                System.out.println("FAILED");
+            }
+            System.out.println("FAILED");
+        }
+    }
+
+}
\ No newline at end of file

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.c?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.c (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.c Fri Dec 15 00:33:21 2006
@@ -0,0 +1,36 @@
+
+#include "TestNativeAllocation.h"
+
+/*
+ * Class:     shutdown_TestNativeAllocation_WorkerThread
+ * Method:    callJNI
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_shutdown_TestNativeAllocation_00024WorkerThread_callJNI
+  (JNIEnv * jni_env, jobject thread)
+{
+    static int allocated = 0;
+    jclass thread_class;
+    jmethodID methID;
+
+    ++allocated;
+    thread_class = (*jni_env)->GetObjectClass(jni_env, thread);
+    methID = (*jni_env)->GetMethodID(jni_env, thread_class, "calledFromJNI", "()V");
+    if (methID == NULL) {
+        --allocated;
+        if (allocated == 0) {
+            printf("PASSED");
+        }
+        return;
+    }
+
+    (*jni_env)->CallVoidMethod(jni_env, thread, methID);
+    if ((*jni_env)->ExceptionOccurred(jni_env)) {
+        --allocated;
+        if (allocated == 0) {
+            printf("PASSED");
+        }
+        return;
+    }
+    printf("FAILED");
+}
\ No newline at end of file

Propchange: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.h?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.h Fri Dec 15 00:33:21 2006
@@ -0,0 +1,27 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class shutdown_TestNativeAllocation_WorkerThread */
+
+#ifndef _Included_shutdown_TestNativeAllocation_WorkerThread
+#define _Included_shutdown_TestNativeAllocation_WorkerThread
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef shutdown_TestNativeAllocation_WorkerThread_MIN_PRIORITY
+#define shutdown_TestNativeAllocation_WorkerThread_MIN_PRIORITY 1L
+#undef shutdown_TestNativeAllocation_WorkerThread_NORM_PRIORITY
+#define shutdown_TestNativeAllocation_WorkerThread_NORM_PRIORITY 5L
+#undef shutdown_TestNativeAllocation_WorkerThread_MAX_PRIORITY
+#define shutdown_TestNativeAllocation_WorkerThread_MAX_PRIORITY 10L
+/*
+ * Class:     shutdown_TestNativeAllocation_WorkerThread
+ * Method:    callJNI
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_shutdown_TestNativeAllocation_00024WorkerThread_callJNI
+  (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

Propchange: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.java?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.java (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestNativeAllocation.java Fri Dec 15 00:33:21 2006
@@ -0,0 +1,56 @@
+package shutdown;
+
+public class TestNativeAllocation {
+    private static Object start = new Object();
+    private static Object sync = new Object();
+
+    public static void main(String[] args) {
+        synchronized (start) {
+            try {
+                Thread worker = new WorkerThread();
+                worker.setDaemon(true);
+                worker.start();
+                start.wait();
+            } catch (InterruptedException e) {
+                System.out.println("FAILED");
+            }
+        }
+    }
+
+    static class WorkerThread extends Thread {
+        private int recursion = 0;
+    
+        static {
+            System.loadLibrary("TestNativeAllocation");
+        }
+
+
+        public native void callJNI();
+    
+        public void calledFromJNI() {
+            if (recursion < 30) {
+                 ++recursion;
+                 run();
+            }
+            synchronized (sync) {
+                synchronized (start) {
+                    start.notify();
+                }
+                try {
+                    // wait here forever
+                    sync.wait();
+                } catch (Throwable e) {
+                    System.out.println("FAILED");
+                } finally {
+                    System.out.println("FAILED");
+                }
+            }
+            System.out.println("FAILED");
+        }
+
+        public void run() {
+            callJNI();
+            System.out.println("FAILED");
+        }
+    }
+}

Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestWaitSet.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestWaitSet.java?view=auto&rev=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestWaitSet.java (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/shutdown/TestWaitSet.java Fri Dec 15 00:33:21 2006
@@ -0,0 +1,34 @@
+package shutdown;
+
+public class TestWaitSet {
+    private static Object sync = new Object();
+
+    public static void main(String[] args) {
+        synchronized (sync) {
+            try {
+                Thread worker = new WorkerThread();
+                worker.setDaemon(true);
+                worker.start();
+                sync.wait();
+            } catch (InterruptedException e) {
+                System.out.println("FAILED");
+            }
+        }
+        System.out.println("PASSED");
+    }
+
+    static class WorkerThread extends Thread {
+        public void run() {
+            synchronized (sync) {
+                try {
+                    sync.notify();
+                    sync.wait();
+                } catch (InterruptedException e) {
+                    System.out.println("FAILED");
+                }
+                System.out.println("FAILED");
+            }
+            System.out.println("FAILED");
+        }
+    }
+}
\ No newline at end of file

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h Fri Dec 15 00:33:21 2006
@@ -42,6 +42,9 @@
 
 struct Global_Env {
   public:
+     // Global VM states.
+    enum VM_STATE { VM_INITIALIZING, VM_RUNNING, VM_SHUTDOWNING };
+
     apr_pool_t*               mem_pool; // memory pool
     BootstrapClassLoader*     bootstrap_class_loader;
     UserDefinedClassLoader*   system_class_loader;
@@ -167,7 +170,6 @@
     Class* java_lang_ExceptionInInitializerError_Class;
     Class* java_lang_NullPointerException_Class;
     Class* java_lang_StackOverflowError_Class;
-    Class* java_lang_ThreadDeathError_Class;
 
     Class* java_lang_ClassNotFoundException_Class;
     Class* java_lang_NoClassDefFoundError_Class;
@@ -177,8 +179,11 @@
     Class* java_lang_ArithmeticException_Class;
     Class* java_lang_ClassCastException_Class;
     Class* java_lang_OutOfMemoryError_Class;
+    Class* java_lang_ThreadDeath_Class;
+
+    ObjectHandle java_lang_Object;
     ObjectHandle java_lang_OutOfMemoryError;
-    ObjectHandle java_lang_ThreadDeathError;
+    ObjectHandle java_lang_ThreadDeath;
     // object of java.lang.Error class used for JVMTI JIT PopFrame support
     ObjectHandle popFrameException;
 
@@ -206,6 +211,9 @@
     // Offset to the vm_class field in java.lang.Class;
     unsigned vm_class_offset;
 
+    // The VM state. See VM_STATE enum above.
+    volatile int vm_state;
+
     // FIXME
     // The whole environemt will be refactored to VM instance
     // The following contains a cached copy of EM interface table
@@ -235,6 +243,18 @@
     void FinishVMBootstrap() {
         assert(bootstrapping);
         bootstrapping = false;
+    }
+
+    int isVmInitializing() {
+        return vm_state == VM_INITIALIZING;
+    }
+
+    int isVmRunning() {
+        return vm_state == VM_RUNNING;
+    }
+
+    int IsVmShutdowning() {
+        return vm_state == VM_SHUTDOWNING;
     }
 
     //load a class via bootstrap classloader

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/init.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/init.h?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/init.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/init.h Fri Dec 15 00:33:21 2006
@@ -26,6 +26,8 @@
 jint vm_init1(JavaVM_Internal * java_vm, JavaVMInitArgs * vm_arguments);
 jint vm_init2(JNIEnv * jni_env);
 jint vm_destroy(JavaVM_Internal * java_vm, jthread java_thread);
+void vm_interrupt_handler(int);
+void vm_dump_handler(int);
 
 void initialize_vm_cmd_state(Global_Env *p_env, JavaVMInitArgs* arguments);
 void set_log_levels_from_cmd(JavaVMInitArgs* vm_arguments);

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/stack_trace.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/stack_trace.h?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/stack_trace.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/stack_trace.h Fri Dec 15 00:33:21 2006
@@ -153,20 +153,30 @@
 void st_print_frame(ExpandableMemBlock* buf, StackTraceFrame* stf);
 
 /**
- * Prints the current thread's trace.
+ * Prints stack trace of all java threads.
  *
- * This function supports and prints all Java and M2N frames.
+ * This function supports and prints all Java frames.
  *
  * @param[in] f - the pointer to the file, where the stack trace will be printed
  *
  * @note Intended for debugging purposes.
  */
-void st_print(FILE* f);
+void st_print_all(FILE* f);
 
 /**
- * Prints the current thread's trace into the <code>stderr</code> stream.
+ * Prints the current java thread stack trace into specified stream.
  *
- * This function supports and prints all Java and M2N frames.
+ * This function supports and prints all Java frames.
+ *
+ * @param[in] f - the pointer to the file, where the stack trace will be printed
+ * @param[in] thread - the thread wich stack should be printed
+ *
+ * @note Intended for debugging purposes.
+ */
+void st_print(FILE* f, hythread_t thread);
+
+/**
+ * Prints the current java thread stack trace into the <code>stderr</code> stream.
  *
  * @note Intended for debugging purposes.
  */

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp Fri Dec 15 00:33:21 2006
@@ -168,7 +168,6 @@
     JavaLangClass_Class = NULL;
     java_lang_Throwable_Class = NULL;
     java_lang_Error_Class = NULL;
-    java_lang_ThreadDeathError_Class = NULL;
     java_lang_ExceptionInInitializerError_Class = NULL;
     java_lang_NullPointerException_Class = NULL;
     java_lang_StackOverflowError_Class = NULL;
@@ -177,6 +176,7 @@
     java_lang_ArithmeticException_Class = NULL;
     java_lang_ClassCastException_Class = NULL;
     java_lang_OutOfMemoryError_Class = NULL;
+    java_lang_ThreadDeath_Class = NULL;
 
     java_lang_OutOfMemoryError = NULL;
     popFrameException = NULL;
@@ -193,6 +193,7 @@
     JavaLangString_VTable = NULL;
 
     vm_class_offset = 0;
+    vm_state = VM_INITIALIZING;
 
     TI = new DebugUtilsTI; 
     vm_methods = new Method_Lookup_Table;
@@ -203,10 +204,6 @@
 
 Global_Env::~Global_Env()
 {
-    if (get_boolean_property("vm.noCleanupOnExit", false, VM_PROPERTIES)) {
-        return;
-    }
-
     GlobalClassLoaderIterator ClIterator;
     ClassLoader *cl = ClIterator.first();
     

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_impl.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_impl.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_impl.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_impl.cpp Fri Dec 15 00:33:21 2006
@@ -215,10 +215,6 @@
     vm_execute_java_method_array((jmethodID) init_cause_method, &ret_val,
         args);
     tmn_suspend_enable();
-
-    if (exn_raised()) {
-        DIE(("Exception constructor has thrown an exception"));
-    }
 }
 
 jthrowable create_exception(Class* exc_class, Method* exc_init, jvalue* args) {

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp Fri Dec 15 00:33:21 2006
@@ -209,18 +209,13 @@
         si_goto_previous(si);
     }
 
-    Method *interrupted_method = NULL;
-    NativeCodePtr interrupted_method_location = NULL;
-    JIT *interrupted_method_jit = NULL;
+    assert(!si_is_native(si));
 
-    if (!si_is_native(si))
-    {
-        CodeChunkInfo *interrupted_cci = si_get_code_chunk_info(si);
-        assert(interrupted_cci);
-        interrupted_method = interrupted_cci->get_method();
-        interrupted_method_location = si_get_ip(si);
-        interrupted_method_jit = interrupted_cci->get_jit();
-    }
+    CodeChunkInfo *interrupted_cci = si_get_code_chunk_info(si);
+    assert(interrupted_cci);
+    Method *interrupted_method = interrupted_cci->get_method();
+    NativeCodePtr interrupted_method_location = si_get_ip(si);
+    JIT *interrupted_method_jit = interrupted_cci->get_jit();
 
     // Remove single step breakpoints which could have been set on the
     // exception bytecode
@@ -236,6 +231,13 @@
         ti->vm_brpt->unlock();
     }
 
+    // When VM is in shutdown stage we need to execute final block to
+    // release monitors and propogate an exception to the upper frames.
+    if (VM_Global_State::loader_env->IsVmShutdowning()) {
+        exn_class = VM_Global_State::loader_env->JavaLangObject_Class;
+        *exn_obj = NULL;
+    }
+
     bool same_frame = true;
     while (!si_is_past_end(si) && !si_is_native(si)) {
         CodeChunkInfo *cci = si_get_code_chunk_info(si);
@@ -262,10 +264,15 @@
                 // Found a handler that catches the exception.
 #ifdef VM_STATS
                 cci->num_catches++;
-                if (same_frame)
+                if (same_frame) {
                     VM_Statistics::get_vm_stats().num_exceptions_caught_same_frame++;
-                if (handler->is_exc_obj_dead())
+                }
+                if (handler->is_exc_obj_dead()) {
                     VM_Statistics::get_vm_stats().num_exceptions_dead_object++;
+                    if (!*exn_obj) {
+                        VM_Statistics::get_vm_stats().num_exceptions_object_not_created++;
+                    }
+                }
 #endif // VM_STATS
                 // Setup handler context
                 jit->fix_handler_context(method, si_get_jit_context(si));
@@ -293,18 +300,9 @@
                 }
 
                 // Create exception if necessary
-                if (!*exn_obj) {
-                    if (handler->is_exc_obj_dead()
-                            && !VM_Global_State::loader_env->TI->isEnabled()) {
-#ifdef VM_STATS
-                        VM_Statistics::get_vm_stats().num_exceptions_object_not_created++;
-#endif // VM_STATS
-                    }
-                    else {
-                        *exn_obj =
-                            create_lazy_exception(exn_class, exn_constr,
-                                jit_exn_constr_args, vm_exn_constr_args);
-                    }
+                if (!*exn_obj && !handler->is_exc_obj_dead()) {
+                    *exn_obj = create_lazy_exception(exn_class, exn_constr,
+                        jit_exn_constr_args, vm_exn_constr_args);
                 }
 
                 BEGIN_RAISE_AREA;
@@ -339,12 +337,12 @@
     }
 
     // Exception propagates to the native code
+    assert(si_is_native(si));
 
     // The current thread exception is set to the exception and we return 0/NULL to the native code
     if (*exn_obj == NULL) {
-        *exn_obj =
-            create_lazy_exception(exn_class, exn_constr,
-                jit_exn_constr_args, vm_exn_constr_args);
+        *exn_obj = create_lazy_exception(exn_class, exn_constr,
+            jit_exn_constr_args, vm_exn_constr_args);
     }
     assert(!hythread_is_suspend_enabled());
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/finalize.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/finalize.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/finalize.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/finalize.cpp Fri Dec 15 00:33:21 2006
@@ -336,12 +336,14 @@
     vm_execute_java_method_array((jmethodID) finalize_meth, 0, args);
     tmn_suspend_enable();
 
+#ifndef NDEBUG
     if (exn_raised()) {
         INFO2("finalize", "Uncaught exception "
             << exn_get_name()
-            << " while running a wakeFinalization in FinalizerThread");
-        exn_clear();
+            << " while running a wakeFinalization in FinalizerThread");        
     }
+#endif
+    exn_clear();
     p_TLS_vmthread->finalize_thread_flags &= ~FINALIZER_STARTER;
 } //Objects_To_Finalize::run_finalizers
 
@@ -416,7 +418,8 @@
         TRACE2("finalize", "finalize object " << class_get_name(handle->object->vt()->clss));
         vm_execute_java_method_array( (jmethodID) finalize, 0, args);
         tmn_suspend_enable();
-        
+
+#ifndef NDEBUG
         if (exn_raised()) {
             tmn_suspend_disable();
             assert(handle->object->vt()->clss);
@@ -424,9 +427,10 @@
                 << exn_get_name()
                 << " while running a finalize of the object"
                 << class_get_name(object->vt()->clss) << ".");
-            tmn_suspend_enable();
-            exn_clear();
+            tmn_suspend_enable();            
         }
+#endif
+        exn_clear();
     }
     return i;
 } //Objects_To_Finalize::do_finalization
@@ -463,6 +467,7 @@
         vm_execute_java_method_array( (jmethodID) enqueue, &r, args);
         tmn_suspend_enable();
 
+#ifndef NDEBUG
         if (exn_raised()) {
             tmn_suspend_disable();
             assert(object->vt()->clss);
@@ -471,8 +476,10 @@
                 << " while running a enqueue method of the object"
                 << class_get_name(object->vt()->clss) << ".");
             tmn_suspend_enable();
-            exn_clear();
+            
         }
+#endif
+        exn_clear();
     }
 
     TRACE2("ref", "enqueue_references() completed");

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/parse_arguments.cpp Fri Dec 15 00:33:21 2006
@@ -203,8 +203,6 @@
         "              Do not launch compilation in parallel\n"
         "    -Xdumpfile:<file>\n"
         "              Specifies a file name for the dump\n"
-        "    -XnoCleanupOnExit\n"
-        "              Exit without cleaning internal resorces\n"
         "    -XD<name>=<value>\n"
         "              set an internal system property\n");
 } //print_help_on_nonstandard_options
@@ -233,8 +231,6 @@
         "            Use verifier.\n"
         "    vm.jvmti.enabled (default FALSE):\n"
         "            Whether JVMTI mode is enabled.\n"
-        "    vm.cleanupOnExit (default FALSE):\n"
-        "            Excplicitly free VM resources before exit.\n"
         "    vm.bootclasspath.appendclasspath (default FALSE):\n"
         "            Append classpath to the bootclasspath.\n"
         "\nOther properties:\n\n"
@@ -480,9 +476,6 @@
         else if (strcmp(option, "-Xdumpfile:") == 0) {
             const char* arg = option + strlen("-Xdumpfile:");
             dump_file_name = arg;
-        }
-        else if (strcmp(option, "-XnoCleanupOnExit") == 0) {
-            p_env->VmProperties()->set("vm.noCleanupOnExit", "true");
         }
         else if (strcmp(option, "_org.apache.harmony.vmi.portlib") == 0) {
             // Store a pointer to the portlib

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp?view=diff&rev=487483&r1=487482&r2=487483
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp Fri Dec 15 00:33:21 2006
@@ -376,8 +376,6 @@
         preload_class(vm_env, "java/lang/StackTraceElement");
     vm_env->java_lang_Error_Class =
         preload_class(vm_env, "java/lang/Error");
-    vm_env->java_lang_ThreadDeathError_Class =
-        preload_class(vm_env, "java/lang/ThreadDeath");
     vm_env->java_lang_ExceptionInInitializerError_Class =
         preload_class(vm_env, "java/lang/ExceptionInInitializerError");
     vm_env->java_lang_NoClassDefFoundError_Class =
@@ -398,6 +396,8 @@
         preload_class(vm_env, "java/lang/ClassCastException");
     vm_env->java_lang_OutOfMemoryError_Class = 
         preload_class(vm_env, "java/lang/OutOfMemoryError");
+    vm_env->java_lang_ThreadDeath_Class = 
+        preload_class(vm_env, "java/lang/ThreadDeath");
 
     vm_env->java_lang_Cloneable_Class =
         preload_class(vm_env, vm_env->Clonable_String);
@@ -704,11 +704,19 @@
 
     // Now the thread is attached to VM and it is valid to disable it.
     hythread_suspend_disable();
-    
-    // Create OutOfMemoryError.
+
+    // Create java.lang.Object.    
+    vm_env->java_lang_Object = oh_allocate_global_handle();
+    vm_env->java_lang_Object->object =
+        class_alloc_new_object(vm_env->JavaLangObject_Class);    
+    // Create java.lang.OutOfMemoryError.
     vm_env->java_lang_OutOfMemoryError = oh_allocate_global_handle();
     vm_env->java_lang_OutOfMemoryError->object = 
         class_alloc_new_object(vm_env->java_lang_OutOfMemoryError_Class);
+    // Create java.lang.ThreadDeath.
+    vm_env->java_lang_ThreadDeath = oh_allocate_global_handle();
+    vm_env->java_lang_ThreadDeath->object = 
+        class_alloc_new_object(vm_env->java_lang_ThreadDeath_Class);
 
     // Create pop frame exception.
     vm_env->popFrameException = oh_allocate_global_handle();
@@ -717,8 +725,8 @@
 
     // Precompile StackOverflowError.
     class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_StackOverflowError_Class);
-    // Precompile ThreadDeathError.
-    class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_ThreadDeathError_Class);
+    // Precompile ThreadDeath.
+    class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_ThreadDeath_Class);
     
     hythread_suspend_enable();
 



Mime
View raw message