From aae1264d7f4bc21d92f08f5b2f8d2ed7249bdfae Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sat, 22 Oct 2016 00:34:12 -0700 Subject: [PATCH] ircd::js: Add some GC related stats/controls. --- include/ircd/js/context.h | 8 +-- include/ircd/js/debug.h | 2 + include/ircd/js/runtime.h | 31 ++++++++++-- ircd/js.cc | 103 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 134 insertions(+), 10 deletions(-) diff --git a/include/ircd/js/context.h b/include/ircd/js/context.h index e7d180852..087da6d6a 100644 --- a/include/ircd/js/context.h +++ b/include/ircd/js/context.h @@ -116,9 +116,11 @@ JSObject *current_global(context &c); JSObject *current_global(); // thread_local // Memory -inline void out_of_memory(context &c) { JS_ReportOutOfMemory(c); } -inline void allocation_overflow(context &c) { JS_ReportAllocationOverflow(c); } -inline void run_gc(context &c) { JS_MaybeGC(c); } +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); // Exception bool pending_exception(const context &c); diff --git a/include/ircd/js/debug.h b/include/ircd/js/debug.h index 1d4683e10..619f538e2 100644 --- a/include/ircd/js/debug.h +++ b/include/ircd/js/debug.h @@ -27,11 +27,13 @@ namespace js { const char *reflect(const JSExnType &); const char *reflect(const JSGCStatus &); +const char *reflect(const JSGCParamKey &); const char *reflect(const JSFinalizeStatus &); std::string debug(const JS::Value &); std::string debug(const JS::HandleObject &); std::string debug(const JSErrorReport &); +void debug_log_gcparams(); } // namespace js } // namespace ircd diff --git a/include/ircd/js/runtime.h b/include/ircd/js/runtime.h index a0ad9ea68..0ce472774 100644 --- a/include/ircd/js/runtime.h +++ b/include/ircd/js/runtime.h @@ -76,8 +76,13 @@ const runtime &our(const JSRuntime *const &); runtime &our(JSRuntime *const &); // Get to our runtime from any JSObject -const runtime &object_runtime(const JSObject &); -runtime &object_runtime(JSObject &); +const runtime &our_runtime(const JSObject &); +runtime &our_runtime(JSObject &); + +// Get to our runtime from any JSFreeOp +JSFreeOp *default_freeop(runtime &); +const runtime &our_runtime(const JSFreeOp &); +runtime &our_runtime(JSFreeOp &); // Do not call interrupt() unless you know what you're doing; see context.h. void interrupt(runtime &r); @@ -97,13 +102,31 @@ interrupt(runtime &r) } inline runtime & -object_runtime(JSObject &o) +our_runtime(JSFreeOp &o) +{ + return our(o.runtime()); +} + +inline const runtime & +our_runtime(const JSFreeOp &o) +{ + return our(o.runtime()); +} + +inline JSFreeOp * +default_freeop(runtime &r) +{ + return JS_GetDefaultFreeOp(r); +} + +inline runtime & +our_runtime(JSObject &o) { return our(JS_GetObjectRuntime(&o)); } inline const runtime & -object_runtime(const JSObject &o) +our_runtime(const JSObject &o) { return our(JS_GetObjectRuntime(const_cast(&o))); } diff --git a/ircd/js.cc b/ircd/js.cc index 3d833b79e..b6e97995b 100644 --- a/ircd/js.cc +++ b/ircd/js.cc @@ -977,6 +977,35 @@ ircd::js::jserror::create(JSErrorReport &report) // ircd/js/debug.h // +void +ircd::js::debug_log_gcparams() +{ + for(int i(0); i < 50; ++i) + { + const auto key(static_cast(i)); + const char *const name(reflect(key)); + if(!strlen(name)) + continue; + + // These trigger assertion failures + switch(key) + { + case JSGC_NUMBER: + case JSGC_MAX_CODE_CACHE_BYTES: + case JSGC_DECOMMIT_THRESHOLD: + continue; + + default: + break; + } + + log.debug("context(%p) %s => %u", + (const void *)cx, + name, + get(*cx, key)); + } +} + std::string ircd::js::debug(const JSErrorReport &r) { @@ -1077,7 +1106,40 @@ ircd::js::reflect(const JSFinalizeStatus &s) case JSFINALIZE_COLLECTION_END: return "COLLECTION_END"; } - return "????"; + return ""; +} + +const char * +ircd::js::reflect(const JSGCParamKey &s) +{ + switch(s) + { + case JSGC_MAX_BYTES: return "JSGC_MAX_BYTES"; + case JSGC_MAX_MALLOC_BYTES: return "JSGC_MAX_MALLOC_BYTES"; + case JSGC_BYTES: return "JSGC_BYTES"; + case JSGC_NUMBER: return "JSGC_NUMBER"; + case JSGC_MAX_CODE_CACHE_BYTES: return "JSGC_MAX_CODE_CACHE_BYTES"; + case JSGC_MODE: return "JSGC_MODE"; + case JSGC_UNUSED_CHUNKS: return "JSGC_UNUSED_CHUNKS"; + case JSGC_TOTAL_CHUNKS: return "JSGC_TOTAL_CHUNKS"; + case JSGC_SLICE_TIME_BUDGET: return "JSGC_SLICE_TIME_BUDGET"; + case JSGC_MARK_STACK_LIMIT: return "JSGC_MARK_STACK_LIMIT"; + case JSGC_HIGH_FREQUENCY_TIME_LIMIT: return "JSGC_HIGH_FREQUENCY_TIME_LIMIT"; + case JSGC_HIGH_FREQUENCY_LOW_LIMIT: return "JSGC_HIGH_FREQUENCY_LOW_LIMIT"; + case JSGC_HIGH_FREQUENCY_HIGH_LIMIT: return "JSGC_HIGH_FREQUENCY_HIGH_LIMIT"; + case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX: return "JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX"; + case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN: return "JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN"; + case JSGC_LOW_FREQUENCY_HEAP_GROWTH: return "JSGC_LOW_FREQUENCY_HEAP_GROWTH"; + case JSGC_DYNAMIC_HEAP_GROWTH: return "JSGC_DYNAMIC_HEAP_GROWTH"; + case JSGC_DYNAMIC_MARK_SLICE: return "JSGC_DYNAMIC_MARK_SLICE"; + case JSGC_ALLOCATION_THRESHOLD: return "JSGC_ALLOCATION_THRESHOLD"; + case JSGC_DECOMMIT_THRESHOLD: return "JSGC_DECOMMIT_THRESHOLD"; + case JSGC_MIN_EMPTY_CHUNK_COUNT: return "JSGC_MIN_EMPTY_CHUNK_COUNT"; + case JSGC_MAX_EMPTY_CHUNK_COUNT: return "JSGC_MAX_EMPTY_CHUNK_COUNT"; + case JSGC_COMPACTING_ENABLED: return "JSGC_COMPACTING_ENABLED"; + } + + return ""; } const char * @@ -1089,7 +1151,7 @@ ircd::js::reflect(const JSGCStatus &s) case JSGC_END: return "END"; } - return "????"; + return ""; } const char * @@ -1109,7 +1171,7 @@ ircd::js::reflect(const JSExnType &e) case JSEXN_LIMIT: return "?LIMIT?"; } - return "????"; + return ""; } /////////////////////////////////////////////////////////////////////////////// @@ -1426,6 +1488,41 @@ ircd::js::save_exception(context &c, c.report = report; } +void +ircd::js::run_gc(context &c) +{ + JS_MaybeGC(c); +} + +void +ircd::js::out_of_memory(context &c) +{ + JS_ReportOutOfMemory(c); +} + +void +ircd::js::allocation_overflow(context &c) +{ + JS_ReportAllocationOverflow(c); +} + +uint32_t +ircd::js::get(context &c, + const JSGCParamKey &key) +{ + //return JS_GetGCParameterForThread(c, key); // broken + return JS_GetGCParameter(c.runtime(), key); +} + +void +ircd::js::set(context &c, + const JSGCParamKey &key, + const uint32_t &val) +{ + //JS_SetGCParameterForThread(c, key, val); // broken + JS_SetGCParameter(c.runtime(), key, val); +} + /////////////////////////////////////////////////////////////////////////////// // // ircd/js/timer.h