Bug 820862. JSJitInfo should say what sort of function it is. r=jandem, a=akeybl
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 13 Dec 2012 17:08:16 -0500
changeset 122107 e3819aecff294f26975bacc89fbe8dc3791ffaa7
parent 122106 7d2decad5ef61189e67cca702d65ca877a0c6171
child 122108 5ae606d1b31bae809e22d82af7747ab7259256f9
push id1997
push userakeybl@mozilla.com
push dateMon, 07 Jan 2013 21:25:26 +0000
treeherdermozilla-beta@4baf45cdcf21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem, akeybl
bugs820862
milestone19.0a2
Bug 820862. JSJitInfo should say what sort of function it is. r=jandem, a=akeybl
dom/bindings/Codegen.py
js/src/ion/IonBuilder.cpp
js/src/jsfriendapi.h
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -4087,16 +4087,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.
     """
@@ -4174,16 +4175,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.
     """
@@ -4253,16 +4255,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):
@@ -4348,41 +4351,42 @@ class CGMemberJITInfo(CGThing):
     """
     def __init__(self, descriptor, member):
         self.member = member
         self.descriptor = descriptor
 
     def declare(self):
         return ""
 
-    def defineJitInfo(self, infoName, opName, infallible):
+    def defineJitInfo(self, infoName, opName, opType, infallible):
         protoID = "prototypes::id::%s" % self.descriptor.name
         depth = "PrototypeTraits<%s>::Depth" % protoID
         failstr = "true" if infallible else "false"
         return ("\n"
                 "const JSJitInfo %s = {\n"
                 "  %s,\n"
                 "  %s,\n"
                 "  %s,\n"
+                "  JSJitInfo::%s,\n"
                 "  %s,  /* isInfallible. False in setters. */\n"
                 "  false  /* isConstant. Only relevant for getters. */\n"
-                "};\n" % (infoName, opName, protoID, depth, failstr))
+                "};\n" % (infoName, opName, protoID, depth, opType, failstr))
 
     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)
-            result = self.defineJitInfo(getterinfo, getter, getterinfal)
+            result = self.defineJitInfo(getterinfo, getter, "Getter", getterinfal)
             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)
+                result += self.defineJitInfo(setterinfo, setter, "Setter", 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
@@ -4393,17 +4397,17 @@ 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)
+            result = self.defineJitInfo(methodinfo, method, "Method", methodInfal)
             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
@@ -5533,27 +5533,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)
@@ -5889,17 +5892,17 @@ IonBuilder::getPropTryConstant(bool *emi
         current->add(MGuardObject::New(obj));
 	else if (testString)
         current->add(MGuardString::New(obj));
 
     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);
@@ -5951,17 +5954,17 @@ IonBuilder::getPropTryCommonGetter(bool 
     if (!TestCommonPropFunc(cx, unaryTypes.inTypes, id, &commonGetter, true, &isDOM))
         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->op, obj, jitinfo->isInfallible);
         current->add(get);
         current->push(get);
 
         if (!resumeAfter(get))
             return false;
         if (!pushTypeBarrier(get, types, barrier))
@@ -6106,17 +6109,17 @@ IonBuilder::jsop_setprop(HandlePropertyN
     types::StackTypeSet *types = binaryTypes.lhsTypes;
 
     JSFunction *commonSetter;
     bool isDOM;
     if (!TestCommonPropFunc(cx, types, id, &commonSetter, false, &isDOM))
         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
@@ -1423,19 +1423,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);