Skip to content

Commit

Permalink
Auto merge of #8040 - froydnj:codegen-arg-info, r=jdm
Browse files Browse the repository at this point in the history
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 -->
  • Loading branch information
bors-servo committed Oct 27, 2015
2 parents 98dc67d + 4f649ac commit d1295e9
Showing 1 changed file with 93 additions and 2 deletions.
95 changes: 93 additions & 2 deletions components/script/dom/bindings/codegen/CodegenRust.py
Expand Up @@ -1445,7 +1445,11 @@ def specData(m):
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"
Expand Down Expand Up @@ -3089,6 +3093,26 @@ def jitInfoInitializer(isTypedMethod):
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)))
Expand Down Expand Up @@ -3290,6 +3314,73 @@ def getSingleReturnType(existingType, t):
# 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
Expand Down Expand Up @@ -5086,7 +5177,7 @@ def __init__(self, config, prefix, webIDLFile):
'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}',
Expand Down

0 comments on commit d1295e9

Please sign in to comment.