Bug 820862. JSJitInfo should say what sort of function it is. r=jandem
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 13 Dec 2012 17:08:43 -0500
changeset 125090 55b2d38ac36c986f3d76117be170f17e7dbde297
parent 125089 c603d181b69eb02fa16ebfe11c6cceb5db582795
child 125091 66f91a854410103cdf77d6a884d7b4bdb751fe1d
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs820862
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 820862. JSJitInfo should say what sort of function it is. r=jandem
dom/bindings/Codegen.py
js/src/ion/IonBuilder.cpp
js/src/jsfriendapi.h
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -4212,16 +4212,17 @@ class CGGenericMethod(CGAbstractBindingM
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
                 Argument('JS::Value*', 'vp')]
         CGAbstractBindingMethod.__init__(self, descriptor, 'genericMethod', args)
 
     def generate_code(self):
         return CGIndenter(CGGeneric(
             "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
+            "MOZ_ASSERT(info->type == JSJitInfo::Method);\n"
             "JSJitMethodOp method = (JSJitMethodOp)info->op;\n"
             "return method(cx, obj, self, argc, vp);"))
 
 class CGSpecializedMethod(CGAbstractStaticMethod):
     """
     A class for generating the C++ code for a specialized method that the JIT
     can call with lower overhead.
     """
@@ -4299,16 +4300,17 @@ class CGGenericGetter(CGAbstractBindingM
             name = "genericGetter"
             unwrapFailureCode = None
         CGAbstractBindingMethod.__init__(self, descriptor, name, args,
                                          unwrapFailureCode)
 
     def generate_code(self):
         return CGIndenter(CGGeneric(
             "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
+            "MOZ_ASSERT(info->type == JSJitInfo::Getter);\n"
             "JSJitPropertyOp getter = info->op;\n"
             "return getter(cx, obj, self, vp);"))
 
 class CGSpecializedGetter(CGAbstractStaticMethod):
     """
     A class for generating the code for a specialized attribute getter
     that the JIT can call with lower overhead.
     """
@@ -4378,16 +4380,17 @@ class CGGenericSetter(CGAbstractBindingM
     def generate_code(self):
         return CGIndenter(CGGeneric(
                 "JS::Value* argv = JS_ARGV(cx, vp);\n"
                 "JS::Value undef = JS::UndefinedValue();\n"
                 "if (argc == 0) {\n"
                 "  argv = &undef;\n"
                 "}\n"
                 "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
+                "MOZ_ASSERT(info->type == JSJitInfo::Setter);\n"
                 "JSJitPropertyOp setter = info->op;\n"
                 "if (!setter(cx, obj, self, argv)) {\n"
                 "  return false;\n"
                 "}\n"
                 "*vp = JSVAL_VOID;\n"
                 "return true;"))
 
 class CGSpecializedSetter(CGAbstractStaticMethod):
@@ -4473,43 +4476,47 @@ class CGMemberJITInfo(CGThing):
     """
     def __init__(self, descriptor, member):
         self.member = member
         self.descriptor = descriptor
 
     def declare(self):
         return ""
 
-    def defineJitInfo(self, infoName, opName, infallible, constant):
+    def defineJitInfo(self, infoName, opName, opType, infallible, constant):
         protoID = "prototypes::id::%s" % self.descriptor.name
         depth = "PrototypeTraits<%s>::Depth" % protoID
         failstr = toStringBool(infallible)
         conststr = toStringBool(constant)
         return ("\n"
                 "const JSJitInfo %s = {\n"
                 "  %s,\n"
                 "  %s,\n"
                 "  %s,\n"
+                "  JSJitInfo::%s,\n"
                 "  %s,  /* isInfallible. False in setters. */\n"
                 "  %s  /* isConstant. Only relevant for getters. */\n"
-                "};\n" % (infoName, opName, protoID, depth, failstr, conststr))
+                "};\n" % (infoName, opName, protoID, depth, opType, failstr,
+                          conststr))
 
     def define(self):
         if self.member.isAttr():
             getterinfo = ("%s_getterinfo" % self.member.identifier.name)
             getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name)
             getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
             getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
             getterconst = self.member.getExtendedAttribute("Constant")
-            result = self.defineJitInfo(getterinfo, getter, getterinfal, getterconst)
+            result = self.defineJitInfo(getterinfo, getter, "Getter",
+                                        getterinfal, getterconst)
             if not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None:
                 setterinfo = ("%s_setterinfo" % self.member.identifier.name)
                 setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name)
                 # Setters are always fallible, since they have to do a typed unwrap.
-                result += self.defineJitInfo(setterinfo, setter, False, False)
+                result += self.defineJitInfo(setterinfo, setter, "Setter",
+                                             False, False)
             return result
         if self.member.isMethod():
             methodinfo = ("%s_methodinfo" % self.member.identifier.name)
             name = CppKeywords.checkMethodName(self.member.identifier.name)
             # Actually a JSJitMethodOp, but JSJitPropertyOp by struct definition.
             method = ("(JSJitPropertyOp)%s" % name)
 
             # Methods are infallible if they are infallible, have no arguments
@@ -4520,17 +4527,18 @@ class CGMemberJITInfo(CGThing):
             if len(sigs) == 1:
                 # Don't handle overloading. If there's more than one signature,
                 # one of them must take arguments.
                 sig = sigs[0]
                 if len(sig[1]) == 0 and infallibleForMember(self.member, sig[0], self.descriptor):
                     # No arguments and infallible return boxing
                     methodInfal = True
 
-            result = self.defineJitInfo(methodinfo, method, methodInfal, False)
+            result = self.defineJitInfo(methodinfo, method, "Method",
+                                        methodInfal, False)
             return result
         raise TypeError("Illegal member type to CGPropertyJITInfo")
 
 def getEnumValueName(value):
     # Some enum values can be empty strings.  Others might have weird
     # characters in them.  Deal with the former by returning "_empty",
     # deal with possible name collisions from that by throwing if the
     # enum value is actually "_empty", and throw on any value
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -5938,27 +5938,30 @@ IonBuilder::TestCommonPropFunc(JSContext
 
     *funcp = found->toFunction();
     *isDOM = thinkDOM;
 
     return true;
 }
 
 static bool
-TestShouldDOMCall(JSContext *cx, types::TypeSet *inTypes, HandleFunction func)
+TestShouldDOMCall(JSContext *cx, types::TypeSet *inTypes, HandleFunction func,
+                  JSJitInfo::OpType opType)
 {
     if (!func->isNative() || !func->jitInfo())
         return false;
     // If all the DOM objects flowing through are legal with this
     // property, we can bake in a call to the bottom half of the DOM
     // accessor
     DOMInstanceClassMatchesProto instanceChecker =
         GetDOMCallbacks(cx->runtime)->instanceClassMatchesProto;
 
     const JSJitInfo *jinfo = func->jitInfo();
+    if (jinfo->type != opType)
+        return false;
 
     for (unsigned i = 0; i < inTypes->getObjectCount(); i++) {
         types::TypeObject *curType = inTypes->getTypeObject(i);
 
         if (!curType) {
             JSObject *curObj = inTypes->getSingleObject(i);
 
             if (!curObj)
@@ -6298,17 +6301,17 @@ IonBuilder::getPropTryConstant(bool *emi
         current->add(MGuardString::New(obj));
     else
         obj->setFoldedUnchecked();
 
     MConstant *known = MConstant::New(ObjectValue(*singleton));
     if (singleton->isFunction()) {
         RootedFunction singletonFunc(cx, singleton->toFunction());
         if (TestAreKnownDOMTypes(cx, unaryTypes.inTypes) &&
-            TestShouldDOMCall(cx, unaryTypes.inTypes, singletonFunc))
+            TestShouldDOMCall(cx, unaryTypes.inTypes, singletonFunc, JSJitInfo::Method))
         {
             FreezeDOMTypes(cx, unaryTypes.inTypes);
             known->setDOMFunction();
         }
     }
 
     current->add(known);
     current->push(known);
@@ -6364,17 +6367,17 @@ IonBuilder::getPropTryCommonGetter(bool 
         return false;
     }
     if (!commonGetter)
         return true;
 
     MDefinition *obj = current->pop();
     RootedFunction getter(cx, commonGetter);
 
-    if (isDOM && TestShouldDOMCall(cx, unaryTypes.inTypes, getter)) {
+    if (isDOM && TestShouldDOMCall(cx, unaryTypes.inTypes, getter, JSJitInfo::Getter)) {
         const JSJitInfo *jitinfo = getter->jitInfo();
         MGetDOMProperty *get = MGetDOMProperty::New(jitinfo, obj, guard);
         current->add(get);
         current->push(get);
 
         if (get->isEffectful() && !resumeAfter(get))
             return false;
         if (!pushTypeBarrier(get, types, barrier))
@@ -6521,17 +6524,17 @@ IonBuilder::jsop_setprop(HandlePropertyN
     types::StackTypeSet *types = binaryTypes.lhsTypes;
 
     JSFunction *commonSetter;
     bool isDOM;
     if (!TestCommonPropFunc(cx, types, id, &commonSetter, false, &isDOM, NULL))
         return false;
     if (!monitored && commonSetter) {
         RootedFunction setter(cx, commonSetter);
-        if (isDOM && TestShouldDOMCall(cx, types, setter)) {
+        if (isDOM && TestShouldDOMCall(cx, types, setter, JSJitInfo::Setter)) {
             MSetDOMProperty *set = MSetDOMProperty::New(setter->jitInfo()->op, obj, value);
             if (!set)
                 return false;
 
             current->add(set);
             current->push(value);
 
             return resumeAfter(set);
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1419,19 +1419,26 @@ JS_GetDataViewData(JSObject *obj);
 typedef bool
 (* JSJitPropertyOp)(JSContext *cx, JSHandleObject thisObj,
                     void *specializedThis, JS::Value *vp);
 typedef bool
 (* JSJitMethodOp)(JSContext *cx, JSHandleObject thisObj,
                   void *specializedThis, unsigned argc, JS::Value *vp);
 
 struct JSJitInfo {
+    enum OpType {
+        Getter,
+        Setter,
+        Method
+    };
+
     JSJitPropertyOp op;
     uint32_t protoID;
     uint32_t depth;
+    OpType type;
     bool isInfallible;    /* Is op fallible? False in setters. */
     bool isConstant;      /* Getting a construction-time constant? */
 };
 
 static JS_ALWAYS_INLINE const JSJitInfo *
 FUNCTION_VALUE_TO_JITINFO(const JS::Value& v)
 {
     JS_ASSERT(js::GetObjectClass(&v.toObject()) == &js::FunctionClass);