mirror of
https://github.com/servo/servo.git
synced 2025-06-25 17:44:33 +01:00
Make GC work.
This commit is contained in:
parent
535bfb3cbb
commit
db5eca4764
10 changed files with 128 additions and 42 deletions
7
src/patches/README
Normal file
7
src/patches/README
Normal file
|
@ -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.
|
72
src/patches/mozjs-stack-bounds.diff
Normal file
72
src/patches/mozjs-stack-bounds.diff
Normal file
|
@ -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
|
||||||
|
|
|
@ -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) };
|
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() {
|
if node.is_none() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,12 @@ pub extern fn trace(tracer: *JSTracer, obj: *JSObject) {
|
||||||
let wrapper = cache.get_wrapper();
|
let wrapper = cache.get_wrapper();
|
||||||
assert!(wrapper.is_not_null());
|
assert!(wrapper.is_not_null());
|
||||||
unsafe {
|
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);
|
error!("tracing %?:", obj as uint);
|
||||||
|
|
|
@ -290,10 +290,8 @@ static DOM_PROXY_OBJECT_SLOT: uint = js::JSSLOT_PROXY_PRIVATE as uint;
|
||||||
// changes.
|
// changes.
|
||||||
static DOM_PROTO_INSTANCE_CLASS_SLOT: u32 = 0;
|
static DOM_PROTO_INSTANCE_CLASS_SLOT: u32 = 0;
|
||||||
|
|
||||||
// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. We have to
|
// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT.
|
||||||
// start at 1 past JSCLASS_GLOBAL_SLOT_COUNT because XPConnect uses
|
pub static DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT;
|
||||||
// that one.
|
|
||||||
pub static DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT + 1;
|
|
||||||
|
|
||||||
// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
|
// 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
|
// LSetDOMProperty. Those constants need to be changed accordingly if this value
|
||||||
|
@ -580,6 +578,10 @@ pub impl WrapperCache {
|
||||||
self.wrapper = wrapper;
|
self.wrapper = wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_rootable(&self) -> **JSObject {
|
||||||
|
return ptr::addr_of(&self.wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
fn new() -> WrapperCache {
|
fn new() -> WrapperCache {
|
||||||
WrapperCache {
|
WrapperCache {
|
||||||
wrapper: ptr::null()
|
wrapper: ptr::null()
|
||||||
|
|
|
@ -16,7 +16,7 @@ use js::crust::{JS_PropertyStub, JS_StrictPropertyStub};
|
||||||
use js::global::jsval_to_rust_str;
|
use js::global::jsval_to_rust_str;
|
||||||
use js::glue::bindgen::*;
|
use js::glue::bindgen::*;
|
||||||
use js::glue::bindgen::RUST_JSVAL_TO_INT;
|
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_GetReservedSlot, JS_SetReservedSlot};
|
||||||
use js::jsapi::bindgen::{JS_ValueToString};
|
use js::jsapi::bindgen::{JS_ValueToString};
|
||||||
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSFunctionSpec};
|
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);
|
assert!(argc == 1);
|
||||||
// Abstract this pattern and use it in debug, too?
|
// Abstract this pattern and use it in debug, too?
|
||||||
let jsstr = JS_ValueToString(cx, *ptr::offset(argv, 0));
|
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));
|
(*unwrap(JS_THIS_OBJECT(cx, vp))).payload.alert(jsval_to_rust_str(cx, jsstr));
|
||||||
|
|
||||||
JS_SET_RVAL(cx, vp, JSVAL_NULL);
|
JS_SET_RVAL(cx, vp, JSVAL_NULL);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
1_i32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn setTimeout(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
|
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> {
|
unsafe fn unwrap(obj: *JSObject) -> *rust_box<Window> {
|
||||||
let val = JS_GetReservedSlot(obj, 0);
|
let val = JS_GetReservedSlot(obj, 0);
|
||||||
cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val))
|
cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val))
|
||||||
|
@ -99,7 +110,14 @@ pub fn init(compartment: @mut Compartment) {
|
||||||
JSFunctionSpec {
|
JSFunctionSpec {
|
||||||
name: compartment.add_name(~"close"),
|
name: compartment.add_name(~"close"),
|
||||||
call: JSNativeWrapper { op: close, info: null() },
|
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,
|
flags: 0,
|
||||||
selfHostedName: null()
|
selfHostedName: null()
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,9 +27,9 @@ pub fn Document(root: AbstractNode,
|
||||||
};
|
};
|
||||||
let compartment = global_content().compartment.get();
|
let compartment = global_content().compartment.get();
|
||||||
do root.with_imm_node |node| {
|
do root.with_imm_node |node| {
|
||||||
let wrapper = node.wrapper.get_wrapper();
|
assert!(node.wrapper.get_wrapper().is_not_null());
|
||||||
assert!(wrapper.is_not_null());
|
let rootable = node.wrapper.get_rootable();
|
||||||
unsafe { JS_AddObjectRoot(compartment.cx.ptr, ptr::addr_of(&wrapper)); }
|
unsafe { JS_AddObjectRoot(compartment.cx.ptr, rootable); }
|
||||||
}
|
}
|
||||||
document::create(compartment, doc);
|
document::create(compartment, doc);
|
||||||
doc
|
doc
|
||||||
|
@ -40,9 +40,9 @@ impl Drop for Document {
|
||||||
fn finalize(&self) {
|
fn finalize(&self) {
|
||||||
let compartment = global_content().compartment.get();
|
let compartment = global_content().compartment.get();
|
||||||
do self.root.with_imm_node |node| {
|
do self.root.with_imm_node |node| {
|
||||||
let wrapper = node.wrapper.get_wrapper();
|
assert!(node.wrapper.get_wrapper().is_not_null());
|
||||||
assert!(wrapper.is_not_null());
|
let rootable = node.wrapper.get_rootable();
|
||||||
unsafe { JS_RemoveObjectRoot(compartment.cx.ptr, ptr::addr_of(&wrapper)); }
|
unsafe { JS_RemoveObjectRoot(compartment.cx.ptr, rootable); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,6 @@ pub struct Element {
|
||||||
attrs: ~[Attr],
|
attrs: ~[Attr],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
|
||||||
impl Drop for Element {
|
|
||||||
fn finalize(&self) {
|
|
||||||
fail!(~"uh oh");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
pub enum ElementTypeId {
|
pub enum ElementTypeId {
|
||||||
HTMLAnchorElementTypeId,
|
HTMLAnchorElementTypeId,
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
div #styled {
|
#styled {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
|
@ -4,6 +4,6 @@
|
||||||
<script src="test_hammer_layout.js"></script>
|
<script src="test_hammer_layout.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="styled">This text is unstyled.</div>
|
<div id="">This text is unstyled.</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,17 +1,6 @@
|
||||||
window.setTimeout(function() {
|
var divs = document.getElementsByTagName("div");
|
||||||
//var divs = document.getElementsByTagName("div");
|
var div = divs[0];
|
||||||
// divs[0].setAttribute('id', 'styled');
|
for (var i = 0; i < 1000000; i++) {
|
||||||
function print_tree(n) {
|
div.setAttribute('id', 'styled');
|
||||||
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);
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue