diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2015-10-28 01:06:06 +0530 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2015-10-28 01:06:06 +0530 |
commit | d1295e9e7d0acfa32a55827fa8e28a297dbcf214 (patch) | |
tree | 5c0e50e8503a86d2f53adc0329681ef74a28f830 /components/script/dom/bindings/codegen | |
parent | 98dc67dbec7f4f9a6d8b62d75a9b2e0aca91eb7d (diff) | |
parent | 4f649ac6dde24f0d70791ca94ae8abe2538149e1 (diff) | |
download | servo-d1295e9e7d0acfa32a55827fa8e28a297dbcf214.tar.gz servo-d1295e9e7d0acfa32a55827fa8e28a297dbcf214.zip |
Auto merge of #8040 - froydnj:codegen-arg-info, r=jdm
generate JIT argument type information for methods
This enhances `CodegenRust.py` to output `JSTypedMethodJitInfo` structures where appropriate. This brings a notable speedup to tests like Dromaeo's `dom-attr/getAttribute`, which improves by several orders of magnitude with these patches applied.
If there are tricks for addressing the XXX comments, I would appreciate hearing them.
I think this addresses all of #6904.
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8040)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom/bindings/codegen')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 95 |
1 files changed, 93 insertions, 2 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index b251c4cc66a..2350203d549 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1445,7 +1445,11 @@ class MethodDefiner(PropertyDefiner): selfHostedName = "0 as *const libc::c_char" if m.get("methodInfo", True): identifier = m.get("nativeName", m["name"]) - jitinfo = "&%s_methodinfo" % identifier + # Go through an intermediate type here, because it's not + # easy to tell whether the methodinfo is a JSJitInfo or + # a JSTypedMethodJitInfo here. The compiler knows, though, + # so let it do the work. + jitinfo = "&%s_methodinfo as *const _ as *const JSJitInfo" % identifier accessor = "Some(generic_method)" else: jitinfo = "0 as *const JSJitInfo" @@ -3089,6 +3093,26 @@ class CGMemberJITInfo(CGThing): slotIndex=slotIndex) return initializer.rstrip() + if args is not None: + argTypes = "%s_argTypes" % infoName + args = [CGMemberJITInfo.getJSArgType(arg.type) for arg in args] + args.append("ArgType::ArgTypeListEnd as i32") + argTypesDecl = ( + "const %s: [i32; %d] = [ %s ];\n" % + (argTypes, len(args), ", ".join(args))) + return fill( + """ + $*{argTypesDecl} + const ${infoName}: JSTypedMethodJitInfo = JSTypedMethodJitInfo { + base: ${jitInfo}, + argTypes: &${argTypes} as *const _ as *const ArgType, + }; + """, + argTypesDecl=argTypesDecl, + infoName=infoName, + jitInfo=indent(jitInfoInitializer(True)), + argTypes=argTypes) + return ("\n" "const %s: JSJitInfo = %s;\n" % (infoName, jitInfoInitializer(False))) @@ -3290,6 +3314,73 @@ class CGMemberJITInfo(CGThing): # Different types return "JSVAL_TYPE_UNKNOWN" + @staticmethod + def getJSArgType(t): + assert not t.isVoid() + if t.nullable(): + # Sometimes it might return null, sometimes not + return "ArgType::Null as i32 | %s" % CGMemberJITInfo.getJSArgType(t.inner) + if t.isArray(): + # No idea yet + assert False + if t.isSequence(): + return "ArgType::Object as i32" + if t.isGeckoInterface(): + return "ArgType::Object as i32" + if t.isString(): + return "ArgType::String as i32" + if t.isEnum(): + return "ArgType::String as i32" + if t.isCallback(): + return "ArgType::Object as i32" + if t.isAny(): + # The whole point is to return various stuff + return "ArgType::Any as i32" + if t.isObject(): + return "ArgType::Object as i32" + if t.isSpiderMonkeyInterface(): + return "ArgType::Object as i32" + if t.isUnion(): + u = t.unroll() + type = "JSJitInfo::Null as i32" if u.hasNullableType else "" + return reduce(CGMemberJITInfo.getSingleArgType, + u.flatMemberTypes, type) + if t.isDictionary(): + return "ArgType::Object as i32" + if t.isDate(): + return "ArgType::Object as i32" + if not t.isPrimitive(): + raise TypeError("No idea what type " + str(t) + " is.") + tag = t.tag() + if tag == IDLType.Tags.bool: + return "ArgType::Boolean as i32" + if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, + IDLType.Tags.int16, IDLType.Tags.uint16, + IDLType.Tags.int32]: + return "ArgType::Integer as i32" + if tag in [IDLType.Tags.int64, IDLType.Tags.uint64, + IDLType.Tags.unrestricted_float, IDLType.Tags.float, + IDLType.Tags.unrestricted_double, IDLType.Tags.double]: + # These all use JS_NumberValue, which can return int or double. + # But TI treats "double" as meaning "int or double", so we're + # good to return JSVAL_TYPE_DOUBLE here. + return "ArgType::Double as i32" + if tag != IDLType.Tags.uint32: + raise TypeError("No idea what type " + str(t) + " is.") + # uint32 is sometimes int and sometimes double. + return "ArgType::Double as i32" + + @staticmethod + def getSingleArgType(existingType, t): + type = CGMemberJITInfo.getJSArgType(t) + if existingType == "": + # First element of the list; just return its type + return type + + if type == existingType: + return existingType + return "%s | %s" % (existingType, type) + def getEnumValueName(value): # Some enum values can be empty strings. Others might have weird @@ -5086,7 +5177,7 @@ class CGBindingRoot(CGThing): 'js::jsapi::{RootedValue, JSNativeWrapper, JSNative, JSObject, JSPropertyDescriptor}', 'js::jsapi::{RootedId, JS_InternString, RootedString, INTERNED_STRING_TO_JSID}', 'js::jsapi::{JSPropertySpec}', - 'js::jsapi::{JSString, JSTracer, JSJitInfo, OpType, AliasSet}', + 'js::jsapi::{JSString, JSTracer, JSJitInfo, JSTypedMethodJitInfo, OpType, AliasSet, ArgType}', 'js::jsapi::{MutableHandle, Handle, HandleId, JSType, JSValueType}', 'js::jsapi::{SymbolCode, ObjectOpResult, HandleValueArray}', 'js::jsapi::{JSJitGetterCallArgs, JSJitSetterCallArgs, JSJitMethodCallArgs, CallArgs}', |