diff options
author | Josh Matthews <josh@joshmatthews.net> | 2013-04-10 10:37:49 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2013-04-23 23:56:40 +0200 |
commit | db5eca476491597e9b29a7acce7333784ca1ca93 (patch) | |
tree | dad0b5087950199d76d0efdeaef80ddc7f605224 | |
parent | 535bfb3cbb343b969e46e556f5f20ee77560c1b4 (diff) | |
download | servo-db5eca476491597e9b29a7acce7333784ca1ca93.tar.gz servo-db5eca476491597e9b29a7acce7333784ca1ca93.zip |
Make GC work.
-rw-r--r-- | src/patches/README | 7 | ||||
-rw-r--r-- | src/patches/mozjs-stack-bounds.diff | 72 | ||||
-rw-r--r-- | src/servo/dom/bindings/element.rs | 11 | ||||
-rw-r--r-- | src/servo/dom/bindings/utils.rs | 10 | ||||
-rw-r--r-- | src/servo/dom/bindings/window.rs | 24 | ||||
-rw-r--r-- | src/servo/dom/document.rs | 12 | ||||
-rw-r--r-- | src/servo/dom/element.rs | 7 | ||||
-rw-r--r-- | src/test/test_hammer_layout.css | 2 | ||||
-rw-r--r-- | src/test/test_hammer_layout.html | 2 | ||||
-rw-r--r-- | src/test/test_hammer_layout.js | 23 |
10 files changed, 128 insertions, 42 deletions
diff --git a/src/patches/README b/src/patches/README new file mode 100644 index 00000000000..63868fe4824 --- /dev/null +++ b/src/patches/README @@ -0,0 +1,7 @@ +Patches live here for submodules that should remain as pristine as possible. +This will allow us to unconditionally update them, then apply necessary +patches as needed. + +* mozjs-stack-bounds.diff: + add a public API to overwrite the engine's computed stack bounds for + GC scanning. diff --git a/src/patches/mozjs-stack-bounds.diff b/src/patches/mozjs-stack-bounds.diff new file mode 100644 index 00000000000..e09e9194100 --- /dev/null +++ b/src/patches/mozjs-stack-bounds.diff @@ -0,0 +1,72 @@ +diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp +index 5571fc0..df2fabd 100644 +--- a/js/src/jsapi.cpp ++++ b/js/src/jsapi.cpp +@@ -735,6 +735,7 @@ JSRuntime::JSRuntime() + #endif + selfHostedGlobal_(NULL), + nativeStackBase(0), ++ nativeStackEnd(0), + nativeStackQuota(0), + interpreterFrames(NULL), + cxCallback(NULL), +@@ -7084,6 +7085,13 @@ JS_SetRuntimeThread(JSRuntime *rt) + #endif + } + ++extern JS_PUBLIC_API(void) ++JS_SetNativeStackBounds(JSRuntime *rt, uintptr_t stackBase, uintptr_t stackEnd) ++{ ++ rt->nativeStackBase = stackBase; ++ rt->nativeStackEnd = stackEnd; ++} ++ + extern JS_NEVER_INLINE JS_PUBLIC_API(void) + JS_AbortIfWrongThread(JSRuntime *rt) + { +diff --git a/js/src/jsapi.h b/js/src/jsapi.h +index c8ab0f0..0edb722 100644 +--- a/js/src/jsapi.h ++++ b/js/src/jsapi.h +@@ -6248,6 +6248,9 @@ JS_ClearRuntimeThread(JSRuntime *rt); + extern JS_PUBLIC_API(void) + JS_SetRuntimeThread(JSRuntime *rt); + ++extern JS_PUBLIC_API(void) ++JS_SetNativeStackBounds(JSRuntime *rt, uintptr_t stackBase, uintptr_t stackEnd); ++ + #ifdef __cplusplus + JS_END_EXTERN_C + +diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h +index 0bb6d1c..32e016e 100644 +--- a/js/src/jscntxt.h ++++ b/js/src/jscntxt.h +@@ -439,6 +439,9 @@ struct JSRuntime : js::RuntimeFriendFields + /* Base address of the native stack for the current thread. */ + uintptr_t nativeStackBase; + ++ /* Base address of the native stack for the current thread. */ ++ uintptr_t nativeStackEnd; ++ + /* The native stack size limit that runtime should not exceed. */ + size_t nativeStackQuota; + +diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp +index f5cbc62..eae29da 100644 +--- a/js/src/jsgc.cpp ++++ b/js/src/jsgc.cpp +@@ -1177,9 +1177,11 @@ MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots) + uintptr_t *stackMin, *stackEnd; + #if JS_STACK_GROWTH_DIRECTION > 0 + stackMin = rt->nativeStackBase; +- stackEnd = cgcd->nativeStackTop; ++ stackEnd = rt->nativeStackEnd ? reinterpret_cast<uintptr_t*>(rt->nativeStackEnd) ++ : cgcd->nativeStackTop; + #else +- stackMin = cgcd->nativeStackTop + 1; ++ stackMin = rt->nativeStackEnd ? reinterpret_cast<uintptr_t*>(rt->nativeStackEnd) ++ : cgcd->nativeStackTop + 1; + stackEnd = reinterpret_cast<uintptr_t *>(rt->nativeStackBase); + #endif + diff --git a/src/servo/dom/bindings/element.rs b/src/servo/dom/bindings/element.rs index 52af49b497f..ae0599afa65 100644 --- a/src/servo/dom/bindings/element.rs +++ b/src/servo/dom/bindings/element.rs @@ -32,10 +32,10 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) { } } -pub extern fn trace(tracer: *JSTracer, obj: *JSObject) { +pub extern fn trace(tracer: *mut JSTracer, obj: *JSObject) { let node = unsafe { unwrap(obj) }; - fn trace_node(tracer: *JSTracer, node: Option<AbstractNode>, name: &str) { + fn trace_node(tracer: *mut JSTracer, node: Option<AbstractNode>, name: &str) { if node.is_none() { return; } @@ -45,7 +45,12 @@ pub extern fn trace(tracer: *JSTracer, obj: *JSObject) { let wrapper = cache.get_wrapper(); assert!(wrapper.is_not_null()); unsafe { - JS_CallTracer(tracer, wrapper, JSTRACE_OBJECT as u32); + (*tracer).debugPrinter = ptr::null(); + (*tracer).debugPrintIndex = -1; + do str::as_c_str(name) |name| { + (*tracer).debugPrintArg = name as *libc::c_void; + JS_CallTracer(cast::transmute(tracer), wrapper, JSTRACE_OBJECT as u32); + } } } error!("tracing %?:", obj as uint); diff --git a/src/servo/dom/bindings/utils.rs b/src/servo/dom/bindings/utils.rs index 3e23170a904..85ac2bf23c0 100644 --- a/src/servo/dom/bindings/utils.rs +++ b/src/servo/dom/bindings/utils.rs @@ -290,10 +290,8 @@ static DOM_PROXY_OBJECT_SLOT: uint = js::JSSLOT_PROXY_PRIVATE as uint; // changes. static DOM_PROTO_INSTANCE_CLASS_SLOT: u32 = 0; -// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. We have to -// start at 1 past JSCLASS_GLOBAL_SLOT_COUNT because XPConnect uses -// that one. -pub static DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT + 1; +// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. +pub static DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT; // NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and // LSetDOMProperty. Those constants need to be changed accordingly if this value @@ -580,6 +578,10 @@ pub impl WrapperCache { self.wrapper = wrapper; } + fn get_rootable(&self) -> **JSObject { + return ptr::addr_of(&self.wrapper); + } + fn new() -> WrapperCache { WrapperCache { wrapper: ptr::null() diff --git a/src/servo/dom/bindings/window.rs b/src/servo/dom/bindings/window.rs index f50bb1f6c2c..0bd710516e1 100644 --- a/src/servo/dom/bindings/window.rs +++ b/src/servo/dom/bindings/window.rs @@ -16,7 +16,7 @@ use js::crust::{JS_PropertyStub, JS_StrictPropertyStub}; use js::global::jsval_to_rust_str; use js::glue::bindgen::*; use js::glue::bindgen::RUST_JSVAL_TO_INT; -use js::jsapi::bindgen::{JS_DefineFunctions}; +use js::jsapi::bindgen::{JS_DefineFunctions, JS_GC, JS_GetRuntime}; use js::jsapi::bindgen::{JS_GetReservedSlot, JS_SetReservedSlot}; use js::jsapi::bindgen::{JS_ValueToString}; use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSFunctionSpec}; @@ -31,12 +31,15 @@ extern fn alert(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool { assert!(argc == 1); // Abstract this pattern and use it in debug, too? let jsstr = JS_ValueToString(cx, *ptr::offset(argv, 0)); + if jsstr.is_null() { + return 0; + } (*unwrap(JS_THIS_OBJECT(cx, vp))).payload.alert(jsval_to_rust_str(cx, jsstr)); JS_SET_RVAL(cx, vp, JSVAL_NULL); + return 1; } - 1_i32 } extern fn setTimeout(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool { @@ -63,6 +66,14 @@ extern fn close(cx: *JSContext, _argc: c_uint, vp: *JSVal) -> JSBool { } } +extern fn gc(cx: *JSContext, _argc: c_uint, _vp: *JSVal) -> JSBool { + unsafe { + let runtime = JS_GetRuntime(cx); + JS_GC(runtime); + return 1; + } +} + unsafe fn unwrap(obj: *JSObject) -> *rust_box<Window> { let val = JS_GetReservedSlot(obj, 0); cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val)) @@ -99,7 +110,14 @@ pub fn init(compartment: @mut Compartment) { JSFunctionSpec { name: compartment.add_name(~"close"), call: JSNativeWrapper { op: close, info: null() }, - nargs: 2, + nargs: 0, + flags: 0, + selfHostedName: null() + }, + JSFunctionSpec { + name: compartment.add_name(~"_trigger_gc"), + call: JSNativeWrapper { op: gc, info: null() }, + nargs: 0, flags: 0, selfHostedName: null() }, diff --git a/src/servo/dom/document.rs b/src/servo/dom/document.rs index 2cd3f9b2ade..26bb27ac26f 100644 --- a/src/servo/dom/document.rs +++ b/src/servo/dom/document.rs @@ -27,9 +27,9 @@ pub fn Document(root: AbstractNode, }; let compartment = global_content().compartment.get(); do root.with_imm_node |node| { - let wrapper = node.wrapper.get_wrapper(); - assert!(wrapper.is_not_null()); - unsafe { JS_AddObjectRoot(compartment.cx.ptr, ptr::addr_of(&wrapper)); } + assert!(node.wrapper.get_wrapper().is_not_null()); + let rootable = node.wrapper.get_rootable(); + unsafe { JS_AddObjectRoot(compartment.cx.ptr, rootable); } } document::create(compartment, doc); doc @@ -40,9 +40,9 @@ impl Drop for Document { fn finalize(&self) { let compartment = global_content().compartment.get(); do self.root.with_imm_node |node| { - let wrapper = node.wrapper.get_wrapper(); - assert!(wrapper.is_not_null()); - unsafe { JS_RemoveObjectRoot(compartment.cx.ptr, ptr::addr_of(&wrapper)); } + assert!(node.wrapper.get_wrapper().is_not_null()); + let rootable = node.wrapper.get_rootable(); + unsafe { JS_RemoveObjectRoot(compartment.cx.ptr, rootable); } } } } diff --git a/src/servo/dom/element.rs b/src/servo/dom/element.rs index 5512e0c68d5..489e9bd7a6b 100644 --- a/src/servo/dom/element.rs +++ b/src/servo/dom/element.rs @@ -20,13 +20,6 @@ pub struct Element { attrs: ~[Attr], } -#[unsafe_destructor] -impl Drop for Element { - fn finalize(&self) { - fail!(~"uh oh"); - } -} - #[deriving(Eq)] pub enum ElementTypeId { HTMLAnchorElementTypeId, diff --git a/src/test/test_hammer_layout.css b/src/test/test_hammer_layout.css index 0e141509285..8218b9cab7d 100644 --- a/src/test/test_hammer_layout.css +++ b/src/test/test_hammer_layout.css @@ -1,3 +1,3 @@ -div #styled { +#styled { color: red; }
\ No newline at end of file diff --git a/src/test/test_hammer_layout.html b/src/test/test_hammer_layout.html index b2cb232036a..119d67a1796 100644 --- a/src/test/test_hammer_layout.html +++ b/src/test/test_hammer_layout.html @@ -4,6 +4,6 @@ <script src="test_hammer_layout.js"></script> </head> <body> -<div id="styled">This text is unstyled.</div> +<div id="">This text is unstyled.</div> </body> </html> diff --git a/src/test/test_hammer_layout.js b/src/test/test_hammer_layout.js index 89cb0139d8c..201b41e752e 100644 --- a/src/test/test_hammer_layout.js +++ b/src/test/test_hammer_layout.js @@ -1,17 +1,6 @@ -window.setTimeout(function() { - //var divs = document.getElementsByTagName("div"); -// divs[0].setAttribute('id', 'styled'); - function print_tree(n) { - window.alert(n.nodeType); - //window.alert(n.tagName); - n = n.firstChild; - while (n) { - print_tree(n); - n = n.nextSibling; - } - } - print_tree(document.documentElement); -//window.alert(document.documentElement.tagName); -//window.alert(document.documentElement.firstChild.nodeType); -//window.alert(document.documentElement.firstChild.firstChild.nodeType); -}, 200);
\ No newline at end of file +var divs = document.getElementsByTagName("div"); +var div = divs[0]; +for (var i = 0; i < 1000000; i++) { + div.setAttribute('id', 'styled'); +} + |