aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2015-10-28 01:06:06 +0530
committerbors-servo <lbergstrom+bors@mozilla.com>2015-10-28 01:06:06 +0530
commitd1295e9e7d0acfa32a55827fa8e28a297dbcf214 (patch)
tree5c0e50e8503a86d2f53adc0329681ef74a28f830 /components/script/dom/bindings/codegen
parent98dc67dbec7f4f9a6d8b62d75a9b2e0aca91eb7d (diff)
parent4f649ac6dde24f0d70791ca94ae8abe2538149e1 (diff)
downloadservo-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.py95
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}',