diff --git a/include/ircd/js/context.h b/include/ircd/js/context.h index 8eaf18efa..1aa82ea97 100644 --- a/include/ircd/js/context.h +++ b/include/ircd/js/context.h @@ -128,7 +128,7 @@ void set(context &c, const JSGCParamKey &, const uint32_t &val); uint32_t get(context &c, const JSGCParamKey &); void out_of_memory(context &c); void allocation_overflow(context &c); -void run_gc(context &c); +bool run_gc(context &c) noexcept; // Exception bool pending_exception(const context &c); diff --git a/include/ircd/js/global.h b/include/ircd/js/global.h index dcd076e1b..d5bd8044d 100644 --- a/include/ircd/js/global.h +++ b/include/ircd/js/global.h @@ -26,7 +26,7 @@ namespace ircd { namespace js { struct global -:heap_object +:persist_object { global(trap &, JSPrincipals *const & = nullptr); }; diff --git a/include/ircd/js/object.h b/include/ircd/js/object.h index 834bea03c..d54a9dcc5 100644 --- a/include/ircd/js/object.h +++ b/include/ircd/js/object.h @@ -97,6 +97,7 @@ struct object using object = basic::object; using heap_object = basic::object; +using persist_object = basic::object; // // Implementation diff --git a/include/ircd/js/runtime.h b/include/ircd/js/runtime.h index 9b97502d0..6c6961125 100644 --- a/include/ircd/js/runtime.h +++ b/include/ircd/js/runtime.h @@ -92,15 +92,9 @@ runtime &our_runtime(JSFreeOp &); // Do not call interrupt() unless you know what you're doing; see context.h. void interrupt(runtime &r); -void run_gc(runtime &r); +bool run_gc(runtime &r) noexcept; -inline void -run_gc(runtime &r) -{ - JS_GC(r); -} - inline void interrupt(runtime &r) { diff --git a/include/ircd/js/trap.h b/include/ircd/js/trap.h index 011a8c2d3..4cffb8f38 100644 --- a/include/ircd/js/trap.h +++ b/include/ircd/js/trap.h @@ -44,6 +44,7 @@ class trap virtual bool on_has(object::handle, id::handle); virtual void on_enu(object::handle); virtual void on_new(object::handle, object &, const args &); + virtual void on_trace(const JSObject &); virtual void on_gc(JSObject &); private: diff --git a/include/ircd/js/value.h b/include/ircd/js/value.h index c195ca8a9..6704546e3 100644 --- a/include/ircd/js/value.h +++ b/include/ircd/js/value.h @@ -189,7 +189,8 @@ value::value(const std::string &s) :value::root::type{[&s] { auto buf(native_external_copy(s)); - const auto ret(JS_NewExternalString(*cx, buf.release(), s.size(), &native_external_delete)); + const auto ret(JS_NewExternalString(*cx, buf.get(), s.size(), &native_external_delete)); + buf.release(); return JS::StringValue(ret); }()} { @@ -201,7 +202,8 @@ value::value(const char *const &s) { const auto len(strlen(s)); auto buf(native_external_copy(s, len)); - const auto ret(JS_NewExternalString(*cx, buf.release(), len, &native_external_delete)); + const auto ret(JS_NewExternalString(*cx, buf.get(), len, &native_external_delete)); + buf.release(); return JS::StringValue(ret); }()} { diff --git a/ircd/js.cc b/ircd/js.cc index 384a2e8c2..6573a135b 100644 --- a/ircd/js.cc +++ b/ircd/js.cc @@ -274,6 +274,7 @@ catch(const std::exception &e) ircd::js::task::~task() noexcept { + run_gc(*rt); tasks_remove(); } @@ -371,7 +372,7 @@ ircd::js::task::tasks_next_pid() ircd::js::global::global(trap &trap, JSPrincipals *const &principals) -:heap_object +:persist_object { JS_NewGlobalObject(*cx, &trap.jsclass(), principals, JS::DontFireOnNewGlobalHook) } @@ -542,10 +543,6 @@ noexcept //_class->trace = nullptr; memset(_class.get(), 0x0, sizeof(JSClass)); class_drain.emplace_front(std::move(_class)); - - // Must run GC here to force reclamation of objects before - // the JSClass hosted by this trap destructs. - //run_gc(*rt); } void @@ -973,8 +970,13 @@ ircd::js::trap::handle_trace(JSTracer *const tracer, JSObject *const obj) noexcept try { + assert(cx); + assert(tracer); + assert(obj); + auto &trap(from(*obj)); trap.debug("trace"); + trap.on_trace(*obj); } catch(const jserror &e) { @@ -2548,10 +2550,17 @@ ircd::js::save_exception(context &c, c.report = report; } -void +bool ircd::js::run_gc(context &c) +noexcept { + // JS_MaybeGC dereferences the context's current zone without checking if the context + // is even in a compartment/has a current zone; we must check here. + if(!current_zone(c)) + return false; + JS_MaybeGC(c); + return true; } void @@ -2808,6 +2817,14 @@ noexcept { } +bool +ircd::js::run_gc(runtime &r) +noexcept +{ + JS_GC(r); + return true; +} + bool ircd::js::runtime::handle_interrupt(JSContext *const ctx) noexcept