From 83e5da85cc36162957d47f37319ad747182596f4 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 25 Nov 2013 20:59:37 -0500 Subject: [PATCH] Bug 935855 part 2. Store isSlot information in jitinfo. r=peterv,efaust --- dom/bindings/Codegen.py | 24 +++++++++++++++++++----- dom/bindings/parser/WebIDL.py | 1 + js/src/jsfriendapi.h | 8 +++++++- js/src/shell/js.cpp | 21 ++++++++++++++++++--- 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 57448f21873..ba4b985fd30 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -25,6 +25,7 @@ HASINSTANCE_HOOK_NAME = '_hasInstance' NEWRESOLVE_HOOK_NAME = '_newResolve' ENUMERATE_HOOK_NAME= '_enumerate' ENUM_ENTRY_VARIABLE_NAME = 'strings' +INSTANCE_RESERVED_SLOTS = 3 def replaceFileIfChanged(filename, newContents): """ @@ -192,12 +193,13 @@ class CGDOMJSClass(CGThing): def define(self): traceHook = TRACE_HOOK_NAME if self.descriptor.customTrace else 'nullptr' callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr' + slotCount = INSTANCE_RESERVED_SLOTS classFlags = "JSCLASS_IS_DOMJSCLASS | " if self.descriptor.interface.getExtendedAttribute("Global"): classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS) | JSCLASS_IMPLEMENTS_BARRIERS" traceHook = "mozilla::dom::TraceGlobal" else: - classFlags += "JSCLASS_HAS_RESERVED_SLOTS(3)" + classFlags += "JSCLASS_HAS_RESERVED_SLOTS(%d)" % slotCount if self.descriptor.interface.getExtendedAttribute("NeedNewResolve"): newResolveHook = "(JSResolveOp)" + NEWRESOLVE_HOOK_NAME classFlags += " | JSCLASS_NEW_RESOLVE" @@ -6001,13 +6003,15 @@ class CGMemberJITInfo(CGThing): return "" def defineJitInfo(self, infoName, opName, opType, infallible, constant, - pure, returnTypes): + pure, hasSlot, slotIndex, returnTypes): assert(not constant or pure) # constants are always pure + assert(not hasSlot or pure) # Things with slots had better be pure protoID = "prototypes::id::%s" % self.descriptor.name depth = "PrototypeTraits<%s>::Depth" % protoID failstr = toStringBool(infallible) conststr = toStringBool(constant) purestr = toStringBool(pure) + slotStr = toStringBool(hasSlot) returnType = reduce(CGMemberJITInfo.getSingleReturnType, returnTypes, "") return ("\n" @@ -6019,9 +6023,12 @@ class CGMemberJITInfo(CGThing): " %s, /* isInfallible. False in setters. */\n" " %s, /* isConstant. Only relevant for getters. */\n" " %s, /* isPure. Only relevant for getters. */\n" + " %s, /* hasSlot. Only relevant for getters. */\n" + " %d, /* Reserved slot index, if we're stored in a slot, else 0. */\n" " %s /* returnType. Only relevant for getters/methods. */\n" "};\n" % (infoName, opName, protoID, depth, opType, failstr, - conststr, purestr, returnType)) + conststr, purestr, slotStr, slotIndex, + returnType)) def define(self): if self.member.isAttr(): @@ -6036,8 +6043,15 @@ class CGMemberJITInfo(CGThing): assert (getterinfal or (not getterconst and not getterpure)) getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor) + isInSlot = self.member.getExtendedAttribute("StoreInSlot") + if isInSlot: + slotIndex = INSTANCE_RESERVED_SLOTS + self.member.slotIndex; + else: + slotIndex = 0 + result = self.defineJitInfo(getterinfo, getter, "Getter", getterinfal, getterconst, getterpure, + isInSlot, slotIndex, [self.member.type]) if (not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None or @@ -6048,7 +6062,7 @@ class CGMemberJITInfo(CGThing): setter = ("(JSJitGetterOp)set_%s" % self.member.identifier.name) # Setters are always fallible, since they have to do a typed unwrap. result += self.defineJitInfo(setterinfo, setter, "Setter", - False, False, False, + False, False, False, False, 0, [BuiltinTypes[IDLBuiltinType.Types.void]]) return result if self.member.isMethod(): @@ -6075,7 +6089,7 @@ class CGMemberJITInfo(CGThing): methodInfal = "infallible" in self.descriptor.getExtendedAttributes(self.member) result = self.defineJitInfo(methodinfo, method, "Method", - methodInfal, False, False, + methodInfal, False, False, False, 0, [s[0] for s in sigs]) return result raise TypeError("Illegal member type to CGPropertyJITInfo") diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index dc2fd276a65..94da97faa60 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -2603,6 +2603,7 @@ class IDLAttribute(IDLInterfaceMember): self.stringifier = stringifier self.enforceRange = False self.clamp = False + self.slotIndex = 0 if static and identifier.name == "prototype": raise WebIDLError("The identifier of a static attribute must not be 'prototype'", diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index e9e54f26222..eb0a4c0879c 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1453,6 +1453,12 @@ struct JSJitInfo { bool isPure; /* As long as no non-pure DOM things happen, will keep returning the same value for the given "this" object" */ + // XXXbz should we have a JSGetterJitInfo subclass or something? + // XXXbz should we have a JSValueType for the type of the member? + bool isInSlot; /* True if this is a getter that can get a member + from a slot of the "this" object directly. */ + size_t slotIndex; /* If isMember is true, the index of the slot to get + the value from. Otherwise 0. */ JSValueType returnType; /* The return type tag. Might be JSVAL_TYPE_UNKNOWN */ /* An alternative native that's safe to call in parallel mode. */ @@ -1460,7 +1466,7 @@ struct JSJitInfo { }; #define JS_JITINFO_NATIVE_PARALLEL(op) \ - {{nullptr},0,0,JSJitInfo::OpType_None,false,false,false,JSVAL_TYPE_MISSING,op} + {{nullptr},0,0,JSJitInfo::OpType_None,false,false,false,false,0,JSVAL_TYPE_MISSING,op} static JS_ALWAYS_INLINE const JSJitInfo * FUNCTION_VALUE_TO_JITINFO(const JS::Value& v) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 29992017ea7..3fe529e2c08 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -4792,7 +4792,12 @@ static const JSJitInfo dom_x_getterinfo = { 0, /* depth */ JSJitInfo::Getter, true, /* isInfallible. False in setters. */ - true /* isConstant. Only relevant for getters. */ + true, /* isConstant. Only relevant for getters. */ + true, /* isPure */ + false, /* isInSlot */ + 0, /* slotIndex */ + JSVAL_TYPE_UNKNOWN, /* returnType */ + nullptr /* parallelNative */ }; static const JSJitInfo dom_x_setterinfo = { @@ -4801,7 +4806,12 @@ static const JSJitInfo dom_x_setterinfo = { 0, /* depth */ JSJitInfo::Setter, false, /* isInfallible. False in setters. */ - false /* isConstant. Only relevant for getters. */ + false, /* isConstant. Only relevant for getters. */ + false, /* isPure */ + false, /* isInSlot */ + 0, /* slotIndex */ + JSVAL_TYPE_UNKNOWN, /* returnType */ + nullptr /* parallelNative */ }; static const JSJitInfo doFoo_methodinfo = { @@ -4810,7 +4820,12 @@ static const JSJitInfo doFoo_methodinfo = { 0, /* depth */ JSJitInfo::Method, false, /* isInfallible. False in setters. */ - false /* isConstant. Only relevant for getters. */ + false, /* isConstant. Only relevant for getters. */ + false, /* isPure */ + false, /* isInSlot */ + 0, /* slotIndex */ + JSVAL_TYPE_UNKNOWN, /* returnType */ + nullptr /* parallelNative */ }; static const JSPropertySpec dom_props[] = {