Implement discarding Document objects to reclaim space.

This commit is contained in:
Alan Jeffrey 2016-11-18 20:50:53 -06:00
parent 955e2851bf
commit 78c87ea8d7
8 changed files with 301 additions and 218 deletions

View file

@ -901,18 +901,24 @@ impl Window {
}
pub fn clear_js_runtime(&self) {
// We tear down the active document, which causes all the attached
// nodes to dispose of their layout data. This messages the layout
// thread, informing it that it can safely free the memory.
self.Document().upcast::<Node>().teardown();
// The above code may not catch all DOM objects
// (e.g. DOM objects removed from the tree that haven't
// been collected yet). Forcing a GC here means that
// those DOM objects will be able to call dispose()
// to free their layout data before the layout thread
// exits. Without this, those remaining objects try to
// send a message to free their layout data to the
// layout thread when the script thread is dropped,
// which causes a panic!
// The above code may not catch all DOM objects (e.g. DOM
// objects removed from the tree that haven't been collected
// yet). There should not be any such DOM nodes with layout
// data, but if there are, then when they are dropped, they
// will attempt to send a message to the closed layout thread.
// This causes memory safety issues, because the DOM node uses
// the layout channel from its window, and the window has
// already been GC'd. For nodes which do not have a live
// pointer, we can avoid this by GCing now:
self.Gc();
// but there may still be nodes being kept alive by user
// script.
// TODO: ensure that this doesn't happen!
self.current_state.set(WindowState::Zombie);
*self.js_runtime.borrow_mut() = None;
@ -1445,6 +1451,12 @@ impl Window {
None
}
pub fn freeze(&self) {
self.upcast::<GlobalScope>().suspend();
// A hint to the JS runtime that now would be a good time to GC this window.
self.Gc();
}
pub fn thaw(&self) {
self.upcast::<GlobalScope>().resume();