You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by mf...@apache.org on 2007/07/31 15:36:53 UTC

svn commit: r561327 - in /harmony/enhanced/drlvm/trunk: src/test/regression/H4514/ vm/jitrino/src/codegenerator/ia32/ vm/port/include/ vm/port/src/lil/em64t/pim/ vm/port/src/lil/ia32/pim/ vm/port/src/lil/ipf/pim/ vm/vmcore/src/util/ipf/base/ vm/vmcore/...

Author: mfursov
Date: Tue Jul 31 06:36:49 2007
New Revision: 561327

URL: http://svn.apache.org/viewvc?view=rev&rev=561327
Log:
Fix for HARMONY-4433 (IPF related)
Fix for HARMONY-4568 (Native SOE in recursion-based algorithm in Jitrino.OPT)
update for regression from HARMONY-4514 - making it more sensitive to bytecode offsets.

Modified:
    harmony/enhanced/drlvm/trunk/src/test/regression/H4514/Test.java
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp
    harmony/enhanced/drlvm/trunk/vm/port/include/m2n.h
    harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/lil_code_generator_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf_internal.h
    harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/exceptions_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/stub_code_utils.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/Code_Emitter.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/stub_code_utils.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/vm_ipf.h

Modified: harmony/enhanced/drlvm/trunk/src/test/regression/H4514/Test.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/src/test/regression/H4514/Test.java?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/src/test/regression/H4514/Test.java (original)
+++ harmony/enhanced/drlvm/trunk/src/test/regression/H4514/Test.java Tue Jul 31 06:36:49 2007
@@ -3,49 +3,64 @@
 public class Test extends TestCase {
     
     public void testTrace1() {
+        //some useless code
+        int i=0;
+        int j=1;
         try {
             assertEquals(0, 1); //the number of this line must be in tracktracelement
         } catch (Throwable e) {
             StackTraceElement thisFrame = findThisFrame(e);
-            assertEquals(7, thisFrame.getLineNumber());
+            assertEquals(10, thisFrame.getLineNumber());
         }
     }
 
     public void testTrace2() {
+        //some useless code
+        int i=0;
+        int j=1;
         try {
             fail();//the number of this line must be in tracktracelement
         } catch (Throwable e) {
             StackTraceElement thisFrame = findThisFrame(e);
-            assertEquals(16, thisFrame.getLineNumber());
+            assertEquals(22, thisFrame.getLineNumber());
         }
     }
 
     public void testTrace3() {
+        //some useless code
+        int i=0;
+        int j=1;
         try {
             assertEquals(true, false);//the number of this line must be in tracktracelement
         } catch (Throwable e) {
             StackTraceElement thisFrame = findThisFrame(e);
-            assertEquals(25, thisFrame.getLineNumber());
+            assertEquals(34, thisFrame.getLineNumber());
         }
 
     }
 
     public void testTrace4() {
+        //some useless code
+        int i=0;
+        int j=1;
         try {
             assertNotNull(null);//the number of this line must be in tracktracelement
         } catch (Throwable e) {
             StackTraceElement thisFrame = findThisFrame(e);
-            assertEquals(35, thisFrame.getLineNumber());
+            assertEquals(47, thisFrame.getLineNumber());
         }
 
     }
 
     public void testTrace5() {
+        //some useless code
+        int i=0;
+        int j=1;
         try {
             assertEquals("", "fail");//the number of this line must be in tracktracelement
         } catch (Throwable e) {
             StackTraceElement thisFrame = findThisFrame(e);
-            assertEquals(45, thisFrame.getLineNumber());
+            assertEquals(60, thisFrame.getLineNumber());
         }
 
     }

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp Tue Jul 31 06:36:49 2007
@@ -69,6 +69,7 @@
     
     ///methods fo registering bc-offsets for inlined methods
     void registerBCOffsets(Node* node, InlineInfoMap::Entry* parentEntry);
+    InlineInfoMap::Entry* processBlockOffsets(Node* node, InlineInfoMap::Entry* parentEntry);
     void registerBCMappingAndInlineInfo();
 
     void orderNodesAndMarkInlinees(StlList<MethodMarkerPseudoInst*>& container, 
@@ -336,10 +337,7 @@
     return getTopLevelEntryOffset(entry->parentEntry);
 }
 
-void CodeEmitter::registerBCOffsets(Node* node, InlineInfoMap::Entry* parentEntry) {
-    assert(traversalInfo[node->getId()] == 0);
-    traversalInfo[node->getId()] = 1;   
-    
+InlineInfoMap::Entry* CodeEmitter::processBlockOffsets(Node* node, InlineInfoMap::Entry* parentEntry) {
     for (Inst* inst = (Inst*)node->getFirstInst(); inst!=NULL; inst = inst->getNextInst()) {
         if (inst->getKind() == Inst::Kind_MethodEntryPseudoInst) {
             if (Log::isEnabled()) {
@@ -394,6 +392,13 @@
             }
         }
     }
+    return parentEntry;
+}
+
+void CodeEmitter::registerBCOffsets(Node* node, InlineInfoMap::Entry* parentEntry) {
+    assert(traversalInfo[node->getId()] == 0);
+    traversalInfo[node->getId()] = 1;   
+    parentEntry = processBlockOffsets(node, parentEntry);
     const Edges& edges = node->getOutEdges();
     for (Edges::const_iterator ite = edges.begin(), ende = edges.end(); ite!=ende; ++ite) {
         Edge* e = *ite;

Modified: harmony/enhanced/drlvm/trunk/vm/port/include/m2n.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/include/m2n.h?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/include/m2n.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/include/m2n.h Tue Jul 31 06:36:49 2007
@@ -41,23 +41,19 @@
 
 struct M2nFrame;
 
-enum frame_type {
-    FRAME_UNKNOWN = 0x00,
-    FRAME_NON_UNWINDABLE = 0x80,
-    FRAME_JNI = 0x01 | FRAME_NON_UNWINDABLE,
-    FRAME_COMPILATION = 0x02 | FRAME_NON_UNWINDABLE,
+typedef uint32 frame_type;
 
-    FRAME_UNPOPABLE = 0x0000,
-    FRAME_POPABLE = 0x0100,
-    FRAME_POP_NOW = 0x0200,
-    FRAME_POP_DONE = FRAME_POPABLE | FRAME_POP_NOW,
-
-    FRAME_POP_MASK = 0x0700,
-
-    FRAME_SAFE_POINT = 0x0800,
-
-    FRAME_MODIFIED_STACK = 0x1000
-};
+extern const uint32 FRAME_UNKNOWN;
+extern const uint32 FRAME_NON_UNWINDABLE;
+extern const uint32 FRAME_JNI;
+extern const uint32 FRAME_COMPILATION;
+extern const uint32 FRAME_UNPOPABLE;
+extern const uint32 FRAME_POPABLE;
+extern const uint32 FRAME_POP_NOW;
+extern const uint32 FRAME_POP_DONE;
+extern const uint32 FRAME_POP_MASK;
+extern const uint32 FRAME_SAFE_POINT;
+extern const uint32 FRAME_MODIFIED_STACK;
 
 // The pushing and popping of native frames is done only by stubs that
 // implement the managed to native transitions. These stubs use code that is

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp Tue Jul 31 06:36:49 2007
@@ -311,7 +311,6 @@
 // Stack Iterator Interface
 
 StackIterator * si_create_from_native() {
-    ASSERT_NO_INTERPRETER
     return si_create_from_native(p_TLS_vmthread);
 }
 

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp Tue Jul 31 06:36:49 2007
@@ -232,18 +232,7 @@
 
 StackIterator* si_create_from_native()
 {
-    ASSERT_NO_INTERPRETER
-    // Allocate iterator
-    StackIterator* res = (StackIterator*)STD_MALLOC(sizeof(StackIterator));
-    assert(res);
-    memset(res, 0, sizeof(StackIterator));
-
-    res->cci = NULL;
-    res->m2nfl = m2n_get_last_frame();
-    res->ip = 0;
-    res->c.p_eip = &res->ip;
-
-    return res;
+    return si_create_from_native(p_TLS_vmthread);
 }
 
 StackIterator* si_create_from_native(VM_thread* thread)

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/lil_code_generator_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/lil_code_generator_ipf.cpp?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/lil_code_generator_ipf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/lil_code_generator_ipf.cpp Tue Jul 31 06:36:49 2007
@@ -600,6 +600,10 @@
         return 16 + stk_output_size;
     }
 
+    bool has_push_m2n() {
+        return has_m2n;
+    }
+
 private:
     //*****************
     // helper functions, used by visitor functions
@@ -1966,7 +1970,13 @@
                 // Set new gp
                 emit_mov_imm_compactor(emitter, GP_REG, (uint64)gp_new);
             }
-            emitter.ipf_brl_call(br_many, br_sptk, br_none, BRANCH_RETURN_LINK_REG, (uint64)fn_addr);
+            emit_mov_imm_compactor(emitter, tmp_res->addr, (uint64)fn_addr, 0);
+            if (context.has_push_m2n()) {
+                emitter.ipf_mtbr(BRANCH_CALL_REG, tmp_res->addr);
+                emit_mov_imm_compactor(emitter, tmp_res->addr, (uint64)m2n_gen_flush_and_call(), 0);
+            }
+            emitter.ipf_mtbr(tmp_br, tmp_res->addr);
+            emitter.ipf_bricall(br_few, br_sptk, br_none, BRANCH_RETURN_LINK_REG, tmp_br);
             if (gp_new != gp_old) {
                 // Restore gp
                 const LcgIpfLoc* gp_save_gr = context.get_gp_save_gr();
@@ -1990,9 +2000,12 @@
             else {
                 ASSERT(0, "Unexpected kind");  // address can't be FP!
             }
+            if (context.has_push_m2n()) {
+                emitter.ipf_mtbr(BRANCH_CALL_REG, call_addr_gr);
+                emit_mov_imm_compactor(emitter, call_addr_gr, (uint64)m2n_gen_flush_and_call(), 0);
+            }
             emitter.ipf_mtbr(tmp_br, call_addr_gr);
-            emitter.ipf_bricall(br_few, br_sptk, br_none,
-                                 BRANCH_RETURN_LINK_REG, tmp_br);
+            emitter.ipf_bricall(br_few, br_sptk, br_none, BRANCH_RETURN_LINK_REG, tmp_br);
         }
     }  // call
 

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=561327&r1=561326&r2=561327
==============================================================================
--- 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 Tue Jul 31 06:36:49 2007
@@ -74,6 +74,7 @@
 
 uint64* m2n_get_extra_saved(M2nFrame* m2nf)
 {
+    do_flushrs();
     return (uint64*)*get_stacked_register_address(m2n_get_bsp(m2nf), M2N_EXTRA_SAVED_PTR);
 }
 
@@ -194,6 +195,44 @@
 
 //***** Stub Interface
 
+// Flushes register stack of the current thread into backing store and calls target procedure.
+NativeCodePtr m2n_gen_flush_and_call() {
+    static NativeCodePtr addr = NULL;
+
+    if (addr != NULL) {
+        return addr;
+    }
+
+    tl::MemoryPool mem_pool;
+    Merced_Code_Emitter emitter(mem_pool, 2, 0);
+    emitter.disallow_instruction_exchange();
+    emitter.memory_type_is_unknown();
+
+    // We need to remember pfs & b0 here but there is no space to save them in.
+    // Register stack contains valid outputs and we don't know how many registers are used.
+    // Memory stack holds output values beyound those 8 which are on register stack.
+    // The only place is general caller-saves registers. It is save to use them with out preserving
+    // because they are alredy preserved by the corresponding M2N frame.
+
+    // r4 is used to keep a thread pointer...so let's use r5 & r6.
+
+    emitter.ipf_mfap(PRESERV_GENERAL_REG1, AR_pfs);
+    emitter.ipf_mfbr(PRESERV_GENERAL_REG2, BRANCH_RETURN_LINK_REG);
+
+    emitter.flush_buffer();
+    emitter.ipf_flushrs();
+
+    emitter.ipf_bricall(br_many, br_sptk, br_none, BRANCH_RETURN_LINK_REG, BRANCH_CALL_REG);
+
+    emitter.ipf_mtbr(BRANCH_RETURN_LINK_REG, PRESERV_GENERAL_REG2);
+    emitter.ipf_mtap(AR_pfs, PRESERV_GENERAL_REG1);
+
+    emitter.ipf_brret(br_few, br_sptk, br_none, BRANCH_RETURN_LINK_REG);
+
+    addr = finalize_stub(emitter, "");
+    return addr;
+}
+
 unsigned m2n_gen_push_m2n(Merced_Code_Emitter* emitter, Method_Handle method, frame_type current_frame_type, bool handles, unsigned num_on_stack, unsigned num_local, unsigned num_out, bool do_alloc)
 {
     // Allocate new frame
@@ -211,7 +250,8 @@
     // Save predicates, SP, and callee saves general registers
     emitter->ipf_adds(M2N_SAVED_SP, num_on_stack, SP_REG);
 
-    emitter->ipf_mfpr(M2N_SAVED_PR              );
+    emitter->ipf_mfpr(M2N_SAVED_PR               );
+    emitter->ipf_mfap(M2N_SAVED_UNAT,     AR_unat);
     emitter->ipf_mov (M2N_SAVED_R4,             4);
     emitter->ipf_mov (M2N_SAVED_R5,             5);
     emitter->ipf_mov (M2N_SAVED_R6,             6);
@@ -222,6 +262,61 @@
     emit_mov_imm_compactor(*emitter, M2N_METHOD, (uint64)method);
     emit_mov_imm_compactor(*emitter, M2N_FRAME_TYPE, (uint64)current_frame_type);
 
+    const int P1 = SCRATCH_PRED_REG;
+    const int P2 = SCRATCH_PRED_REG2;
+    const int OLD_RSE_MODE = SCRATCH_GENERAL_REG2;
+    const int NEW_RSE_MODE = SCRATCH_GENERAL_REG3;
+    // SCRATCH_GENERAL_REG4 & SCRATCH_GENERAL_REG5 are reserved for std places.
+    const int BSP = SCRATCH_GENERAL_REG6;
+    const int IMM_8 = SCRATCH_GENERAL_REG7;
+    const int IMM_1F8 = SCRATCH_GENERAL_REG8;
+    const int TMP_REG = SCRATCH_GENERAL_REG9;
+    // Scratch branch register.
+    const int TMP_BRANCH_REG = 6;
+
+    // Switch RSE to "forced lazy" mode. This is required to access RNAT.
+    emitter->ipf_mfap(OLD_RSE_MODE, AR_rsc);
+    emitter->ipf_dep(NEW_RSE_MODE, 0, OLD_RSE_MODE, 0, 2);
+    emitter->ipf_mtap(AR_rsc, NEW_RSE_MODE);
+
+    // Flush must be the first instruction in the group.
+    emitter->flush_buffer();
+    // Spill parent frames so that corresponding RNAT bits become valid.
+    emitter->ipf_flushrs();
+    // Extract backing store pointer
+    emitter->ipf_mfap(BSP, AR_bsp);
+    // Remember parent RNAT collection.
+    emitter->ipf_mfap(M2N_EXTRA_RNAT, AR_rnat);
+
+    // TODO: This is not fully legal reset nat bits for the whole m2n frame because it
+    // contains r4-r7 general registers which may have corresponding unat bits up.
+    emitter->ipf_mov(M2N_EXTRA_UNAT, 0);
+
+/* The following code spills M2N into backing store.
+    emitter->ipf_movl(IMM_1F8, 0, (uint64)0x1f8);
+    emitter->ipf_movl(IMM_8, 0, (uint64)0x8);
+
+    // Forcebly spill M2N frame into backing store.
+    for(int i = M2N_NUMBER_INPUTS; i < M2N_NUMBER_LOCALS; i++) {
+        emitter->ipf_and(TMP_REG, IMM_1F8, BSP);
+        emitter->ipf_cmp(icmp_eq, cmp_none, P1, P2, IMM_1F8, TMP_REG);
+        emitter->ipf_add(BSP, BSP, IMM_8, P1);
+        emitter->ipf_st_inc_imm(int_mem_size_8, mem_st_spill, mem_none, BSP, 32 + i, 8);
+    }
+
+    // Remember UNAT collection for the current frame.
+    emitter->ipf_sub(BSP, BSP, IMM_8);
+    emitter->ipf_mfap(M2N_EXTRA_UNAT, AR_unat);
+    emitter->ipf_st(int_mem_size_8, mem_st_none, mem_none, BSP, M2N_EXTRA_UNAT);
+
+    // Restore original UNAT.
+    emitter->ipf_mtap(AR_unat, M2N_SAVED_UNAT);
+    emitter->flush_buffer();
+*/
+
+    // Switch RSE to the original mode.
+    emitter->ipf_mtap(AR_rsc, OLD_RSE_MODE);
+
     // Link M2nFrame into list of current thread
     size_t offset_lm2nf = (size_t)&((VM_thread*)0)->last_m2n_frame;
     emitter->ipf_adds(SCRATCH_GENERAL_REG2, (int)offset_lm2nf, THREAD_PTR_REG);
@@ -284,9 +379,9 @@
     }
 
     if (handles) {
-        emit_call_with_gp(*emitter, (void**)m2n_pop_local_handles);
+        emit_call_with_gp(*emitter, (void**)m2n_pop_local_handles, false);
     } else {
-        emit_call_with_gp(*emitter, (void**)m2n_free_local_handles);
+        emit_call_with_gp(*emitter, (void**)m2n_free_local_handles, false);
     }
     
     // Restore return register

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf_internal.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf_internal.h?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf_internal.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/m2n_ipf_internal.h Tue Jul 31 06:36:49 2007
@@ -100,11 +100,14 @@
 uint64* m2n_get_bsp(M2nFrame*);
 uint64* m2n_get_extra_saved(M2nFrame*);
 
+// Flushes register stack of the current thread into backing store and calls target procedure.
+NativeCodePtr m2n_gen_flush_and_call();
+
 // An M2nFrame will always have 8 input registers, some local stacked registers to save stuff, and some outputs
 
 #define M2N_NUMBER_ALIGNS            2
 #define M2N_NUMBER_INPUTS            8
-#define M2N_NUMBER_LOCALS            14
+#define M2N_NUMBER_LOCALS            17
 
 // The following registers are used in M2nFrames to hold the indicated values
 // The register numbers must be distinct, at least 40 (so they don't conflict with inputs), and less than 40+M2N_NUMBER_LOCALS
@@ -115,14 +118,18 @@
 #define M2N_SAVED_SP                 43
 #define M2N_SAVED_GP                 44
 #define M2N_SAVED_PR                 45
-#define M2N_SAVED_R4                 46
-#define M2N_SAVED_R5                 47
-#define M2N_SAVED_R6                 48
-#define M2N_SAVED_R7                 49
-#define M2N_EXTRA_SAVED_PTR          50
-#define M2N_OBJECT_HANDLES           51
-#define M2N_METHOD                   52
-#define M2N_FRAME_TYPE               53
+#define M2N_SAVED_UNAT               46
+#define M2N_SAVED_R4                 47
+#define M2N_SAVED_R5                 48
+#define M2N_SAVED_R6                 49
+#define M2N_SAVED_R7                 50
+#define M2N_EXTRA_SAVED_PTR          51
+#define M2N_OBJECT_HANDLES           52
+#define M2N_METHOD                   53
+#define M2N_FRAME_TYPE               54
+#define M2N_EXTRA_RNAT               55
+// this must be last register
+#define M2N_EXTRA_UNAT               56
 
 // Only the callee saves general registers are normally saved in the M2nFrame along with special things like pfs, return address, etc.
 // The full set of preserved registers includes callee saves floating point and branch registers as well.

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp Tue Jul 31 06:36:49 2007
@@ -71,8 +71,8 @@
     M2nFrame*         m2nfl;
     uint64            ip;
     uint64*           bsp;
-    uint64*           last_legal_rsnat;
-    uint64            extra_nats;
+    uint64            extra_rnats;
+    uint64            extra_unats;
 };
 
 //////////////////////////////////////////////////////////////////////////
@@ -82,28 +82,60 @@
 // this flush.  We assume that all nat bits we are interested in do not change from the time of flush
 // to after we are finished with the iterator that calls this function, even if the rse engine has
 // returned to a point prior to bsp.
+/*
 static void si_init_nats(StackIterator* si, uint64* bsp, uint64 rnat)
 {
     si->last_legal_rsnat = (uint64*)((uint64)bsp & ~0x1f8);
     si->extra_nats = rnat;
 }
+*/
 
 // This function flushes the rse and puts the value of bsp/bspstore into res[1] and rnat into res[0]
+/*
 extern "C" void get_rnat_and_bsp(uint64* res);
 extern "C" void get_rnat_and_bspstore(uint64* res);
+*/
+
+static uint64 get_rnat(uint64 * bsp) {
+    uint64 * last_m2n = (uint64 *)m2n_get_last_frame();
+    uint64 * rnat_ptr = (uint64*)((uint64)bsp | (uint64)0x1f8);
+    uint64 * extra_nat_ptr;
+
+    if (rnat_ptr <= last_m2n) {
+        return *rnat_ptr;
+    }
+
+    // All nat bits for last M2N are stored at M2N_EXTRA_UNAT.
+    // All nat bits for parent frames are stored at M2N_EXTRA_RNAT.
+
+    if (bsp >= last_m2n) {
+        extra_nat_ptr = last_m2n + (M2N_EXTRA_UNAT - 32);
+    } else {
+        extra_nat_ptr = last_m2n + (M2N_EXTRA_RNAT - 32);
+    }
+
+    if (rnat_ptr <= extra_nat_ptr) {
+        // There is rnat collection inside M2N. Need to adjust...
+        extra_nat_ptr += 1;
+    }
+
+    return *extra_nat_ptr;
+}
 
 // Setup the stacked register for the current frame given bsp and ar.pfs (cfm for current frame)
 static void si_setup_stacked_registers(StackIterator* si)
 {
+    const uint64 ALL_ONES = ~0;
     uint64 pfs = *si->c.p_ar_pfs;
     unsigned sof = (unsigned)EXTRACT64_SOF(pfs);
 
     uint64 nats_lo = si->c.nats_lo & 0xffffffff;
     uint64 nats_hi = 0;
     uint64* bsp = si->bsp;
-    uint64 nats = (bsp<=si->last_legal_rsnat ? *(uint64*)((uint64)bsp|(uint64)0x1f8) : si->extra_nats);
+    uint64 nats = get_rnat(bsp);
+
     unsigned index = (unsigned)(((uint64)bsp & (uint64)0x1f8) >> 3);
-    uint64 mask = 1 << index;
+    uint64 mask = ((uint64)1) << index;
 
     for(unsigned i=0; i<sof; i++) {
         // Set the location of the stack register
@@ -119,12 +151,9 @@
         mask <<= 1;
         // If bsp is on a spilled rsnat recompute nats and mask
         if (((uint64)bsp&(uint64)0x1f8) == (uint64)0x1f8) {
-            if (bsp<=si->last_legal_rsnat)
-                nats = *bsp;
-            else
-                nats = si->extra_nats;
             bsp++;
             mask = 1;
+            nats = get_rnat(bsp);
         }
     }
 
@@ -154,11 +183,12 @@
     assert(M2N_SAVED_R7 < 64);
     si->c.nats_lo = si->c.nats_lo & ~(uint64)0xf0 | (si->c.nats_lo >> (M2N_SAVED_R4-4)) & (uint64)0xf0;
 
-    // IP, SP, PFS, preds, m2nfl
+    // IP, SP, PFS, preds, unat, m2nfl
     si->c.p_eip    =  si->c.p_gr[M2N_SAVED_RETURN_ADDRESS];
     si->c.sp       = *si->c.p_gr[M2N_SAVED_SP];
     si->c.p_ar_pfs =  si->c.p_gr[M2N_SAVED_PFS];
     si->c.preds    = *si->c.p_gr[M2N_SAVED_PR];
+    si->c.ar_unat     = *si->c.p_gr[M2N_SAVED_UNAT];
     si->m2nfl      = m2n_get_previous_frame(si->m2nfl);
 }
 
@@ -167,18 +197,17 @@
 {
     uint64 pfs = *si->c.p_ar_pfs;
     unsigned sol = (unsigned)EXTRACT64_SOL(pfs);
-    assert(sol<=96); // ichebyki
-    // ichebyki assert(sol<96);
-    uint64* bsp = si->bsp;
 
-    // Direct computation, see IPF arch manual, volume 3, table 6.2.
-    uint64 b = (uint64)bsp;
-    uint64 s = sol<<3;
+    assert(sol<=96);
 
-    uint64 d2 = b-s;
-    uint64 d3 = 62*8-(b&0x1f8)+s;
-    if (d3>=63*8)
-        if (d3>=126*8)
+    uint64 bsp = (uint64)si->bsp;
+    uint64 local_area_size = sol << 3;
+
+    // Direct computation, see IPF arch manual, volume 3, table 6.2.
+    uint64 d2 = bsp - local_area_size;
+    uint64 d3 = 62*8 - (bsp & 0x1f8) + local_area_size;
+    if (d3 >= 63*8)
+        if (d3 >= 126*8)
             d2 -= 16;
         else
             d2 -= 8;
@@ -327,126 +356,27 @@
 //////////////////////////////////////////////////////////////////////////
 // Stack Iterator Interface
 
-StackIterator* si_create_from_native()
-{
-    hythread_suspend_disable();
-    // Allocate iterator
-    StackIterator* res = (StackIterator*)STD_MALLOC(sizeof(StackIterator));
-    assert(res);
-
-    // Setup last_legal_rsnat and extra_nats
-    uint64 t[2];
-    get_rnat_and_bsp(t);
-    si_init_nats(res, (uint64*)t[1], t[0]);
-
-    // Setup current frame
-    res->cci = NULL;
-    res->m2nfl = m2n_get_last_frame();
-    res->ip = 0;
-    res->c.p_eip = &res->ip;
-    hythread_suspend_enable();
-    return res;
-}
-
-#if defined (PLATFORM_POSIX)
 StackIterator* si_create_from_native(VM_thread* thread)
 {
-	hythread_suspend_disable();
     // Allocate iterator
     StackIterator* res = (StackIterator*)STD_MALLOC(sizeof(StackIterator));
     assert(res);
 
-    // Setup last_legal_rsnat and extra_nats
-    uint64 t[2];
-    get_rnat_and_bsp(t);
-    si_init_nats(res, (uint64*)t[1], t[0]);
-
     // Setup current frame
     res->cci = NULL;
     res->m2nfl = m2n_get_last_frame(thread);
     res->ip = 0;
     res->c.p_eip = &res->ip;
-    hythread_suspend_enable();
     return res;
+}
 
-#if 0	
-    // FIXME: code is outdated
-    assert(0);
-    abort();
-
-    // Allocate iterator
-    StackIterator* res = (StackIterator*)malloc(sizeof(StackIterator));
-    assert(res);
-
-    TRACE2("SIGNALLING", "stack iterator: create from native pthread_t " << ((pthread_t)GetCurrentThreadId()));
-
-    if (thread == p_TLS_vmthread) {
-        get_rnat_and_bspstore(thread->t);
-    } else {
-        assert(thread->suspend_request > 0);
-
-        TRACE2("SIGNALLING", "thread state before " << thread << " " <<
-            thread->t[0] << " " << thread->t[1] << " " << thread->suspended_state);
-        //if (thread->suspended_state == NOT_SUSPENDED) {
-        TRACE2("SIGNALLING", "sending SIGUSR2 to thread " << thread);
-        assert(thread->thread_id != 0);
-        
-        if (sem_init(&thread->suspend_self, 0, 0) != 0) {
-            DIE("sem_init() failed" <<  strerror(errno));
-        }
-        
-        thread->t[0] = NOT_VALID;
-        thread->t[1] = NOT_VALID;
-        
-        TRACE2("SIGNALLING", "BEFORE KILL thread = " << thread << " killing " << thread->thread_id);
-
-        if (pthread_kill(thread->thread_id, SIGUSR2) != 0) {
-            DIE("pthread_kill(" << thread->thread_id << ", SIGUSR2) failed :" << strerror(errno));
-        }
-        
-        si_reload_registers();
-        
-        TRACE2("SIGNALLING", "BEFORE WAIT thread = " << thread);
-        
-        int ret;
-        do {
-            ret = sem_wait(&thread->suspend_self);
-            TRACE2("SIGNALLING", "sem_wait " << (&thread->suspend_self) <<
-                " exited, errno = " << errno);
-        } while((ret != 0) && (errno == EINTR));
-        
-        TRACE2("SIGNALLING", "AFTER WAIT thread = " << thread);
-        
-        sem_destroy(&thread->suspend_self);
-        assert(thread->suspended_state == SUSPENDED_IN_SIGNAL_HANDLER);
-        thread->suspended_state = NOT_SUSPENDED;
-        // assert(thread->t[0] != NOT_VALID);
-        // assert(thread->t[1] != NOT_VALID);
-    }
-    
-    TRACE2("SIGNALLING", "thread state after " << thread << " " << thread->t[0] << " " <<  thread->t[1] << " " << m2n_get_last_frame(thread));
-
-    TRACE2("SIGNALLING", "stack iterator: create from native, rnat, bsp/bspstore " << thread->t[0] << " " <<  thread->t[1]);
-
-    // Setup last_legal_rsnat and extra_nats
-    uint64 rnat = thread->t[0];
-    uint64* bsp = (uint64*)thread->t[1];
-
-    si_init_nats(res, bsp, rnat);
-
-    // Check that bsp covers everything
-    assert((uint64)m2n_get_last_frame(thread)+(M2N_NUMBER_LOCALS+9)*8 <= (uint64)bsp);
-
-    // Setup current frame
-    res->cci = NULL;
-    res->m2nfl = m2n_get_last_frame(thread);
-    res->ip = 0;
-    res->c.p_eip = &res->ip;
-
-    return res;
-#endif
+StackIterator* si_create_from_native()
+{
+    return si_create_from_native(p_TLS_vmthread);
 }
 
+/*
+#if defined (PLATFORM_POSIX)
 #elif defined (PLATFORM_NT)
 
 // Get the bspstore and rnat values of another thread from the OS.
@@ -488,6 +418,7 @@
 #else
 #error Stack iterator is not implemented for the given platform
 #endif
+*/
 
 // On IPF stack iterators must be created from threads (suspended) in native code.
 // We do not support threads suspended in managed code yet.

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/exceptions_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/exceptions_ipf.cpp?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/exceptions_ipf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/exceptions_ipf.cpp Tue Jul 31 06:36:49 2007
@@ -72,7 +72,7 @@
     emitter.ipf_mov(out_arg0+1,  IN_REG1);
     emitter.ipf_mov(out_arg0+2,  0);
     emitter.ipf_mov(out_arg0+3,  0);
-    emit_call_with_gp(emitter, (void **)exn_athrow, 5);
+    emit_call_with_gp(emitter, (void **)exn_athrow, true, 5);
 } //gen_vm_rt_athrow_internal_compactor
 
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp Tue Jul 31 06:36:49 2007
@@ -222,7 +222,7 @@
         emitter.ipf_mov(out_arg0 + arg, IN_REG0 + arg);
     }
 
-    emit_call_with_gp(emitter, func);
+    emit_call_with_gp(emitter, func, true);
 
     // 20030512 If compressing references, translate a NULL result to a managed null (heap_base).
     if (translate_returned_ref) {
@@ -320,7 +320,7 @@
     emitter.ipf_mov(out0+0, IN_REG0);
     emitter.ipf_mov(out0+1, IN_REG1);
     emitter.ipf_adds(out0+2, (int)offset_gc_local, THREAD_PTR_REG);
-    emit_call_with_gp(emitter, (void **)p_update_allocation_stats);
+    emit_call_with_gp(emitter, (void **)p_update_allocation_stats, false);
     emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
     enforce_calling_conventions(&emitter);
 #endif // VM_STATS
@@ -371,7 +371,7 @@
         emitter.ipf_mov(out0+0, IN_REG0);
         emitter.ipf_mov(out0+1, IN_REG1);
         emitter.ipf_adds(out0+2, (int)offset_gc_local, THREAD_PTR_REG);
-        emit_call_with_gp(emitter, fast_obj_alloc_proc);
+        emit_call_with_gp(emitter, fast_obj_alloc_proc, false);
 
         // If the fast allocation procedure returned a non-NULL result then return, else fall through to the slow allocation path.
         emitter.ipf_cmp(icmp_eq, cmp_none, SCRATCH_PRED_REG, SCRATCH_PRED_REG2, 0, RETURN_VALUE_REG);
@@ -387,7 +387,7 @@
     emitter.ipf_mov(out_arg0+0, IN_REG0);
     emitter.ipf_mov(out_arg0+1, IN_REG1);
     emitter.ipf_adds(out_arg0+2, (int)offset_gc_local, THREAD_PTR_REG);
-    emit_call_with_gp(emitter, slow_obj_alloc_proc);
+    emit_call_with_gp(emitter, slow_obj_alloc_proc, true);
 
     // pop m2n frame and return
     m2n_gen_pop_m2n(&emitter, false, MPR_Gr);
@@ -416,7 +416,7 @@
         emitter.ipf_mov(out0+0, IN_REG0);
         emitter.ipf_mov(out0+1, IN_REG1);
         emitter.ipf_adds(out0+2, (int)offset_gc_local, THREAD_PTR_REG);
-        emit_call_with_gp(emitter, (void **)p_vm_new_vector_update_stats);
+        emit_call_with_gp(emitter, (void **)p_vm_new_vector_update_stats, false);
         emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
         enforce_calling_conventions(&emitter);
     }
@@ -434,7 +434,7 @@
         emitter.ipf_mov(out0, IN_REG0);
         emitter.ipf_mov(out0+1, IN_REG1);
         emitter.ipf_adds(out0+2, (int)offset_gc_local, THREAD_PTR_REG);
-        emit_call_with_gp(emitter, fast_obj_alloc_proc);
+        emit_call_with_gp(emitter, fast_obj_alloc_proc, false);
 
         // If the fast allocation procedure returned a non-NULL result then return, else fall through to the slow allocation path.
         emitter.ipf_cmp(icmp_eq, cmp_none, SCRATCH_PRED_REG, SCRATCH_PRED_REG2, 0, RETURN_VALUE_REG);
@@ -449,7 +449,7 @@
     emitter.ipf_mov(out_arg0+0, IN_REG0);
     emitter.ipf_mov(out_arg0+1, IN_REG1);
     emitter.ipf_adds(out_arg0+2, (int)offset_gc_local, THREAD_PTR_REG);
-    emit_call_with_gp(emitter, slow_obj_alloc_proc);
+    emit_call_with_gp(emitter, slow_obj_alloc_proc, true);
 
     // pop m2n frame and return
     m2n_gen_pop_m2n(&emitter, false, MPR_Gr);
@@ -761,7 +761,7 @@
     emitter.ipf_add(sc1, sc2, sc3);
     emitter.ipf_ld(int_mem_size_8, mem_ld_none, mem_none, out0+0, sc1);
     emitter.ipf_mov(out0+1, super_class);
-    emit_call_with_gp(emitter, (void **)p_class_is_subtype);
+    emit_call_with_gp(emitter, (void **)p_class_is_subtype, false);
     emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
 
     if (is_instanceof)
@@ -793,7 +793,7 @@
         emitter.ipf_mov(out0+i, IN_REG0+i);
     }
 
-    emit_call_with_gp(emitter, function);
+    emit_call_with_gp(emitter, function, false);
 
     emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
     enforce_calling_conventions(&emitter);
@@ -828,7 +828,7 @@
     emitter.ipf_mov(out0+0, IN_REG0);
     emitter.ipf_mov(out0+1, IN_REG1);
     emitter.ipf_mov(out0+2, IN_REG2);
-    emit_call_with_gp(emitter, (void **)p_vm_rt_aastore);
+    emit_call_with_gp(emitter, (void **)p_vm_rt_aastore, false);
 
     // Restore pfs, b0, and gp
     emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
@@ -1105,7 +1105,7 @@
 
     Boolean (*p_is_class_initialized)(Class *clss);
     p_is_class_initialized = is_class_initialized;
-    emit_call_with_gp(emitter, (void**)p_is_class_initialized);
+    emit_call_with_gp(emitter, (void**)p_is_class_initialized, false);
 
     emitter.ipf_cmp(icmp_ne, cmp_none, SCRATCH_PRED_REG, SCRATCH_PRED_REG2, RETURN_VALUE_REG, SCRATCH_GENERAL_REG3);
     emitter.ipf_brret(br_many, br_sptk, br_none, BRANCH_RETURN_LINK_REG, SCRATCH_PRED_REG);
@@ -1115,7 +1115,7 @@
     emitter.ipf_mov(out_arg0+0, IN_REG0);
     void (*p_class_initialize)(Class *clss);
     p_class_initialize = vm_rt_class_initialize;
-    emit_call_with_gp(emitter, (void **)p_class_initialize);
+    emit_call_with_gp(emitter, (void **)p_class_initialize, true);
     // pop m2n frame and return
     m2n_gen_pop_m2n(&emitter, false, MPR_None);
     enforce_calling_conventions(&emitter);
@@ -1364,7 +1364,7 @@
         // Call struct_Class_to_java_lang_Class() to convert the struct Class* argument to a java_lang_Class reference. 
         int out_arg0 = m2n_gen_push_m2n(&emitter, 0, FRAME_UNKNOWN, false, 0, 0, 1);
         emitter.ipf_mov(out_arg0, IN_REG0);
-        emit_call_with_gp(emitter, (void **)p_struct_Class_to_java_lang_Class);
+        emit_call_with_gp(emitter, (void **)p_struct_Class_to_java_lang_Class, true);
         m2n_gen_pop_m2n(&emitter, false, MPR_Gr);
         enforce_calling_conventions(&emitter);
 
@@ -1376,7 +1376,7 @@
         // Call struct_Class_to_java_lang_Class() to convert the struct Class* argument to a java_lang_Class reference. 
         int out_arg0 = m2n_gen_push_m2n(&emitter, 0, FRAME_UNKNOWN, false, 0, 0, 1);
         emitter.ipf_mov(out_arg0, IN_REG0);
-        emit_call_with_gp(emitter, (void **)p_struct_Class_to_java_lang_Class);
+        emit_call_with_gp(emitter, (void **)p_struct_Class_to_java_lang_Class, true);
         m2n_gen_pop_m2n(&emitter, false, MPR_Gr);
         enforce_calling_conventions(&emitter);
 
@@ -1522,7 +1522,7 @@
         out0, save_pfs, save_b0, save_gp);
 
     emitter.ipf_mov(out0, IN_REG0);
-    emit_call_with_gp(emitter, (void **)p_generic_hashcode);
+    emit_call_with_gp(emitter, (void **)p_generic_hashcode, false);
 
     // Restore pfs, b0, and gp
     emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
@@ -1549,7 +1549,7 @@
     emitter.ipf_mov(out0+3, IN_REG3);
     emitter.ipf_mov(out0+4, IN_REG4);
     
-    emit_call_with_gp(emitter, (void **)p_array_copy);
+    emit_call_with_gp(emitter, (void **)p_array_copy, false);
 
     // Restore pfs, b0, and gp
     emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
@@ -1572,7 +1572,7 @@
         (void **)func,
         out0, save_pfs, save_b0, save_gp);
 
-    emit_call_with_gp(emitter, (void **)func);
+    emit_call_with_gp(emitter, (void **)func, false);
 
     // Restore pfs, b0, and gp
     emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
@@ -1647,7 +1647,7 @@
     emitter.ipf_mov(out0+5, IN_REG4);
 
     int (*func)(JNIEnv*, Java_java_io_FileInputStream*, int, Vector_Handle, int, int) = readinternal_override;
-    emit_call_with_gp(emitter, (void **)func);
+    emit_call_with_gp(emitter, (void **)func, false);
     
     // Restore pfs, b0, and gp
     emitter.ipf_mov(GP_REG, save_gp);
@@ -2186,7 +2186,7 @@
     emitter.ipf_adds(out0+0, first_element_offset, sc2);
     emitter.ipf_adds(out0+1, first_element_offset, sc1);
     emitter.ipf_add(out0+2, length, length);
-    emit_call_with_gp(emitter, (void **)p_memmove);
+    emit_call_with_gp(emitter, (void **)p_memmove, false);
 
     // Restore pfs, b0, and gp
     emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
@@ -2331,7 +2331,7 @@
     {
         emitter.ipf_mov(out0+i, IN_REG0+i);
     }
-    emit_call_with_gp(emitter, fptr);
+    emit_call_with_gp(emitter, fptr, false);
 
     // Restore pfs, b0, and gp
     emit_dealloc_for_single_call(emitter, save_pfs, save_b0, save_gp);
@@ -2530,7 +2530,7 @@
 
     // Call increment_helper_count. 
     emit_movl_compactor(emitter, out0, (uint64)f);
-    emit_call_with_gp(emitter, (void **)p_increment_helper_count);
+    emit_call_with_gp(emitter, (void **)p_increment_helper_count, false);
 
     // Restore fp args
     emitter.ipf_adds(SP_REG, 16, SP_REG);

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/stub_code_utils.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/stub_code_utils.cpp?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/stub_code_utils.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/stub_code_utils.cpp Tue Jul 31 06:36:49 2007
@@ -75,10 +75,11 @@
     emitter.ipf_mtbr(BRANCH_RETURN_LINK_REG, save_b0_reg, pred);
 }
 
-
+NativeCodePtr m2n_gen_flush_and_call();
 
 void emit_call_with_gp(Merced_Code_Emitter& emitter,
                        void **proc_ptr,
+                       bool flushrs,
                        int saved_gp_reg)
 {
     void *new_gp = proc_ptr[1];
@@ -94,7 +95,14 @@
 
     uint64 branch_target = (uint64)(*proc_ptr);
 
-    emitter.ipf_brl_call(br_many, br_sptk, br_none, BRANCH_RETURN_LINK_REG, branch_target);
+    emit_mov_imm_compactor(emitter, SCRATCH_GENERAL_REG, branch_target, 0);
+    if (flushrs) {
+        emitter.ipf_mtbr(BRANCH_CALL_REG, SCRATCH_GENERAL_REG);
+        emit_mov_imm_compactor(emitter, SCRATCH_GENERAL_REG, (uint64)m2n_gen_flush_and_call(), 0);
+    }
+    emitter.ipf_mtbr(SCRATCH_BRANCH_REG, SCRATCH_GENERAL_REG);
+    emitter.ipf_bricall(br_few, br_sptk, br_none, BRANCH_RETURN_LINK_REG, SCRATCH_BRANCH_REG);
+
     // Restore the saved GP.
     if (new_gp != vm_gp && saved_gp_reg != 0)
         emitter.ipf_mov(GP_REG, saved_gp_reg);
@@ -102,7 +110,7 @@
 
 
 void emit_branch_with_gp(Merced_Code_Emitter& emitter,
-             void **proc_ptr)
+                         void **proc_ptr)
 {
     void *new_gp = proc_ptr[1];
     void *vm_gp = get_vm_gp_value();
@@ -115,7 +123,7 @@
 
     uint64 branch_target = (uint64)(*proc_ptr);
 
-    emit_movl_compactor(emitter, SCRATCH_GENERAL_REG, branch_target, 0);
+    emit_mov_imm_compactor(emitter, SCRATCH_GENERAL_REG, branch_target, 0);
     emitter.ipf_mtbr(SCRATCH_BRANCH_REG, SCRATCH_GENERAL_REG);
     emitter.ipf_bri(br_cond, br_few, br_sptk, br_none, SCRATCH_BRANCH_REG);
 
@@ -241,7 +249,7 @@
     emit_movl_compactor(emitter, out0, (uint64) msg);
     emitter.ipf_mov(out0+1, print_reg);
     // call a helper function
-    emit_call_with_gp(emitter, (void **) print_helper);
+    emit_call_with_gp(emitter, (void **) print_helper, false);
 
     emitter.ipf_adds(SP_REG, 16, SP_REG);
     // restore the scratch regs

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/Code_Emitter.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/Code_Emitter.h?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/Code_Emitter.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/Code_Emitter.h Tue Jul 31 06:36:49 2007
@@ -331,6 +331,10 @@
       { encoder->ipf_movl(dest, upper_32, lower_32, pred);
         _gen_an_IR_1i_0(curr_bc_addr, ST_il, pred, dest/**/); }
 
+    void ipf_movi64 (unsigned dest, uint64 imm64, unsigned pred=0)
+     { encoder->ipf_movi64(dest, imm64, pred);
+        _gen_an_IR_1i_0(curr_bc_addr, ST_il, pred, dest/**/); }
+
      void ipf_brl_call(Branch_Prefetch_Hint ph, Branch_Whether_Hint wh, Branch_Dealloc_Hint dh, unsigned b1, uint64 imm64, unsigned pred=0)
      {
          encoder->ipf_brl_call(ph, wh, dh, b1, imm64, pred);

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/stub_code_utils.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/stub_code_utils.h?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/stub_code_utils.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/stub_code_utils.h Tue Jul 31 06:36:49 2007
@@ -68,13 +68,14 @@
 // If saved_gp_reg is not specified, then gp is neither saved nor restored.
 void emit_call_with_gp(Merced_Code_Emitter& emitter,
                        void **proc_ptr,
+                       bool flushrs,
                        int saved_gp_reg = 0);
 
 // Emit a branch instruction.  Before the branch, the gp is set to the
 // value specified in the function pointer.
 // This function is normally used to implement tail calls.
 void emit_branch_with_gp(Merced_Code_Emitter& emitter,
-             void **proc_ptr);
+                         void **proc_ptr);
 
 
 void emit_movl_compactor(Merced_Code_Emitter& emitter, unsigned dst_reg, uint64 u64_value, unsigned pred=0);

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/vm_ipf.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/vm_ipf.h?view=diff&rev=561327&r1=561326&r2=561327
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/vm_ipf.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/include/vm_ipf.h Tue Jul 31 06:36:49 2007
@@ -39,6 +39,7 @@
 #define SCRATCH_PRED_REG9      14
 #define SCRATCH_PRED_REG10     15
 #define SCRATCH_BRANCH_REG      6
+#define SCRATCH_BRANCH_REG2     7
 #define BRANCH_RETURN_LINK_REG  0
 #define GP_REG                  1
 #define RETURN_VALUE_REG        8
@@ -60,12 +61,16 @@
 #define SCRATCH_GENERAL_REG16  29
 #define SCRATCH_GENERAL_REG17  30
 #define SCRATCH_GENERAL_REG18  31
+#define PRESERV_GENERAL_REG1    5
+#define PRESERV_GENERAL_REG2    6
 #define SP_REG                 12
 #define FIRST_PRES_FP_REG      16
 #define LAST_PRES_FP_REG       31
 #define FIRST_FP_ARG_REG        8
 #define LAST_FP_ARG_REG        15
 
+// br2 is used for keeping function address to be called.
+#define BRANCH_CALL_REG SCRATCH_BRANCH_REG2
 
 #define IN_REG0                32
 #define IN_REG1                33