harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From wjwashb...@apache.org
Subject 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
Date Fri, 06 Oct 2006 19:52:21 GMT
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



Mime
View raw message