add memory profiling tooling
This commit is contained in:
parent
ceb728b1a7
commit
432d8200f3
|
@ -79,6 +79,7 @@ actor.delay = function(fn, seconds) {
|
||||||
var timers = this.timers;
|
var timers = this.timers;
|
||||||
var stop = function() {
|
var stop = function() {
|
||||||
timers.remove(stop);
|
timers.remove(stop);
|
||||||
|
stop = undefined;
|
||||||
rm();
|
rm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +105,21 @@ actor.delay = function(fn, seconds) {
|
||||||
timers.push(stop);
|
timers.push(stop);
|
||||||
return stop;
|
return stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`;
|
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`;
|
||||||
|
|
||||||
|
actor.interval = function(fn, seconds)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
var stop;
|
||||||
|
var usefn = function() {
|
||||||
|
fn();
|
||||||
|
stop = self.delay(usefn, seconds);
|
||||||
|
}
|
||||||
|
stop = self.delay(usefn, seconds);
|
||||||
|
|
||||||
|
return stop;
|
||||||
|
}
|
||||||
|
|
||||||
actor.padawans = [];
|
actor.padawans = [];
|
||||||
|
|
||||||
global.app = Object.create(actor);
|
global.app = Object.create(actor);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
"use math";
|
"use math";
|
||||||
|
|
||||||
prosperon.gc_start = function(){}
|
os.mem_limit.doc = "Set the memory limit of the runtime in bytes.";
|
||||||
prosperon.gc_end = function(){}
|
os.gc_threshold.doc = "Set the threshold before a GC pass is triggered in bytes. This is set to malloc_size + malloc_size>>1 after a GC pass.";
|
||||||
|
os.max_stacksize.doc = "Set the max stack size in bytes.";
|
||||||
|
|
||||||
Object.defineProperty(String.prototype, 'rm', {
|
Object.defineProperty(String.prototype, 'rm', {
|
||||||
value: function(index, endidx = index+1) { return this.slice(0,index) + this.slice(endidx); }
|
value: function(index, endidx = index+1) { return this.slice(0,index) + this.slice(endidx); }
|
||||||
|
|
|
@ -294,6 +294,7 @@ profile.print_mem = function()
|
||||||
{
|
{
|
||||||
var mem = os.mem();
|
var mem = os.mem();
|
||||||
say('total memory used: ' + profile.best_mem(mem.memory_used_size));
|
say('total memory used: ' + profile.best_mem(mem.memory_used_size));
|
||||||
|
say('total malloced: ' + profile.best_mem(mem.malloc_size));
|
||||||
delete mem.memory_used_size;
|
delete mem.memory_used_size;
|
||||||
delete mem.malloc_size;
|
delete mem.malloc_size;
|
||||||
for (var i in mem) {
|
for (var i in mem) {
|
||||||
|
@ -302,4 +303,21 @@ profile.print_mem = function()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
profile.atom_count = function()
|
||||||
|
{
|
||||||
|
// return os.dump_atoms().split(
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.print_gc = function()
|
||||||
|
{
|
||||||
|
var gc = os.check_gc();
|
||||||
|
if (!gc) return;
|
||||||
|
var mem = os.mem();
|
||||||
|
say("GC Hit");
|
||||||
|
say (`time: ${profile.best_t(gc.time)}`);
|
||||||
|
say(`new threshold: ${profile.best_mem(mem.gc_threshold)}`);
|
||||||
|
say(`memory checked: ${profile.best_mem(gc.mem)}`);
|
||||||
|
say(`memory freed: ${profile.best_mem(gc.startmem - gc.mem)}`);
|
||||||
|
}
|
||||||
|
|
||||||
return {profile};
|
return {profile};
|
||||||
|
|
|
@ -972,6 +972,13 @@ prosperon.process = function process() {
|
||||||
var dt = profile.secs(profile.now()) - frame_t;
|
var dt = profile.secs(profile.now()) - frame_t;
|
||||||
frame_t = profile.secs(profile.now());
|
frame_t = profile.secs(profile.now());
|
||||||
|
|
||||||
|
/* debugging: check for gc */
|
||||||
|
profile.print_gc();
|
||||||
|
|
||||||
|
var cycles = os.check_cycles();
|
||||||
|
if (cycles) say(cycles);
|
||||||
|
|
||||||
|
|
||||||
profile.frame("app update");
|
profile.frame("app update");
|
||||||
prosperon.appupdate(dt);
|
prosperon.appupdate(dt);
|
||||||
profile.endframe();
|
profile.endframe();
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "sokol_glue.h"
|
#include "sokol_glue.h"
|
||||||
#include <chipmunk/chipmunk_unsafe.h>
|
#include <chipmunk/chipmunk_unsafe.h>
|
||||||
#include <chipmunk/chipmunk_structs.h>
|
#include <chipmunk/chipmunk_structs.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
@ -2483,7 +2484,6 @@ static const JSCFunctionListEntry js_nota_funcs[] = {
|
||||||
MIST_FUNC_DEF(nota, decode, 1)
|
MIST_FUNC_DEF(nota, decode, 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
JSValue js_os_cwd(JSContext *js, JSValue self, int argc, JSValue *argv)
|
JSValue js_os_cwd(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||||
{
|
{
|
||||||
char cwd[PATH_MAX];
|
char cwd[PATH_MAX];
|
||||||
|
@ -2522,17 +2522,69 @@ JSC_CCALL(os_mem_limit, script_mem_limit(js2number(argv[0])))
|
||||||
JSC_CCALL(os_gc_threshold, script_gc_threshold(js2number(argv[0])))
|
JSC_CCALL(os_gc_threshold, script_gc_threshold(js2number(argv[0])))
|
||||||
JSC_CCALL(os_max_stacksize, script_max_stacksize(js2number(argv[0])))
|
JSC_CCALL(os_max_stacksize, script_max_stacksize(js2number(argv[0])))
|
||||||
|
|
||||||
|
static JSValue tmp2js(FILE *tmp)
|
||||||
|
{
|
||||||
|
size_t size = ftell(tmp);
|
||||||
|
rewind(tmp);
|
||||||
|
char *buffer = calloc(size+1, sizeof(char));
|
||||||
|
fread(buffer, sizeof(char),size, tmp);
|
||||||
|
JSValue ret = str2js(buffer);
|
||||||
|
free(buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC_CCALL(os_dump_value,
|
||||||
|
|
||||||
|
FILE *tmp = tmpfile();
|
||||||
|
quickjs_set_dumpout(tmp);
|
||||||
|
JS_DumpMyValue(rt, argv[0]);
|
||||||
|
ret = tmp2js(tmp);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_dump_atoms,
|
||||||
|
FILE *tmp = tmpfile();
|
||||||
|
quickjs_set_dumpout(tmp);
|
||||||
|
JS_PrintAtoms(rt);
|
||||||
|
ret = tmp2js(tmp);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_dump_shapes,
|
||||||
|
FILE *tmp = tmpfile();
|
||||||
|
quickjs_set_dumpout(tmp);
|
||||||
|
JS_PrintShapes(rt);
|
||||||
|
size_t size = ftell(tmp);
|
||||||
|
rewind(tmp);
|
||||||
|
char buffer[size];
|
||||||
|
fgets(buffer, sizeof(char)*size, tmp);
|
||||||
|
fclose(tmp);
|
||||||
|
ret = str2js(buffer);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_calc_mem,
|
||||||
|
return number2js(JS_MyValueSize(rt, argv[0]));
|
||||||
|
)
|
||||||
|
|
||||||
#define JSOBJ_ADD_FIELD(OBJ, STRUCT, FIELD, TYPE) \
|
#define JSOBJ_ADD_FIELD(OBJ, STRUCT, FIELD, TYPE) \
|
||||||
js_setpropstr(OBJ, #FIELD, TYPE##2js(STRUCT.FIELD));\
|
js_setpropstr(OBJ, #FIELD, TYPE##2js(STRUCT.FIELD));\
|
||||||
|
|
||||||
#define JSJMEMRET(FIELD) JSOBJ_ADD_FIELD(ret, jsmem, FIELD, number)
|
#define JSJMEMRET(FIELD) JSOBJ_ADD_FIELD(ret, jsmem, FIELD, number)
|
||||||
|
|
||||||
|
JSC_CCALL(os_memstate,
|
||||||
|
JSMemoryUsage jsmem;
|
||||||
|
JS_FillMemoryState(rt, &jsmem);
|
||||||
|
ret = JS_NewObject(js);
|
||||||
|
JSJMEMRET(malloc_size)
|
||||||
|
JSJMEMRET(malloc_limit)
|
||||||
|
JSJMEMRET(gc_threshold)
|
||||||
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_mem,
|
JSC_CCALL(os_mem,
|
||||||
JSMemoryUsage jsmem;
|
JSMemoryUsage jsmem;
|
||||||
JS_ComputeMemoryUsage(rt, &jsmem);
|
JS_ComputeMemoryUsage(rt, &jsmem);
|
||||||
ret = JS_NewObject(js);
|
ret = JS_NewObject(js);
|
||||||
JSJMEMRET(malloc_size)
|
JSJMEMRET(malloc_size)
|
||||||
JSJMEMRET(malloc_limit)
|
JSJMEMRET(malloc_limit)
|
||||||
|
JSJMEMRET(gc_threshold)
|
||||||
JSJMEMRET(memory_used_size)
|
JSJMEMRET(memory_used_size)
|
||||||
JSJMEMRET(memory_used_count)
|
JSJMEMRET(memory_used_count)
|
||||||
JSJMEMRET(atom_count)
|
JSJMEMRET(atom_count)
|
||||||
|
@ -2558,6 +2610,45 @@ JSC_CCALL(os_mem,
|
||||||
JSJMEMRET(binary_object_size)
|
JSJMEMRET(binary_object_size)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_dump_mem,
|
||||||
|
FILE *tmp = tmpfile();
|
||||||
|
JSMemoryUsage mem = {0};
|
||||||
|
JS_DumpMemoryUsage(tmp, &mem, rt);
|
||||||
|
ret = tmp2js(tmp);
|
||||||
|
)
|
||||||
|
|
||||||
|
static double gc_t = 0;
|
||||||
|
static double gc_mem = 0;
|
||||||
|
static double gc_startmem = 0;
|
||||||
|
void script_report_gc_time(double t, double startmem, double mem)
|
||||||
|
{
|
||||||
|
gc_t = t;
|
||||||
|
gc_mem = mem;
|
||||||
|
gc_startmem = startmem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FILE *cycles;
|
||||||
|
|
||||||
|
JSC_CCALL(os_check_cycles,
|
||||||
|
if (ftell(cycles) == 0) return JS_UNDEFINED;
|
||||||
|
ret = tmp2js(cycles);
|
||||||
|
cycles = tmpfile();
|
||||||
|
quickjs_set_cycleout(cycles);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_check_gc,
|
||||||
|
if (gc_t == 0) return JS_UNDEFINED;
|
||||||
|
|
||||||
|
JSValue gc = JS_NewObject(js);
|
||||||
|
js_setpropstr(gc, "time", number2js(gc_t));
|
||||||
|
js_setpropstr(gc, "mem", number2js(gc_mem));
|
||||||
|
js_setpropstr(gc, "startmem", number2js(gc_startmem));
|
||||||
|
gc_t = 0;
|
||||||
|
gc_mem = 0;
|
||||||
|
gc_startmem = 0;
|
||||||
|
return gc;
|
||||||
|
)
|
||||||
|
|
||||||
JSC_SSCALL(os_eval, ret = script_eval(str, str2))
|
JSC_SSCALL(os_eval, ret = script_eval(str, str2))
|
||||||
|
|
||||||
JSC_CCALL(os_make_body,
|
JSC_CCALL(os_make_body,
|
||||||
|
@ -3007,7 +3098,15 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
MIST_FUNC_DEF(os, mem, 1),
|
MIST_FUNC_DEF(os, mem, 1),
|
||||||
MIST_FUNC_DEF(os, mem_limit, 1),
|
MIST_FUNC_DEF(os, mem_limit, 1),
|
||||||
MIST_FUNC_DEF(os, gc_threshold, 1),
|
MIST_FUNC_DEF(os, gc_threshold, 1),
|
||||||
MIST_FUNC_DEF(os, max_stacksize, 1)
|
MIST_FUNC_DEF(os, max_stacksize, 1),
|
||||||
|
MIST_FUNC_DEF(os, dump_value, 1),
|
||||||
|
MIST_FUNC_DEF(os, dump_mem, 0),
|
||||||
|
MIST_FUNC_DEF(os, dump_shapes, 0),
|
||||||
|
MIST_FUNC_DEF(os, dump_atoms,0),
|
||||||
|
MIST_FUNC_DEF(os, calc_mem, 1),
|
||||||
|
MIST_FUNC_DEF(os, check_gc, 0),
|
||||||
|
MIST_FUNC_DEF(os, check_cycles, 0),
|
||||||
|
MIST_FUNC_DEF(os, memstate, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "steam.h"
|
#include "steam.h"
|
||||||
|
@ -3018,6 +3117,9 @@ JS_SetPropertyFunctionList(js, js_##NAME, js_##NAME##_funcs, countof(js_##NAME##
|
||||||
JS_SetPrototype(js, js_##NAME, PARENT); \
|
JS_SetPrototype(js, js_##NAME, PARENT); \
|
||||||
|
|
||||||
void ffi_load() {
|
void ffi_load() {
|
||||||
|
cycles = tmpfile();
|
||||||
|
quickjs_set_cycleout(cycles);
|
||||||
|
|
||||||
JSUNDEF = JS_UNDEFINED;
|
JSUNDEF = JS_UNDEFINED;
|
||||||
globalThis = JS_GetGlobalObject(js);
|
globalThis = JS_GetGlobalObject(js);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ extern "C" {
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <chipmunk/chipmunk.h>
|
#include <chipmunk/chipmunk.h>
|
||||||
|
|
||||||
|
void script_report_gc_time(double t, double startmem, double mem);
|
||||||
|
|
||||||
extern JSValue cpShape2js(cpShape *s);
|
extern JSValue cpShape2js(cpShape *s);
|
||||||
|
|
||||||
#define MIST_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } }
|
#define MIST_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } }
|
||||||
|
|
|
@ -16,8 +16,7 @@ JSRuntime *rt = NULL;
|
||||||
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT | JS_EVAL_FLAG_STRIP
|
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT | JS_EVAL_FLAG_STRIP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static JSValue start_gc;
|
static JSValue report_gc;
|
||||||
static JSValue end_gc;
|
|
||||||
|
|
||||||
void script_startup() {
|
void script_startup() {
|
||||||
rt = JS_NewRuntime();
|
rt = JS_NewRuntime();
|
||||||
|
|
|
@ -34,6 +34,11 @@ void script_mem_limit(size_t limit);
|
||||||
void script_gc_threshold(size_t threshold);
|
void script_gc_threshold(size_t threshold);
|
||||||
void script_max_stacksize(size_t size);
|
void script_max_stacksize(size_t size);
|
||||||
|
|
||||||
|
void _script_gcstart();
|
||||||
|
void _script_gcend();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
265
source/engine/thirdparty/quickjs/quickjs.c
vendored
265
source/engine/thirdparty/quickjs/quickjs.c
vendored
|
@ -33,6 +33,9 @@
|
||||||
#include <fenv.h>
|
#include <fenv.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <script.h>
|
#include <script.h>
|
||||||
|
#include <jsffi.h>
|
||||||
|
#include <sokol/sokol_time.h>
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <malloc/malloc.h>
|
#include <malloc/malloc.h>
|
||||||
#elif defined(__linux__) || defined(__GLIBC__)
|
#elif defined(__linux__) || defined(__GLIBC__)
|
||||||
|
@ -79,15 +82,17 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static FILE *dumpout = NULL;
|
static FILE *dumpout = NULL;
|
||||||
|
static FILE *cycleout = NULL;
|
||||||
|
|
||||||
void quickjs_set_dumpout(FILE *f)
|
void quickjs_set_dumpout(FILE *f)
|
||||||
{
|
{
|
||||||
dumpout = f;
|
dumpout = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void quickjs_set_cycleout(FILE *f) { cycleout = f; }
|
||||||
|
|
||||||
/* dump object free */
|
/* dump object free */
|
||||||
//#define DUMP_FREE
|
//#define DUMP_FREE
|
||||||
//#define DUMP_CLOSURE
|
|
||||||
/* dump the bytecode of the compiled functions: combination of bits
|
/* dump the bytecode of the compiled functions: combination of bits
|
||||||
1: dump pass 3 final byte code
|
1: dump pass 3 final byte code
|
||||||
2: dump pass 2 code
|
2: dump pass 2 code
|
||||||
|
@ -116,13 +121,9 @@ void quickjs_set_dumpout(FILE *f)
|
||||||
#ifdef DUMP
|
#ifdef DUMP
|
||||||
//#define DUMP_FREE
|
//#define DUMP_FREE
|
||||||
//#define DUMP_MEM
|
//#define DUMP_MEM
|
||||||
//#define DUMP_CLOSURE
|
|
||||||
#define DUMP_GC
|
#define DUMP_GC
|
||||||
//#define DUMP_GC_FREE
|
|
||||||
#define DUMP_LEAKS 1
|
#define DUMP_LEAKS 1
|
||||||
//#define DUMP_OBJECTS
|
//#define DUMP_OBJECTS
|
||||||
#define DUMP_CLOSURE
|
|
||||||
//#define DUMP_OBJECTS
|
|
||||||
//#define DUMP_ATOMS
|
//#define DUMP_ATOMS
|
||||||
//#define DUMP_SHAPES
|
//#define DUMP_SHAPES
|
||||||
//#define DUMP_MODULE_RESOLVE
|
//#define DUMP_MODULE_RESOLVE
|
||||||
|
@ -329,6 +330,25 @@ struct JSRuntime {
|
||||||
void *user_opaque;
|
void *user_opaque;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SETRT(FIELD) JS_SetPropertyStr(js, v, #FIELD, JS_NewFloat64(js, rt->FIELD));
|
||||||
|
|
||||||
|
JSValue JS_GetRTInfo(JSRuntime *rt, JSContext *js)
|
||||||
|
{
|
||||||
|
JSValue v = JS_NewObject(js);
|
||||||
|
SETRT(atom_hash_size);
|
||||||
|
SETRT(atom_count);
|
||||||
|
SETRT(atom_size);
|
||||||
|
SETRT(class_count);
|
||||||
|
SETRT(stack_size);
|
||||||
|
SETRT(stack_top);
|
||||||
|
SETRT(stack_limit);
|
||||||
|
SETRT(malloc_gc_threshold);
|
||||||
|
SETRT(malloc_state.malloc_count);
|
||||||
|
SETRT(malloc_state.malloc_size);
|
||||||
|
SETRT(malloc_state.malloc_limit);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
struct JSClass {
|
struct JSClass {
|
||||||
uint32_t class_id; /* 0 means free entry */
|
uint32_t class_id; /* 0 means free entry */
|
||||||
JSAtom class_name;
|
JSAtom class_name;
|
||||||
|
@ -1068,12 +1088,12 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
|
||||||
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
|
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
|
||||||
static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
|
static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
|
||||||
static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p);
|
static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p);
|
||||||
static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
|
static __maybe_unused void JS_DumpObjectHeader(FILE *fp, JSRuntime *rt);
|
||||||
static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
|
static __maybe_unused void JS_DumpObject(FILE *fp, JSRuntime *rt, JSObject *p);
|
||||||
static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
|
static __maybe_unused void JS_DumpGCObject(FILE *fp, JSRuntime *rt, JSGCObjectHeader *p);
|
||||||
static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, JSValueConst val);
|
static __maybe_unused void JS_DumpValueShort(FILE *fp, JSRuntime *rt, JSValueConst val);
|
||||||
static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
|
static __maybe_unused void JS_DumpValue(FILE *fp, JSContext *ctx, JSValueConst val);
|
||||||
static __maybe_unused void JS_PrintValue(JSContext *ctx,
|
static __maybe_unused void JS_PrintValue(FILE *fp,JSContext *ctx,
|
||||||
const char *str,
|
const char *str,
|
||||||
JSValueConst val);
|
JSValueConst val);
|
||||||
static __maybe_unused void JS_DumpShapes(JSRuntime *rt);
|
static __maybe_unused void JS_DumpShapes(JSRuntime *rt);
|
||||||
|
@ -1309,6 +1329,27 @@ static const JSClassExoticMethods js_proxy_exotic_methods;
|
||||||
static const JSClassExoticMethods js_module_ns_exotic_methods;
|
static const JSClassExoticMethods js_module_ns_exotic_methods;
|
||||||
static JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT;
|
static JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT;
|
||||||
|
|
||||||
|
|
||||||
|
////// CUSTOM DUMP FUNCTIONS
|
||||||
|
void JS_DumpMyValue(JSRuntime *rt, JSValue v)
|
||||||
|
{
|
||||||
|
uint32_t tag = JS_VALUE_GET_TAG(v);
|
||||||
|
if (tag == JS_TAG_OBJECT)
|
||||||
|
JS_DumpObject(dumpout, rt, JS_VALUE_GET_OBJ(v));
|
||||||
|
else
|
||||||
|
JS_DumpValueShort(dumpout, rt, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JS_PrintShapes(JSRuntime *rt)
|
||||||
|
{
|
||||||
|
JS_DumpShapes(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JS_PrintAtoms(JSRuntime *rt)
|
||||||
|
{
|
||||||
|
JS_DumpAtoms(rt);
|
||||||
|
}
|
||||||
|
|
||||||
static void js_trigger_gc(JSRuntime *rt, size_t size)
|
static void js_trigger_gc(JSRuntime *rt, size_t size)
|
||||||
{
|
{
|
||||||
BOOL force_gc;
|
BOOL force_gc;
|
||||||
|
@ -1320,7 +1361,7 @@ static void js_trigger_gc(JSRuntime *rt, size_t size)
|
||||||
#endif
|
#endif
|
||||||
if (force_gc) {
|
if (force_gc) {
|
||||||
#ifdef DUMP_GC
|
#ifdef DUMP_GC
|
||||||
fprintf(dumpout, dumpout, "GC: size=%" PRIu64 "\n",
|
fprintf(dumpout, "GC: size=%" PRIu64 "\n",
|
||||||
(uint64_t)rt->malloc_state.malloc_size);
|
(uint64_t)rt->malloc_state.malloc_size);
|
||||||
#endif
|
#endif
|
||||||
JS_RunGC(rt);
|
JS_RunGC(rt);
|
||||||
|
@ -2004,11 +2045,11 @@ void JS_FreeRuntime(JSRuntime *rt)
|
||||||
p = list_entry(el, JSGCObjectHeader, link);
|
p = list_entry(el, JSGCObjectHeader, link);
|
||||||
if (p->ref_count != 0) {
|
if (p->ref_count != 0) {
|
||||||
if (!header_done) {
|
if (!header_done) {
|
||||||
fprintf(dumpout, dumpout, "Object leaks:\n");
|
fprintf(cycleout, "Object leaks:\n");
|
||||||
JS_DumpObjectHeader(rt);
|
JS_DumpObjectHeader(cycleout, rt);
|
||||||
header_done = TRUE;
|
header_done = TRUE;
|
||||||
}
|
}
|
||||||
JS_DumpGCObject(rt, p);
|
JS_DumpGCObject(cycleout, rt, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2020,7 +2061,7 @@ void JS_FreeRuntime(JSRuntime *rt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count != 0)
|
if (count != 0)
|
||||||
fprintf(dumpout, "Secondary object leaks: %d\n", count);
|
fprintf(cycleout, "Secondary object leaks: %d\n", count);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(list_empty(&rt->gc_obj_list));
|
assert(list_empty(&rt->gc_obj_list));
|
||||||
|
@ -5837,7 +5878,7 @@ static void gc_free_cycles(JSRuntime *rt)
|
||||||
{
|
{
|
||||||
struct list_head *el, *el1;
|
struct list_head *el, *el1;
|
||||||
JSGCObjectHeader *p;
|
JSGCObjectHeader *p;
|
||||||
#ifdef DUMP_GC_FREE
|
#ifdef DUMP
|
||||||
BOOL header_done = FALSE;
|
BOOL header_done = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -5855,13 +5896,13 @@ static void gc_free_cycles(JSRuntime *rt)
|
||||||
case JS_GC_OBJ_TYPE_JS_OBJECT:
|
case JS_GC_OBJ_TYPE_JS_OBJECT:
|
||||||
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
|
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
|
||||||
case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
|
case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
|
||||||
#ifdef DUMP_GC_FREE
|
#ifdef DUMP
|
||||||
if (!header_done) {
|
if (!header_done) {
|
||||||
fprintf(dumpout, "Freeing cycles:\n");
|
fprintf(cycleout, "Freeing cycles:\n");
|
||||||
JS_DumpObjectHeader(rt);
|
JS_DumpObjectHeader(cycleout, rt);
|
||||||
header_done = TRUE;
|
header_done = TRUE;
|
||||||
}
|
}
|
||||||
JS_DumpGCObject(rt, p);
|
JS_DumpGCObject(cycleout, rt, p);
|
||||||
#endif
|
#endif
|
||||||
free_gc_object(rt, p);
|
free_gc_object(rt, p);
|
||||||
break;
|
break;
|
||||||
|
@ -5886,6 +5927,9 @@ static void gc_free_cycles(JSRuntime *rt)
|
||||||
|
|
||||||
void JS_RunGC(JSRuntime *rt)
|
void JS_RunGC(JSRuntime *rt)
|
||||||
{
|
{
|
||||||
|
double n = stm_now();
|
||||||
|
double size = rt->malloc_state.malloc_size;
|
||||||
|
|
||||||
/* decrement the reference of the children of each object. mark =
|
/* decrement the reference of the children of each object. mark =
|
||||||
1 after this pass. */
|
1 after this pass. */
|
||||||
gc_decref(rt);
|
gc_decref(rt);
|
||||||
|
@ -5895,6 +5939,8 @@ void JS_RunGC(JSRuntime *rt)
|
||||||
|
|
||||||
/* free the GC objects in a cycle */
|
/* free the GC objects in a cycle */
|
||||||
gc_free_cycles(rt);
|
gc_free_cycles(rt);
|
||||||
|
|
||||||
|
script_report_gc_time(stm_now()-n, size, rt->malloc_state.malloc_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return false if not an object or if the object has already been
|
/* Return false if not an object or if the object has already been
|
||||||
|
@ -5989,6 +6035,25 @@ static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double JS_MyValueSize(JSRuntime *rt, JSValue v)
|
||||||
|
{
|
||||||
|
JSMemoryUsage_helper mem = {0};
|
||||||
|
compute_value_size(v, &mem);
|
||||||
|
return mem.memory_used_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JS_FillMemoryState(JSRuntime *rt, JSMemoryUsage *s)
|
||||||
|
{
|
||||||
|
s->malloc_count = rt->malloc_state.malloc_count;
|
||||||
|
s->malloc_size = rt->malloc_state.malloc_size;
|
||||||
|
s->malloc_limit = rt->malloc_state.malloc_limit;
|
||||||
|
|
||||||
|
s->gc_threshold = rt->malloc_gc_threshold;
|
||||||
|
|
||||||
|
s->memory_used_count = 2; /* rt + rt->class_array */
|
||||||
|
s->memory_used_size = sizeof(JSRuntime) + sizeof(JSValue) * rt->class_count;
|
||||||
|
}
|
||||||
|
|
||||||
void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
|
void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
|
||||||
{
|
{
|
||||||
struct list_head *el, *el1;
|
struct list_head *el, *el1;
|
||||||
|
@ -6000,6 +6065,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
|
||||||
s->malloc_size = rt->malloc_state.malloc_size;
|
s->malloc_size = rt->malloc_state.malloc_size;
|
||||||
s->malloc_limit = rt->malloc_state.malloc_limit;
|
s->malloc_limit = rt->malloc_state.malloc_limit;
|
||||||
|
|
||||||
|
s->gc_threshold = rt->malloc_gc_threshold;
|
||||||
|
|
||||||
s->memory_used_count = 2; /* rt + rt->class_array */
|
s->memory_used_count = 2; /* rt + rt->class_array */
|
||||||
s->memory_used_size = sizeof(JSRuntime) + sizeof(JSValue) * rt->class_count;
|
s->memory_used_size = sizeof(JSRuntime) + sizeof(JSValue) * rt->class_count;
|
||||||
|
|
||||||
|
@ -6279,7 +6346,7 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
|
||||||
|
|
||||||
void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
|
void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
|
||||||
{
|
{
|
||||||
fprintf(dumpout, fp, "QuickJS memory usage -- "
|
fprintf(fp, "QuickJS memory usage -- "
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
"BigNum "
|
"BigNum "
|
||||||
#endif
|
#endif
|
||||||
|
@ -6305,14 +6372,14 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
|
||||||
unsigned int size1 = js_malloc_usable_size_rt(rt, p);
|
unsigned int size1 = js_malloc_usable_size_rt(rt, p);
|
||||||
if (size1 >= size) {
|
if (size1 >= size) {
|
||||||
usage_size_ok = 1;
|
usage_size_ok = 1;
|
||||||
fprintf(dumpout, fp, " %3u + %-2u %s\n",
|
fprintf(fp, " %3u + %-2u %s\n",
|
||||||
size, size1 - size, object_types[i].name);
|
size, size1 - size, object_types[i].name);
|
||||||
}
|
}
|
||||||
js_free_rt(rt, p);
|
js_free_rt(rt, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!usage_size_ok) {
|
if (!usage_size_ok) {
|
||||||
fprintf(dumpout, fp, " malloc_usable_size unavailable\n");
|
fprintf(fp, " malloc_usable_size unavailable\n");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int obj_classes[JS_CLASS_INIT_COUNT + 1] = { 0 };
|
int obj_classes[JS_CLASS_INIT_COUNT + 1] = { 0 };
|
||||||
|
@ -6326,82 +6393,82 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
|
||||||
obj_classes[min_uint32(p->class_id, JS_CLASS_INIT_COUNT)]++;
|
obj_classes[min_uint32(p->class_id, JS_CLASS_INIT_COUNT)]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(dumpout, fp, "\n" "JSObject classes\n");
|
fprintf(fp, "\n" "JSObject classes\n");
|
||||||
if (obj_classes[0])
|
if (obj_classes[0])
|
||||||
fprintf(dumpout, fp, " %5d %2.0d %s\n", obj_classes[0], 0, "none");
|
fprintf(fp, " %5d %2.0d %s\n", obj_classes[0], 0, "none");
|
||||||
for (class_id = 1; class_id < JS_CLASS_INIT_COUNT; class_id++) {
|
for (class_id = 1; class_id < JS_CLASS_INIT_COUNT; class_id++) {
|
||||||
if (obj_classes[class_id] && class_id < rt->class_count) {
|
if (obj_classes[class_id] && class_id < rt->class_count) {
|
||||||
char buf[ATOM_GET_STR_BUF_SIZE];
|
char buf[ATOM_GET_STR_BUF_SIZE];
|
||||||
fprintf(dumpout, fp, " %5d %2.0d %s\n", obj_classes[class_id], class_id,
|
fprintf(fp, " %5d %2.0d %s\n", obj_classes[class_id], class_id,
|
||||||
JS_AtomGetStrRT(rt, buf, sizeof(buf), rt->class_array[class_id].class_name));
|
JS_AtomGetStrRT(rt, buf, sizeof(buf), rt->class_array[class_id].class_name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (obj_classes[JS_CLASS_INIT_COUNT])
|
if (obj_classes[JS_CLASS_INIT_COUNT])
|
||||||
fprintf(dumpout, fp, " %5d %2.0d %s\n", obj_classes[JS_CLASS_INIT_COUNT], 0, "other");
|
fprintf(fp, " %5d %2.0d %s\n", obj_classes[JS_CLASS_INIT_COUNT], 0, "other");
|
||||||
}
|
}
|
||||||
fprintf(dumpout, fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fprintf(dumpout, fp, "%-20s %8s %8s\n", "NAME", "COUNT", "SIZE");
|
fprintf(fp, "%-20s %8s %8s\n", "NAME", "COUNT", "SIZE");
|
||||||
|
|
||||||
if (s->malloc_count) {
|
if (s->malloc_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per block)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per block)\n",
|
||||||
"memory allocated", s->malloc_count, s->malloc_size,
|
"memory allocated", s->malloc_count, s->malloc_size,
|
||||||
(double)s->malloc_size / s->malloc_count);
|
(double)s->malloc_size / s->malloc_count);
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%d overhead, %0.1f average slack)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%d overhead, %0.1f average slack)\n",
|
||||||
"memory used", s->memory_used_count, s->memory_used_size,
|
"memory used", s->memory_used_count, s->memory_used_size,
|
||||||
MALLOC_OVERHEAD, ((double)(s->malloc_size - s->memory_used_size) /
|
MALLOC_OVERHEAD, ((double)(s->malloc_size - s->memory_used_size) /
|
||||||
s->memory_used_count));
|
s->memory_used_count));
|
||||||
}
|
}
|
||||||
if (s->atom_count) {
|
if (s->atom_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per atom)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per atom)\n",
|
||||||
"atoms", s->atom_count, s->atom_size,
|
"atoms", s->atom_count, s->atom_size,
|
||||||
(double)s->atom_size / s->atom_count);
|
(double)s->atom_size / s->atom_count);
|
||||||
}
|
}
|
||||||
if (s->str_count) {
|
if (s->str_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per string)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per string)\n",
|
||||||
"strings", s->str_count, s->str_size,
|
"strings", s->str_count, s->str_size,
|
||||||
(double)s->str_size / s->str_count);
|
(double)s->str_size / s->str_count);
|
||||||
}
|
}
|
||||||
if (s->obj_count) {
|
if (s->obj_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per object)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per object)\n",
|
||||||
"objects", s->obj_count, s->obj_size,
|
"objects", s->obj_count, s->obj_size,
|
||||||
(double)s->obj_size / s->obj_count);
|
(double)s->obj_size / s->obj_count);
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per object)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per object)\n",
|
||||||
" properties", s->prop_count, s->prop_size,
|
" properties", s->prop_count, s->prop_size,
|
||||||
(double)s->prop_count / s->obj_count);
|
(double)s->prop_count / s->obj_count);
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per shape)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per shape)\n",
|
||||||
" shapes", s->shape_count, s->shape_size,
|
" shapes", s->shape_count, s->shape_size,
|
||||||
(double)s->shape_size / s->shape_count);
|
(double)s->shape_size / s->shape_count);
|
||||||
}
|
}
|
||||||
if (s->js_func_count) {
|
if (s->js_func_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64"\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64"\n",
|
||||||
"bytecode functions", s->js_func_count, s->js_func_size);
|
"bytecode functions", s->js_func_count, s->js_func_size);
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per function)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per function)\n",
|
||||||
" bytecode", s->js_func_count, s->js_func_code_size,
|
" bytecode", s->js_func_count, s->js_func_code_size,
|
||||||
(double)s->js_func_code_size / s->js_func_count);
|
(double)s->js_func_code_size / s->js_func_count);
|
||||||
if (s->js_func_pc2line_count) {
|
if (s->js_func_pc2line_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per function)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per function)\n",
|
||||||
" pc2line", s->js_func_pc2line_count,
|
" pc2line", s->js_func_pc2line_count,
|
||||||
s->js_func_pc2line_size,
|
s->js_func_pc2line_size,
|
||||||
(double)s->js_func_pc2line_size / s->js_func_pc2line_count);
|
(double)s->js_func_pc2line_size / s->js_func_pc2line_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s->c_func_count) {
|
if (s->c_func_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64"\n", "C functions", s->c_func_count);
|
fprintf(fp, "%-20s %8"PRId64"\n", "C functions", s->c_func_count);
|
||||||
}
|
}
|
||||||
if (s->array_count) {
|
if (s->array_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64"\n", "arrays", s->array_count);
|
fprintf(fp, "%-20s %8"PRId64"\n", "arrays", s->array_count);
|
||||||
if (s->fast_array_count) {
|
if (s->fast_array_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64"\n", " fast arrays", s->fast_array_count);
|
fprintf(fp, "%-20s %8"PRId64"\n", " fast arrays", s->fast_array_count);
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per fast array)\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64" (%0.1f per fast array)\n",
|
||||||
" elements", s->fast_array_elements,
|
" elements", s->fast_array_elements,
|
||||||
s->fast_array_elements * (int)sizeof(JSValue),
|
s->fast_array_elements * (int)sizeof(JSValue),
|
||||||
(double)s->fast_array_elements / s->fast_array_count);
|
(double)s->fast_array_elements / s->fast_array_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s->binary_object_count) {
|
if (s->binary_object_count) {
|
||||||
fprintf(dumpout, fp, "%-20s %8"PRId64" %8"PRId64"\n",
|
fprintf(fp, "%-20s %8"PRId64" %8"PRId64"\n",
|
||||||
"binary objects", s->binary_object_count, s->binary_object_size);
|
"binary objects", s->binary_object_count, s->binary_object_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11874,14 +11941,14 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)
|
static __maybe_unused void JS_DumpObjectHeader(FILE *fp, JSRuntime *rt)
|
||||||
{
|
{
|
||||||
fprintf(dumpout, "%14s %4s %4s %14s %10s %s\n",
|
fprintf(fp, "%14s %4s %4s %14s %10s %s\n",
|
||||||
"ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS");
|
"ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for debug only: dump an object without side effect */
|
/* for debug only: dump an object without side effect */
|
||||||
static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
|
static __maybe_unused void JS_DumpObject(FILE *fp, JSRuntime *rt, JSObject *p)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
char atom_buf[ATOM_GET_STR_BUF_SIZE];
|
char atom_buf[ATOM_GET_STR_BUF_SIZE];
|
||||||
|
@ -11892,28 +11959,28 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
|
||||||
|
|
||||||
/* XXX: should encode atoms with special characters */
|
/* XXX: should encode atoms with special characters */
|
||||||
sh = p->shape; /* the shape can be NULL while freeing an object */
|
sh = p->shape; /* the shape can be NULL while freeing an object */
|
||||||
fprintf(dumpout, "%14p %4d ",
|
fprintf(fp, "%14p %4d ",
|
||||||
(void *)p,
|
(void *)p,
|
||||||
p->header.ref_count);
|
p->header.ref_count);
|
||||||
if (sh) {
|
if (sh) {
|
||||||
fprintf(dumpout, "%3d%c %14p ",
|
fprintf(fp, "%3d%c %14p ",
|
||||||
sh->header.ref_count,
|
sh->header.ref_count,
|
||||||
" *"[sh->is_hashed],
|
" *"[sh->is_hashed],
|
||||||
(void *)sh->proto);
|
(void *)sh->proto);
|
||||||
} else {
|
} else {
|
||||||
fprintf(dumpout, "%3s %14s ", "-", "-");
|
fprintf(fp, "%3s %14s ", "-", "-");
|
||||||
}
|
}
|
||||||
fprintf(dumpout, "%10s ",
|
fprintf(fp, "%10s ",
|
||||||
JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), rt->class_array[p->class_id].class_name));
|
JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), rt->class_array[p->class_id].class_name));
|
||||||
if (p->is_exotic && p->fast_array) {
|
if (p->is_exotic && p->fast_array) {
|
||||||
fprintf(dumpout, "[ ");
|
fprintf(fp, "[ ");
|
||||||
for(i = 0; i < p->u.array.count; i++) {
|
for(i = 0; i < p->u.array.count; i++) {
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
fprintf(dumpout, ", ");
|
fprintf(fp, ", ");
|
||||||
switch (p->class_id) {
|
switch (p->class_id) {
|
||||||
case JS_CLASS_ARRAY:
|
case JS_CLASS_ARRAY:
|
||||||
case JS_CLASS_ARGUMENTS:
|
case JS_CLASS_ARGUMENTS:
|
||||||
JS_DumpValueShort(rt, p->u.array.u.values[i]);
|
JS_DumpValueShort(fp, rt, p->u.array.u.values[i]);
|
||||||
break;
|
break;
|
||||||
case JS_CLASS_UINT8C_ARRAY:
|
case JS_CLASS_UINT8C_ARRAY:
|
||||||
case JS_CLASS_INT8_ARRAY:
|
case JS_CLASS_INT8_ARRAY:
|
||||||
|
@ -11930,40 +11997,40 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
|
||||||
int size = 1 << typed_array_size_log2(p->class_id);
|
int size = 1 << typed_array_size_log2(p->class_id);
|
||||||
const uint8_t *b = p->u.array.u.uint8_ptr + i * size;
|
const uint8_t *b = p->u.array.u.uint8_ptr + i * size;
|
||||||
while (size-- > 0)
|
while (size-- > 0)
|
||||||
fprintf(dumpout, "%02X", *b++);
|
fprintf(fp, "%02X", *b++);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(dumpout, " ] ");
|
fprintf(fp, " ] ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sh) {
|
if (sh) {
|
||||||
fprintf(dumpout, "{ ");
|
fprintf(fp, "{ ");
|
||||||
for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {
|
for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {
|
||||||
if (prs->atom != JS_ATOM_NULL) {
|
if (prs->atom != JS_ATOM_NULL) {
|
||||||
pr = &p->prop[i];
|
pr = &p->prop[i];
|
||||||
if (!is_first)
|
if (!is_first)
|
||||||
fprintf(dumpout, ", ");
|
fprintf(fp, ", ");
|
||||||
fprintf(dumpout, "%s: ",
|
fprintf(fp, "%s: ",
|
||||||
JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), prs->atom));
|
JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), prs->atom));
|
||||||
if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {
|
if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {
|
||||||
fprintf(dumpout, "[getset %p %p]", (void *)pr->u.getset.getter,
|
fprintf(fp, "[getset %p %p]", (void *)pr->u.getset.getter,
|
||||||
(void *)pr->u.getset.setter);
|
(void *)pr->u.getset.setter);
|
||||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
|
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
|
||||||
fprintf(dumpout, "[varref %p]", (void *)pr->u.var_ref);
|
fprintf(fp, "[varref %p]", (void *)pr->u.var_ref);
|
||||||
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
|
||||||
fprintf(dumpout, "[autoinit %p %d %p]",
|
fprintf(fp, "[autoinit %p %d %p]",
|
||||||
(void *)js_autoinit_get_realm(pr),
|
(void *)js_autoinit_get_realm(pr),
|
||||||
js_autoinit_get_id(pr),
|
js_autoinit_get_id(pr),
|
||||||
(void *)pr->u.init.opaque);
|
(void *)pr->u.init.opaque);
|
||||||
} else {
|
} else {
|
||||||
JS_DumpValueShort(rt, pr->u.value);
|
JS_DumpValueShort(fp, rt, pr->u.value);
|
||||||
}
|
}
|
||||||
is_first = FALSE;
|
is_first = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(dumpout, " }");
|
fprintf(fp, " }");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (js_class_has_bytecode(p->class_id)) {
|
if (js_class_has_bytecode(p->class_id)) {
|
||||||
|
@ -11971,53 +12038,53 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
|
||||||
JSVarRef **var_refs;
|
JSVarRef **var_refs;
|
||||||
if (b->closure_var_count) {
|
if (b->closure_var_count) {
|
||||||
var_refs = p->u.func.var_refs;
|
var_refs = p->u.func.var_refs;
|
||||||
fprintf(dumpout, " Closure:");
|
fprintf(fp, " Closure:");
|
||||||
for(i = 0; i < b->closure_var_count; i++) {
|
for(i = 0; i < b->closure_var_count; i++) {
|
||||||
fprintf(dumpout, " ");
|
fprintf(fp, " ");
|
||||||
JS_DumpValueShort(rt, var_refs[i]->value);
|
JS_DumpValueShort(fp, rt, var_refs[i]->value);
|
||||||
}
|
}
|
||||||
if (p->u.func.home_object) {
|
if (p->u.func.home_object) {
|
||||||
fprintf(dumpout, " HomeObject: ");
|
fprintf(fp, " HomeObject: ");
|
||||||
JS_DumpValueShort(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object));
|
JS_DumpValueShort(fp, rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(dumpout, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
|
static __maybe_unused void JS_DumpGCObject(FILE *fp, JSRuntime *rt, JSGCObjectHeader *p)
|
||||||
{
|
{
|
||||||
if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {
|
if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {
|
||||||
JS_DumpObject(rt, (JSObject *)p);
|
JS_DumpObject(fp, rt, (JSObject *)p);
|
||||||
} else {
|
} else {
|
||||||
fprintf(dumpout, "%14p %4d ",
|
fprintf(fp, "%14p %4d ",
|
||||||
(void *)p,
|
(void *)p,
|
||||||
p->ref_count);
|
p->ref_count);
|
||||||
switch(p->gc_obj_type) {
|
switch(p->gc_obj_type) {
|
||||||
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
|
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
|
||||||
fprintf(dumpout, "[function bytecode]");
|
fprintf(fp, "[function bytecode]");
|
||||||
break;
|
break;
|
||||||
case JS_GC_OBJ_TYPE_SHAPE:
|
case JS_GC_OBJ_TYPE_SHAPE:
|
||||||
fprintf(dumpout, "[shape]");
|
fprintf(fp, "[shape]");
|
||||||
break;
|
break;
|
||||||
case JS_GC_OBJ_TYPE_VAR_REF:
|
case JS_GC_OBJ_TYPE_VAR_REF:
|
||||||
fprintf(dumpout, "[var_ref]");
|
fprintf(fp, "[var_ref]");
|
||||||
break;
|
break;
|
||||||
case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
|
case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
|
||||||
fprintf(dumpout, "[async_function]");
|
fprintf(fp, "[async_function]");
|
||||||
break;
|
break;
|
||||||
case JS_GC_OBJ_TYPE_JS_CONTEXT:
|
case JS_GC_OBJ_TYPE_JS_CONTEXT:
|
||||||
fprintf(dumpout, "[js_context]");
|
fprintf(fp, "[js_context]");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(dumpout, "[unknown %d]", p->gc_obj_type);
|
fprintf(fp, "[unknown %d]", p->gc_obj_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(dumpout, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
|
static __maybe_unused void JS_DumpValueShort(FILE *fp, JSRuntime *rt,
|
||||||
JSValueConst val)
|
JSValueConst val)
|
||||||
{
|
{
|
||||||
uint32_t tag = JS_VALUE_GET_NORM_TAG(val);
|
uint32_t tag = JS_VALUE_GET_NORM_TAG(val);
|
||||||
|
@ -12025,7 +12092,7 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
|
||||||
|
|
||||||
switch(tag) {
|
switch(tag) {
|
||||||
case JS_TAG_INT:
|
case JS_TAG_INT:
|
||||||
fprintf(dumpout, "%d", JS_VALUE_GET_INT(val));
|
fprintf(fp, "%d", JS_VALUE_GET_INT(val));
|
||||||
break;
|
break;
|
||||||
case JS_TAG_BOOL:
|
case JS_TAG_BOOL:
|
||||||
if (JS_VALUE_GET_BOOL(val))
|
if (JS_VALUE_GET_BOOL(val))
|
||||||
|
@ -12045,10 +12112,10 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
|
||||||
case JS_TAG_UNDEFINED:
|
case JS_TAG_UNDEFINED:
|
||||||
str = "undefined";
|
str = "undefined";
|
||||||
print_str:
|
print_str:
|
||||||
fprintf(dumpout, "%s", str);
|
fprintf(fp, "%s", str);
|
||||||
break;
|
break;
|
||||||
case JS_TAG_FLOAT64:
|
case JS_TAG_FLOAT64:
|
||||||
fprintf(dumpout, "%.14g", JS_VALUE_GET_FLOAT64(val));
|
fprintf(fp, "%.14g", JS_VALUE_GET_FLOAT64(val));
|
||||||
break;
|
break;
|
||||||
case JS_TAG_BIG_INT:
|
case JS_TAG_BIG_INT:
|
||||||
{
|
{
|
||||||
|
@ -12056,7 +12123,7 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
|
||||||
char *str;
|
char *str;
|
||||||
str = bf_ftoa(NULL, &p->num, 10, 0,
|
str = bf_ftoa(NULL, &p->num, 10, 0,
|
||||||
BF_RNDZ | BF_FTOA_FORMAT_FRAC);
|
BF_RNDZ | BF_FTOA_FORMAT_FRAC);
|
||||||
fprintf(dumpout, "%sn", str);
|
fprintf(fp, "%sn", str);
|
||||||
bf_realloc(&rt->bf_ctx, str, 0);
|
bf_realloc(&rt->bf_ctx, str, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -12067,7 +12134,7 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
|
||||||
char *str;
|
char *str;
|
||||||
str = bf_ftoa(NULL, &p->num, 16, BF_PREC_INF,
|
str = bf_ftoa(NULL, &p->num, 16, BF_PREC_INF,
|
||||||
BF_RNDZ | BF_FTOA_FORMAT_FREE | BF_FTOA_ADD_PREFIX);
|
BF_RNDZ | BF_FTOA_FORMAT_FREE | BF_FTOA_ADD_PREFIX);
|
||||||
fprintf(dumpout, "%sl", str);
|
fprintf(fp, "%sl", str);
|
||||||
bf_free(&rt->bf_ctx, str);
|
bf_free(&rt->bf_ctx, str);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -12077,7 +12144,7 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
|
||||||
char *str;
|
char *str;
|
||||||
str = bfdec_ftoa(NULL, &p->num, BF_PREC_INF,
|
str = bfdec_ftoa(NULL, &p->num, BF_PREC_INF,
|
||||||
BF_RNDZ | BF_FTOA_FORMAT_FREE);
|
BF_RNDZ | BF_FTOA_FORMAT_FREE);
|
||||||
fprintf(dumpout, "%sm", str);
|
fprintf(fp, "%sm", str);
|
||||||
bf_free(&rt->bf_ctx, str);
|
bf_free(&rt->bf_ctx, str);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -12093,7 +12160,7 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
|
||||||
{
|
{
|
||||||
JSFunctionBytecode *b = JS_VALUE_GET_PTR(val);
|
JSFunctionBytecode *b = JS_VALUE_GET_PTR(val);
|
||||||
char buf[ATOM_GET_STR_BUF_SIZE];
|
char buf[ATOM_GET_STR_BUF_SIZE];
|
||||||
fprintf(dumpout, "[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));
|
fprintf(fp, "[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JS_TAG_OBJECT:
|
case JS_TAG_OBJECT:
|
||||||
|
@ -12101,7 +12168,7 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
|
||||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||||
JSAtom atom = rt->class_array[p->class_id].class_name;
|
JSAtom atom = rt->class_array[p->class_id].class_name;
|
||||||
char atom_buf[ATOM_GET_STR_BUF_SIZE];
|
char atom_buf[ATOM_GET_STR_BUF_SIZE];
|
||||||
fprintf(dumpout, "[%s %p]",
|
fprintf(fp, "[%s %p]",
|
||||||
JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), atom), (void *)p);
|
JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), atom), (void *)p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -12109,32 +12176,32 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
|
||||||
{
|
{
|
||||||
JSAtomStruct *p = JS_VALUE_GET_PTR(val);
|
JSAtomStruct *p = JS_VALUE_GET_PTR(val);
|
||||||
char atom_buf[ATOM_GET_STR_BUF_SIZE];
|
char atom_buf[ATOM_GET_STR_BUF_SIZE];
|
||||||
fprintf(dumpout, "Symbol(%s)",
|
fprintf(fp, "Symbol(%s)",
|
||||||
JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), js_get_atom_index(rt, p)));
|
JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), js_get_atom_index(rt, p)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JS_TAG_MODULE:
|
case JS_TAG_MODULE:
|
||||||
fprintf(dumpout, "[module]");
|
fprintf(fp, "[module]");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(dumpout, "[unknown tag %d]", tag);
|
fprintf(fp, "[unknown tag %d]", tag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static __maybe_unused void JS_DumpValue(JSContext *ctx,
|
static __maybe_unused void JS_DumpValue(FILE *fp, JSContext *ctx,
|
||||||
JSValueConst val)
|
JSValueConst val)
|
||||||
{
|
{
|
||||||
JS_DumpValueShort(ctx->rt, val);
|
JS_DumpValueShort(fp, ctx->rt, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __maybe_unused void JS_PrintValue(JSContext *ctx,
|
static __maybe_unused void JS_PrintValue(FILE *fp, JSContext *ctx,
|
||||||
const char *str,
|
const char *str,
|
||||||
JSValueConst val)
|
JSValueConst val)
|
||||||
{
|
{
|
||||||
fprintf(dumpout, "%s=", str);
|
fprintf(fp, "%s=", str);
|
||||||
JS_DumpValueShort(ctx->rt, val);
|
JS_DumpValueShort(fp, ctx->rt, val);
|
||||||
fprintf(dumpout, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return -1 if exception (proxy case) or TRUE/FALSE */
|
/* return -1 if exception (proxy case) or TRUE/FALSE */
|
||||||
|
|
9
source/engine/thirdparty/quickjs/quickjs.h
vendored
9
source/engine/thirdparty/quickjs/quickjs.h
vendored
|
@ -92,7 +92,11 @@ typedef struct JSRefCountHeader {
|
||||||
} JSRefCountHeader;
|
} JSRefCountHeader;
|
||||||
|
|
||||||
void quickjs_set_dumpout(FILE *f);
|
void quickjs_set_dumpout(FILE *f);
|
||||||
|
void quickjs_set_cycleout(FILE *f);
|
||||||
void JS_SetInterruptRate(int count);
|
void JS_SetInterruptRate(int count);
|
||||||
|
void JS_PrintShapes(JSRuntime *rt);
|
||||||
|
void JS_PrintAtoms(JSRuntime *rt);
|
||||||
|
|
||||||
|
|
||||||
#define JS_FLOAT64_NAN NAN
|
#define JS_FLOAT64_NAN NAN
|
||||||
|
|
||||||
|
@ -339,6 +343,7 @@ JSRuntime *JS_NewRuntime(void);
|
||||||
void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
|
void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
|
||||||
void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
|
void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
|
||||||
void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
|
void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
|
||||||
|
JSValue JS_GetRTInfo(JSRuntime *rt, JSContext *js);
|
||||||
/* use 0 to disable maximum stack size check */
|
/* use 0 to disable maximum stack size check */
|
||||||
void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size);
|
void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size);
|
||||||
/* should be called when changing thread to update the stack top value
|
/* should be called when changing thread to update the stack top value
|
||||||
|
@ -404,6 +409,7 @@ char *js_strndup(JSContext *ctx, const char *s, size_t n);
|
||||||
|
|
||||||
typedef struct JSMemoryUsage {
|
typedef struct JSMemoryUsage {
|
||||||
int64_t malloc_size, malloc_limit, memory_used_size;
|
int64_t malloc_size, malloc_limit, memory_used_size;
|
||||||
|
int64_t gc_threshold;
|
||||||
int64_t malloc_count;
|
int64_t malloc_count;
|
||||||
int64_t memory_used_count;
|
int64_t memory_used_count;
|
||||||
int64_t atom_count, atom_size;
|
int64_t atom_count, atom_size;
|
||||||
|
@ -419,7 +425,10 @@ typedef struct JSMemoryUsage {
|
||||||
} JSMemoryUsage;
|
} JSMemoryUsage;
|
||||||
|
|
||||||
void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s);
|
void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s);
|
||||||
|
void JS_FillMemoryState(JSRuntime *rt, JSMemoryUsage *s);
|
||||||
void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
|
void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
|
||||||
|
void JS_DumpMyValue(JSRuntime *rt, JSValue v);
|
||||||
|
double JS_MyValueSize(JSRuntime *rt, JSValue v);
|
||||||
|
|
||||||
/* atom support */
|
/* atom support */
|
||||||
#define JS_ATOM_NULL 0
|
#define JS_ATOM_NULL 0
|
||||||
|
|
Loading…
Reference in a new issue