Auto merge of #8147 - nox:weakref, r=Ms2ger

Implement weak-referenceable JS-managed objects

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8147)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-11-13 06:22:40 +05:30
commit e63b1e83d4
10 changed files with 268 additions and 5 deletions

View file

@ -1761,12 +1761,16 @@ class CGDOMJSClass(CGThing):
def define(self):
traceHook = 'Some(%s)' % TRACE_HOOK_NAME
if self.descriptor.isGlobal():
assert not self.descriptor.weakReferenceable
traceHook = "Some(js::jsapi::JS_GlobalObjectTraceHook)"
flags = "JSCLASS_IS_GLOBAL | JSCLASS_DOM_GLOBAL"
slots = "JSCLASS_GLOBAL_SLOT_COUNT + 1"
else:
flags = "0"
slots = "1"
if self.descriptor.weakReferenceable:
slots = "2"
else:
slots = "1"
return """\
static Class: DOMJSClass = DOMJSClass {
base: js::jsapi::Class {
@ -2171,6 +2175,9 @@ let obj = RootedObject::new(cx, obj);\
"\n"
"JS_SetReservedSlot(obj.ptr, DOM_OBJECT_SLOT,\n"
" PrivateValue(raw as *const libc::c_void));")
if descriptor.weakReferenceable:
create += """
JS_SetReservedSlot(obj.ptr, DOM_WEAK_SLOT, PrivateValue(ptr::null()));"""
return create
@ -4517,8 +4524,8 @@ class CGAbstractClassHook(CGAbstractExternMethod):
args)
def definition_body_prologue(self):
return CGGeneric("""\
let this = private_from_object(obj) as *const %s;
return CGGeneric("""
let this = native_from_object::<%s>(obj).unwrap();
""" % self.descriptor.concreteType)
def definition_body(self):
@ -4537,6 +4544,24 @@ def finalizeHook(descriptor, hookName, context):
release += """\
finalize_global(obj);
"""
elif descriptor.weakReferenceable:
release += """\
let weak_box_ptr = JS_GetReservedSlot(obj, DOM_WEAK_SLOT).to_private() as *mut WeakBox<%s>;
if !weak_box_ptr.is_null() {
let count = {
let weak_box = &*weak_box_ptr;
assert!(weak_box.value.get().is_some());
assert!(weak_box.count.get() > 0);
weak_box.value.set(None);
let count = weak_box.count.get() - 1;
weak_box.count.set(count);
count
};
if count == 0 {
mem::drop(Box::from_raw(weak_box_ptr));
}
}
""" % descriptor.concreteType
release += """\
let _ = Box::from_raw(this as *mut %s);
debug!("%s finalize: {:p}", this);\
@ -4714,6 +4739,16 @@ class CGInterfaceTrait(CGThing):
return self.cgRoot.define()
class CGWeakReferenceableTrait(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
assert descriptor.weakReferenceable
self.code = "impl WeakReferenceable for %s {}" % descriptor.interface.identifier.name
def define(self):
return self.code
class CGDescriptor(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
@ -4822,6 +4857,8 @@ class CGDescriptor(CGThing):
if not descriptor.interface.isCallback():
cgThings.append(CGIDLInterface(descriptor))
cgThings.append(CGInterfaceTrait(descriptor))
if descriptor.weakReferenceable:
cgThings.append(CGWeakReferenceableTrait(descriptor))
cgThings = CGList(cgThings, "\n")
# self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
@ -5212,7 +5249,7 @@ class CGBindingRoot(CGThing):
'dom::bindings::conversions::{ConversionBehavior, DOM_OBJECT_SLOT, IDLInterface}',
'dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior}',
'dom::bindings::conversions::{ToJSValConvertible, jsid_to_str, native_from_handlevalue}',
'dom::bindings::conversions::{private_from_object, root_from_object}',
'dom::bindings::conversions::{native_from_object, private_from_object, root_from_object}',
'dom::bindings::conversions::{root_from_handleobject, root_from_handlevalue}',
'dom::bindings::codegen::{PrototypeList, RegisterBindings, UnionTypes}',
'dom::bindings::codegen::Bindings::*',
@ -5226,6 +5263,7 @@ class CGBindingRoot(CGThing):
'dom::bindings::str::ByteString',
'dom::bindings::str::USVString',
'dom::bindings::trace::RootedVec',
'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
'mem::heap_size_of_raw_self_and_children',
'libc',
'util::str::DOMString',