You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by wj...@apache.org on 2006/10/06 21:52:21 UTC

svn commit: r453745 - in /incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet: bcproc.cpp cg.h cg_fld_arr.cpp cg_obj.cpp compiler.h enc.cpp enc.h enc_ia32.cpp magics.cpp

Author: wjwashburn
Date: Fri Oct  6 12:52:20 2006
New Revision: 453745

URL: http://svn.apache.org/viewvc?view=rev&rev=453745
Log:
HARMONY-1677, vmmagic for Jitrino.JET compiler.  Basically all the vmmagic regression tests pass except atomic CAS
Tested on windowsXP and RedHat Linux w/ gcc 3.4.5

Added:
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp
Modified:
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h
    incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp?view=diff&rev=453745&r1=453744&r2=453745
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp Fri Oct  6 12:52:20 2006
@@ -46,37 +46,43 @@
         gen_dbg_check_stack(true);
     }
 
-    const InstrDesc& idesc = instrs[jinst.opcode];
-    switch (idesc.ik) {
-    case ik_a:
-        handle_ik_a(jinst);
-        break;
-    case ik_cf:
-        handle_ik_cf(jinst);
-        break;
-    case ik_cnv:
-        handle_ik_cnv(jinst);
-        break;
-    case ik_ls:
-        handle_ik_ls(jinst);
-        break;
-    case ik_meth:
-        handle_ik_meth(jinst);
-        break;
-    case ik_obj:
-        handle_ik_obj(jinst);
-        break;
-    case ik_stack:
-        handle_ik_stack(jinst);
-        break;
-    case ik_throw:
-        gen_athrow();
-        break;
-    default:
-        assert(jinst.opcode == OPCODE_NOP);
-        break;
-    };
-    
+    // First test if this is a magic. If not, then proceed with regular
+    // code gen.
+    if (!gen_magic()) {
+        const InstrDesc& idesc = instrs[jinst.opcode];
+        switch (idesc.ik) {
+            case ik_a:
+                handle_ik_a(jinst);
+                break;
+            case ik_cf:
+                handle_ik_cf(jinst);
+                break;
+            case ik_cnv:
+                handle_ik_cnv(jinst);
+                break;
+            case ik_ls:
+                handle_ik_ls(jinst);
+                break;
+            case ik_meth:
+                handle_ik_meth(jinst);
+                break;
+            case ik_obj:
+                handle_ik_obj(jinst);
+                break;
+            case ik_stack:
+                handle_ik_stack(jinst);
+                break;
+            case ik_throw:
+                gen_athrow();
+                break;
+            default:
+                assert(jinst.opcode == OPCODE_NOP);
+                break;
+        } // ~switch(opcodegroup)
+    } else {  // if (!gen_magic()) {
+        // no op. Just check stack (if applicable) and do mem manipulations
+    }
+
     if (is_set(DBG_CHECK_STACK)) {
         gen_dbg_check_stack(false);
     }

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h?view=diff&rev=453745&r1=453744&r2=453745
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h Fri Oct  6 12:52:20 2006
@@ -375,7 +375,7 @@
      *
      * Also invokes gen_check_bounds() and gen_check_null().
      */
-    void gen_arr_store(jtype jt);
+    void gen_arr_store(jtype jt, bool helperOk = true);
     /**
      * @brief Generates code to check bounds for array access.
      * @param aref_depth - depth (in the operand stack) of the array's object

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp?view=diff&rev=453745&r1=453744&r2=453745
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp Fri Oct  6 12:52:20 2006
@@ -124,11 +124,11 @@
     }
 }
 
-void CodeGen::gen_arr_store(jtype jt)
+void CodeGen::gen_arr_store(jtype jt, bool helperOk)
 {
     vunref(jt);
     // stack: [.., aref, idx, val]
-    if (jt == jobj) {
+    if (jt == jobj && helperOk) {
         static const CallSig cs_aastore(CCONV_HELPERS, jobj, i32, jobj);
         unsigned stackFix = gen_stack_to_args(true, cs_aastore, 0);
 #ifdef _EM64T_

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp?view=diff&rev=453745&r1=453744&r2=453745
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp Fri Oct  6 12:52:20 2006
@@ -39,8 +39,9 @@
 void CodeGen::gen_new_array(Allocation_Handle ah)
 {
     const JInst& jinst = *m_curr_inst;
-    assert(jinst.opcode == OPCODE_NEWARRAY || 
-           jinst.opcode == OPCODE_ANEWARRAY);
+    assert(jinst.opcode == OPCODE_NEWARRAY 
+        ||  jinst.opcode == OPCODE_ANEWARRAY 
+        || jinst.opcode == OPCODE_INVOKESTATIC); //OPCODE_INVOKESTATIC is used to generate magic
 
     if (ah == 0) {
         // it's unexpected that that something failed for a primitive type

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h?view=diff&rev=453745&r1=453744&r2=453745
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h Fri Oct  6 12:52:20 2006
@@ -350,6 +350,12 @@
      */
     void gen_ret(unsigned idx);
     
+    /**
+     * @brief Checks current inst and generates magic if needed
+     * @return  - true if current inst is magic call, false otherwise.
+     */
+    bool gen_magic(void);
+    
     //
     // Method being compiled info
     //

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp?view=diff&rev=453745&r1=453744&r2=453745
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp Fri Oct  6 12:52:20 2006
@@ -314,7 +314,10 @@
     if (cond==lt) return ":lt";
     if (cond==eq) return ":eq";
     if (cond==ne) return ":ne";
+    if (cond==ae) return ":ae";
+    if (cond==be) return ":be";
     if (cond==above) return ":above";
+    if (cond==below) return ":below";
     assert(false);
     return "???";
 }

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=453745&r1=453744&r2=453745
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h Fri Oct  6 12:52:20 2006
@@ -455,7 +455,7 @@
     // signed
     ge, le, gt, lt, eq, z=eq, ne, nz=ne, 
     /// unsigned
-    above,
+    ae, be, above, below,
     // 
     cond_none
 };
@@ -476,7 +476,7 @@
  */
 unsigned gen_num_calle_save(void);
 /**
- * @brief Returns i-th float-point register for regiter-based calling 
+ * @brief Returns i-th float-point register for register-based calling 
  *        conventions.
  *
  * The presumption used: the set of registers is constant across a platform
@@ -487,7 +487,7 @@
  */
 AR get_cconv_fr(unsigned i);
 /**
- * @brief Returns i-th general-purpose register for regiter-based calling 
+ * @brief Returns i-th general-purpose register for register-based calling 
  *        conventions.
  * @see get_cconv_fr
  */
@@ -502,7 +502,7 @@
  * @brief Represents an operand the Encoder works with.
  *
  * The Opnd can represent either immediate integer constant, or a register
- * operand, or a memory operand with compex address form [base+index*scale+
+ * operand, or a memory operand with complex address form [base+index*scale+
  * displacement].
  * 
  * Once created, instances of Opnd class are immutable. E.g. to change the 
@@ -531,7 +531,7 @@
      * @brief Constructs immediate operand of the given type and 
      *        initializes immediate field with the given value.
      * 
-     * The width of any_val is wide enough to fit any neccessary value - 
+     * The width of any_val is wide enough to fit any necessary value - 
      * a pointer, #dbl64 or #i64.
      */
     Opnd(jtype jt, jlong any_val)
@@ -998,6 +998,38 @@
     }
     
     /**
+    * Performs bitwise NOT operation.
+    */
+    void bitwise_not(const Opnd& op0) {
+        if (is_trace_on()) {
+            trace(string("not"), to_str(op0), to_str(""));
+        }
+        not_impl(op0);
+    }
+
+    /**
+    * Generates CMOVxx operation.
+    */
+    void cmovcc(COND cond, const Opnd& op0, const Opnd& op1)
+    {
+        if (is_trace_on()) {
+            trace(string("cmov:")+ to_str(cond), to_str(op0), to_str(op1));
+        }
+        cmovcc_impl(cond, op0, op1);
+    }
+
+    /**
+    * Generates CMPXCHG operation.
+    */
+    void cmpxchg(bool lockPrefix, AR addrBaseReg, AR newReg, AR oldReg)
+    {
+        if (is_trace_on()) {
+            trace(string("cmpxchg:")+ (lockPrefix ? "(locked) ":"") + to_str(addrBaseReg), to_str(newReg), to_str(oldReg));
+        }
+        cmpxchg_impl(lockPrefix, addrBaseReg, newReg, oldReg);
+    }
+
+    /**
      * Generates ALU operation between two registers.
      *
      * The registers are used as \c jt type.
@@ -1418,8 +1450,14 @@
     
     /// Implementation of mov().
     void mov_impl(const Opnd& op0, const Opnd& op1);
+    /// Implementation of not().
+    void not_impl(const Opnd& op0);
     /// Implementation of alu().
     void alu_impl(ALU op, const Opnd& op0, const Opnd& op1);
+    /// Implementation of cmovcc().
+    void cmovcc_impl(COND c, const Opnd& op0, const Opnd& op1);
+    /// Implementation of cmpxchg().
+    void cmpxchg_impl(bool lockPrefix, AR addrReg, AR newReg, AR oldReg);
     /// Implementation of lea().
     void lea_impl(const Opnd& reg, const Opnd& mem);
     /// Implementation of movp().

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=453745&r1=453744&r2=453745
==============================================================================
--- 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 Fri Oct  6 12:52:20 2006
@@ -247,13 +247,22 @@
 
 ConditionMnemonic devirt(COND cond)
 {
-    if (cond==ge) return ConditionMnemonic_GE;
-    if (cond==le) return ConditionMnemonic_LE;
-    if (cond==gt) return ConditionMnemonic_G;
-    if (cond==lt) return ConditionMnemonic_L;
-    if (cond==eq) return ConditionMnemonic_Z;
-    if (cond==ne) return ConditionMnemonic_NZ;
-    if (cond==above) return ConditionMnemonic_A;
+    switch (cond) {
+        case ge: return ConditionMnemonic_GE;
+        case le: return ConditionMnemonic_LE;
+        case gt: return ConditionMnemonic_G;
+        case lt: return ConditionMnemonic_L;
+
+        case eq: return ConditionMnemonic_Z;
+        case ne: return ConditionMnemonic_NZ;
+
+        case be   : return ConditionMnemonic_BE;
+        case ae   : return ConditionMnemonic_AE;
+        case above: return ConditionMnemonic_A;
+        case below: return ConditionMnemonic_B;
+
+        default: break;
+    }
     assert(false);
     return ConditionMnemonic_Count;
 }
@@ -631,6 +640,14 @@
     emu_unfix_opnds(this, op0, op1, _op0, _op1);
 }
 
+void Encoder::not_impl(const Opnd& op0)
+{
+    Mnemonic mn = Mnemonic_NOT;
+    EncoderBase::Operands args;
+    add_arg(args, op0, false);
+    ip(EncoderBase::encode(ip(), mn, args));
+}
+
 void Encoder::alu_impl(ALU alu, const Opnd& op0, const Opnd& op1)
 {
     Mnemonic mn = to_mn(op0.jt(), alu);
@@ -639,6 +656,54 @@
     // For alu_test can not shrink imm32 to imm8.
     add_arg(args, Opnd(op1), alu != alu_test);
     ip(EncoderBase::encode(ip(), mn, args));
+}
+
+void Encoder::cmovcc_impl(COND c, const Opnd& op0, const Opnd& op1) 
+{
+    ConditionMnemonic cm = devirt(c);
+    Mnemonic mn = (Mnemonic)(Mnemonic_CMOVcc + cm);
+    EncoderBase::Operands args;
+    add_args(args, op0);
+    add_args(args, op1);
+    ip(EncoderBase::encode(ip(), mn, args));
+}
+
+//TODO: reuse the same func for all XCHG ops in this file
+static void xchg_regs(Encoder * enc, RegName reg1, RegName reg2) {
+    EncoderBase::Operands xargs;
+    xargs.add(reg1);
+    xargs.add(reg2);
+    enc->ip(EncoderBase::encode(enc->ip(), Mnemonic_XCHG, xargs));
+}
+
+void Encoder::cmpxchg_impl(bool lockPrefix, AR addrReg, AR newReg, AR oldReg) {
+    RegName dNewReg = devirt(newReg);
+    RegName dOldReg = devirt(oldReg);
+    RegName dAddrReg = devirt(addrReg);
+    bool eaxFix = dOldReg != RegName_EAX;
+    if (eaxFix) {
+        if (dAddrReg == RegName_EAX) {
+            dAddrReg = dOldReg;
+        } else if (dNewReg == RegName_EAX) {
+            dNewReg = dOldReg;
+        }
+        xchg_regs(this, dOldReg, RegName_EAX);
+    }
+
+    if (lockPrefix) {
+        ip(EncoderBase::prefix(ip(), InstPrefix_LOCK));
+    }
+
+    EncoderBase::Operands args;
+    args.add(EncoderBase::Operand(OpndSize_32, dAddrReg, 0)); //TODO: EM64t fix!
+    args.add(dNewReg);
+    args.add(RegName_EAX);
+    ip(EncoderBase::encode(ip(), Mnemonic_CMPXCHG, args));
+
+    if (eaxFix) {
+        xchg_regs(this, RegName_EAX, devirt(oldReg));
+    }
+
 }
 
 void Encoder::lea_impl(const Opnd& reg, const Opnd& mem)

Added: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp?view=auto&rev=453745
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp (added)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp Fri Oct  6 12:52:20 2006
@@ -0,0 +1,528 @@
+/*
+*  Licensed to the Apache Software Foundation (ASF) under one or more
+*  contributor license agreements.  See the NOTICE file distributed with
+*  this work for additional information regarding copyright ownership.
+*  The ASF licenses this file to You under the Apache License, Version 2.0
+*  (the "License"); you may not use this file except in compliance with
+*  the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+/**
+ * @version $Revision$
+ */
+
+/**
+ * @file
+ * @brief Magics and WBs support for MMTk.
+*/
+ 
+#include "compiler.h"
+#include "enc_defs.h"
+#include "enc.h"
+
+#include "open/vm.h"
+#include "jit_import.h"
+#include "jit_intf.h"
+
+#include <vector>
+using std::vector;
+
+namespace Jitrino {
+namespace Jet {
+
+bool is_magic(Class_Handle k)
+{
+    static const char unboxedName[] = "org/vmmagic/unboxed/";
+    static const unsigned nameLen = sizeof(unboxedName)-1;
+    const char * kname = class_get_name(k);
+    return !strncmp(kname, unboxedName, nameLen);
+}
+
+bool is_magic(Method_Handle m)
+{
+    Class_Handle klass = method_get_class(m);
+    return is_magic(klass);
+}
+
+
+static size_t sizeof_jt(jtype jt) {
+    static size_t sizes[] =  { 
+        1, //i8,
+        2, //i16, 
+        2, //u16,
+        4, //i32,
+        8, //i64,
+        4, //flt32,
+        8, //dbl64,
+        4, //jobj,
+        4, //jvoid,
+        4, //jretAddr,
+        0, //jtypes_count, 
+    };
+    size_t res= sizes[jt];
+    assert(res >= 1 && res<=8 && (res%2==0 || res == 1));
+    return res;
+}
+
+/** creates new opnd with the specified type and generates move from old one to new one */
+static void vstack_replace_top_opnd(Compiler* c, jtype jt) {
+    Opnd before = c->vstack(0).as_opnd();
+    assert(sizeof_jt(jt) >= sizeof_jt(before.jt()) && sizeof(jt)<=32);
+    Opnd after(jt, c->valloc(jt));
+    c->mov(after, before);
+    c->vpop(); 
+    c->vpush(after);
+}
+
+bool Compiler::gen_magic(void)
+{
+#ifdef _EM64T_ 
+    return false; //not tested
+#else
+    const JInst& jinst = m_insts[m_pc];
+    if (jinst.opcode != OPCODE_INVOKEVIRTUAL && 
+        jinst.opcode != OPCODE_INVOKESTATIC &&
+        jinst.opcode != OPCODE_INVOKESPECIAL &&
+        jinst.opcode != OPCODE_NEW) {
+        return false;
+    }
+    
+    if (jinst.opcode == OPCODE_NEW) {
+        // trying to create a magic instance ?
+        Class_Handle klass = NULL;
+        klass = vm_resolve_class_new(m_compileHandle, m_klass, jinst.op0);
+        if (!is_magic(klass)) {
+            // not a magic - proceed as usual
+            return false;
+        }
+        // Create fake instance on the stack:
+        vpush(jobj);
+        vstack(0).set(VA_NZ);
+        return true;
+    }
+    //
+    //
+    //
+    JavaByteCodes opkod = jinst.opcode;
+    vector<jtype> args;
+    jtype retType;
+    bool is_static = opkod == OPCODE_INVOKESTATIC;
+    get_args_info(is_static, jinst.op0, args, &retType);
+    Method_Handle meth = NULL;
+    if (opkod == OPCODE_INVOKESTATIC) {
+        meth = resolve_static_method(m_compileHandle, m_klass, jinst.op0);
+    } 
+    else if (opkod == OPCODE_INVOKEVIRTUAL) {
+        meth = resolve_virtual_method(m_compileHandle, m_klass, jinst.op0);
+    }
+    else {
+        assert(opkod == OPCODE_INVOKESPECIAL);
+        meth = resolve_special_method(m_compileHandle, m_klass, jinst.op0);
+    }
+    if (meth == NULL || !is_magic(meth)) {
+        return false;
+    }
+    //
+    // 
+    //
+    const char* mname = method_get_name(meth);
+    //
+    // Construction
+    //
+    if (!strcmp(mname, "<init>")) {
+        // Currently only 'new <Magic>()' expected and handled
+        assert(args.size() == 1);
+        vpop();
+        return true;
+    }
+    
+    //
+    // ADD, SUB, DIFF, etc - 2 args arithmetics
+    ALU oper = alu_count;
+    
+    if (!strcmp(mname, "add"))          { oper = alu_add; }
+    else if (!strcmp(mname, "plus"))          { oper = alu_add; }
+    else if (!strcmp(mname, "sub"))     { oper = alu_sub; }
+    else if (!strcmp(mname, "minus"))     { oper = alu_sub; }
+    else if (!strcmp(mname, "diff"))    { oper = alu_sub; }
+    else if (!strcmp(mname, "or"))      { oper = alu_or; }
+    else if (!strcmp(mname, "xor"))     { oper = alu_xor; }
+    else if (!strcmp(mname, "and"))     { oper = alu_and; }
+    if (oper != alu_count) {
+        Val& v0 = vstack(0, true);
+        Val& v1 = vstack(1, true);
+        Opnd newObj(jobj, valloc(jobj));
+        mov(newObj, v1.as_opnd());
+        alu(oper, newObj, v0.as_opnd());
+        vpop();
+        vpop();
+        vpush(newObj);
+        return true;
+    }
+    
+    JavaByteCodes shiftOp = OPCODE_NOP;
+    if (!strcmp(mname, "lsh"))        {shiftOp = OPCODE_ISHL;}
+    else if (!strcmp(mname, "rsha"))  {shiftOp = OPCODE_ISHR;}
+    else if (!strcmp(mname, "rshl"))  {shiftOp = OPCODE_IUSHR;}
+    
+    if (shiftOp != OPCODE_NOP) {
+        Opnd shiftAmount = vstack(0, false).as_opnd(i32);
+        shiftAmount = vstack(0, true).as_opnd(i32);
+        rlock(shiftAmount.reg());
+        vpop();
+        //changing type of obj opnd type to ia32
+        vstack_replace_top_opnd(this, i32);
+        vpush(shiftAmount);
+        runlock(shiftAmount.reg());
+        //processing as java bytecode and converting back to the obj type
+        gen_a(shiftOp, i32);
+        vstack_replace_top_opnd(this, jobj);
+        return true;
+    }
+    
+    if (!strcmp(mname, "not")) {
+        Opnd v1 = vstack(0, true).as_opnd(jobj);
+        rlock(v1.reg());
+        Opnd v2(jobj, valloc(jobj));
+        mov(v2, v1);
+        bitwise_not(v2);
+        runlock(v1.reg());
+        vpop();
+        vpush(v2);
+        return true;
+    }
+    
+    //
+    // EQ, GE, GT, LE, LT, sXX - 2 args compare
+    //
+    COND cm = cond_none;
+    if (!strcmp(mname, "EQ"))       { cm = eq; }
+    if (!strcmp(mname, "equals"))   { cm = eq; }
+    else if (!strcmp(mname, "NE"))  { cm = ne; }
+    // unsigned compare
+    else if (!strcmp(mname, "GE"))  { cm = ae; }
+    else if (!strcmp(mname, "GT"))  { cm = above; }
+    else if (!strcmp(mname, "LE"))  { cm = be;}
+    else if (!strcmp(mname, "LT"))  { cm = below; }
+    // signed compare
+    else if (!strcmp(mname, "sGE"))  { cm = ge; }
+    else if (!strcmp(mname, "sGT"))  { cm = gt; }
+    else if (!strcmp(mname, "sLE"))  { cm = le;}
+    else if (!strcmp(mname, "sLT"))  { cm = lt; }
+    //     
+    if (cm != cond_none) {
+        Opnd o1 = vstack(1, true).as_opnd(i32); 
+        Opnd o2 = vstack(0, true).as_opnd(i32); 
+        alu(alu_cmp, o1, o2);
+        vpop();
+        vpop();
+        Opnd boolResult(i32, valloc(i32));
+        rlock(boolResult.reg());
+        mov(boolResult, g_iconst_0);
+        cmovcc(cm, boolResult, vaddr(i32, &g_iconst_1));
+        runlock(boolResult.reg());
+        vpush(boolResult);
+        return true;
+    } 
+
+    //
+    // is<Smth> one arg testing
+    //
+    bool oneArgCmp = false;
+    int theConst = 0;
+    if (!strcmp(mname, "isZero")) { oneArgCmp = true; theConst = 0; }
+    else if (!strcmp(mname, "isMax")) { oneArgCmp = true; theConst = ~0; }
+    else if (!strcmp(mname, "isNull")) { oneArgCmp = true; theConst = 0; }
+    if (oneArgCmp) {
+        AR regVal = vstack(0, true).reg();
+        rlock(regVal);
+        alu(alu_cmp, Opnd(jobj, regVal), theConst);
+        
+        //save the result
+        AR resultReg = valloc(i32);
+        rlock(resultReg);
+        mov(resultReg, Opnd(g_iconst_0)); 
+        cmovcc(z, resultReg, vaddr(i32, &g_iconst_1));
+        runlock(resultReg);
+        vpop();
+        vpush(Opnd(i32, resultReg));
+
+        runlock(regVal);
+        return true;
+    }
+    
+    //
+    // fromXXX - static creation from something
+    //
+    if (!strcmp(mname, "fromInt")) {
+        vstack_replace_top_opnd(this, jobj);
+        return true;
+    }
+    else if (!strcmp(mname, "fromIntSignExtend")) {
+        vstack_replace_top_opnd(this, jobj);
+        return true;
+    }
+    else if (!strcmp(mname, "fromIntZeroExtend")) {
+        vstack_replace_top_opnd(this, jobj);
+        return true;
+    }
+    else if (!strcmp(mname, "fromObject") || 
+             !strcmp(mname, "toAddress") ||
+             !strcmp(mname, "toObjectReference")) 
+    {
+        vstack_replace_top_opnd(this, jobj);
+        return true;
+    }
+
+    const char* msig = method_get_descriptor(meth);
+    //
+    // load<type> things
+    //
+    jtype jt = jvoid;
+    bool load = true;
+    bool has_offset = false;
+
+    if (!strcmp(mname, "loadObjectReference"))  { jt = jobj; }
+    else if (!strcmp(mname, "loadAddress"))     { jt = jobj; }
+    else if (!strcmp(mname, "loadWord"))        { jt = jobj; }
+    else if (!strcmp(mname, "loadByte"))        { jt = i8; }
+    else if (!strcmp(mname, "loadChar"))        { jt = u16; }
+    else if (!strcmp(mname, "loadDouble"))      { jt = dbl64; }
+    else if (!strcmp(mname, "loadFloat"))       { jt = flt32; }
+    else if (!strcmp(mname, "loadInt"))         { jt = i32; }
+    else if (!strcmp(mname, "loadLong"))        { jt = i64; }
+    else if (!strcmp(mname, "loadShort"))       { jt = i16; }
+    else if (!strcmp(mname, "prepareWord"))              { jt = i32; }
+    else if (!strcmp(mname, "prepareObjectReference"))   { jt = jobj;}
+    else if (!strcmp(mname, "prepareAddress"))           { jt = jobj;}
+    else if (!strcmp(mname, "prepareInt"))               { jt = i32; }
+    else if (!strcmp(mname, "store")) {
+        load = false;
+        // store() must have at least one arg
+        assert(strlen(msig) > strlen("()V"));
+        char ch = msig[1]; // first symbol after '('.
+        VM_Data_Type vdt = (VM_Data_Type)ch;
+        switch(vdt) {
+        case VM_DATA_TYPE_BOOLEAN:  // i8
+        case VM_DATA_TYPE_INT8:     jt = i8; break;
+        case VM_DATA_TYPE_INT16:    jt = i16; break;
+        case VM_DATA_TYPE_CHAR:     jt = u16; break;
+        case VM_DATA_TYPE_INT32:    jt = i32; break;
+        case VM_DATA_TYPE_INT64:    jt = i64; break;
+        case VM_DATA_TYPE_F4:       jt = flt32; break;
+        case VM_DATA_TYPE_F8:       jt = dbl64; break;
+        case VM_DATA_TYPE_ARRAY:    // jobj
+        case VM_DATA_TYPE_CLASS:    jt = jobj; break;
+        default: assert(false);
+        }
+        jtype retType;
+        vector<jtype> args;
+        get_args_info(meth, args, &retType);
+        assert(args.size()>=2);
+        has_offset = args.size() > 2;
+    }
+    if (jt != jvoid) {
+        size_t jt_size = sizeof_jt(jt);
+        if (load) {
+            // if loadXX() has any arg, then it's offset
+            if(strncmp(msig, "()", 2)) {
+                has_offset = true;
+            }
+        }
+        unsigned addr_depth = has_offset ? 1 : 0;
+        if (!load) {
+            ++addr_depth;
+            if (is_wide(jt)) {
+                ++addr_depth;
+            }
+        }
+        AR addrReg = vstack(addr_depth, true).reg();
+        rlock(addrReg);
+        
+        if (has_offset) {
+            //Add offset. Save to the new location.
+            AR addrWithOffsetReg = valloc(jobj);
+            mov(addrWithOffsetReg, addrReg);
+            runlock(addrReg);
+            addrReg = addrWithOffsetReg;
+            rlock(addrReg);
+
+            AR offsetReg = vstack(0, true).reg();
+            vpop();
+            alu(alu_add, addrReg, offsetReg);
+        }
+
+        if (load) {
+            vpop();
+            if (!is_big(jt)) {
+                AR resReg = valloc(jt);
+                ld(jt, resReg, addrReg);
+                Opnd resOpnd(jt, resReg);
+                if (jt_size < 4) {
+                    Opnd extendedOpnd(i32, valloc(i32));
+                    if (jt == u16) {
+                        zx2(extendedOpnd, resOpnd);
+                    } else {
+                        sx(extendedOpnd, resOpnd);
+                    }
+                    resOpnd = extendedOpnd;
+                } 
+                vpush(resOpnd);
+
+            } else { //code is taken from array element load -> TODO: avoid duplication
+                AR ar_lo = valloc(jt);
+                Opnd lo(jt, ar_lo);
+                rlock(lo);
+
+                do_mov(lo, Opnd(i32, addrReg, 0));
+                
+                AR ar_hi = valloc(jt);
+                Opnd hi(jt, ar_hi);
+                rlock(hi);
+                Opnd mem_hi(jt, Opnd(i32, addrReg, 4));
+                do_mov(hi, mem_hi);
+                vpush2(lo, hi);
+                runlock(lo);
+                runlock(hi);
+            }
+        } else {
+            Opnd v0 = vstack(0, true).as_opnd(jt);
+            if (!is_big(jt)) {
+                mov(Opnd(jt, addrReg, 0), v0);
+            } else {
+                do_mov(Opnd(i32, addrReg, 0), v0);
+                Opnd v1 = vstack(1, true).as_opnd(jt);
+                do_mov(Opnd(i32, addrReg, 4), v1);
+            }
+            vpop();   // pop out value
+            vpop(); // pop out Address
+        }
+        runlock(addrReg);
+        return true;
+    }
+    //
+    // max, one, zero
+    //
+    bool loadConst = false;
+    if (!strcmp(mname, "max"))          { loadConst = true; theConst = -1;}
+    else if (!strcmp(mname, "one"))     { loadConst = true; theConst =  1;}
+    else if (!strcmp(mname, "zero"))    { loadConst = true; theConst =  0;}
+    else if (!strcmp(mname, "nullReference"))
+                                        { loadConst = true; theConst =  0;}
+    if (loadConst) {
+        Opnd regOpnd(jobj, valloc(jobj));
+        mov(regOpnd, theConst);
+        vpush(regOpnd);
+        return true;
+    }
+    //
+    // toInt, toLong, toObjectRef, toWord(), etc.
+    //
+    jt = jvoid;
+    if (!strcmp(mname, "toInt"))            { jt = i32;  }
+    else if (!strcmp(mname, "toLong"))      { jt = i64;  }
+    else if (!strcmp(mname, "toObjectRef")) { jt = jobj; }
+    else if (!strcmp(mname, "toWord"))      { jt = jobj; }
+    else if (!strcmp(mname, "toAddress"))   { jt = jobj; }
+    else if (!strcmp(mname, "toObject"))    { jt = jobj; }
+    else if (!strcmp(mname, "toExtent"))    { jt = jobj; }
+    else if (!strcmp(mname, "toOffset"))    { jt = jobj; }
+    if (jt != jvoid) {
+        if (jt!=i64) {
+            vstack_replace_top_opnd(this, jt);
+            return true;
+        }
+        vstack_replace_top_opnd(this, i32);
+    
+        Opnd srcOpnd = vstack(0, true).as_opnd(i32);
+        Opnd lo(jt, valloc(jt));
+        do_mov(lo, srcOpnd);
+
+        Opnd hi(jt, g_iconst_0);
+        vpop();
+        vpush2(lo, hi);
+        return true;
+    }
+
+    if (!strcmp(mname, "attempt")) {
+        AR addrReg;
+        if (args.size() == 4) { //attempt with Offset
+            AR newAddressReg = valloc(jobj);
+            rlock(newAddressReg);
+            addrReg= vstack(3, true).reg();
+            mov(newAddressReg, addrReg);
+            AR offsetReg= vstack(0, true).reg();
+            alu(alu_add, newAddressReg, offsetReg);
+            runlock(newAddressReg);
+            addrReg = newAddressReg;
+            vpop();
+        } else {
+            addrReg = vstack(2, true).reg();
+        }
+        rlock(addrReg);
+        AR newReg = vstack(0, true).reg();
+        rlock(newReg);
+        AR oldReg = vstack(1, true).reg();
+
+        cmpxchg(true, addrReg, newReg, oldReg);
+
+        runlock(addrReg);
+        runlock(newReg);
+
+        //save the result
+        AR resultReg = valloc(i32);
+        rlock(resultReg);
+        mov(resultReg, Opnd(g_iconst_0)); 
+        cmovcc(z, resultReg, vaddr(i32, &g_iconst_1));
+        runlock(resultReg);
+
+        //fixing the stack and saving the result.
+        vpop();
+        vpop();
+        vpop();
+        vpush(Opnd(i32, resultReg));
+        
+        return true;
+    }
+
+    //
+    // xArray stuff
+    //
+    if (!strcmp(mname, "create")) {
+        VM_Data_Type atype = VM_DATA_TYPE_INT32;
+        Class_Handle elem_class = class_get_class_of_primitive_type(atype);
+        assert(elem_class != NULL);
+        Class_Handle array_class = class_get_array_of_class(elem_class);
+        assert(array_class != NULL);
+        Allocation_Handle ah = class_get_allocation_handle(array_class);
+        gen_new_array(ah);
+        return true;
+    }
+
+    if (!strcmp(mname, "get")) {
+        gen_arr_load(jobj);
+        return true;
+    }
+    
+    if (!strcmp(mname, "set")) {
+        gen_arr_store(jobj, false);
+        return true;
+    }
+    if (!strcmp(mname, "length")) {
+        gen_array_length();
+        return true;
+    }
+    //assert(false);
+    return false;
+
+#endif //not em64t
+}
+
+}};             // ~namespace Jitrino::Jet



Re: svn commit: r453745 - in /incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet: bcproc.cpp cg.h cg_fld_arr.cpp cg_obj.cpp compiler.h enc.cpp enc.h enc_ia32.cpp magics.cpp

Posted by Mikhail Fursov <mi...@gmail.com>.
I tested CAS ops in this implementation and it worked.
Could you show me the test that fails?

On 10/8/06, Geir Magnusson Jr <ge...@pobox.com> wrote:
>
> Did that test pass before?
>
> wjwashburn@apache.org wrote:
> > Author: wjwashburn
> > Date: Fri Oct  6 12:52:20 2006
> > New Revision: 453745
> >
> > URL: http://svn.apache.org/viewvc?view=rev&rev=453745
> > Log:
> > HARMONY-1677, vmmagic for Jitrino.JET compiler.  Basically all the
> vmmagic regression tests pass except atomic CAS
>


-- 
Mikhail Fursov

Re: svn commit: r453745 - in /incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet: bcproc.cpp cg.h cg_fld_arr.cpp cg_obj.cpp compiler.h enc.cpp enc.h enc_ia32.cpp magics.cpp

Posted by Geir Magnusson Jr <ge...@pobox.com>.
Did that test pass before?

wjwashburn@apache.org wrote:
> Author: wjwashburn
> Date: Fri Oct  6 12:52:20 2006
> New Revision: 453745
> 
> URL: http://svn.apache.org/viewvc?view=rev&rev=453745
> Log:
> HARMONY-1677, vmmagic for Jitrino.JET compiler.  Basically all the vmmagic regression tests pass except atomic CAS
> Tested on windowsXP and RedHat Linux w/ gcc 3.4.5
> 
> Added:
>     incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp
> Modified:
>     incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp
>     incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h
>     incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp
>     incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp
>     incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h
>     incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp
>     incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h
>     incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp
> 
> Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp
> URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp?view=diff&rev=453745&r1=453744&r2=453745
> ==============================================================================
> --- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp (original)
> +++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/bcproc.cpp Fri Oct  6 12:52:20 2006
> @@ -46,37 +46,43 @@
>          gen_dbg_check_stack(true);
>      }
>  
> -    const InstrDesc& idesc = instrs[jinst.opcode];
> -    switch (idesc.ik) {
> -    case ik_a:
> -        handle_ik_a(jinst);
> -        break;
> -    case ik_cf:
> -        handle_ik_cf(jinst);
> -        break;
> -    case ik_cnv:
> -        handle_ik_cnv(jinst);
> -        break;
> -    case ik_ls:
> -        handle_ik_ls(jinst);
> -        break;
> -    case ik_meth:
> -        handle_ik_meth(jinst);
> -        break;
> -    case ik_obj:
> -        handle_ik_obj(jinst);
> -        break;
> -    case ik_stack:
> -        handle_ik_stack(jinst);
> -        break;
> -    case ik_throw:
> -        gen_athrow();
> -        break;
> -    default:
> -        assert(jinst.opcode == OPCODE_NOP);
> -        break;
> -    };
> -    
> +    // First test if this is a magic. If not, then proceed with regular
> +    // code gen.
> +    if (!gen_magic()) {
> +        const InstrDesc& idesc = instrs[jinst.opcode];
> +        switch (idesc.ik) {
> +            case ik_a:
> +                handle_ik_a(jinst);
> +                break;
> +            case ik_cf:
> +                handle_ik_cf(jinst);
> +                break;
> +            case ik_cnv:
> +                handle_ik_cnv(jinst);
> +                break;
> +            case ik_ls:
> +                handle_ik_ls(jinst);
> +                break;
> +            case ik_meth:
> +                handle_ik_meth(jinst);
> +                break;
> +            case ik_obj:
> +                handle_ik_obj(jinst);
> +                break;
> +            case ik_stack:
> +                handle_ik_stack(jinst);
> +                break;
> +            case ik_throw:
> +                gen_athrow();
> +                break;
> +            default:
> +                assert(jinst.opcode == OPCODE_NOP);
> +                break;
> +        } // ~switch(opcodegroup)
> +    } else {  // if (!gen_magic()) {
> +        // no op. Just check stack (if applicable) and do mem manipulations
> +    }
> +
>      if (is_set(DBG_CHECK_STACK)) {
>          gen_dbg_check_stack(false);
>      }
> 
> Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h
> URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h?view=diff&rev=453745&r1=453744&r2=453745
> ==============================================================================
> --- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h (original)
> +++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h Fri Oct  6 12:52:20 2006
> @@ -375,7 +375,7 @@
>       *
>       * Also invokes gen_check_bounds() and gen_check_null().
>       */
> -    void gen_arr_store(jtype jt);
> +    void gen_arr_store(jtype jt, bool helperOk = true);
>      /**
>       * @brief Generates code to check bounds for array access.
>       * @param aref_depth - depth (in the operand stack) of the array's object
> 
> Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp
> URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp?view=diff&rev=453745&r1=453744&r2=453745
> ==============================================================================
> --- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp (original)
> +++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp Fri Oct  6 12:52:20 2006
> @@ -124,11 +124,11 @@
>      }
>  }
>  
> -void CodeGen::gen_arr_store(jtype jt)
> +void CodeGen::gen_arr_store(jtype jt, bool helperOk)
>  {
>      vunref(jt);
>      // stack: [.., aref, idx, val]
> -    if (jt == jobj) {
> +    if (jt == jobj && helperOk) {
>          static const CallSig cs_aastore(CCONV_HELPERS, jobj, i32, jobj);
>          unsigned stackFix = gen_stack_to_args(true, cs_aastore, 0);
>  #ifdef _EM64T_
> 
> Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp
> URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp?view=diff&rev=453745&r1=453744&r2=453745
> ==============================================================================
> --- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp (original)
> +++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_obj.cpp Fri Oct  6 12:52:20 2006
> @@ -39,8 +39,9 @@
>  void CodeGen::gen_new_array(Allocation_Handle ah)
>  {
>      const JInst& jinst = *m_curr_inst;
> -    assert(jinst.opcode == OPCODE_NEWARRAY || 
> -           jinst.opcode == OPCODE_ANEWARRAY);
> +    assert(jinst.opcode == OPCODE_NEWARRAY 
> +        ||  jinst.opcode == OPCODE_ANEWARRAY 
> +        || jinst.opcode == OPCODE_INVOKESTATIC); //OPCODE_INVOKESTATIC is used to generate magic
>  
>      if (ah == 0) {
>          // it's unexpected that that something failed for a primitive type
> 
> Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h
> URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h?view=diff&rev=453745&r1=453744&r2=453745
> ==============================================================================
> --- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h (original)
> +++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/compiler.h Fri Oct  6 12:52:20 2006
> @@ -350,6 +350,12 @@
>       */
>      void gen_ret(unsigned idx);
>      
> +    /**
> +     * @brief Checks current inst and generates magic if needed
> +     * @return  - true if current inst is magic call, false otherwise.
> +     */
> +    bool gen_magic(void);
> +    
>      //
>      // Method being compiled info
>      //
> 
> Modified: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp
> URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp?view=diff&rev=453745&r1=453744&r2=453745
> ==============================================================================
> --- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp (original)
> +++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.cpp Fri Oct  6 12:52:20 2006
> @@ -314,7 +314,10 @@
>      if (cond==lt) return ":lt";
>      if (cond==eq) return ":eq";
>      if (cond==ne) return ":ne";
> +    if (cond==ae) return ":ae";
> +    if (cond==be) return ":be";
>      if (cond==above) return ":above";
> +    if (cond==below) return ":below";
>      assert(false);
>      return "???";
>  }
> 
> 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=453745&r1=453744&r2=453745
> ==============================================================================
> --- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h (original)
> +++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h Fri Oct  6 12:52:20 2006
> @@ -455,7 +455,7 @@
>      // signed
>      ge, le, gt, lt, eq, z=eq, ne, nz=ne, 
>      /// unsigned
> -    above,
> +    ae, be, above, below,
>      // 
>      cond_none
>  };
> @@ -476,7 +476,7 @@
>   */
>  unsigned gen_num_calle_save(void);
>  /**
> - * @brief Returns i-th float-point register for regiter-based calling 
> + * @brief Returns i-th float-point register for register-based calling 
>   *        conventions.
>   *
>   * The presumption used: the set of registers is constant across a platform
> @@ -487,7 +487,7 @@
>   */
>  AR get_cconv_fr(unsigned i);
>  /**
> - * @brief Returns i-th general-purpose register for regiter-based calling 
> + * @brief Returns i-th general-purpose register for register-based calling 
>   *        conventions.
>   * @see get_cconv_fr
>   */
> @@ -502,7 +502,7 @@
>   * @brief Represents an operand the Encoder works with.
>   *
>   * The Opnd can represent either immediate integer constant, or a register
> - * operand, or a memory operand with compex address form [base+index*scale+
> + * operand, or a memory operand with complex address form [base+index*scale+
>   * displacement].
>   * 
>   * Once created, instances of Opnd class are immutable. E.g. to change the 
> @@ -531,7 +531,7 @@
>       * @brief Constructs immediate operand of the given type and 
>       *        initializes immediate field with the given value.
>       * 
> -     * The width of any_val is wide enough to fit any neccessary value - 
> +     * The width of any_val is wide enough to fit any necessary value - 
>       * a pointer, #dbl64 or #i64.
>       */
>      Opnd(jtype jt, jlong any_val)
> @@ -998,6 +998,38 @@
>      }
>      
>      /**
> +    * Performs bitwise NOT operation.
> +    */
> +    void bitwise_not(const Opnd& op0) {
> +        if (is_trace_on()) {
> +            trace(string("not"), to_str(op0), to_str(""));
> +        }
> +        not_impl(op0);
> +    }
> +
> +    /**
> +    * Generates CMOVxx operation.
> +    */
> +    void cmovcc(COND cond, const Opnd& op0, const Opnd& op1)
> +    {
> +        if (is_trace_on()) {
> +            trace(string("cmov:")+ to_str(cond), to_str(op0), to_str(op1));
> +        }
> +        cmovcc_impl(cond, op0, op1);
> +    }
> +
> +    /**
> +    * Generates CMPXCHG operation.
> +    */
> +    void cmpxchg(bool lockPrefix, AR addrBaseReg, AR newReg, AR oldReg)
> +    {
> +        if (is_trace_on()) {
> +            trace(string("cmpxchg:")+ (lockPrefix ? "(locked) ":"") + to_str(addrBaseReg), to_str(newReg), to_str(oldReg));
> +        }
> +        cmpxchg_impl(lockPrefix, addrBaseReg, newReg, oldReg);
> +    }
> +
> +    /**
>       * Generates ALU operation between two registers.
>       *
>       * The registers are used as \c jt type.
> @@ -1418,8 +1450,14 @@
>      
>      /// Implementation of mov().
>      void mov_impl(const Opnd& op0, const Opnd& op1);
> +    /// Implementation of not().
> +    void not_impl(const Opnd& op0);
>      /// Implementation of alu().
>      void alu_impl(ALU op, const Opnd& op0, const Opnd& op1);
> +    /// Implementation of cmovcc().
> +    void cmovcc_impl(COND c, const Opnd& op0, const Opnd& op1);
> +    /// Implementation of cmpxchg().
> +    void cmpxchg_impl(bool lockPrefix, AR addrReg, AR newReg, AR oldReg);
>      /// Implementation of lea().
>      void lea_impl(const Opnd& reg, const Opnd& mem);
>      /// Implementation of movp().
> 
> 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=453745&r1=453744&r2=453745
> ==============================================================================
> --- 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 Fri Oct  6 12:52:20 2006
> @@ -247,13 +247,22 @@
>  
>  ConditionMnemonic devirt(COND cond)
>  {
> -    if (cond==ge) return ConditionMnemonic_GE;
> -    if (cond==le) return ConditionMnemonic_LE;
> -    if (cond==gt) return ConditionMnemonic_G;
> -    if (cond==lt) return ConditionMnemonic_L;
> -    if (cond==eq) return ConditionMnemonic_Z;
> -    if (cond==ne) return ConditionMnemonic_NZ;
> -    if (cond==above) return ConditionMnemonic_A;
> +    switch (cond) {
> +        case ge: return ConditionMnemonic_GE;
> +        case le: return ConditionMnemonic_LE;
> +        case gt: return ConditionMnemonic_G;
> +        case lt: return ConditionMnemonic_L;
> +
> +        case eq: return ConditionMnemonic_Z;
> +        case ne: return ConditionMnemonic_NZ;
> +
> +        case be   : return ConditionMnemonic_BE;
> +        case ae   : return ConditionMnemonic_AE;
> +        case above: return ConditionMnemonic_A;
> +        case below: return ConditionMnemonic_B;
> +
> +        default: break;
> +    }
>      assert(false);
>      return ConditionMnemonic_Count;
>  }
> @@ -631,6 +640,14 @@
>      emu_unfix_opnds(this, op0, op1, _op0, _op1);
>  }
>  
> +void Encoder::not_impl(const Opnd& op0)
> +{
> +    Mnemonic mn = Mnemonic_NOT;
> +    EncoderBase::Operands args;
> +    add_arg(args, op0, false);
> +    ip(EncoderBase::encode(ip(), mn, args));
> +}
> +
>  void Encoder::alu_impl(ALU alu, const Opnd& op0, const Opnd& op1)
>  {
>      Mnemonic mn = to_mn(op0.jt(), alu);
> @@ -639,6 +656,54 @@
>      // For alu_test can not shrink imm32 to imm8.
>      add_arg(args, Opnd(op1), alu != alu_test);
>      ip(EncoderBase::encode(ip(), mn, args));
> +}
> +
> +void Encoder::cmovcc_impl(COND c, const Opnd& op0, const Opnd& op1) 
> +{
> +    ConditionMnemonic cm = devirt(c);
> +    Mnemonic mn = (Mnemonic)(Mnemonic_CMOVcc + cm);
> +    EncoderBase::Operands args;
> +    add_args(args, op0);
> +    add_args(args, op1);
> +    ip(EncoderBase::encode(ip(), mn, args));
> +}
> +
> +//TODO: reuse the same func for all XCHG ops in this file
> +static void xchg_regs(Encoder * enc, RegName reg1, RegName reg2) {
> +    EncoderBase::Operands xargs;
> +    xargs.add(reg1);
> +    xargs.add(reg2);
> +    enc->ip(EncoderBase::encode(enc->ip(), Mnemonic_XCHG, xargs));
> +}
> +
> +void Encoder::cmpxchg_impl(bool lockPrefix, AR addrReg, AR newReg, AR oldReg) {
> +    RegName dNewReg = devirt(newReg);
> +    RegName dOldReg = devirt(oldReg);
> +    RegName dAddrReg = devirt(addrReg);
> +    bool eaxFix = dOldReg != RegName_EAX;
> +    if (eaxFix) {
> +        if (dAddrReg == RegName_EAX) {
> +            dAddrReg = dOldReg;
> +        } else if (dNewReg == RegName_EAX) {
> +            dNewReg = dOldReg;
> +        }
> +        xchg_regs(this, dOldReg, RegName_EAX);
> +    }
> +
> +    if (lockPrefix) {
> +        ip(EncoderBase::prefix(ip(), InstPrefix_LOCK));
> +    }
> +
> +    EncoderBase::Operands args;
> +    args.add(EncoderBase::Operand(OpndSize_32, dAddrReg, 0)); //TODO: EM64t fix!
> +    args.add(dNewReg);
> +    args.add(RegName_EAX);
> +    ip(EncoderBase::encode(ip(), Mnemonic_CMPXCHG, args));
> +
> +    if (eaxFix) {
> +        xchg_regs(this, RegName_EAX, devirt(oldReg));
> +    }
> +
>  }
>  
>  void Encoder::lea_impl(const Opnd& reg, const Opnd& mem)
> 
> Added: incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp
> URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp?view=auto&rev=453745
> ==============================================================================
> --- incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp (added)
> +++ incubator/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/magics.cpp Fri Oct  6 12:52:20 2006
> @@ -0,0 +1,528 @@
> +/*
> +*  Licensed to the Apache Software Foundation (ASF) under one or more
> +*  contributor license agreements.  See the NOTICE file distributed with
> +*  this work for additional information regarding copyright ownership.
> +*  The ASF licenses this file to You under the Apache License, Version 2.0
> +*  (the "License"); you may not use this file except in compliance with
> +*  the License.  You may obtain a copy of the License at
> +*
> +*     http://www.apache.org/licenses/LICENSE-2.0
> +*
> +*  Unless required by applicable law or agreed to in writing, software
> +*  distributed under the License is distributed on an "AS IS" BASIS,
> +*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +*  See the License for the specific language governing permissions and
> +*  limitations under the License.
> +*/
> +/**
> + * @version $Revision$
> + */
> +
> +/**
> + * @file
> + * @brief Magics and WBs support for MMTk.
> +*/
> + 
> +#include "compiler.h"
> +#include "enc_defs.h"
> +#include "enc.h"
> +
> +#include "open/vm.h"
> +#include "jit_import.h"
> +#include "jit_intf.h"
> +
> +#include <vector>
> +using std::vector;
> +
> +namespace Jitrino {
> +namespace Jet {
> +
> +bool is_magic(Class_Handle k)
> +{
> +    static const char unboxedName[] = "org/vmmagic/unboxed/";
> +    static const unsigned nameLen = sizeof(unboxedName)-1;
> +    const char * kname = class_get_name(k);
> +    return !strncmp(kname, unboxedName, nameLen);
> +}
> +
> +bool is_magic(Method_Handle m)
> +{
> +    Class_Handle klass = method_get_class(m);
> +    return is_magic(klass);
> +}
> +
> +
> +static size_t sizeof_jt(jtype jt) {
> +    static size_t sizes[] =  { 
> +        1, //i8,
> +        2, //i16, 
> +        2, //u16,
> +        4, //i32,
> +        8, //i64,
> +        4, //flt32,
> +        8, //dbl64,
> +        4, //jobj,
> +        4, //jvoid,
> +        4, //jretAddr,
> +        0, //jtypes_count, 
> +    };
> +    size_t res= sizes[jt];
> +    assert(res >= 1 && res<=8 && (res%2==0 || res == 1));
> +    return res;
> +}
> +
> +/** creates new opnd with the specified type and generates move from old one to new one */
> +static void vstack_replace_top_opnd(Compiler* c, jtype jt) {
> +    Opnd before = c->vstack(0).as_opnd();
> +    assert(sizeof_jt(jt) >= sizeof_jt(before.jt()) && sizeof(jt)<=32);
> +    Opnd after(jt, c->valloc(jt));
> +    c->mov(after, before);
> +    c->vpop(); 
> +    c->vpush(after);
> +}
> +
> +bool Compiler::gen_magic(void)
> +{
> +#ifdef _EM64T_ 
> +    return false; //not tested
> +#else
> +    const JInst& jinst = m_insts[m_pc];
> +    if (jinst.opcode != OPCODE_INVOKEVIRTUAL && 
> +        jinst.opcode != OPCODE_INVOKESTATIC &&
> +        jinst.opcode != OPCODE_INVOKESPECIAL &&
> +        jinst.opcode != OPCODE_NEW) {
> +        return false;
> +    }
> +    
> +    if (jinst.opcode == OPCODE_NEW) {
> +        // trying to create a magic instance ?
> +        Class_Handle klass = NULL;
> +        klass = vm_resolve_class_new(m_compileHandle, m_klass, jinst.op0);
> +        if (!is_magic(klass)) {
> +            // not a magic - proceed as usual
> +            return false;
> +        }
> +        // Create fake instance on the stack:
> +        vpush(jobj);
> +        vstack(0).set(VA_NZ);
> +        return true;
> +    }
> +    //
> +    //
> +    //
> +    JavaByteCodes opkod = jinst.opcode;
> +    vector<jtype> args;
> +    jtype retType;
> +    bool is_static = opkod == OPCODE_INVOKESTATIC;
> +    get_args_info(is_static, jinst.op0, args, &retType);
> +    Method_Handle meth = NULL;
> +    if (opkod == OPCODE_INVOKESTATIC) {
> +        meth = resolve_static_method(m_compileHandle, m_klass, jinst.op0);
> +    } 
> +    else if (opkod == OPCODE_INVOKEVIRTUAL) {
> +        meth = resolve_virtual_method(m_compileHandle, m_klass, jinst.op0);
> +    }
> +    else {
> +        assert(opkod == OPCODE_INVOKESPECIAL);
> +        meth = resolve_special_method(m_compileHandle, m_klass, jinst.op0);
> +    }
> +    if (meth == NULL || !is_magic(meth)) {
> +        return false;
> +    }
> +    //
> +    // 
> +    //
> +    const char* mname = method_get_name(meth);
> +    //
> +    // Construction
> +    //
> +    if (!strcmp(mname, "<init>")) {
> +        // Currently only 'new <Magic>()' expected and handled
> +        assert(args.size() == 1);
> +        vpop();
> +        return true;
> +    }
> +    
> +    //
> +    // ADD, SUB, DIFF, etc - 2 args arithmetics
> +    ALU oper = alu_count;
> +    
> +    if (!strcmp(mname, "add"))          { oper = alu_add; }
> +    else if (!strcmp(mname, "plus"))          { oper = alu_add; }
> +    else if (!strcmp(mname, "sub"))     { oper = alu_sub; }
> +    else if (!strcmp(mname, "minus"))     { oper = alu_sub; }
> +    else if (!strcmp(mname, "diff"))    { oper = alu_sub; }
> +    else if (!strcmp(mname, "or"))      { oper = alu_or; }
> +    else if (!strcmp(mname, "xor"))     { oper = alu_xor; }
> +    else if (!strcmp(mname, "and"))     { oper = alu_and; }
> +    if (oper != alu_count) {
> +        Val& v0 = vstack(0, true);
> +        Val& v1 = vstack(1, true);
> +        Opnd newObj(jobj, valloc(jobj));
> +        mov(newObj, v1.as_opnd());
> +        alu(oper, newObj, v0.as_opnd());
> +        vpop();
> +        vpop();
> +        vpush(newObj);
> +        return true;
> +    }
> +    
> +    JavaByteCodes shiftOp = OPCODE_NOP;
> +    if (!strcmp(mname, "lsh"))        {shiftOp = OPCODE_ISHL;}
> +    else if (!strcmp(mname, "rsha"))  {shiftOp = OPCODE_ISHR;}
> +    else if (!strcmp(mname, "rshl"))  {shiftOp = OPCODE_IUSHR;}
> +    
> +    if (shiftOp != OPCODE_NOP) {
> +        Opnd shiftAmount = vstack(0, false).as_opnd(i32);
> +        shiftAmount = vstack(0, true).as_opnd(i32);
> +        rlock(shiftAmount.reg());
> +        vpop();
> +        //changing type of obj opnd type to ia32
> +        vstack_replace_top_opnd(this, i32);
> +        vpush(shiftAmount);
> +        runlock(shiftAmount.reg());
> +        //processing as java bytecode and converting back to the obj type
> +        gen_a(shiftOp, i32);
> +        vstack_replace_top_opnd(this, jobj);
> +        return true;
> +    }
> +    
> +    if (!strcmp(mname, "not")) {
> +        Opnd v1 = vstack(0, true).as_opnd(jobj);
> +        rlock(v1.reg());
> +        Opnd v2(jobj, valloc(jobj));
> +        mov(v2, v1);
> +        bitwise_not(v2);
> +        runlock(v1.reg());
> +        vpop();
> +        vpush(v2);
> +        return true;
> +    }
> +    
> +    //
> +    // EQ, GE, GT, LE, LT, sXX - 2 args compare
> +    //
> +    COND cm = cond_none;
> +    if (!strcmp(mname, "EQ"))       { cm = eq; }
> +    if (!strcmp(mname, "equals"))   { cm = eq; }
> +    else if (!strcmp(mname, "NE"))  { cm = ne; }
> +    // unsigned compare
> +    else if (!strcmp(mname, "GE"))  { cm = ae; }
> +    else if (!strcmp(mname, "GT"))  { cm = above; }
> +    else if (!strcmp(mname, "LE"))  { cm = be;}
> +    else if (!strcmp(mname, "LT"))  { cm = below; }
> +    // signed compare
> +    else if (!strcmp(mname, "sGE"))  { cm = ge; }
> +    else if (!strcmp(mname, "sGT"))  { cm = gt; }
> +    else if (!strcmp(mname, "sLE"))  { cm = le;}
> +    else if (!strcmp(mname, "sLT"))  { cm = lt; }
> +    //     
> +    if (cm != cond_none) {
> +        Opnd o1 = vstack(1, true).as_opnd(i32); 
> +        Opnd o2 = vstack(0, true).as_opnd(i32); 
> +        alu(alu_cmp, o1, o2);
> +        vpop();
> +        vpop();
> +        Opnd boolResult(i32, valloc(i32));
> +        rlock(boolResult.reg());
> +        mov(boolResult, g_iconst_0);
> +        cmovcc(cm, boolResult, vaddr(i32, &g_iconst_1));
> +        runlock(boolResult.reg());
> +        vpush(boolResult);
> +        return true;
> +    } 
> +
> +    //
> +    // is<Smth> one arg testing
> +    //
> +    bool oneArgCmp = false;
> +    int theConst = 0;
> +    if (!strcmp(mname, "isZero")) { oneArgCmp = true; theConst = 0; }
> +    else if (!strcmp(mname, "isMax")) { oneArgCmp = true; theConst = ~0; }
> +    else if (!strcmp(mname, "isNull")) { oneArgCmp = true; theConst = 0; }
> +    if (oneArgCmp) {
> +        AR regVal = vstack(0, true).reg();
> +        rlock(regVal);
> +        alu(alu_cmp, Opnd(jobj, regVal), theConst);
> +        
> +        //save the result
> +        AR resultReg = valloc(i32);
> +        rlock(resultReg);
> +        mov(resultReg, Opnd(g_iconst_0)); 
> +        cmovcc(z, resultReg, vaddr(i32, &g_iconst_1));
> +        runlock(resultReg);
> +        vpop();
> +        vpush(Opnd(i32, resultReg));
> +
> +        runlock(regVal);
> +        return true;
> +    }
> +    
> +    //
> +    // fromXXX - static creation from something
> +    //
> +    if (!strcmp(mname, "fromInt")) {
> +        vstack_replace_top_opnd(this, jobj);
> +        return true;
> +    }
> +    else if (!strcmp(mname, "fromIntSignExtend")) {
> +        vstack_replace_top_opnd(this, jobj);
> +        return true;
> +    }
> +    else if (!strcmp(mname, "fromIntZeroExtend")) {
> +        vstack_replace_top_opnd(this, jobj);
> +        return true;
> +    }
> +    else if (!strcmp(mname, "fromObject") || 
> +             !strcmp(mname, "toAddress") ||
> +             !strcmp(mname, "toObjectReference")) 
> +    {
> +        vstack_replace_top_opnd(this, jobj);
> +        return true;
> +    }
> +
> +    const char* msig = method_get_descriptor(meth);
> +    //
> +    // load<type> things
> +    //
> +    jtype jt = jvoid;
> +    bool load = true;
> +    bool has_offset = false;
> +
> +    if (!strcmp(mname, "loadObjectReference"))  { jt = jobj; }
> +    else if (!strcmp(mname, "loadAddress"))     { jt = jobj; }
> +    else if (!strcmp(mname, "loadWord"))        { jt = jobj; }
> +    else if (!strcmp(mname, "loadByte"))        { jt = i8; }
> +    else if (!strcmp(mname, "loadChar"))        { jt = u16; }
> +    else if (!strcmp(mname, "loadDouble"))      { jt = dbl64; }
> +    else if (!strcmp(mname, "loadFloat"))       { jt = flt32; }
> +    else if (!strcmp(mname, "loadInt"))         { jt = i32; }
> +    else if (!strcmp(mname, "loadLong"))        { jt = i64; }
> +    else if (!strcmp(mname, "loadShort"))       { jt = i16; }
> +    else if (!strcmp(mname, "prepareWord"))              { jt = i32; }
> +    else if (!strcmp(mname, "prepareObjectReference"))   { jt = jobj;}
> +    else if (!strcmp(mname, "prepareAddress"))           { jt = jobj;}
> +    else if (!strcmp(mname, "prepareInt"))               { jt = i32; }
> +    else if (!strcmp(mname, "store")) {
> +        load = false;
> +        // store() must have at least one arg
> +        assert(strlen(msig) > strlen("()V"));
> +        char ch = msig[1]; // first symbol after '('.
> +        VM_Data_Type vdt = (VM_Data_Type)ch;
> +        switch(vdt) {
> +        case VM_DATA_TYPE_BOOLEAN:  // i8
> +        case VM_DATA_TYPE_INT8:     jt = i8; break;
> +        case VM_DATA_TYPE_INT16:    jt = i16; break;
> +        case VM_DATA_TYPE_CHAR:     jt = u16; break;
> +        case VM_DATA_TYPE_INT32:    jt = i32; break;
> +        case VM_DATA_TYPE_INT64:    jt = i64; break;
> +        case VM_DATA_TYPE_F4:       jt = flt32; break;
> +        case VM_DATA_TYPE_F8:       jt = dbl64; break;
> +        case VM_DATA_TYPE_ARRAY:    // jobj
> +        case VM_DATA_TYPE_CLASS:    jt = jobj; break;
> +        default: assert(false);
> +        }
> +        jtype retType;
> +        vector<jtype> args;
> +        get_args_info(meth, args, &retType);
> +        assert(args.size()>=2);
> +        has_offset = args.size() > 2;
> +    }
> +    if (jt != jvoid) {
> +        size_t jt_size = sizeof_jt(jt);
> +        if (load) {
> +            // if loadXX() has any arg, then it's offset
> +            if(strncmp(msig, "()", 2)) {
> +                has_offset = true;
> +            }
> +        }
> +        unsigned addr_depth = has_offset ? 1 : 0;
> +        if (!load) {
> +            ++addr_depth;
> +            if (is_wide(jt)) {
> +                ++addr_depth;
> +            }
> +        }
> +        AR addrReg = vstack(addr_depth, true).reg();
> +        rlock(addrReg);
> +        
> +        if (has_offset) {
> +            //Add offset. Save to the new location.
> +            AR addrWithOffsetReg = valloc(jobj);
> +            mov(addrWithOffsetReg, addrReg);
> +            runlock(addrReg);
> +            addrReg = addrWithOffsetReg;
> +            rlock(addrReg);
> +
> +            AR offsetReg = vstack(0, true).reg();
> +            vpop();
> +            alu(alu_add, addrReg, offsetReg);
> +        }
> +
> +        if (load) {
> +            vpop();
> +            if (!is_big(jt)) {
> +                AR resReg = valloc(jt);
> +                ld(jt, resReg, addrReg);
> +                Opnd resOpnd(jt, resReg);
> +                if (jt_size < 4) {
> +                    Opnd extendedOpnd(i32, valloc(i32));
> +                    if (jt == u16) {
> +                        zx2(extendedOpnd, resOpnd);
> +                    } else {
> +                        sx(extendedOpnd, resOpnd);
> +                    }
> +                    resOpnd = extendedOpnd;
> +                } 
> +                vpush(resOpnd);
> +
> +            } else { //code is taken from array element load -> TODO: avoid duplication
> +                AR ar_lo = valloc(jt);
> +                Opnd lo(jt, ar_lo);
> +                rlock(lo);
> +
> +                do_mov(lo, Opnd(i32, addrReg, 0));
> +                
> +                AR ar_hi = valloc(jt);
> +                Opnd hi(jt, ar_hi);
> +                rlock(hi);
> +                Opnd mem_hi(jt, Opnd(i32, addrReg, 4));
> +                do_mov(hi, mem_hi);
> +                vpush2(lo, hi);
> +                runlock(lo);
> +                runlock(hi);
> +            }
> +        } else {
> +            Opnd v0 = vstack(0, true).as_opnd(jt);
> +            if (!is_big(jt)) {
> +                mov(Opnd(jt, addrReg, 0), v0);
> +            } else {
> +                do_mov(Opnd(i32, addrReg, 0), v0);
> +                Opnd v1 = vstack(1, true).as_opnd(jt);
> +                do_mov(Opnd(i32, addrReg, 4), v1);
> +            }
> +            vpop();   // pop out value
> +            vpop(); // pop out Address
> +        }
> +        runlock(addrReg);
> +        return true;
> +    }
> +    //
> +    // max, one, zero
> +    //
> +    bool loadConst = false;
> +    if (!strcmp(mname, "max"))          { loadConst = true; theConst = -1;}
> +    else if (!strcmp(mname, "one"))     { loadConst = true; theConst =  1;}
> +    else if (!strcmp(mname, "zero"))    { loadConst = true; theConst =  0;}
> +    else if (!strcmp(mname, "nullReference"))
> +                                        { loadConst = true; theConst =  0;}
> +    if (loadConst) {
> +        Opnd regOpnd(jobj, valloc(jobj));
> +        mov(regOpnd, theConst);
> +        vpush(regOpnd);
> +        return true;
> +    }
> +    //
> +    // toInt, toLong, toObjectRef, toWord(), etc.
> +    //
> +    jt = jvoid;
> +    if (!strcmp(mname, "toInt"))            { jt = i32;  }
> +    else if (!strcmp(mname, "toLong"))      { jt = i64;  }
> +    else if (!strcmp(mname, "toObjectRef")) { jt = jobj; }
> +    else if (!strcmp(mname, "toWord"))      { jt = jobj; }
> +    else if (!strcmp(mname, "toAddress"))   { jt = jobj; }
> +    else if (!strcmp(mname, "toObject"))    { jt = jobj; }
> +    else if (!strcmp(mname, "toExtent"))    { jt = jobj; }
> +    else if (!strcmp(mname, "toOffset"))    { jt = jobj; }
> +    if (jt != jvoid) {
> +        if (jt!=i64) {
> +            vstack_replace_top_opnd(this, jt);
> +            return true;
> +        }
> +        vstack_replace_top_opnd(this, i32);
> +    
> +        Opnd srcOpnd = vstack(0, true).as_opnd(i32);
> +        Opnd lo(jt, valloc(jt));
> +        do_mov(lo, srcOpnd);
> +
> +        Opnd hi(jt, g_iconst_0);
> +        vpop();
> +        vpush2(lo, hi);
> +        return true;
> +    }
> +
> +    if (!strcmp(mname, "attempt")) {
> +        AR addrReg;
> +        if (args.size() == 4) { //attempt with Offset
> +            AR newAddressReg = valloc(jobj);
> +            rlock(newAddressReg);
> +            addrReg= vstack(3, true).reg();
> +            mov(newAddressReg, addrReg);
> +            AR offsetReg= vstack(0, true).reg();
> +            alu(alu_add, newAddressReg, offsetReg);
> +            runlock(newAddressReg);
> +            addrReg = newAddressReg;
> +            vpop();
> +        } else {
> +            addrReg = vstack(2, true).reg();
> +        }
> +        rlock(addrReg);
> +        AR newReg = vstack(0, true).reg();
> +        rlock(newReg);
> +        AR oldReg = vstack(1, true).reg();
> +
> +        cmpxchg(true, addrReg, newReg, oldReg);
> +
> +        runlock(addrReg);
> +        runlock(newReg);
> +
> +        //save the result
> +        AR resultReg = valloc(i32);
> +        rlock(resultReg);
> +        mov(resultReg, Opnd(g_iconst_0)); 
> +        cmovcc(z, resultReg, vaddr(i32, &g_iconst_1));
> +        runlock(resultReg);
> +
> +        //fixing the stack and saving the result.
> +        vpop();
> +        vpop();
> +        vpop();
> +        vpush(Opnd(i32, resultReg));
> +        
> +        return true;
> +    }
> +
> +    //
> +    // xArray stuff
> +    //
> +    if (!strcmp(mname, "create")) {
> +        VM_Data_Type atype = VM_DATA_TYPE_INT32;
> +        Class_Handle elem_class = class_get_class_of_primitive_type(atype);
> +        assert(elem_class != NULL);
> +        Class_Handle array_class = class_get_array_of_class(elem_class);
> +        assert(array_class != NULL);
> +        Allocation_Handle ah = class_get_allocation_handle(array_class);
> +        gen_new_array(ah);
> +        return true;
> +    }
> +
> +    if (!strcmp(mname, "get")) {
> +        gen_arr_load(jobj);
> +        return true;
> +    }
> +    
> +    if (!strcmp(mname, "set")) {
> +        gen_arr_store(jobj, false);
> +        return true;
> +    }
> +    if (!strcmp(mname, "length")) {
> +        gen_array_length();
> +        return true;
> +    }
> +    //assert(false);
> +    return false;
> +
> +#endif //not em64t
> +}
> +
> +}};             // ~namespace Jitrino::Jet
> 
> 
> 
> 

---------------------------------------------------------------------
Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: harmony-dev-unsubscribe@incubator.apache.org
For additional commands, e-mail: harmony-dev-help@incubator.apache.org