Skip to content

Commit a6135ab

Browse files
committed
feat: support js function profiler tracking
1 parent 1ca801c commit a6135ab

1 file changed

Lines changed: 64 additions & 2 deletions

File tree

quickjs.c

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
#include "libunicode.h"
4848
#include "dtoa.h"
4949

50+
/* WebF JS thread profiler hooks */
51+
#include "js_profiler_hooks.h"
52+
#define WEBF_PROF_JS_FUNCTION 0
53+
#define WEBF_PROF_C_FUNCTION 1
54+
5055
#define OPTIMIZE 1
5156
#define SHORT_OPCODES 1
5257
#if defined(EMSCRIPTEN)
@@ -16820,11 +16825,65 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
1682016825
not_a_function:
1682116826
return JS_ThrowTypeError(caller_ctx, "not a function");
1682216827
}
16823-
return call_func(caller_ctx, func_obj, this_obj, argc,
16824-
(JSValueConst *)argv, flags);
16828+
{
16829+
int32_t _cprof_idx = -1;
16830+
JSValue _cret;
16831+
if (webf_js_profiler_enabled()) {
16832+
/* Try to extract function name atom from 'name' property */
16833+
JSAtom _cfunc_name = 0;
16834+
JSProperty *_cpr;
16835+
JSShapeProperty *_cprs = find_own_property(&_cpr, p, JS_ATOM_name);
16836+
if (_cprs) {
16837+
JSValue _name_val = _cpr->u.value;
16838+
if (JS_VALUE_GET_TAG(_name_val) == JS_TAG_STRING) {
16839+
_cfunc_name = JS_ValueToAtom(caller_ctx, _name_val);
16840+
}
16841+
}
16842+
_cprof_idx = webf_js_profiler_on_function_entry(WEBF_PROF_C_FUNCTION, _cfunc_name);
16843+
if (_cprof_idx >= 0 && _cfunc_name != 0 && !webf_js_profiler_is_atom_known(_cfunc_name)) {
16844+
const char *_cname = JS_AtomToCString(caller_ctx, _cfunc_name);
16845+
if (_cname) {
16846+
webf_js_profiler_register_atom_name(_cfunc_name, _cname);
16847+
JS_FreeCString(caller_ctx, _cname);
16848+
}
16849+
}
16850+
if (_cfunc_name != 0)
16851+
JS_FreeAtom(caller_ctx, _cfunc_name);
16852+
}
16853+
_cret = call_func(caller_ctx, func_obj, this_obj, argc,
16854+
(JSValueConst *)argv, flags);
16855+
if (_cprof_idx >= 0)
16856+
webf_js_profiler_on_function_exit(_cprof_idx);
16857+
return _cret;
16858+
}
1682516859
}
1682616860
b = p->u.func.function_bytecode;
1682716861

16862+
/* WebF profiler: record JS function entry */
16863+
int32_t _prof_idx = -1;
16864+
if (webf_js_profiler_enabled()) {
16865+
JSAtom _func_atom = b->func_name;
16866+
/* For anonymous functions, try to get the inferred name from 'name' property */
16867+
if (_func_atom == 0) {
16868+
JSProperty *_fpr;
16869+
JSShapeProperty *_fprs = find_own_property(&_fpr, p, JS_ATOM_name);
16870+
if (_fprs && JS_VALUE_GET_TAG(_fpr->u.value) == JS_TAG_STRING) {
16871+
_func_atom = JS_ValueToAtom(caller_ctx, _fpr->u.value);
16872+
}
16873+
}
16874+
_prof_idx = webf_js_profiler_on_function_entry(WEBF_PROF_JS_FUNCTION, _func_atom);
16875+
if (_prof_idx >= 0 && _func_atom != 0 && !webf_js_profiler_is_atom_known(_func_atom)) {
16876+
const char *_fname = JS_AtomToCString(caller_ctx, _func_atom);
16877+
if (_fname) {
16878+
webf_js_profiler_register_atom_name(_func_atom, _fname);
16879+
JS_FreeCString(caller_ctx, _fname);
16880+
}
16881+
}
16882+
/* Free atom only if we created it (not the bytecode's own atom) */
16883+
if (_func_atom != 0 && _func_atom != b->func_name)
16884+
JS_FreeAtom(caller_ctx, _func_atom);
16885+
}
16886+
1682816887
if (unlikely(argc < b->arg_count || (flags & JS_CALL_FLAG_COPY_ARGV))) {
1682916888
arg_allocated_size = b->arg_count;
1683016889
} else {
@@ -19388,6 +19447,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
1938819447
JS_FreeValue(ctx, *pval);
1938919448
}
1939019449
}
19450+
/* WebF profiler: record JS function exit */
19451+
if (_prof_idx >= 0)
19452+
webf_js_profiler_on_function_exit(_prof_idx);
1939119453
rt->current_stack_frame = sf->prev_frame;
1939219454
return ret_val;
1939319455
}

0 commit comments

Comments
 (0)