Cache legacy callback interface objects in proto_or_icache_array

We need them to be cached to not instantiate them multiple times with
lazy initialisation.
This commit is contained in:
Anthony Ramine 2016-01-23 23:32:51 +01:00
parent 2c4d5da866
commit ca979e115b
3 changed files with 31 additions and 18 deletions

View file

@ -2379,9 +2379,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
properties should be a PropertyArrays instance. properties should be a PropertyArrays instance.
""" """
def __init__(self, descriptor, properties): def __init__(self, descriptor, properties):
args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', 'global')] args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', 'global'),
if not descriptor.interface.isCallback(): Argument('*mut ProtoOrIfaceArray', 'cache')]
args.append(Argument('*mut ProtoOrIfaceArray', 'cache'))
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args, CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args,
unsafe=True) unsafe=True)
self.properties = properties self.properties = properties
@ -2391,7 +2390,14 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
if self.descriptor.interface.isCallback(): if self.descriptor.interface.isCallback():
assert not self.descriptor.interface.ctor() and self.descriptor.interface.hasConstants() assert not self.descriptor.interface.ctor() and self.descriptor.interface.hasConstants()
return CGGeneric("""\ return CGGeneric("""\
create_callback_interface_object(cx, global, sConstants, %s);""" % str_to_const_array(name)) let mut interface = RootedObject::new(cx, ptr::null_mut());
create_callback_interface_object(cx, global, sConstants, %(name)s, interface.handle_mut());
assert!(!interface.ptr.is_null());
(*cache)[PrototypeList::Constructor::%(id)s as usize] = interface.ptr;
if <*mut JSObject>::needs_post_barrier(interface.ptr) {
<*mut JSObject>::post_barrier((*cache).as_mut_ptr().offset(PrototypeList::Constructor::%(id)s as isize));
}
""" % {"id": name, "name": str_to_const_array(name)})
if len(self.descriptor.prototypeChain) == 1: if len(self.descriptor.prototypeChain) == 1:
if self.descriptor.interface.getExtendedAttribute("ExceptionClass"): if self.descriptor.interface.getExtendedAttribute("ExceptionClass"):
@ -2672,14 +2678,14 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
def definition_body(self): def definition_body(self):
if self.descriptor.interface.isCallback(): if self.descriptor.interface.isCallback():
code = "CreateInterfaceObjects(cx, global);" function = "GetConstructorObject"
else: else:
code = """\ function = "GetProtoObject"
return CGGeneric("""\
assert!(!global.get().is_null());
let mut proto = RootedObject::new(cx, ptr::null_mut()); let mut proto = RootedObject::new(cx, ptr::null_mut());
GetProtoObject(cx, global, proto.handle_mut()); %s(cx, global, proto.handle_mut());
assert!(!proto.ptr.is_null()); assert!(!proto.ptr.is_null());""" % function)
"""
return CGGeneric("assert!(!global.get().is_null());\n" + code)
def needCx(returnType, arguments, considerTypes): def needCx(returnType, arguments, considerTypes):
@ -4956,7 +4962,8 @@ class CGDescriptor(CGThing):
cgThings = [] cgThings = []
if not descriptor.interface.isCallback(): if not descriptor.interface.isCallback():
cgThings.append(CGGetProtoObjectMethod(descriptor)) cgThings.append(CGGetProtoObjectMethod(descriptor))
if descriptor.interface.hasInterfaceObject() and descriptor.hasDescendants(): if (descriptor.interface.hasInterfaceObject() and
descriptor.shouldHaveGetConstructorObjectMethod()):
cgThings.append(CGGetConstructorObjectMethod(descriptor)) cgThings.append(CGGetConstructorObjectMethod(descriptor))
for m in descriptor.interface.members: for m in descriptor.interface.members:
@ -6093,7 +6100,8 @@ class GlobalGenRoots():
# Prototype ID enum. # Prototype ID enum.
interfaces = config.getDescriptors(isCallback=False) interfaces = config.getDescriptors(isCallback=False)
protos = [d.name for d in interfaces] protos = [d.name for d in interfaces]
constructors = [d.name for d in interfaces if d.hasDescendants()] constructors = [d.name for d in config.getDescriptors(hasInterfaceObject=True)
if d.shouldHaveGetConstructorObjectMethod()]
proxies = [d.name for d in config.getDescriptors(proxy=True)] proxies = [d.name for d in config.getDescriptors(proxy=True)]
return CGList([ return CGList([

View file

@ -345,6 +345,10 @@ class Descriptor(DescriptorProvider):
return (self.interface.getUserData("hasConcreteDescendant", False) or return (self.interface.getUserData("hasConcreteDescendant", False) or
self.interface.getUserData("hasProxyDescendant", False)) self.interface.getUserData("hasProxyDescendant", False))
def shouldHaveGetConstructorObjectMethod(self):
assert self.interface.hasInterfaceObject()
return self.interface.isCallback() or self.hasDescendants()
def isGlobal(self): def isGlobal(self):
""" """
Returns true if this is the primary interface for a global object Returns true if this is the primary interface for a global object

View file

@ -178,13 +178,14 @@ pub unsafe fn create_callback_interface_object(
cx: *mut JSContext, cx: *mut JSContext,
receiver: HandleObject, receiver: HandleObject,
constants: &'static [ConstantSpec], constants: &'static [ConstantSpec],
name: &'static [u8]) { name: &'static [u8],
rval: MutableHandleObject) {
assert!(!constants.is_empty()); assert!(!constants.is_empty());
let interface_object = RootedObject::new(cx, JS_NewObject(cx, ptr::null())); rval.set(JS_NewObject(cx, ptr::null()));
assert!(!interface_object.ptr.is_null()); assert!(!rval.ptr.is_null());
define_constants(cx, interface_object.handle(), constants); define_constants(cx, rval.handle(), constants);
define_name(cx, interface_object.handle(), name); define_name(cx, rval.handle(), name);
define_on_global_object(cx, receiver, name, interface_object.handle()); define_on_global_object(cx, receiver, name, rval.handle());
} }
/// Create the interface prototype object of a non-callback interface. /// Create the interface prototype object of a non-callback interface.