harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject svn commit: r449244 - in /incubator/harmony/enhanced/drlvm/trunk/vm: jitrino/src/jet/ port/src/encoder/ia32_em64t/ vmcore/include/ vmcore/src/jvmti/
Date Sat, 23 Sep 2006 13:53:33 GMT
Author: geirm
Date: Sat Sep 23 06:53:32 2006
New Revision: 449244

URL: http://svn.apache.org/viewvc?view=rev&rev=449244
Log:
HARMONY-1550

The patch introduces the following changes mainly in Jitrino.JET and encoder/decoder routines:

JVMTI SingleStep support improvements in Jitrino.JET

To simplify the JVMTI's SingleStep implementation, Jitrino.JET
ensures that every bytecode instruction has its own separate
address (adds NOP for those that do not produce any native code).


JVMTI PopFrame support in Jitrino.JET

In order to support JVMTI's PopFrame, the compiled method now gets
a special prolog that allows to restore full registers context (including
scraptch registers) in JIT_unwind_stack_frame().


Improved disassembler/decoder for JVMTI

In order to suport SingleStep the InstructionDisaasembler now decodes fully
(including arguments) indirect call and jump instructions.
        Instruction disassembler improved to parse indirect call/jump instructions 

Ubuntu 6 - smoke, c-unit


Modified:
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_meth.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/mib.h
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt_ia32.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/sframe.h
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/trace.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h
    incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_dasm.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_dasm.cpp

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_meth.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_meth.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_meth.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_meth.cpp Sat Sep 23 06:53:32 2006
@@ -68,8 +68,9 @@
     //
     // Debugging things
     //
-    
-    // Ensure stack is aligned properly
+
+    // Ensure stack is aligned properly - for _ALIGN16 only here.
+    // _ALIGN_HALF16 is handled below.
     if (is_set(DBG_CHECK_STACK) && (m_ci.cc() & CCONV_STACK_ALIGN16)){
         alu(alu_test, sp, 0xF);
         unsigned br_off = br(eq, 0, 0);
@@ -132,6 +133,15 @@
         AR ar = valloc(i32);
         ld4(ar, sp, frameSize-i*PAGE_SIZE);
     }
+    // When requested, store the whole context (==including scratch registers)
+    // - normally for JVMTI PopFrame support.
+    // Scratch registers get stored separately from the callee-save:
+    // The callee-save registers are stored into spill area, but we can't
+    // save scratch regs there - this area is already used to temporary
+    // save scratch regs during method calls, etc (see gen_vm_call_restore).
+    // Thus, we dedicate a separate place.
+    const bool storeWholeContext =
+        m_infoBlock.get_compile_params().exe_restore_context_after_unwind;
 #ifdef _DEBUG
     // Fill the whole stack frame with a special value
     // -1 to avoid erasing retAddr
@@ -142,6 +152,14 @@
     AR ridx = valloc(i32);
     runlock(ar);
     Opnd idx(i32, ridx);
+    //
+    // When filling up the frame, the regs context is destroyed - preserve
+    // it.
+    if (storeWholeContext) {
+        push(fill);
+        push(idx);
+    }
+    //
     mov(fill, 0xDEADBEEF);
     mov(idx, num_words);
     unsigned _loop = ipoff();
@@ -149,7 +167,12 @@
     alu(alu_sub, idx, 1);
     unsigned br_off = br(nz, 0, 0);
     patch(br_off, ip(_loop));
-#endif    
+    if (storeWholeContext) {
+        pop(idx);
+        pop(fill);
+    }
+#endif
+
     // save callee-save registers. If frame size is less than 1 page, 
     // the page was not touched yet, and the SOE may happen here
     for (unsigned i=0; i<ar_num; i++) {
@@ -165,6 +188,25 @@
         m_infoBlock.saved(ar);
     }
     
+    if (storeWholeContext) {
+        // For JVMTI's PopFrame we store all scratch registers to a special
+        // place.
+        if (is_set(DBG_TRACE_CG)) { dbg(";;>jvmti.save.all.regs\n"); }
+        for (unsigned i=0; i<ar_num; i++) {
+            AR ar = _ar(i);
+            if (is_callee_save(ar) || ar==sp) {
+                continue;
+            }
+            // use maximum possible size to store the register
+            jtype jt = is_f(ar) ? dbl64 : jobj;
+            // Here, always use sp-based addressing - bp frame is not ready
+            // yet.
+            st(jt, ar, sp, frameSize+m_stack.jvmti_register_spill_offset(ar));
+        }
+        if (is_set(DBG_TRACE_CG)) { dbg(";;>~jvmti.save.all.regs\n"); }
+    }
+
+
     // ok, if we pass to this point at runtime, then we have enough stack
     // and we stored all needed registers, so in case of unwind_stack() 
     // we'll simply restore registers from the stack.
@@ -213,6 +255,7 @@
             ++local;
         }
     }
+
     // Now, process input args: 
     //  - set GC maps for objects came as input args, 
     //  - move input args into the slots in the local stack frame (for some
@@ -230,13 +273,26 @@
                 // .. callee-saved GP regs or ..
                 regs_map |= 1<<ar_idx(m_ra[local]);
             }
-            else if (vis_arg(local)) {
-                // .. local vars that are kept on the input slots  or ..
-                assert(m_ci.reg(i) == ar_x);
+            else if (vis_arg(local) || storeWholeContext) {
+                // .. local vars that are kept on the input slots or
+                // when we need to keep input args valid during enumeration
+                // (for example for JVMTI PopFrame needs) ...
+                assert(m_ci.reg(i) == ar_x || storeWholeContext);
                 assert(0 == m_ci.off(i)%STACK_SLOT_SIZE);
                 int inVal = m_ci.off(i)/STACK_SLOT_SIZE;
-                args_map[word_no(inVal)] = 
+                // TODO: With storeWholeContext it only works with
+                // stack-based parameters. On Intel64 with register-based
+                // calling convention, need to track the registers that are
+                // spilled separately from spill area (see above how the
+                // storeWholeContext is processed).
+                args_map[word_no(inVal)] =
                             args_map[word_no(inVal)] | (1 <<bit_no(inVal));
+                if (storeWholeContext) {
+                    // .. a 'regular' GC map for locals - must report
+                    // together with input args in case of storeWholeContext
+                    locals_map[word_no(local)] =
+                                locals_map[word_no(local)] | (1 <<bit_no(local));
+                }
             }
             else {
                 // .. a 'regular' GC map for locals.
@@ -247,8 +303,8 @@
         jtype jtm = jtmov(jt);
         // as_type() => Convert narrow types (<i32) to i32.
         Opnd arg = m_ci.get(i, sp_offset).as_type(jt);
-        
-        // If we need to store 'this' for special reporting (ie. 
+
+        // If we need to store 'this' for special reporting (i.e.
         // monitor_exit or for stack trace) - store it.
         if (i==0 && is_set(JMF_REPORT_THIS)) {
             if (is_set(DBG_TRACE_CG)) {dbg(";;>copy thiz\n");}

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp Sat Sep 23 06:53:32 2006
@@ -35,6 +35,7 @@
 {
     unsigned start = is_f(jt) ? ar_idx(fr0) : ar_idx(gr0);
     unsigned count = is_f(jt) ? fr_num : gr_num;
+    unsigned highest_index = start+count-1;
     //
     // We are going to allocate a temporary register - we do several tries 
     // to reach the following goals:
@@ -44,7 +45,7 @@
     // Try to find the first SCRATCH (non callee-save) register
     
     AR last_used = rlast(jt);
-    for (unsigned i=ar_idx(last_used)+1; i<start+count; i++) {
+    for (unsigned i=ar_idx(last_used)+1; i<highest_index; i++) {
         AR ar = _ar(i);
         if (is_callee_save(ar) || ar == sp || ar == m_base) continue;
         if (rrefs(ar) == 0 && rlocks(ar) == 0 && !m_global_rusage.test(i)) {
@@ -54,7 +55,7 @@
         }
     }
     // No free scratch registers above the 'last used'. Try any scratch reg.
-    for (unsigned i=start; i<start+count; i++) {
+    for (unsigned i=start; i<highest_index; i++) {
         AR ar = _ar(i);
         if (is_callee_save(ar) || ar == sp || ar == m_base) continue;
         if (rrefs(ar) == 0 && rlocks(ar) == 0 && !m_global_rusage.test(i)) {
@@ -69,7 +70,7 @@
     //
     // not now. currently, only scratch regs are used as temporaries,
     // and callee-save are used as global regs. may revisit it.
-    for (unsigned i=start; i<start+count; i++) {
+    for (unsigned i=start; i<highest_index; i++) {
         AR ar = _ar(i);
         if (ar == sp || ar == m_base) continue;
         if (m_bbstate->regs[i].refs == 0 && m_bbstate->regs[i].locks==0 && 
@@ -87,7 +88,7 @@
     // try to locate first non locked scratch register with min number of 
     // refs
     unsigned min_ref = NOTHING, min_idx = NOTHING;
-    for (unsigned i=start; i<start+count; i++) {
+    for (unsigned i=start; i<highest_index; i++) {
         AR ar = _ar(i);
         if (is_callee_save(ar) || ar == sp || ar == m_base) continue;
         if (min_ref > rrefs(ar) && rlocks(ar)==0 && !m_global_rusage.test(i)) {
@@ -118,7 +119,7 @@
     start = !is_f(jt) ? ar_idx(fr0) : ar_idx(gr0);
     count = !is_f(jt) ? fr_num : gr_num;
     AR otherKind = ar_x;
-    for (unsigned i=start; i<start+count; i++) {
+    for (unsigned i=start; i<highest_index; i++) {
         AR ar = _ar(i);
         if (is_callee_save(ar) || ar == sp || ar == m_base) continue;
         if (m_bbstate->regs[i].refs == 0 && !m_bbstate->regs[i].locked) {
@@ -512,6 +513,12 @@
 
 bool CodeGen::vis_arg(unsigned local_idx) const
 {
+    // Under JVMTI - never use input args as locals. Doing this keeps us
+    // away from problems with rt_{get|set}_local_var which does not handle
+    // input args.
+    if (g_jvmtiMode) {
+        return false;
+    }
     if (local_idx >= m_argSlots)return false;
     int argid = m_argids[local_idx];
     if(argid == -1)             return false;

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.cpp Sat Sep 23 06:53:32 2006
@@ -32,6 +32,8 @@
 #include "jit_intf.h"
 
 #include "../shared/mkernel.h"
+//FIXME: needed for NOPs fix only, to be removed
+#include "enc_ia32.h"
 
 #include "jet.h"
 
@@ -83,6 +85,14 @@
                              const OpenMethodExecutionParams& params)
 {
     compilation_params = params;
+
+    /*
+    compilation_params.exe_restore_context_after_unwind = true;
+    compilation_params.exe_provide_access_to_this = true;
+    //vm_properties_set_value("vm.jvmti.enabled", "true");
+    g_jvmtiMode = true;
+    */
+
     m_compileHandle = ch;
     MethInfo::init(method);
 
@@ -313,11 +323,16 @@
         compile_flags |= JMF_REPORT_THIS;
     }
 
+    // Always report 'this' if we're asked about this explicitly
+    if (compilation_params.exe_provide_access_to_this && !meth_is_static()) {
+        compile_flags |= JMF_REPORT_THIS;
+    }
+
     m_infoBlock.init(bc_size, max_stack, num_locals, num_input_slots, 
                      compile_flags);
-
+    m_infoBlock.set_compile_params(compilation_params);
     bool eh_ok = comp_resolve_ehandlers();    
-    
+
     if (!eh_ok) {
         // At least on of the exception handlers classes was not resolved:
         // unable to resolve class of Exception => will be unable to register
@@ -638,7 +653,6 @@
             ji.id = id++;
         }
     }
-
 }
 
 void Compiler::comp_alloc_regs(void)
@@ -981,6 +995,14 @@
         vcheck();
 #endif
         unsigned inst_code_end = m_codeStream.ipoff();
+        if (g_jvmtiMode && (inst_code_end == inst_code_dump_start)) {
+            // XXX, FIXME: quick fix for JVMTI testing:
+            // if bytecode did not produce any native code, then add a fake
+            // NOP, so every BC instruction has its own separate native 
+            // address
+            ip(EncoderBase::nops(ip(), 1));
+            inst_code_end = m_codeStream.ipoff();
+        }
         unsigned inst_code_dump_size = inst_code_end - inst_code_dump_start;
 
         unsigned bb_off = inst_code_start - bb_ip_start;
@@ -1345,7 +1367,7 @@
     VTBL_BASE = (const char*)vm_get_vtable_base();
     NULL_REF  = g_refs_squeeze ? OBJ_BASE : NULL;
 
-    g_jvmtiMode =  vm_get_property_value_boolean("vm.jvmti.enabled", false);
+    g_jvmtiMode = vm_get_property_value_boolean("vm.jvmti.enabled", false);
     
     rt_helper_monitor_enter = 
                 (char*)vm_get_rt_support_addr(VM_RT_MONITOR_ENTER);

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h Sat Sep 23 06:53:32 2006
@@ -309,8 +309,6 @@
     fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15, 
 #endif
     //
-    ar_num, ar_total = ar_num,
-    //
     // Specials
     //
 #ifdef _EM64T_
@@ -323,15 +321,16 @@
     //
     //
 #ifdef _EM64T_
-    gr_num=15,      // not including sp
-    gr_total = 16,  // including sp
+    gr_num=15,      /// not including sp
+    gr_total = 16,  /// including sp
     fr_num=16,
 #else
-    gr_num=7,       // not including sp
-    gr_total = 8,   // including sp
+    gr_num=7,       /// not including sp
+    gr_total = 8,   /// including sp
     fr_num=8,
 #endif
     fr_total=fr_num,
+    ar_total = fr_total + gr_total, ar_num = ar_total,
 };
 
 /**

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp Sat Sep 23 06:53:32 2006
@@ -69,7 +69,7 @@
 RegName devirt(AR ar, jtype jt)
 {
     RegName reg = RegName_Null;
-    if (ar != gr_x && ar!=ar_total) {
+    if (ar != gr_x) { // && ar!=ar_total) {
         //return RegName_Null;
         assert(COUNTOF(reg_map) == gr_total);
         unsigned idx = type_idx(ar);

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/jet.cpp Sat Sep 23 06:53:32 2006
@@ -481,25 +481,13 @@
 
 OpenMethodExecutionParams get_exe_capabilities()
 {
-    static const OpenMethodExecutionParams supported = {
-        true,  // exe_notify_method_entry
-        true,  // exe_notify_method_exit
-        
-        true, // exe_notify_field_access
-        true, // exe_notify_field_modification 
-        false, // exe_notify_exception_throw
-        false, // exe_notify_exception_catch
-        false, // exe_notify_monitor_enter
-        false, // exe_notify_monitor_exit
-        false, // exe_notify_contended_monitor_enter
-        false, // exe_notify_contended_monitor_exit
-        false, // exe_do_method_inlining
-        
-        true,  // exe_do_code_mapping
-        true,  // exe_do_local_var_mapping
-        
-        false, // exe_insert_write_barriers
-    };
+    OpenMethodExecutionParams supported = {0};
+    supported.exe_notify_method_entry = true;
+    supported.exe_notify_method_exit = true;
+    supported.exe_do_code_mapping = true;
+    supported.exe_do_local_var_mapping = true;
+    supported.exe_restore_context_after_unwind = true;
+    supported.exe_provide_access_to_this = true;
     return supported;
 }
 
@@ -543,121 +531,204 @@
 using std::map;
 #include "../main/Log.h"
 #include "../main/LogStream.h"
+#include "../main/PMF.h"
+
 //
 // PMF and JitInstanceContext things uses various stuff from Jitrino::.
 // Define it here to allow standalone .jet build.
 // 
+
+
 namespace Jitrino {
-void crash(const char* fmt, ...)
-{
-    va_list valist;
-    va_start(valist, fmt);
-    vprintf(fmt, valist);
-    exit(0);
-}
-//
-// JITInstanceContex stub
-//
 typedef map<JIT_Handle, JITInstanceContext*> JITCTXLIST;
 static JITCTXLIST jitContextList;
-
-JITInstanceContext* Jitrino::getJITInstanceContext(JIT_Handle jitHandle)
-{
-    assert(jitContextList.find(jitHandle) != jitContextList.end());
-    return jitContextList[jitHandle];
-}
+static MemoryManager g_mm(4026, "global MM");
 
 //
 // CompilationContext stub
 //
-
-class CompilationContext {
-public:
-    CompilationContext(JIT_Handle jitHandle, Method_Handle meth);
-    ~CompilationContext();
-    static CompilationContext* getCurrentContext(void);
-    JITInstanceContext* getCurrentJITContext(void)
-    {
-        return jitContext;
-    } 
-    //
-    JITInstanceContext*     jitContext;
-};
-
 static TlsStack<CompilationContext> ccTls;
-static MemoryManager g_mm(4026, "global MM");
 
 CompilationContext* CompilationContext::getCurrentContext() {
     CompilationContext* currentCC = ccTls.get();
     return currentCC;
 }
 
-CompilationContext::CompilationContext(JIT_Handle jitHandle, 
-                                       Method_Handle meth)
-{
-    jitContext = Jitrino::getJITInstanceContext(jitHandle);
-    ccTls.push(this);
-    Class_Handle klass = method_get_class(meth);
-    const char* kname = class_get_name(klass);
-    const char* mname = method_get_name(meth);
-    const char* msig = method_get_descriptor(meth);
-    LogStreams::current(jitContext).beginMethod(kname, mname, msig);
+CompilationContext::CompilationContext(MemoryManager& _mm,
+                                       CompilationInterface * ci,
+                                       JITInstanceContext * jtx) : mm(_mm)
+{
+    compilationInterface = ci;
+    compilationFailed = false;
+    compilationFinished = false;
+
+    jitContext = jtx;
+    hirm = NULL;
+    lirm = NULL;
+    currentSessionAction = NULL;
+    currentSessionNum = 0;
+    currentLogStreams = NULL;
+    pipeline = NULL;
+    //
+    //
+    ccTls.push((CompilationContext*)this);
 }
 
 CompilationContext::~CompilationContext()
 {
-    LogStreams::current(jitContext).endMethod();
-#ifdef _DEBUG
-    CompilationContext* last = ccTls.pop();
-    assert(this == last);
-#else 
+    assert(this == ccTls.get());
     ccTls.pop();
-#endif
 }
 
-//
-// LogStream::current()
-//
-
-static size_t threadnb = 0;
+static int thread_nb = 0;
 
 struct TlsLogStreams {
+
+    int threadnb;
     MemoryManager mm;
-    LogStreams logstreams;
-    TlsLogStreams (PMF& pmf)   
-        :mm(0, "TlsLogStreams"), logstreams(mm, pmf, ++threadnb) {}
-    ~TlsLogStreams () 
-        {}
+
+    typedef std::pair<JITInstanceContext*, LogStreams*> Jit2Log;
+
+    typedef StlVector<Jit2Log> Jit2Logs;
+    Jit2Logs jit2logs;
+
+    TlsLogStreams ()
+        :threadnb(thread_nb), mm(0, "TlsLogStreams"), jit2logs(mm) {}
+
+    ~TlsLogStreams ();
 };
 
+
+TlsLogStreams::~TlsLogStreams ()
+{
+    Jit2Logs::iterator ptr = jit2logs.begin(),
+                       end = jit2logs.end();
+    for (; ptr != end; ++ptr)
+        ptr->second->~LogStreams();
+}
+
+
 static TlsStore<TlsLogStreams> tlslogstreams;
 
+
+/*
+    Because CompilationContext is a transient object (it created on start of compilation
+    and destroyed on end of compilation for every method), LogStreams table cannot reside
+    in it. Thread-local storage (TLS) is used to keep LogStreams.
+    On the other hand, different Jits can run on the same thread, so several LogStreams
+    have to be keept for single thread.
+    To optimize access, pointer to LogStreams is cached in CompilationContext.
+
+ */
 LogStreams& LogStreams::current(JITInstanceContext* jitContext) {
+
+    CompilationContext* ccp = CompilationContext::getCurrentContext();
+    LogStreams* cls = ccp->getCurrentLogs();
+    if (cls != 0)
+        return *cls;
+
+//  No cached pointer is available for this CompilationContext.
+//  Find TLS for this thread.
+
     TlsLogStreams* sp = tlslogstreams.get();
-    if (sp == NULL)
+    if (sp == 0)
     {   // new thread
-        if (jitContext == NULL) {
-            jitContext = 
-            CompilationContext::getCurrentContext()->getCurrentJITContext(); 
-        }
-        sp = new TlsLogStreams(jitContext->getPMF());
+        ++thread_nb;
+        sp = new TlsLogStreams();
         tlslogstreams.put(sp);
     }
-    return sp->logstreams;
+
+//  Find which Jit is running now.
+
+    if (jitContext == 0)
+        jitContext = ccp->getCurrentJITContext();
+
+//  Was LogStreams created for this Jit already?
+
+    TlsLogStreams::Jit2Logs::iterator ptr = sp->jit2logs.begin(),
+                                      end = sp->jit2logs.end();
+    for (; ptr != end; ++ptr)
+        if (ptr->first == jitContext) {
+        //  yes, it was - store pointer in the CompilationContext
+            ccp->setCurrentLogs(cls = ptr->second);
+            return *cls;
+        }
+
+//  This is the first logger usage by the running Jit in the current thread.
+//  Create LogStreams now.
+
+    cls = new (sp->mm) LogStreams(sp->mm, jitContext->getPMF(), sp->threadnb);
+    sp->jit2logs.push_back(TlsLogStreams::Jit2Log(jitContext, cls));
+    ccp->setCurrentLogs(cls);
+
+    return *cls;
+}
+
+
+LogStream& LogStream::log (SID sid, HPipeline* hp)
+{
+    if (hp == 0)
+        hp = CompilationContext::getCurrentContext()->getPipeline();
+    Str name = ((PMF::Pipeline*)hp)->name;
+    return LogStream::log(sid, name.ptr, name.count);
 }
 
 //
-// Fake XTimer
-void XTimer::initialize(bool) {}
+// JITInstanceContex stub
+//
+JITInstanceContext::JITInstanceContext(MemoryManager& _mm,
+                                       JIT_Handle _jitHandle,
+                                       const char* _jitName) : mm(_mm)
+{
+    jitHandle = _jitHandle;
+    jitName = _jitName;
+    pmf = new (mm) PMF(mm, *this);
+    profInterface = NULL;
+    useJet = true;
+}
+
+
+JITInstanceContext* JITInstanceContext::getContextForJIT(JIT_Handle jitHandle)
+{
+    assert(jitContextList.find(jitHandle) != jitContextList.end());
+    return jitContextList[jitHandle];
+}
+
+JITInstanceContext* Jitrino::getJITInstanceContext(JIT_Handle jitHandle)
+{
+    return JITInstanceContext::getContextForJIT(jitHandle);
+}
+
+
+//
+// Fake XTimer stuff
 double XTimer::getSeconds(void)const { return 0.0; }
+void SummTimes::add(char const *,double) {}
 
+//
+// Crash handler
+void crash(const char* fmt, ...)
+{
+    va_list valist;
+    va_start(valist, fmt);
+    vprintf(fmt, valist);
+    exit(0);
+}
 
 }; // ~namespace Jitrino
 
+//
+// Symbols from local 'Jitrino::'
 using Jitrino::JITInstanceContext;
 using Jitrino::MemoryManager;
 using Jitrino::jitContextList;
 using Jitrino::g_mm;
+//
+//
+using Jitrino::CompilationContext;
+using Jitrino::PMF;
+using Jitrino::HPipeline;
+using Jitrino::LogStreams;
 
 /**
  * @see setup
@@ -667,7 +738,7 @@
 {
     JITInstanceContext* jic = 
                 new(g_mm) JITInstanceContext(g_mm, jit, name);
-    assert(Jitrino::jitContextList.find(jit) == Jitrino::jitContextList.end());
+    assert(jitContextList.find(jit) == jitContextList.end());
     jitContextList[jit] = jic;
     jic->getPMF().init();
     Jitrino::Jet::setup(jit, name);
@@ -698,8 +769,10 @@
                               Method_Handle method,
                               JIT_Flags flags)
 {
-    Jitrino::CompilationContext ctx(jit, method);
-    return Jitrino::Jet::compile(jit, ch, method, flags);
+    //Jitrino::CompilationContext ctx(jit, method);
+    //return Jitrino::Jet::compile(jit, ch, method, flags);
+    assert(false); // Obsolete
+    return JIT_FAILURE;
 }
 
 extern "C" JITEXPORT 
@@ -708,8 +781,30 @@
                                           Method_Handle method, 
                                           OpenMethodExecutionParams params)
 {
-    Jitrino::CompilationContext ctx(jit, method);
-    return Jitrino::Jet::compile_with_params(jit, ch, method, params);
+    //Jitrino::CompilationContext ctx(jit, method);
+    MemoryManager memManager(1024, "JIT_compile_method.memManager");
+    JITInstanceContext* jitContext = Jitrino::Jitrino::getJITInstanceContext(jit);
+    assert(jitContext!= NULL);
+    //DrlVMCompilationInterface
+    //        compilationInterface(ch, method, jit, memManager, params, NULL);
+    Jitrino::CompilationInterface* pci = NULL;
+    CompilationContext cs(memManager, pci/*&compilationInterface*/, jitContext);
+    //compilationInterface.setCompilationContext(&cs);
+
+    static int method_seqnb = 0;
+    int current_nb = method_seqnb++;
+
+    Class_Handle klass = method_get_class(method);
+    const char* methodTypeName = class_get_name(klass);
+    const char* methodName = method_get_name(method);
+    const char* methodSig = method_get_descriptor(method);
+    PMF::Pipeline* pipep =
+        jitContext->getPMF().selectPipeline(methodTypeName, methodName, methodSig);
+    cs.setPipeline((HPipeline*)pipep);
+    LogStreams::current(jitContext).beginMethod(methodTypeName, methodName, methodSig, current_nb);
+    JIT_Result result = Jitrino::Jet::compile_with_params(jit, ch, method, params);
+    LogStreams::current(jitContext).endMethod();
+    return result;
 }
 
 /**

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/mib.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/mib.h?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/mib.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/mib.h Sat Sep 23 06:53:32 2006
@@ -27,6 +27,7 @@
 #define __MIB_H_INCLUDED__
 
 #include "enc.h"
+#include "jit_export.h"
 
 namespace Jitrino {
 namespace Jet {
@@ -269,6 +270,16 @@
     {
         return rt_header->code_start;
     }
+
+    void set_compile_params(const OpenMethodExecutionParams& compileParams)
+    {
+        rt_header->compileParams = compileParams;
+    }
+
+    OpenMethodExecutionParams get_compile_params(void) const
+    {
+        return rt_header->compileParams;
+    }
     
     /**
      * @brief Copies MethodInfoBlock's data into a buffer.
@@ -470,7 +481,7 @@
          *        in method's prolog (and thus need to be restored during
          *        unwinding).
          */
-        unsigned    saved_regs[words(ar_total)];
+        unsigned    saved_regs[words(ar_total+1)];
         /**
          * @brief Length of 'warm up code sequence'.
          *
@@ -486,6 +497,8 @@
          * Beyond this point, a regular unwinding procedure is performed.
          */
         unsigned    warmup_len;
+
+        OpenMethodExecutionParams compileParams;
     };
     /**
      * @brief Pointer to a temporary buffer. The buffer is allocated in 

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt.cpp Sat Sep 23 06:53:32 2006
@@ -224,10 +224,34 @@
         context->p_edi = (unsigned*)(sp_val + spill_off);
     }
 #endif
+    // When needed, restore the whole context including scratch registers
+    // (normally, under JVMTI for PopFrame functionality)
+    if (infoBlock.get_compile_params().exe_restore_context_after_unwind) {
+        for (unsigned i=0; i<ar_num; i++) {
+            AR ar = _ar(i);
+            if (is_callee_save(ar) || ar==sp) {
+                continue;
+            }
+            void *** preg = devirt(ar, context);
+            //FIXME: JVMTI-popframe // assert(preg && *preg);
+            // ^^ temporarily disabling the assert, will need to uncomment
+            // when VM also supports all the registers to restore
+            // Currently, XMM regs are not restored as there are no proper
+            // fields in JitFrameContext
+            if (preg && *preg) {
+                *preg = (void**)(sp_val+sframe.jvmti_register_spill_offset(ar));
+                if (infoBlock.get_flags() & DBG_TRACE_RT) {
+                    dbg_rt("\trt.JVMTI.unwind.%s.%s: [%p]=%p\n",
+                        Encoder::to_str(ar, false).c_str(),
+                        Encoder::to_str(ar, true).c_str(), *preg, **preg);
+                }
+            } // ~if (*preg)
+        }
+    }
 
     sp_val += STACK_SLOT_SIZE; // pop out retIP
     *psp = sp_val;
-    
+
     if (infoBlock.get_flags() & DBG_TRACE_RT) {
         void *** pip = devirt(gr_x, context);
         rt_trace("rt.unwind", method, infoBlock, &saveContextForLogs);

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt_ia32.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt_ia32.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt_ia32.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/rt_ia32.cpp Sat Sep 23 06:53:32 2006
@@ -72,7 +72,8 @@
     if (gr == ecx)    return (void***)&jfc->p_ecx;
     if (gr == edx)    return (void***)&jfc->p_edx;
 #endif
-    assert(false);
+    // May happen when XMM regs requested on IA-32/Intel64 - JitFrameContext
+    // currently does not have such fields
     return NULL;
 }
 

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/sframe.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/sframe.h?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/sframe.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/sframe.h Sat Sep 23 06:53:32 2006
@@ -289,11 +289,30 @@
     {
         return scratch() - STACK_SLOT_SIZE;
     }
+    //
+    // Static area for JVMTI needs
+    //
 
+    // An area to preserve all the registers for JVMTI's PopFrame
+    int jvmti_regs_spill_area(void) const
+    {
+        return dbg_scratch() - Encoder::get_all_regs_size();
+    }
+    int jvmti_register_spill_offset(AR ar) const
+    {
+        if (is_gr(ar)) {
+            return jvmti_regs_spill_area() + STACK_SLOT_SIZE*gr_idx(ar);
+        }
+        assert(is_fr(ar));
+        return jvmti_regs_spill_area() + STACK_SLOT_SIZE*gr_num + 8*fr_idx(ar);
+    }
+    // ~Static JVMTI
+    //
     int info_gc_regs(void) const
     {
         assert(words(gen_num_calle_save()) == 1);
-        return dbg_scratch() - sizeof(unsigned);
+        //return dbg_scratch() - sizeof(unsigned);
+        return jvmti_regs_spill_area();
     }
     
     /**

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/trace.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/trace.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/trace.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/trace.cpp Sat Sep 23 06:53:32 2006
@@ -484,9 +484,9 @@
     if (success) {
         unsigned size = method_get_code_block_size_jit(m_method, m_hjit);
         void * start = size ? method_get_code_block_addr_jit(m_method, m_hjit) : NULL;
-        
-        dbg("code.start=%p | code.end=%p | code.size=%d", 
-             start, (char*)start + size, size);    
+
+        dbg("code.begin=%p | code.end=%p | code.size=%d",
+             start, (char*)start + size, size);
     }
     else {
         dbg("[REJECTED:%s]", reason);

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp Sat Sep 23 06:53:32 2006
@@ -46,7 +46,7 @@
         if (b1 == 0x0F) {   // .... but may be a part of SIMD opcode
             return false;
         }
-        return true;
+        return false; //XXX - currently considered as part of opcode//true;
     }
     if (b0==0x67) { // address size prefix
         return true;
@@ -58,6 +58,8 @@
 unsigned DecoderBase::decode(const void * addr, Inst * pinst)
 {
     Inst tmp;
+
+    //assert( *(unsigned char*)addr != 0x66);
     
     const unsigned char * bytes = (unsigned char*)addr;
     // Check prefix first
@@ -108,9 +110,29 @@
     OpcodeByteKind kind = (OpcodeByteKind)(aux & OpcodeByteKind_KindMask);
     unsigned byte = (aux & OpcodeByteKind_OpcodeMask);
     unsigned data_byte = **pbuf;
+    EncoderBase::Operand& opnd = pinst->operands[pinst->argc];
+    const EncoderBase::OpndDesc& opndDesc = odesc.opnds[pinst->argc];
+    
     switch (kind) {
     case OpcodeByteKind_SlashR:
-        decodeModRM(odesc, pbuf, pinst);
+        //decodeModRM(odesc, pbuf, pinst);
+        {
+        const ModRM& modrm = *(ModRM*)*pbuf;
+        unsigned regIndex = odesc.opnds[0].kind == OpndKind_GPReg ? 0 : 1;
+        RegName reg = getRegName(OpndKind_GPReg, opndDesc.size, modrm.reg);
+        EncoderBase::Operand& regOpnd = pinst->operands[regIndex];
+        if (regIndex == 0) {
+            regOpnd = EncoderBase::Operand(reg);
+            ++pinst->argc;
+            decodeModRM(odesc, pbuf, pinst);
+        }
+        else {
+            decodeModRM(odesc, pbuf, pinst);
+            ++pinst->argc;
+            regOpnd = EncoderBase::Operand(reg);
+        }
+        ++pinst->argc;
+        }
         return true;
     case OpcodeByteKind_rb:
     case OpcodeByteKind_rw:
@@ -124,17 +146,24 @@
             return true;
         }
     case OpcodeByteKind_cb:
-        pinst->offset = *(char*)*pbuf;
+        {
+        char offset = *(char*)*pbuf;
         *pbuf += 1;
-        pinst->direct_addr = (void*)(pinst->offset + *pbuf);
+        opnd = EncoderBase::Operand(offset);
+        ++pinst->argc;
+        //pinst->direct_addr = (void*)(pinst->offset + *pbuf);
+        }
         return true;
     case OpcodeByteKind_cw:
         assert(false); // not an error, but not expected in current env
         break;
     case OpcodeByteKind_cd:
-        pinst->offset = *(int*)*pbuf;
+        {
+        int offset = *(int*)*pbuf;
         *pbuf += 4;
-        pinst->direct_addr = (void*)(pinst->offset + *pbuf);
+        opnd = EncoderBase::Operand(offset);
+        ++pinst->argc;
+        }
         return true;
     case OpcodeByteKind_SlashNum:
         {
@@ -143,16 +172,32 @@
             return false;
         }
         decodeModRM(odesc, pbuf, pinst);
+        ++pinst->argc;
         }
         return true;
     case OpcodeByteKind_ib:
+        {
+        char ival = *(char*)*pbuf;
+        opnd = EncoderBase::Operand(ival);
+        ++pinst->argc;
         *pbuf += 1;
+        }        
         return true;
     case OpcodeByteKind_iw:
+        {
+        short ival = *(short*)*pbuf;
+        opnd = EncoderBase::Operand(ival);
+        ++pinst->argc;
         *pbuf += 2;
+        }        
         return true;
     case OpcodeByteKind_id:
+        {
+        int ival = *(int*)*pbuf;
+        opnd = EncoderBase::Operand(ival);
+        ++pinst->argc;
         *pbuf += 4;
+        }        
         return true;
     case OpcodeByteKind_plus_i:
         {
@@ -212,10 +257,26 @@
 bool DecoderBase::decodeModRM(const EncoderBase::OpcodeDesc& odesc,
                               const unsigned char ** pbuf, Inst * pinst)
 {
+    EncoderBase::Operand& opnd = pinst->operands[pinst->argc];
+    const EncoderBase::OpndDesc& opndDesc = odesc.opnds[pinst->argc];
+    
+    //XXX debug ///assert(0x66 != *(*pbuf-2));
     const ModRM& modrm = *(ModRM*)*pbuf;
     *pbuf += 1;
+    
+    RegName reg = RegName_Null;
+    RegName base = RegName_Null;
+    RegName index = RegName_Null;
+    int disp = 0;
+    unsigned scale = 0; 
+    //XXX
+    scale=scale; base = base; index = index; disp = disp; reg = reg;
+
+    reg = getRegName(OpndKind_GPReg, OpndSize_32, modrm.reg);
     if (modrm.mod == 3) {
         // we have only modrm. no sib, no disp.
+        reg = getRegName(OpndKind_GPReg, opndDesc.size, modrm.rm);
+        opnd = EncoderBase::Operand(reg);
         return true;
     }
     const SIB& sib = *(SIB*)*pbuf;
@@ -223,20 +284,39 @@
     if (modrm.rm == 4) {
         // yes, we have SIB
         *pbuf += 1;
+        scale = sib.scale == 0 ? 0 : (1<<sib.scale);
+        if (sib.index == 4) {
+            // no index
+        }
+        else {
+            index = getRegName(OpndKind_GPReg, OpndSize_32, sib.index);
+        }
+        base = getRegName(OpndKind_GPReg, OpndSize_32, sib.base);
+    }
+    else {
+        if (modrm.mod != 0 || modrm.rm != 5) {
+            base = getRegName(OpndKind_GPReg, OpndSize_32, modrm.rm);
+        }
+        else {
+            // mod=0 && rm == 5 => only disp32
+        }
     }
     
     if (modrm.mod == 2) {
         // have disp32 
+        disp = *(int*)*pbuf;
         *pbuf += 4;
     }
     else if (modrm.mod == 1) {
         // have disp8 
+        disp = *(char*)*pbuf;
         *pbuf += 1;
     }
     else {
         assert(modrm.mod == 0);
         if (modrm.rm == 5) {
             // have disp32 w/o sib
+            disp = *(int*)*pbuf;
             *pbuf += 4;
         }
         else if (modrm.rm == 4 && sib.base == 5) {
@@ -244,6 +324,7 @@
             *pbuf += 4;
         }
     }
+    opnd = EncoderBase::Operand(opndDesc.size, base, index, scale, disp);
     return true;
 }
 

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h Sat Sep 23 06:53:32 2006
@@ -32,16 +32,53 @@
 #include "enc_base.h"
 #include "enc_prvt.h"
 
+#ifdef ENCODER_ISOLATE
+using namespace enc_ia32;
+#endif
+
 #define IF_CONDITIONAL  (0x00000000)
 #define IF_SYMMETRIC    (0x00000000)
 #define IF_BRANCH       (0x00000000)
 
 struct Inst {
+    Inst() {
+        mn = Mnemonic_Null;
+        size = 0;
+        flags = 0;
+        //offset = 0;
+        //direct_addr = NULL;
+        argc = 0;
+    }
+    /**
+     * Mnemonic of the instruction.s
+     */
     Mnemonic mn;
-    unsigned flags;
+    /**
+     * Size, in bytes, of the instruction.
+     */
     unsigned size;
-    int      offset;
-    void *   direct_addr;
+    /**
+     * Flags of the instruction.
+     * @see MF_
+     */
+    unsigned flags;
+    /**
+     * An offset of target address, in case of 'CALL offset', 
+     * 'JMP/Jcc offset'.
+     */
+    //int      offset;
+    /**
+     * Direct address of the target (on Intel64/IA-32 is 'instruction IP' + 
+     * 'instruction length' + offset).
+     */
+    //void *   direct_addr;
+    /**
+     * Number of arguments of the instruction.
+     */
+    unsigned argc;
+    //
+    EncoderBase::Operand operands[3];
+    //
     const EncoderBase::OpcodeDesc * odesc;
 };
 

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.cpp Sat Sep 23 06:53:32 2006
@@ -23,8 +23,6 @@
 #include "enc_prvt.h"
 #include <stdio.h>
 
-ENCODER_NAMESPACE_START
-
 //#define JET_PROTO
 
 #ifdef JET_PROTO
@@ -32,6 +30,7 @@
 #include "jvmti_dasm.h"
 #endif
 
+ENCODER_NAMESPACE_START
 
 /**
  * @file
@@ -283,6 +282,10 @@
     }
 #endif
 
+#ifdef JET_PROTO
+    char* saveStream = stream;
+#endif
+
     const OpcodeDesc * odesc = lookup(mn, opnds);
 #if !defined(_EM64T_)
     bool copy_opcode = true;
@@ -358,16 +361,71 @@
     //saveStream 
     Inst inst;
     unsigned len = DecoderBase::decode(saveStream, &inst);
-    if(inst.mn != mn) {
-	__asm { int 3 };
-    }
-    if (len != (unsigned)(stream-saveStream)) {
-	__asm { int 3 };
-    }
-    InstructionDisassembler idi(saveStream, (unsigned char)0xCC);
-    if(idi.get_length_with_prefix() != (int)len) {
-	__asm { int 3 };
+    assert(inst.mn == mn);
+    assert(len == (unsigned)(stream-saveStream));
+    if (mn == Mnemonic_CALL || mn == Mnemonic_JMP || 
+        (Mnemonic_JO<=mn && mn<=Mnemonic_JG)) {
+        assert(inst.argc == opnds.count());
+        
+        InstructionDisassembler idi(saveStream, (unsigned char)0xCC);
+        
+        for (unsigned i=0; i<inst.argc; i++) {
+            const EncoderBase::Operand& original = opnds[i];
+            const EncoderBase::Operand& decoded = inst.operands[i];
+            assert(original.kind() == decoded.kind());
+            assert(original.size() == decoded.size());
+            if (original.is_imm()) {
+                assert(original.imm() == decoded.imm());
+                assert(idi.get_opnd(0).kind == Kind_Imm);
+                if (mn == Mnemonic_CALL) {
+                    assert(idi.get_type() == InstructionDisassembler::RELATIVE_CALL);
+                }
+                else if (mn == Mnemonic_JMP) {
+                    assert(idi.get_type() == InstructionDisassembler::RELATIVE_JUMP);
+                }
+                else {
+                    assert(idi.get_type() == InstructionDisassembler::RELATIVE_COND_JUMP);
+                }
+            }
+            else if (original.is_mem()) {
+                assert(original.base() == decoded.base());
+                assert(original.index() == decoded.index());
+                assert(original.scale() == decoded.scale());
+                assert(original.disp() == decoded.disp());
+                assert(idi.get_opnd(0).kind == Kind_Mem);
+                if (mn == Mnemonic_CALL) {
+                    assert(idi.get_type() == InstructionDisassembler::INDIRECT_CALL);
+                }
+                else if (mn == Mnemonic_JMP) {
+                    assert(idi.get_type() == InstructionDisassembler::INDIRECT_JUMP);
+                }
+                else {
+                    assert(false);
+                }
+            }
+            else {
+                assert(original.is_reg());
+                assert(original.reg() == decoded.reg());
+                assert(idi.get_opnd(0).kind == Kind_Reg);
+                if (mn == Mnemonic_CALL) {
+                    assert(idi.get_type() == InstructionDisassembler::INDIRECT_CALL);
+                }
+                else if (mn == Mnemonic_JMP) {
+                    assert(idi.get_type() == InstructionDisassembler::INDIRECT_JUMP);
+                }
+                else {
+                    assert(false);
+                }
+            }
+        }
+        
+        Inst inst2;
+        len = DecoderBase::decode(saveStream, &inst2);
     }
+    
+ //   if(idi.get_length_with_prefix() != (int)len) {
+	//__asm { int 3 };
+ //   }
 #endif
     
     return stream;

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.h?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_base.h Sat Sep 23 06:53:32 2006
@@ -298,6 +298,10 @@
     class Operand {
     public:
         /**
+         * @brief Initializes the instance with empty size and kind.
+         */
+        Operand() : m_kind(OpndKind_Null), m_size(OpndSize_Null), m_need_rex(false) {}
+        /**
          * @brief Creates register operand from given RegName.
          */
         Operand(RegName reg) : m_kind(getRegKind(reg)), 
@@ -482,10 +486,6 @@
             }
 #endif
         }
-        /**
-         * @brief Initializes the instance with empty size and kind.
-         */
-        Operand() : m_kind(OpndKind_Null), m_size(OpndSize_Null), m_need_rex(false) {}
         // general info
         OpndKind    m_kind;
         OpndSize    m_size;

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_dasm.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_dasm.h?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_dasm.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_dasm.h Sat Sep 23 06:53:32 2006
@@ -25,20 +25,64 @@
 #define __JVMTI_DASM_H_INCLUDED__
 
 #include "open/types.h"
+#include "vm_core_types.h"
 #include "jni_types.h"
 #include <assert.h>
 
 class InstructionDisassembler {
 public:
-
+    /**
+     * Type of instruction.
+     */
     enum Type {
         OPCODEERROR = 0,
         UNKNOWN,
         OTHER=UNKNOWN,
         RELATIVE_JUMP,
         RELATIVE_COND_JUMP,
-        ABSOLUTE_CALL,
-        RELATIVE_CALL
+        RELATIVE_CALL,
+        INDIRECT_JUMP,
+        INDIRECT_CALL
+    };
+    /**
+     * IA-32 general-purpose registers set.
+     */
+    enum Register {
+        IA32_REG_NONE, IA32_REG_EAX, IA32_REG_EBX, IA32_REG_ECX,
+        IA32_REG_EDX, IA32_REG_ESI, IA32_REG_EDI, IA32_REG_EBP, IA32_REG_ESP
+    };
+    /**
+     * Kind of operand 
+     * @see Opnd
+     */
+    enum Kind {
+        /// Operand represents a constant
+        Kind_Imm,
+        /// Operand is memory reference
+        Kind_Mem,
+        /// Operand is register
+        Kind_Reg
+    };
+    /**
+     * Describes an argument of instruction.
+     */
+    struct Opnd {
+        Opnd()
+            {
+                kind = Kind_Imm;
+                base = index = reg = IA32_REG_NONE;
+                scale = 0;
+                disp = 0;
+            }
+        Kind kind;
+        Register    base;
+        Register    index;
+        unsigned    scale;
+        union {
+            int         disp;
+            Register    reg;
+            int         imm;
+        };
     };
     /**
      * @brief Enum of possible condtions for conditional jump-s.
@@ -73,17 +117,17 @@
 
     
     InstructionDisassembler(NativeCodePtr address) :
-        type(OPCODEERROR), target(0), len(0), cond_jump_type(JUMP_OVERFLOW)
+        m_type(OPCODEERROR), m_target(0), m_len(0), m_cond_jump_type(JUMP_OVERFLOW)
     {
         disasm(address, this);
     }
 
     InstructionDisassembler(InstructionDisassembler &d)
     {
-        type = d.type;
-        target = d.target;
-        len = d.len;
-        cond_jump_type = d.cond_jump_type;
+        m_type = d.m_type;
+        m_target = d.m_target;
+        m_len = d.m_len;
+        m_cond_jump_type = d.m_cond_jump_type;
     }
 
     /**
@@ -91,7 +135,7 @@
      */
     Type get_type(void) const
     {
-        return type;
+        return m_type;
     }
     /**
      * @brief Returns length (in bytes) of underlying instruction.
@@ -100,8 +144,8 @@
      */
     jint get_length_with_prefix(void) const
     {
-        assert(type != OPCODEERROR);
-        return len;
+        assert(get_type() != OPCODEERROR);
+        return m_len;
     }
     /**
      * @brief Returns absolute address of target, if applicable.
@@ -111,9 +155,10 @@
      */
     NativeCodePtr get_jump_target_address(void) const
     {
-        assert(type == RELATIVE_JUMP || type == RELATIVE_COND_JUMP ||
-            type == ABSOLUTE_CALL || type == RELATIVE_CALL);
-        return target;
+        assert(get_type() == RELATIVE_JUMP || 
+               get_type() == RELATIVE_COND_JUMP ||
+               get_type() == RELATIVE_CALL);
+        return m_target;
     }
     /**
      * @brief Returns type of conditional jump.
@@ -123,10 +168,35 @@
      */
     CondJumpType get_cond_jump_type(void) const
     {
-        assert(type == RELATIVE_COND_JUMP);
-        return cond_jump_type;
+        assert(get_type() == RELATIVE_COND_JUMP);
+        return m_cond_jump_type;
     }
-
+    
+    /**
+     * Returns number of operands of the instruction.
+     */
+    unsigned get_operands_count(void) const
+    {
+        return m_argc;
+    }
+    
+    /**
+     * Returns \c i-th operand.
+     */
+    const Opnd& get_opnd(unsigned i) const
+    {
+        assert(i<get_operands_count());
+        return m_opnds[i];
+    }
+    /**
+     * Calculates and returns address of target basing on the decoded 
+     * arguments and provided register context.
+     * 
+     * Works for both indirect and direct branches.
+     *
+     * @note Only valid for branch instructions like JMPs, CALLs, etc.
+     */
+    NativeCodePtr get_target_address_from_context(const Registers* pregs) const;
 private:
     /**
      * @brief Performs disassembling, fills out InstructionDisassembler's 
@@ -140,19 +210,27 @@
     /**
      * @brief Type of instruction.
      */
-    Type    type;
+    Type    m_type;
     /**
      * @brief Absolute address of target, if applicable.
      */
-    NativeCodePtr   target;
+    NativeCodePtr   m_target;
     /**
      * @brief Length of the instruction, in bytes.
      */
-    unsigned len;
+    unsigned    m_len;
     /**
      * @brief Type of conditional jump.
      */
-    CondJumpType cond_jump_type;
+    CondJumpType m_cond_jump_type;
+    /**
+     * @brief Number of arguments of the instruction.
+     */
+    unsigned    m_argc;
+    /**
+     * @brief Arguments of the instruction.
+     */
+    Opnd        m_opnds[3];
 };
 
 

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_dasm.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_dasm.cpp?view=diff&rev=449244&r1=449243&r2=449244
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_dasm.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_dasm.cpp Sat Sep 23 06:53:32 2006
@@ -24,35 +24,151 @@
 #include "jvmti_dasm.h"
 #include "dec_base.h"
 
+static InstructionDisassembler::Register convertRegName2Register(RegName reg)
+{
+    switch(reg) {
+    case RegName_Null:  return InstructionDisassembler::IA32_REG_NONE;
+    case RegName_EAX:   return InstructionDisassembler::IA32_REG_EAX;
+    case RegName_EBX:   return InstructionDisassembler::IA32_REG_EBX;
+    case RegName_ECX:   return InstructionDisassembler::IA32_REG_ECX;
+    case RegName_EDX:   return InstructionDisassembler::IA32_REG_EDX;
+    case RegName_ESI:   return InstructionDisassembler::IA32_REG_ESI;
+    case RegName_EDI:   return InstructionDisassembler::IA32_REG_EDI;
+    case RegName_EBP:   return InstructionDisassembler::IA32_REG_EBP;
+    case RegName_ESP:   return InstructionDisassembler::IA32_REG_ESP;
+    default:
+        // currently not supported and unexpected
+        assert(false);
+        break;
+    }
+    return (InstructionDisassembler::Register)-1;
+}
+
+static void convertOperand2Opnd(
+    InstructionDisassembler::Opnd* pdst, 
+    const EncoderBase::Operand& src)
+{
+    if (src.is_imm()) {
+        pdst->kind = InstructionDisassembler::Kind_Imm;
+        pdst->imm = (int)src.imm();
+    }
+    else if (src.is_mem()) {
+        pdst->kind = InstructionDisassembler::Kind_Mem;
+        pdst->base = convertRegName2Register(src.base());
+        pdst->index = convertRegName2Register(src.index());
+        pdst->disp = src.disp();
+        pdst->scale = src.scale();
+    }
+    else {
+        assert(src.is_reg());
+        pdst->kind = InstructionDisassembler::Kind_Reg;
+        pdst->reg = convertRegName2Register(src.reg());
+    }
+}
+
+static const char* get_reg_value(
+    InstructionDisassembler::Register reg,
+    const Registers* pcontext)
+{
+    switch(reg) {
+    case InstructionDisassembler::IA32_REG_NONE: return NULL;
+    case InstructionDisassembler::IA32_REG_EAX:  return (const char*)pcontext->eax;
+    case InstructionDisassembler::IA32_REG_EBX:  return (const char*)pcontext->ebx;
+    case InstructionDisassembler::IA32_REG_ECX:  return (const char*)pcontext->ecx;
+    case InstructionDisassembler::IA32_REG_EDX:  return (const char*)pcontext->edx;
+    case InstructionDisassembler::IA32_REG_ESI:  return (const char*)pcontext->esi;
+    case InstructionDisassembler::IA32_REG_EDI:  return (const char*)pcontext->edi;
+    case InstructionDisassembler::IA32_REG_EBP:  return (const char*)pcontext->ebp;
+    case InstructionDisassembler::IA32_REG_ESP:  return (const char*)pcontext->esp;
+    default: assert(false);
+    }
+    return NULL;
+}
+
+
 void InstructionDisassembler::disasm(const NativeCodePtr addr, 
                                      InstructionDisassembler * pidi)
 {
-    assert(addr);
     assert(pidi != NULL);
     Inst inst;
-    pidi->len = DecoderBase::decode(addr, &inst);
-    if (pidi->len == 0) {
+    pidi->m_len = DecoderBase::decode(addr, &inst);
+    if (pidi->m_len == 0) {
         // Something wrong happened
-        pidi->type = OPCODEERROR;
+        pidi->m_type = OPCODEERROR;
         return;
     }
     
-    pidi->target = (NativeCodePtr)inst.direct_addr;
-    pidi->type = UNKNOWN;
+    pidi->m_type = UNKNOWN;
+    pidi->m_argc = inst.argc;
+    for (unsigned i=0; i<inst.argc; i++) {
+        convertOperand2Opnd(&pidi->m_opnds[i], inst.operands[i]);
+    }
     
-    if (inst.mn == Mnemonic_CALL && 
-        inst.odesc->opnds[0].kind == OpndKind_Imm) {
-        pidi->type = RELATIVE_CALL;
-    }
-    else if (inst.mn == Mnemonic_JMP &&
-             inst.odesc->opnds[0].kind == OpndKind_Imm) {
-        pidi->type = RELATIVE_JUMP;
+    if (inst.mn == Mnemonic_CALL) {
+        assert(pidi->m_argc == 1);
+        if (inst.operands[0].is_imm()) {
+            pidi->m_type = RELATIVE_CALL;
+            pidi->m_target = (NativeCodePtr)((char*)addr + pidi->m_len + inst.operands[0].imm());
+        }
+        else {
+            pidi->m_type = INDIRECT_CALL;
+        }
+    }
+    else if (inst.mn == Mnemonic_JMP) {
+        assert(pidi->m_argc == 1);
+        if (inst.operands[0].is_imm()) {
+            pidi->m_type = RELATIVE_JUMP;
+            pidi->m_target = (NativeCodePtr)((char*)addr + pidi->m_len + inst.operands[0].imm());
+        }
+        else {
+            pidi->m_type = INDIRECT_JUMP;
+        }
     }
     else if (is_jcc(inst.mn)) {
         // relative Jcc is the only possible variant
+        assert(pidi->m_argc == 1);
         assert(inst.odesc->opnds[0].kind == OpndKind_Imm);
-        pidi->cond_jump_type = (CondJumpType)(inst.mn-Mnemonic_Jcc);
-        assert(pidi->cond_jump_type < CondJumpType_Count);
-        pidi->type = RELATIVE_COND_JUMP;
+        pidi->m_cond_jump_type = (CondJumpType)(inst.mn-Mnemonic_Jcc);
+        assert(pidi->m_cond_jump_type < CondJumpType_Count);
+        pidi->m_type = RELATIVE_COND_JUMP;
+    }
+}
+
+NativeCodePtr 
+InstructionDisassembler::get_target_address_from_context(const Registers* pcontext) const
+{
+    switch(get_type()) {
+    case RELATIVE_JUMP:
+    case RELATIVE_COND_JUMP:
+    case RELATIVE_CALL:
+        return m_target;
+    case INDIRECT_JUMP:
+    case INDIRECT_CALL:
+        // Only CALL/JMP mem/reg expected - single argument
+        assert(m_argc == 1);
+        {
+            const Opnd& op = get_opnd(0);
+            if (op.kind == Kind_Reg) {
+                assert(op.reg != IA32_REG_NONE);
+                return (NativeCodePtr)get_reg_value(op.reg, pcontext);
+            }
+            else if (op.kind == Kind_Mem) {
+                char* base = (char*)get_reg_value(op.base, pcontext);
+                char* index = (char*)get_reg_value(op.index, pcontext);
+                unsigned scale = op.scale;
+                int disp = op.disp;
+                char* targetAddrPtr = base + ((long)index)*scale + disp;
+                return (NativeCodePtr)*(void**)targetAddrPtr;
+            }
+        }
+        // 0th arg is neither memory, nor register, possibly immediate? 
+        // can't happen for INDIRECT_xxx.
+        assert(false);
+        return NULL;
+    default:
+        // This method should not be called for non-branch instructions.
+        assert(false);
     }
+    return NULL;
 }
+



Mime
View raw message