aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/patches/README7
-rw-r--r--src/patches/mozjs-stack-bounds.diff72
-rw-r--r--src/servo/dom/bindings/element.rs11
-rw-r--r--src/servo/dom/bindings/utils.rs10
-rw-r--r--src/servo/dom/bindings/window.rs24
-rw-r--r--src/servo/dom/document.rs12
-rw-r--r--src/servo/dom/element.rs7
-rw-r--r--src/test/test_hammer_layout.css2
-rw-r--r--src/test/test_hammer_layout.html2
-rw-r--r--src/test/test_hammer_layout.js23
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');
+}
+