Store proxy handlers in a static array rather than a hashtable per window.

This commit is contained in:
Ms2ger 2014-07-11 17:03:31 +02:00
parent f47b66b0c1
commit fd167f8922
4 changed files with 85 additions and 38 deletions

View file

@ -19,6 +19,7 @@ extern crate servo_net = "net";
extern crate servo_msg = "msg"; extern crate servo_msg = "msg";
#[phase(plugin, link)] #[phase(plugin, link)]
extern crate servo_util = "util"; extern crate servo_util = "util";
extern crate script;
extern crate green; extern crate green;
extern crate gfx; extern crate gfx;
extern crate libc; extern crate libc;
@ -30,6 +31,8 @@ extern crate url;
use compositing::{CompositorChan, CompositorTask, Constellation}; use compositing::{CompositorChan, CompositorTask, Constellation};
#[cfg(not(test))] #[cfg(not(test))]
use servo_msg::constellation_msg::{ConstellationChan, InitLoadUrlMsg}; use servo_msg::constellation_msg::{ConstellationChan, InitLoadUrlMsg};
#[cfg(not(test))]
use script::dom::bindings::codegen::RegisterBindings;
#[cfg(not(test))] #[cfg(not(test))]
use servo_net::image_cache_task::ImageCacheTask; use servo_net::image_cache_task::ImageCacheTask;
@ -94,6 +97,8 @@ pub extern "C" fn android_start(argc: int, argv: **u8) -> int {
#[cfg(not(test))] #[cfg(not(test))]
pub fn run(opts: opts::Opts) { pub fn run(opts: opts::Opts) {
RegisterBindings::RegisterProxyHandlers();
let mut pool_config = green::PoolConfig::new(); let mut pool_config = green::PoolConfig::new();
pool_config.event_loop_factory = rustuv::event_loop; pool_config.event_loop_factory = rustuv::event_loop;
let mut pool = green::SchedPool::new(pool_config); let mut pool = green::SchedPool::new(pool_config);

View file

@ -1763,12 +1763,10 @@ def CreateBindingJSObject(descriptor, parent=None):
if descriptor.proxy: if descriptor.proxy:
assert not descriptor.createGlobal assert not descriptor.createGlobal
create += """ create += """
let js_info = aScope.deref().page().js_info(); let handler = RegisterBindings::proxy_handlers[PrototypeList::proxies::%s as uint];
let mut handlers = js_info.get_ref().dom_static.proxy_handlers.deref().borrow_mut();
let handler = handlers.get(&(PrototypeList::id::%s as uint));
let mut private = PrivateValue(squirrel_away_unique(aObject) as *libc::c_void); let mut private = PrivateValue(squirrel_away_unique(aObject) as *libc::c_void);
let obj = with_compartment(aCx, proto, || { let obj = with_compartment(aCx, proto, || {
NewProxyObject(aCx, *handler, NewProxyObject(aCx, handler,
&private, &private,
proto, %s, proto, %s,
ptr::mut_null(), ptr::mut_null()) ptr::mut_null(), ptr::mut_null())
@ -2039,26 +2037,21 @@ class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
CGGetPerInterfaceObject.definition_body(self), CGGetPerInterfaceObject.definition_body(self),
]) ])
class CGDefineDOMInterfaceMethod(CGAbstractMethod):
class CGDefineProxyHandler(CGAbstractMethod):
""" """
A method for resolve hooks to try to lazily define the interface object for A method to create and cache the proxy trap for a given interface.
a given interface.
""" """
def __init__(self, descriptor): def __init__(self, descriptor):
args = [ assert descriptor.proxy
Argument('&JSRef<Window>', 'window'), CGAbstractMethod.__init__(self, descriptor, 'DefineProxyHandler', '*libc::c_void', [], pub=True)
Argument('&mut JSPageInfo', 'js_info'),
]
CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'void', args, pub=True)
def define(self): def define(self):
return CGAbstractMethod.define(self) return CGAbstractMethod.define(self)
def definition_body(self): def definition_body(self):
body = CGList([]) body = """\
#XXXjdm This self.descriptor.concrete check shouldn't be necessary let traps = ProxyTraps {
if not self.descriptor.concrete or self.descriptor.proxy:
body.append(CGGeneric("""let traps = ProxyTraps {
getPropertyDescriptor: Some(getPropertyDescriptor), getPropertyDescriptor: Some(getPropertyDescriptor),
getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor), getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor),
defineProperty: Some(defineProperty), defineProperty: Some(defineProperty),
@ -2089,21 +2082,35 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
getPrototypeOf: None, getPrototypeOf: None,
trace: Some(%s) trace: Some(%s)
}; };
let mut handlers = js_info.dom_static.proxy_handlers.deref().borrow_mut();
handlers.insert(PrototypeList::id::%s as uint,
CreateProxyHandler(&traps, &Class as *_ as *_));
CreateProxyHandler(&traps, &Class as *_ as *_)
""" % (FINALIZE_HOOK_NAME, """ % (FINALIZE_HOOK_NAME,
TRACE_HOOK_NAME, TRACE_HOOK_NAME)
self.descriptor.name))) return CGGeneric(body)
if self.descriptor.interface.hasInterfaceObject():
body.append(CGGeneric("""let cx = (**js_info.js_context).ptr;
class CGDefineDOMInterfaceMethod(CGAbstractMethod):
"""
A method for resolve hooks to try to lazily define the interface object for
a given interface.
"""
def __init__(self, descriptor):
assert descriptor.interface.hasInterfaceObject()
args = [
Argument('&JSRef<Window>', 'window'),
]
CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'void', args, pub=True)
def define(self):
return CGAbstractMethod.define(self)
def definition_body(self):
return CGGeneric("""\
let cx = window.get_cx();
let global = window.reflector().get_jsobject(); let global = window.reflector().get_jsobject();
assert!(global.is_not_null()); assert!(global.is_not_null());
assert!(GetProtoObject(cx, global, global).is_not_null());""")) assert!(GetProtoObject(cx, global, global).is_not_null());""")
return body
def needCx(returnType, arguments, extendedAttributes, considerTypes): def needCx(returnType, arguments, extendedAttributes, considerTypes):
return (considerTypes and return (considerTypes and
@ -4019,8 +4026,12 @@ class CGDescriptor(CGThing):
CGConstant(m for m in descriptor.interface.members if m.isConst()), CGConstant(m for m in descriptor.interface.members if m.isConst()),
public=True)) public=True))
if descriptor.interface.hasInterfaceObject():
cgThings.append(CGDefineDOMInterfaceMethod(descriptor)) cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
if descriptor.proxy:
cgThings.append(CGDefineProxyHandler(descriptor))
if descriptor.concrete: if descriptor.concrete:
if descriptor.proxy: if descriptor.proxy:
#cgThings.append(CGProxyIsProxy(descriptor)) #cgThings.append(CGProxyIsProxy(descriptor))
@ -4257,7 +4268,6 @@ class CGRegisterProtos(CGAbstractMethod):
def __init__(self, config): def __init__(self, config):
arguments = [ arguments = [
Argument('&JSRef<Window>', 'window'), Argument('&JSRef<Window>', 'window'),
Argument('&mut JSPageInfo', 'js_info'),
] ]
CGAbstractMethod.__init__(self, None, 'Register', 'void', arguments, CGAbstractMethod.__init__(self, None, 'Register', 'void', arguments,
unsafe=False, pub=True) unsafe=False, pub=True)
@ -4265,10 +4275,37 @@ class CGRegisterProtos(CGAbstractMethod):
def definition_body(self): def definition_body(self):
return CGList([ return CGList([
CGGeneric("codegen::Bindings::%sBinding::DefineDOMInterface(window, js_info);" % desc.name) CGGeneric("codegen::Bindings::%sBinding::DefineDOMInterface(window);" % desc.name)
for desc in self.config.getDescriptors(isCallback=False, register=True) for desc in self.config.getDescriptors(hasInterfaceObject=True, register=True)
], "\n") ], "\n")
class CGRegisterProxyHandlersMethod(CGAbstractMethod):
def __init__(self, descriptors):
CGAbstractMethod.__init__(self, None, 'RegisterProxyHandlers', 'void', [],
unsafe=True, pub=True)
self.descriptors = descriptors
def definition_body(self):
return CGList([
CGGeneric("proxy_handlers[proxies::%s as uint] = codegen::Bindings::%sBinding::DefineProxyHandler();" % (desc.name, desc.name))
for desc in self.descriptors
], "\n")
class CGRegisterProxyHandlers(CGThing):
def __init__(self, config):
descriptors = config.getDescriptors(proxy=True)
length = len(descriptors)
self.root = CGList([
CGGeneric("pub static mut proxy_handlers: [*libc::c_void, ..%d] = [0 as *libc::c_void, ..%d];" % (length, length)),
CGRegisterProxyHandlersMethod(descriptors),
], "\n")
def define(self):
return self.root.define()
class CGBindingRoot(CGThing): class CGBindingRoot(CGThing):
""" """
Root codegen class for binding generation. Instantiate the class, and call Root codegen class for binding generation. Instantiate the class, and call
@ -4393,6 +4430,7 @@ class CGBindingRoot(CGThing):
'dom::bindings::conversions::{Default, Empty}', 'dom::bindings::conversions::{Default, Empty}',
'dom::bindings::codegen::*', 'dom::bindings::codegen::*',
'dom::bindings::codegen::Bindings::*', 'dom::bindings::codegen::Bindings::*',
'dom::bindings::codegen::RegisterBindings',
'dom::bindings::codegen::UnionTypes::*', 'dom::bindings::codegen::UnionTypes::*',
'dom::bindings::error::{FailureUnknown, Fallible, Error, ErrorResult}', 'dom::bindings::error::{FailureUnknown, Fallible, Error, ErrorResult}',
'dom::bindings::error::throw_dom_exception', 'dom::bindings::error::throw_dom_exception',
@ -5244,22 +5282,30 @@ class GlobalGenRoots():
def PrototypeList(config): def PrototypeList(config):
# Prototype ID enum. # Prototype ID enum.
protos = [d.name for d in config.getDescriptors(hasInterfacePrototypeObject=True)] protos = [d.name for d in config.getDescriptors(hasInterfacePrototypeObject=True)]
proxies = [d.name for d in config.getDescriptors(proxy=True)]
return CGList([ return CGList([
CGGeneric(AUTOGENERATED_WARNING_COMMENT), CGGeneric(AUTOGENERATED_WARNING_COMMENT),
CGGeneric("pub static MAX_PROTO_CHAIN_LENGTH: uint = %d;\n\n" % config.maxProtoChainLength), CGGeneric("pub static MAX_PROTO_CHAIN_LENGTH: uint = %d;\n\n" % config.maxProtoChainLength),
CGNamespacedEnum('id', 'ID', protos, [0], deriving="PartialEq"), CGNamespacedEnum('id', 'ID', protos, [0], deriving="PartialEq"),
CGNamespacedEnum('proxies', 'Proxy', proxies, [0], deriving="PartialEq"),
]) ])
@staticmethod @staticmethod
def RegisterBindings(config): def RegisterBindings(config):
# TODO - Generate the methods we want # TODO - Generate the methods we want
return CGImports(CGRegisterProtos(config), [], [ code = CGList([
CGRegisterProtos(config),
CGRegisterProxyHandlers(config),
], "\n")
return CGImports(code, [], [
'dom::bindings::codegen', 'dom::bindings::codegen',
'dom::bindings::codegen::PrototypeList::proxies',
'dom::bindings::js::{JS, JSRef}', 'dom::bindings::js::{JS, JSRef}',
'dom::window::Window', 'dom::window::Window',
'page::JSPageInfo', 'libc',
]) ])
@staticmethod @staticmethod

View file

@ -11,10 +11,9 @@ use dom::browsercontext;
use dom::window; use dom::window;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use std::collections::hashmap::HashMap;
use libc; use libc;
use libc::c_uint; use libc::c_uint;
use std::cell::{Cell, RefCell}; use std::cell::Cell;
use std::mem; use std::mem;
use std::cmp::PartialEq; use std::cmp::PartialEq;
use std::ptr; use std::ptr;
@ -52,13 +51,11 @@ use js;
#[allow(raw_pointer_deriving)] #[allow(raw_pointer_deriving)]
#[deriving(Encodable)] #[deriving(Encodable)]
pub struct GlobalStaticData { pub struct GlobalStaticData {
pub proxy_handlers: Untraceable<RefCell<HashMap<uint, *libc::c_void>>>,
pub windowproxy_handler: Untraceable<*libc::c_void>, pub windowproxy_handler: Untraceable<*libc::c_void>,
} }
pub fn GlobalStaticData() -> GlobalStaticData { pub fn GlobalStaticData() -> GlobalStaticData {
GlobalStaticData { GlobalStaticData {
proxy_handlers: Untraceable::new(RefCell::new(HashMap::new())),
windowproxy_handler: Untraceable::new(browsercontext::new_window_proxy_handler()), windowproxy_handler: Untraceable::new(browsercontext::new_window_proxy_handler()),
} }
} }

View file

@ -549,8 +549,7 @@ impl ScriptTask {
window.deref().init_browser_context(&*document); window.deref().init_browser_context(&*document);
with_compartment((**cx).ptr, window.reflector().get_jsobject(), || { with_compartment((**cx).ptr, window.reflector().get_jsobject(), || {
let mut js_info = page.mut_js_info(); RegisterBindings::Register(&*window);
RegisterBindings::Register(&*window, js_info.get_mut_ref());
}); });
self.compositor.set_ready_state(Loading); self.compositor.set_ready_state(Loading);