Bug 558327 - JIT support for in (has) operator (r=edwsmith+)
authorFelix Klock II <fklockii@adobe.com>
Thu, 01 Jul 2010 09:05:01 -0400
changeset 4902 d4ae1396db36cbd31a0dbac05573a1dcfd433e99
parent 4901 678fe4255f0fdf4e4ff519ee9085ddb3a028dbc8
child 4903 6b542c6509d2117376181a2d3299b200446cd116
push id2603
push useredwsmith@adobe.com
push dateThu, 01 Jul 2010 13:05:07 +0000
reviewersedwsmith
bugs558327
Bug 558327 - JIT support for in (has) operator (r=edwsmith+)
core/CodegenLIR.cpp
core/MethodEnv.cpp
core/MethodEnv.h
core/jit-calls.h
--- a/core/CodegenLIR.cpp
+++ b/core/CodegenLIR.cpp
@@ -4885,20 +4885,37 @@ namespace avmplus
                 LIns* out = callIns(FUNCTIONID(instanceof), 3, env_param, lhs, rhs);
                 out = atomToNativeRep(result, out);
                 localSet(sp-1,  out, result);
                 break;
             }
 
             case OP_in:
             {
-                LIns* lhs = loadAtomRep(sp-1);
-                LIns* rhs = loadAtomRep(sp);
-                LIns* out = callIns(FUNCTIONID(op_in), 3, env_param, lhs, rhs);
-                out = atomToNativeRep(result, out);
+                // sp[-1] = env->in_operator(sp[-1], sp[0])
+                int lhsDisp = sp-1;
+                LIns *lhs;
+                LIns *rhs = loadAtomRep(sp);
+                LIns *out;
+                Traits *lhsType = state->value(lhsDisp).traits;
+                switch (bt(lhsType)) {
+                case BUILTIN_uint:
+                    lhs = localGet(lhsDisp);
+                    out = callIns(FUNCTIONID(haspropertylate_u), 3, env_param, rhs, lhs);
+                    break;
+                case BUILTIN_int:
+                    lhs = localGet(lhsDisp);
+                    out = callIns(FUNCTIONID(haspropertylate_i), 3, env_param, rhs, lhs);
+                    break;
+                default:
+                    lhs = loadAtomRep(lhsDisp);
+                    out = callIns(FUNCTIONID(op_in), 3, env_param, lhs, rhs);
+                    out = atomToNativeRep(result, out);
+                    break;
+                }
                 localSet(sp-1, out, result);
                 break;
             }
 
             case OP_dxns:
             {
                 LIns* uri = InsConstPtr((String*)op1); // namespace uri from string pool
                 callIns(FUNCTIONID(setDxns), 3, coreAddr, methodFrame, uri);
--- a/core/MethodEnv.cpp
+++ b/core/MethodEnv.cpp
@@ -426,16 +426,42 @@ namespace avmplus
         extra_8 = (char*)ap + rest_offset;
         const int param_count = ms->param_count();
         const int extra_count = argc > param_count ? argc - param_count : 0;
         return toplevel()->arrayClass->newarray(extra, extra_count);
     }
 
 #endif // FEATURE_NANOJIT
 
+    /*bool*/ int32_t MethodEnv::haspropertylate_u(Atom obj, uint32_t index) const
+    {
+        // keep in sync with Toplevel::in_operator
+        ScriptObject *o = (atomKind(obj) == kObjectType) ?
+            AvmCore::atomToScriptObject(obj) :
+            this->toplevel()->toPrototype(obj);
+        bool present = o->hasUintProperty(index);
+        return (int32_t)present;
+    }
+
+    /*bool*/ int32_t MethodEnv::haspropertylate_i(Atom obj, int32_t index) const
+    {
+        // keep in sync with Toplevel::in_operator
+        ScriptObject *o = (atomKind(obj) == kObjectType) ?
+            AvmCore::atomToScriptObject(obj) :
+            this->toplevel()->toPrototype(obj);
+        bool present;
+        if (index >= 0) {
+            present = o->hasUintProperty((uint32_t)index);
+        } else {
+            Atom interned = this->core()->internInt(index)->atom();
+            present = o->hasAtomProperty(interned);
+        }
+        return (int32_t)present;
+    }
+
     Atom MethodEnv::getpropertylate_i(Atom obj, int32_t index) const
     {
         // here we put the case for bind-none, since we know there are no bindings
         // with numeric names.
         if (atomKind(obj) == kObjectType)
         {
             if (index >= 0)
             {
--- a/core/MethodEnv.h
+++ b/core/MethodEnv.h
@@ -103,16 +103,18 @@ namespace avmplus
 
     // helper functions used from compiled code
     public:
         void argcError(int32_t argc); // never returns; throws argument count error
 
         ArrayObject* createRest(Atom* argv, int32_t argc);
         Atom getpropertylate_i(Atom obj, int32_t index) const;
         Atom getpropertylate_u(Atom obj, uint32_t index) const;
+        /*bool*/ int32_t haspropertylate_i(Atom obj, int32_t index) const;
+        /*bool*/ int32_t haspropertylate_u(Atom obj, uint32_t index) const;
 
 #if defined FEATURE_NANOJIT || defined VMCFG_AOT
         void setpropertyHelper(Atom obj, /* not const */ Multiname *multi, Atom value, VTable *vtable, Atom index);
         void initpropertyHelper(Atom obj, /* not const */ Multiname *multi, Atom value, VTable *vtable, Atom index);
         Atom getpropertyHelper(Atom obj, /* not const */ Multiname *multi, VTable *vtable, Atom index);
         Atom delpropertyHelper(Atom obj, /* not const */ Multiname *multi, Atom index);
 
         void initMultinameLateForDelete(Multiname& name, Atom index);
--- a/core/jit-calls.h
+++ b/core/jit-calls.h
@@ -955,16 +955,18 @@ static const ArgType ARGTYPE_A = ARGTYPE
     METHOD(VECTORDOUBLEADDR(DoubleVectorObject::_getIntProperty), SIG2(A,P,I), DoubleVectorObject_getIntProperty)
     METHOD(VECTORDOUBLEADDR(DoubleVectorObject::_getNativeIntProperty), SIG2(F,P,I), DoubleVectorObject_getNativeIntProperty)
     METHOD(VECTORINTADDR(IntVectorObject::_getIntProperty), SIG2(A,P,I), IntVectorObject_getIntProperty)
     METHOD(VECTORUINTADDR(UIntVectorObject::_getIntProperty), SIG2(A,P,I), UIntVectorObject_getIntProperty)
     METHOD(VECTORINTADDR(IntVectorObject::_getNativeIntProperty), SIG2(I,P,I), IntVectorObject_getNativeIntProperty)
     METHOD(VECTORUINTADDR(UIntVectorObject::_getNativeIntProperty), SIG2(U,P,I), UIntVectorObject_getNativeIntProperty)
     METHOD(ARRAYADDR(ArrayObject::_getIntProperty), SIG2(A,P,I), ArrayObject_getIntProperty)
     METHOD(VECTOROBJADDR(ObjectVectorObject::_getIntProperty), SIG2(A,P,I), ObjectVectorObject_getIntProperty)
+    METHOD(ENVADDR(MethodEnv::haspropertylate_u), SIG3(I,P,A,U), haspropertylate_u)
+    METHOD(ENVADDR(MethodEnv::haspropertylate_i), SIG3(I,P,A,I), haspropertylate_i)
     METHOD(ENVADDR(MethodEnv::findproperty), SIG7(A,P,P,P,I,P,B,P), findproperty)
     METHOD(ENVADDR(MethodEnv::checkfilter), SIG2(V,P,A), checkfilter)
     METHOD(ENVADDR(MethodEnv::getdescendants), SIG3(A,P,A,P), getdescendants)
     METHOD(ENVADDR(MethodEnv::newclass), SIG5(P,P,P,P,P,P), newclass)
     METHOD(ENVADDR(MethodEnv::op_newobject), SIG3(P,P,P,I), op_newobject)
 
     typedef Atom (*constructprop_MethodEnv)(MethodEnv*, const Multiname*, int, Atom*);
     FUNCTION(FUNCADDR((constructprop_MethodEnv)&constructprop<MethodEnv*>), SIG4(A,P,P,I,P), construct_late)