diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index d8223654ecb9..281186628e90 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4399,8 +4399,8 @@ js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, jsval *vp) native = #ifdef JS_TRACER - (fs->flags & JSFUN_TRACEABLE) - ? JS_FUNC_TO_DATA_PTR(JSTraceableNative *, fs->call)->native + (fs->flags & JSFUN_TRCINFO) + ? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, fs->call)->native : #endif (JSFastNative) fs->call; @@ -4498,7 +4498,7 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs) js_generic_fast_native_method_dispatcher : js_generic_native_method_dispatcher, fs->nargs + 1, - flags & ~JSFUN_TRACEABLE); + flags & ~JSFUN_TRCINFO); if (!fun) return JS_FALSE; fun->u.n.extra = (uint16)fs->extra; diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 88f86b60ac1d..5f8d82c3d2ba 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -85,6 +85,7 @@ #include "jsatom.h" #include "jsbit.h" #include "jsbool.h" +#include "jstracer.h" #include "jsbuiltins.h" #include "jscntxt.h" #include "jsversion.h" @@ -3339,15 +3340,15 @@ static JSFunctionSpec array_methods[] = { #if JS_HAS_TOSOURCE JS_FN(js_toSource_str, array_toSource, 0,0), #endif - JS_TN(js_toString_str, array_toString, 0,0, array_toString_trcinfo), + JS_TN(js_toString_str, array_toString, 0,0, &array_toString_trcinfo), JS_FN(js_toLocaleString_str,array_toLocaleString,0,0), /* Perl-ish methods. */ - JS_TN("join", array_join, 1,JSFUN_GENERIC_NATIVE, array_join_trcinfo), + JS_TN("join", array_join, 1,JSFUN_GENERIC_NATIVE, &array_join_trcinfo), JS_FN("reverse", array_reverse, 0,JSFUN_GENERIC_NATIVE), JS_FN("sort", array_sort, 1,JSFUN_GENERIC_NATIVE), - JS_TN("push", array_push, 1,JSFUN_GENERIC_NATIVE, array_push_trcinfo), - JS_TN("pop", array_pop, 0,JSFUN_GENERIC_NATIVE, array_pop_trcinfo), + JS_TN("push", array_push, 1,JSFUN_GENERIC_NATIVE, &array_push_trcinfo), + JS_TN("pop", array_pop, 0,JSFUN_GENERIC_NATIVE, &array_pop_trcinfo), JS_FN("shift", array_shift, 0,JSFUN_GENERIC_NATIVE), JS_FN("unshift", array_unshift, 1,JSFUN_GENERIC_NATIVE), JS_FN("splice", array_splice, 2,JSFUN_GENERIC_NATIVE), diff --git a/js/src/jsbuiltins.h b/js/src/jsbuiltins.h index b1774ea872f4..55829258a996 100644 --- a/js/src/jsbuiltins.h +++ b/js/src/jsbuiltins.h @@ -43,7 +43,6 @@ #ifdef JS_TRACER #include "nanojit/nanojit.h" -#include "jstracer.h" #ifdef THIS #undef THIS @@ -56,6 +55,8 @@ enum { JSTN_ERRTYPE_MASK = 0x07, JSTN_UNBOX_AFTER = 0x08, JSTN_MORE = 0x10, #define JSTN_ERRTYPE(jstn) ((jstn)->flags & JSTN_ERRTYPE_MASK) /* + * Type describing a type specialization of a JSFastNative. + * * |prefix| and |argtypes| declare what arguments should be passed to the * native function. |prefix| can contain the following characters: * @@ -81,8 +82,7 @@ enum { JSTN_ERRTYPE_MASK = 0x07, JSTN_UNBOX_AFTER = 0x08, JSTN_MORE = 0x10, * 'f': a JSObject* argument that is of class js_FunctionClass * 'v': a jsval argument (boxing whatever value is actually being passed in) */ -struct JSTraceableNative { - JSFastNative native; +struct JSSpecializedNative { const nanojit::CallInfo *builtin; const char *prefix; const char *argtypes; @@ -90,6 +90,17 @@ struct JSTraceableNative { JSTN_CONSTRUCTOR */ }; +/* + * Type holding extra trace-specific information about a fast native. + * + * 'specializations' points to a static array of available specializations + * terminated by the lack of having the JSTN_MORE flag set. + */ +struct JSNativeTraceInfo { + JSFastNative native; + JSSpecializedNative *specializations; +}; + /* * We use a magic boxed pointer value to represent error conditions that * trigger a side exit. The address is so low that it should never be actually @@ -381,39 +392,43 @@ class ClosureVarInfo; #define JS_DEFINE_TRCINFO_1(name, tn0) \ _JS_DEFINE_CALLINFO_n tn0 \ - JSTraceableNative name##_trcinfo[] = { \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn0 } \ - }; + JSSpecializedNative name##_sns[] = { \ + { _JS_TN_INIT_HELPER_n tn0 } \ + }; \ + JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns }; #define JS_DEFINE_TRCINFO_2(name, tn0, tn1) \ _JS_DEFINE_CALLINFO_n tn0 \ _JS_DEFINE_CALLINFO_n tn1 \ - JSTraceableNative name##_trcinfo[] = { \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn1 } \ - }; + JSSpecializedNative name##_sns[] = { \ + { _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \ + { _JS_TN_INIT_HELPER_n tn1 } \ + }; \ + JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns }; #define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2) \ _JS_DEFINE_CALLINFO_n tn0 \ _JS_DEFINE_CALLINFO_n tn1 \ _JS_DEFINE_CALLINFO_n tn2 \ - JSTraceableNative name##_trcinfo[] = { \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn2 } \ - }; + JSSpecializedNative name##_sns[] = { \ + { _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \ + { _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \ + { _JS_TN_INIT_HELPER_n tn2 } \ + }; \ + JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns }; #define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3) \ _JS_DEFINE_CALLINFO_n tn0 \ _JS_DEFINE_CALLINFO_n tn1 \ _JS_DEFINE_CALLINFO_n tn2 \ _JS_DEFINE_CALLINFO_n tn3 \ - JSTraceableNative name##_trcinfo[] = { \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn2 | JSTN_MORE }, \ - { (JSFastNative)name, _JS_TN_INIT_HELPER_n tn3 } \ - }; + JSSpecializedNative name##_sns[] = { \ + { _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \ + { _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \ + { _JS_TN_INIT_HELPER_n tn2 | JSTN_MORE }, \ + { _JS_TN_INIT_HELPER_n tn3 } \ + }; \ + JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns }; #define _JS_DEFINE_CALLINFO_n(n, args) JS_DEFINE_CALLINFO_##n args diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp index 2b03402178a8..25eb933ed958 100644 --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -2292,7 +2292,7 @@ JS_DEFINE_TRCINFO_1(date_now, static JSFunctionSpec date_static_methods[] = { JS_FN("UTC", date_UTC, MAXARGS,0), JS_FN("parse", date_parse, 1,0), - JS_TN("now", date_now, 0,0, date_now_trcinfo), + JS_TN("now", date_now, 0,0, &date_now_trcinfo), JS_FS_END }; @@ -2349,7 +2349,7 @@ static JSFunctionSpec date_methods[] = { JS_FN(js_toSource_str, date_toSource, 0,0), #endif JS_FN(js_toString_str, date_toString, 0,0), - JS_TN(js_valueOf_str, date_valueOf, 0,0, date_valueOf_trcinfo), + JS_TN(js_valueOf_str, date_valueOf, 0,0, &date_valueOf_trcinfo), JS_FS_END }; diff --git a/js/src/jsdtracef.cpp b/js/src/jsdtracef.cpp index ee6ac22cd526..940aea0e46c8 100644 --- a/js/src/jsdtracef.cpp +++ b/js/src/jsdtracef.cpp @@ -56,7 +56,7 @@ jsdtrace_fun_classname(JSFunction *fun) { return (fun && !FUN_INTERPRETED(fun) && - !(fun->flags & JSFUN_TRACEABLE) && + !(fun->flags & JSFUN_TRCINFO) && FUN_CLASP(fun)) ? (char *)FUN_CLASP(fun)->name : dempty; diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 00fff7020b04..2cc6a7aab59b 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -2365,7 +2365,7 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs, /* Initialize all function members. */ fun->nargs = nargs; - fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRACEABLE); + fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRCINFO); if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) { JS_ASSERT(!native); JS_ASSERT(nargs == 0); @@ -2381,10 +2381,10 @@ js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs, fun->u.n.extra = 0; fun->u.n.spare = 0; fun->u.n.clasp = NULL; - if (flags & JSFUN_TRACEABLE) { + if (flags & JSFUN_TRCINFO) { #ifdef JS_TRACER - JSTraceableNative *trcinfo = - JS_FUNC_TO_DATA_PTR(JSTraceableNative *, native); + JSNativeTraceInfo *trcinfo = + JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, native); fun->u.n.native = (JSNative) trcinfo->native; fun->u.n.trcinfo = trcinfo; #else diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 2c7e6ca156a3..7e198a9f83d9 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -98,9 +98,9 @@ typedef union JSLocalNames { * pointer-chasing. */ #define JSFUN_EXPR_CLOSURE 0x1000 /* expression closure: function(x) x*x */ -#define JSFUN_TRACEABLE 0x2000 /* can trace across calls to this native - function; use FUN_TRCINFO if set, - FUN_CLASP if unset */ +#define JSFUN_TRCINFO 0x2000 /* when set, u.n.trcinfo is non-null, + JSFunctionSpec::call points to a + JSNativeTraceInfo. */ #define JSFUN_INTERPRETED 0x4000 /* use u.i if kind >= this value else u.n */ #define JSFUN_FLAT_CLOSURE 0x8000 /* flag (aka "display") closure */ #define JSFUN_NULL_CLOSURE 0xc000 /* null closure entrains no scope chain */ @@ -125,7 +125,7 @@ typedef union JSLocalNames { #define FUN_CLASP(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \ fun->u.n.clasp) #define FUN_TRCINFO(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \ - JS_ASSERT((fun)->flags & JSFUN_TRACEABLE), \ + JS_ASSERT((fun)->flags & JSFUN_TRCINFO), \ fun->u.n.trcinfo) struct JSFunction { @@ -140,8 +140,7 @@ struct JSFunction { JSNative native; /* native method pointer or null */ JSClass *clasp; /* class of objects constructed by this function */ - JSTraceableNative *trcinfo; /* tracer metadata; can be first - element of array */ + JSNativeTraceInfo *trcinfo; } n; struct { uint16 nvars; /* number of local variables */ @@ -184,14 +183,15 @@ struct JSFunction { }; /* - * Traceable native. This expands to a JSFunctionSpec initializer (like JS_FN - * in jsapi.h). fastcall is a JSFastNative; trcinfo is a JSTraceableNative *. + * Trace-annotated native. This expands to a JSFunctionSpec initializer (like + * JS_FN in jsapi.h). fastcall is a JSFastNative; trcinfo is a + * JSNativeTraceInfo*. */ #ifdef JS_TRACER /* MSVC demands the intermediate (void *) cast here. */ # define JS_TN(name,fastcall,nargs,flags,trcinfo) \ JS_FN(name, JS_DATA_TO_FUNC_PTR(JSNative, trcinfo), nargs, \ - (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS | JSFUN_TRACEABLE) + (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS | JSFUN_TRCINFO) #else # define JS_TN(name,fastcall,nargs,flags,trcinfo) \ JS_FN(name, fastcall, nargs, flags) diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 6e406d3b2f5d..53e4c69eade8 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -724,24 +724,24 @@ static JSFunctionSpec math_static_methods[] = { #if JS_HAS_TOSOURCE JS_FN(js_toSource_str, math_toSource, 0, 0), #endif - JS_TN("abs", math_abs, 1, 0, math_abs_trcinfo), - JS_TN("acos", math_acos, 1, 0, math_acos_trcinfo), - JS_TN("asin", math_asin, 1, 0, math_asin_trcinfo), - JS_TN("atan", math_atan, 1, 0, math_atan_trcinfo), - JS_TN("atan2", math_atan2, 2, 0, math_atan2_trcinfo), - JS_TN("ceil", js_math_ceil, 1, 0, js_math_ceil_trcinfo), - JS_TN("cos", math_cos, 1, 0, math_cos_trcinfo), - JS_TN("exp", math_exp, 1, 0, math_exp_trcinfo), - JS_TN("floor", js_math_floor, 1, 0, js_math_floor_trcinfo), - JS_TN("log", math_log, 1, 0, math_log_trcinfo), - JS_TN("max", js_math_max, 2, 0, js_math_max_trcinfo), - JS_TN("min", js_math_min, 2, 0, js_math_min_trcinfo), - JS_TN("pow", math_pow, 2, 0, math_pow_trcinfo), - JS_TN("random", math_random, 0, 0, math_random_trcinfo), - JS_TN("round", js_math_round, 1, 0, js_math_round_trcinfo), - JS_TN("sin", math_sin, 1, 0, math_sin_trcinfo), - JS_TN("sqrt", math_sqrt, 1, 0, math_sqrt_trcinfo), - JS_TN("tan", math_tan, 1, 0, math_tan_trcinfo), + JS_TN("abs", math_abs, 1, 0, &math_abs_trcinfo), + JS_TN("acos", math_acos, 1, 0, &math_acos_trcinfo), + JS_TN("asin", math_asin, 1, 0, &math_asin_trcinfo), + JS_TN("atan", math_atan, 1, 0, &math_atan_trcinfo), + JS_TN("atan2", math_atan2, 2, 0, &math_atan2_trcinfo), + JS_TN("ceil", js_math_ceil, 1, 0, &js_math_ceil_trcinfo), + JS_TN("cos", math_cos, 1, 0, &math_cos_trcinfo), + JS_TN("exp", math_exp, 1, 0, &math_exp_trcinfo), + JS_TN("floor", js_math_floor, 1, 0, &js_math_floor_trcinfo), + JS_TN("log", math_log, 1, 0, &math_log_trcinfo), + JS_TN("max", js_math_max, 2, 0, &js_math_max_trcinfo), + JS_TN("min", js_math_min, 2, 0, &js_math_min_trcinfo), + JS_TN("pow", math_pow, 2, 0, &math_pow_trcinfo), + JS_TN("random", math_random, 0, 0, &math_random_trcinfo), + JS_TN("round", js_math_round, 1, 0, &js_math_round_trcinfo), + JS_TN("sin", math_sin, 1, 0, &math_sin_trcinfo), + JS_TN("sqrt", math_sqrt, 1, 0, &math_sqrt_trcinfo), + JS_TN("tan", math_tan, 1, 0, &math_tan_trcinfo), JS_FS_END }; diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 40e80be28f49..959fc7ebbd55 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -234,8 +234,8 @@ JS_DEFINE_TRCINFO_1(num_parseFloat, static JSFunctionSpec number_functions[] = { JS_FN(js_isNaN_str, num_isNaN, 1,0), JS_FN(js_isFinite_str, num_isFinite, 1,0), - JS_TN(js_parseFloat_str, num_parseFloat, 1,0, num_parseFloat_trcinfo), - JS_TN(js_parseInt_str, num_parseInt, 2,0, num_parseInt_trcinfo), + JS_TN(js_parseFloat_str, num_parseFloat, 1,0, &num_parseFloat_trcinfo), + JS_TN(js_parseInt_str, num_parseInt, 2,0, &num_parseInt_trcinfo), JS_FS_END }; @@ -608,8 +608,7 @@ static JSFunctionSpec number_methods[] = { #if JS_HAS_TOSOURCE JS_FN(js_toSource_str, num_toSource, 0,JSFUN_THISP_NUMBER), #endif - JS_TN(js_toString_str, num_toString, 1,JSFUN_THISP_NUMBER, - num_toString_trcinfo), + JS_TN(js_toString_str, num_toString, 1,JSFUN_THISP_NUMBER, &num_toString_trcinfo), JS_FN(js_toLocaleString_str, num_toLocaleString, 0,JSFUN_THISP_NUMBER), JS_FN(js_valueOf_str, num_valueOf, 0,JSFUN_THISP_NUMBER), JS_FN(js_toJSON_str, num_valueOf, 0,JSFUN_THISP_NUMBER), diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 856b00074b2c..b618b49cd00b 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -1983,17 +1983,14 @@ static JSFunctionSpec object_methods[] = { #endif JS_FN(js_toString_str, obj_toString, 0,0), JS_FN(js_toLocaleString_str, obj_toLocaleString, 0,0), - JS_TN(js_valueOf_str, obj_valueOf, 0,0, - obj_valueOf_trcinfo), + JS_TN(js_valueOf_str, obj_valueOf, 0,0, &obj_valueOf_trcinfo), #if JS_HAS_OBJ_WATCHPOINT JS_FN(js_watch_str, obj_watch, 2,0), JS_FN(js_unwatch_str, obj_unwatch, 1,0), #endif - JS_TN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0, - obj_hasOwnProperty_trcinfo), + JS_TN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0, &obj_hasOwnProperty_trcinfo), JS_FN(js_isPrototypeOf_str, obj_isPrototypeOf, 1,0), - JS_TN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0, - obj_propertyIsEnumerable_trcinfo), + JS_TN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0, &obj_propertyIsEnumerable_trcinfo), #if JS_HAS_GETTER_SETTER JS_FN(js_defineGetter_str, js_obj_defineGetter, 2,0), JS_FN(js_defineSetter_str, js_obj_defineSetter, 2,0), diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index 48817150b6cc..975d474ac445 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -128,7 +128,8 @@ typedef struct JSScopeOps JSScopeOps; typedef struct JSScopeProperty JSScopeProperty; typedef struct JSStackHeader JSStackHeader; typedef struct JSSubString JSSubString; -typedef struct JSTraceableNative JSTraceableNative; +typedef struct JSNativeTraceInfo JSNativeTraceInfo; +typedef struct JSSpecializedNative JSSpecializedNative; typedef struct JSXML JSXML; typedef struct JSXMLArray JSXMLArray; typedef struct JSXMLArrayCursor JSXMLArrayCursor; diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 3a7ec0bcc38f..7ed9e8f7aabf 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -2341,15 +2341,14 @@ static JSFunctionSpec string_methods[] = { #endif /* Java-like methods. */ - JS_TN(js_toString_str, js_str_toString, 0,JSFUN_THISP_STRING, - js_str_toString_trcinfo), + JS_TN(js_toString_str, js_str_toString, 0,JSFUN_THISP_STRING, &js_str_toString_trcinfo), JS_FN(js_valueOf_str, js_str_toString, 0,JSFUN_THISP_STRING), JS_FN(js_toJSON_str, js_str_toString, 0,JSFUN_THISP_STRING), JS_FN("substring", str_substring, 2,GENERIC_PRIMITIVE), JS_FN("toLowerCase", str_toLowerCase, 0,GENERIC_PRIMITIVE), JS_FN("toUpperCase", str_toUpperCase, 0,GENERIC_PRIMITIVE), - JS_TN("charAt", str_charAt, 1,GENERIC_PRIMITIVE, str_charAt_trcinfo), - JS_TN("charCodeAt", str_charCodeAt, 1,GENERIC_PRIMITIVE, str_charCodeAt_trcinfo), + JS_TN("charAt", str_charAt, 1,GENERIC_PRIMITIVE, &str_charAt_trcinfo), + JS_TN("charCodeAt", str_charCodeAt, 1,GENERIC_PRIMITIVE, &str_charCodeAt_trcinfo), JS_FN("indexOf", str_indexOf, 1,GENERIC_PRIMITIVE), JS_FN("lastIndexOf", str_lastIndexOf, 1,GENERIC_PRIMITIVE), JS_FN("trim", str_trim, 0,GENERIC_PRIMITIVE), @@ -2369,7 +2368,7 @@ static JSFunctionSpec string_methods[] = { #endif /* Python-esque sequence methods. */ - JS_TN("concat", str_concat, 1,GENERIC_PRIMITIVE, str_concat_trcinfo), + JS_TN("concat", str_concat, 1,GENERIC_PRIMITIVE, &str_concat_trcinfo), JS_FN("slice", str_slice, 2,GENERIC_PRIMITIVE), /* HTML string methods. */ @@ -2486,7 +2485,7 @@ JS_DEFINE_TRCINFO_1(str_fromCharCode, (2, (static, STRING_RETRY, String_fromCharCode, CONTEXT, INT32, 1, 1))) static JSFunctionSpec string_static_methods[] = { - JS_TN("fromCharCode", str_fromCharCode, 1, 0, str_fromCharCode_trcinfo), + JS_TN("fromCharCode", str_fromCharCode, 1, 0, &str_fromCharCode_trcinfo), JS_FS_END }; diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index c552ab9c0d51..5dffe8b12333 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -1706,11 +1706,9 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* _anchor, Fragment* _frag this->wasRootFragment = _fragment == _fragment->root; this->outer = outer; this->outerArgc = outerArgc; - this->pendingTraceableNative = NULL; + this->pendingSpecializedNative = NULL; this->newobj_ins = NULL; this->loopLabel = NULL; - this->generatedTraceableNative = new JSTraceableNative(); - JS_ASSERT(generatedTraceableNative); #ifdef JS_JIT_SPEW debug_only_print0(LC_TMMinimal, "\n"); @@ -1842,7 +1840,6 @@ TraceRecorder::~TraceRecorder() delete func_filter; delete float_filter; delete lir_buf_writer; - delete generatedTraceableNative; } void @@ -3287,8 +3284,8 @@ TraceRecorder::snapshot(ExitType exitType) * instruction after the CALL or APPLY. Even on failure, a _FAIL native * must not be called again from the interpreter. */ - bool resumeAfter = (pendingTraceableNative && - JSTN_ERRTYPE(pendingTraceableNative) == FAIL_STATUS); + bool resumeAfter = (pendingSpecializedNative && + JSTN_ERRTYPE(pendingSpecializedNative) == FAIL_STATUS); if (resumeAfter) { JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEW || *pc == JSOP_SETPROP || *pc == JSOP_SETNAME || *pc == JSOP_SETMETHOD); @@ -3336,7 +3333,7 @@ TraceRecorder::snapshot(ExitType exitType) * (also at the beginning of a trace branched from such a type guard). */ if (pendingUnboxSlot || - (pendingTraceableNative && (pendingTraceableNative->flags & JSTN_UNBOX_AFTER))) { + (pendingSpecializedNative && (pendingSpecializedNative->flags & JSTN_UNBOX_AFTER))) { unsigned pos = stackSlots - 1; if (pendingUnboxSlot == cx->fp->regs->sp - 2) pos = stackSlots - 2; @@ -6159,7 +6156,7 @@ TraceRecorder::monitorRecording(JSContext* cx, TraceRecorder* tr, JSOp op) * Clear one-shot state used to communicate between record_JSOP_CALL and post- * opcode-case-guts record hook (record_NativeCallComplete). */ - tr->pendingTraceableNative = NULL; + tr->pendingSpecializedNative = NULL; tr->newobj_ins = NULL; /* Handle one-shot request from finishGetProp to snapshot post-op state and guard. */ @@ -9127,7 +9124,7 @@ TraceRecorder::getClassPrototype(JSProtoKey key, LIns*& proto_ins) return JSRS_CONTINUE; } -#define IGNORE_NATIVE_CALL_COMPLETE_CALLBACK ((JSTraceableNative*)1) +#define IGNORE_NATIVE_CALL_COMPLETE_CALLBACK ((JSSpecializedNative*)1) JSRecordingStatus TraceRecorder::newString(JSObject* ctor, uint32 argc, jsval* argv, jsval* rval) @@ -9147,7 +9144,7 @@ TraceRecorder::newString(JSObject* ctor, uint32 argc, jsval* argv, jsval* rval) guard(false, lir->ins_eq0(obj_ins), OOM_EXIT); set(rval, obj_ins); - pendingTraceableNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; + pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; return JSRS_CONTINUE; } @@ -9188,7 +9185,7 @@ TraceRecorder::newArray(JSObject* ctor, uint32 argc, jsval* argv, jsval* rval) } set(rval, arr_ins); - pendingTraceableNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; + pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; return JSRS_CONTINUE; } @@ -9269,14 +9266,14 @@ TraceRecorder::emitNativePropertyOp(JSScope* scope, JSScopeProperty* sprop, LIns } JS_REQUIRES_STACK JSRecordingStatus -TraceRecorder::emitNativeCall(JSTraceableNative* known, uintN argc, LIns* args[]) +TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[]) { - bool constructing = known->flags & JSTN_CONSTRUCTOR; + bool constructing = sn->flags & JSTN_CONSTRUCTOR; - if (JSTN_ERRTYPE(known) == FAIL_STATUS) { + if (JSTN_ERRTYPE(sn) == FAIL_STATUS) { // This needs to capture the pre-call state of the stack. So do not set - // pendingTraceableNative before taking this snapshot. - JS_ASSERT(!pendingTraceableNative); + // pendingSpecializedNative before taking this snapshot. + JS_ASSERT(!pendingSpecializedNative); // Take snapshot for js_DeepBail and store it in cx->bailExit. // If we are calling a slow native, add information to the side exit @@ -9294,9 +9291,9 @@ TraceRecorder::emitNativeCall(JSTraceableNative* known, uintN argc, LIns* args[] lir->insGuard(LIR_xbarrier, NULL, guardRec); } - LIns* res_ins = lir->insCall(known->builtin, args); + LIns* res_ins = lir->insCall(sn->builtin, args); rval_ins = res_ins; - switch (JSTN_ERRTYPE(known)) { + switch (JSTN_ERRTYPE(sn)) { case FAIL_NULL: guard(false, lir->ins_eq0(res_ins), OOM_EXIT); break; @@ -9320,7 +9317,7 @@ TraceRecorder::emitNativeCall(JSTraceableNative* known, uintN argc, LIns* args[] * we have to know the actual return value type for calls that return * jsval (like Array_p_pop). */ - pendingTraceableNative = known; + pendingSpecializedNative = sn; return JSRS_CONTINUE; } @@ -9330,11 +9327,9 @@ TraceRecorder::emitNativeCall(JSTraceableNative* known, uintN argc, LIns* args[] * invocation. */ JS_REQUIRES_STACK JSRecordingStatus -TraceRecorder::callTraceableNative(JSFunction* fun, uintN argc, bool constructing) +TraceRecorder::callSpecializedNative(JSNativeTraceInfo *trcinfo, uintN argc, + bool constructing) { - JSTraceableNative* known = FUN_TRCINFO(fun); - JS_ASSERT(known && (JSFastNative)fun->u.n.native == known->native); - JSStackFrame* fp = cx->fp; jsbytecode *pc = fp->regs->pc; @@ -9344,15 +9339,17 @@ TraceRecorder::callTraceableNative(JSFunction* fun, uintN argc, bool constructin LIns* this_ins = get(&tval); LIns* args[nanojit::MAXARGS]; + JSSpecializedNative *sn = trcinfo->specializations; + JS_ASSERT(sn); do { - if (((known->flags & JSTN_CONSTRUCTOR) != 0) != constructing) + if (((sn->flags & JSTN_CONSTRUCTOR) != 0) != constructing) continue; - uintN knownargc = strlen(known->argtypes); + uintN knownargc = strlen(sn->argtypes); if (argc != knownargc) continue; - intN prefixc = strlen(known->prefix); + intN prefixc = strlen(sn->prefix); JS_ASSERT(prefixc <= 3); LIns** argp = &args[argc + prefixc - 1]; char argtype; @@ -9363,7 +9360,7 @@ TraceRecorder::callTraceableNative(JSFunction* fun, uintN argc, bool constructin uintN i; for (i = prefixc; i--; ) { - argtype = known->prefix[i]; + argtype = sn->prefix[i]; if (argtype == 'C') { *argp = cx_ins; } else if (argtype == 'T') { /* this, as an object */ @@ -9401,7 +9398,7 @@ TraceRecorder::callTraceableNative(JSFunction* fun, uintN argc, bool constructin jsval& arg = stackval(0 - (i + 1)); *argp = get(&arg); - argtype = known->argtypes[i]; + argtype = sn->argtypes[i]; if (argtype == 'd' || argtype == 'i') { if (!isNumber(arg)) goto next_specialization; @@ -9429,10 +9426,10 @@ TraceRecorder::callTraceableNative(JSFunction* fun, uintN argc, bool constructin #if defined DEBUG JS_ASSERT(args[0] != (LIns *)0xcdcdcdcd); #endif - return emitNativeCall(known, argc, args); + return emitNativeCall(sn, argc, args); next_specialization:; - } while ((known++)->flags & JSTN_MORE); + } while ((sn++)->flags & JSTN_MORE); return JSRS_STOP; } @@ -9456,7 +9453,7 @@ TraceRecorder::callNative(uintN argc, JSOp mode) LIns* a = get(&vp[2]); if (isPromote(a)) { set(&vp[0], a); - pendingTraceableNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; + pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; return JSRS_CONTINUE; } } @@ -9476,17 +9473,23 @@ TraceRecorder::callNative(uintN argc, JSOp mode) ? LIR_lt : LIR_gt, a, b), a, b))); - pendingTraceableNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; + pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; return JSRS_CONTINUE; } } break; } - if (fun->flags & JSFUN_TRACEABLE) { - JSRecordingStatus status; - if ((status = callTraceableNative(fun, argc, mode == JSOP_NEW)) != JSRS_STOP) - return status; + if (fun->flags & JSFUN_TRCINFO) { + JSNativeTraceInfo *trcinfo = FUN_TRCINFO(fun); + JS_ASSERT(trcinfo && (JSFastNative)fun->u.n.native == trcinfo->native); + + /* Try to call a type specialized version of the native. */ + if (trcinfo->specializations) { + JSRecordingStatus status = callSpecializedNative(trcinfo, argc, mode == JSOP_NEW); + if (status != JSRS_STOP) + return status; + } } if (native == js_fun_apply || native == js_fun_call) @@ -9610,9 +9613,9 @@ TraceRecorder::callNative(uintN argc, JSOp mode) ARGSIZE_P << (5*ARGSIZE_SHIFT); } - // Generate CallInfo and a JSTraceableNative structure on the fly. Do not - // use JSTN_UNBOX_AFTER for mode JSOP_NEW because record_NativeCallComplete - // unboxes the result specially. + // Generate CallInfo and a JSSpecializedNative structure on the fly. + // Do not use JSTN_UNBOX_AFTER for mode JSOP_NEW because + // record_NativeCallComplete unboxes the result specially. CallInfo* ci = (CallInfo*) lir->insSkip(sizeof(struct CallInfo))->payload(); ci->_address = uintptr_t(fun->u.n.native); @@ -9623,19 +9626,18 @@ TraceRecorder::callNative(uintN argc, JSOp mode) ci->_name = JS_GetFunctionName(fun); #endif - // Generate a JSTraceableNative structure on the fly. - generatedTraceableNative->builtin = ci; - generatedTraceableNative->native = (JSFastNative)fun->u.n.native; - generatedTraceableNative->flags = FAIL_STATUS | ((mode == JSOP_NEW) - ? JSTN_CONSTRUCTOR - : JSTN_UNBOX_AFTER); - - generatedTraceableNative->prefix = generatedTraceableNative->argtypes = NULL; + // Generate a JSSpecializedNative structure on the fly. + generatedSpecializedNative.builtin = ci; + generatedSpecializedNative.flags = FAIL_STATUS | ((mode == JSOP_NEW) + ? JSTN_CONSTRUCTOR + : JSTN_UNBOX_AFTER); + generatedSpecializedNative.prefix = NULL; + generatedSpecializedNative.argtypes = NULL; // argc is the original argc here. It is used to calculate where to place // the return value. JSRecordingStatus status; - if ((status = emitNativeCall(generatedTraceableNative, argc, args)) != JSRS_CONTINUE) + if ((status = emitNativeCall(&generatedSpecializedNative, argc, args)) != JSRS_CONTINUE) return status; // Unroot the vp. @@ -9697,7 +9699,7 @@ TraceRecorder::functionCall(uintN argc, JSOp mode) return call_imacro(call_imacros.String); } set(&fval, stringify(argv[0])); - pendingTraceableNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; + pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK; return JSRS_CONTINUE; } } @@ -11042,12 +11044,12 @@ JS_DEFINE_TRCINFO_1(CatchStopIteration_tn, JS_REQUIRES_STACK JSRecordingStatus TraceRecorder::record_NativeCallComplete() { - if (pendingTraceableNative == IGNORE_NATIVE_CALL_COMPLETE_CALLBACK) + if (pendingSpecializedNative == IGNORE_NATIVE_CALL_COMPLETE_CALLBACK) return JSRS_CONTINUE; jsbytecode* pc = cx->fp->regs->pc; - JS_ASSERT(pendingTraceableNative); + JS_ASSERT(pendingSpecializedNative); JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEW || *pc == JSOP_SETPROP); jsval& v = stackval(-1); @@ -11067,12 +11069,12 @@ TraceRecorder::record_NativeCallComplete() * boxed if the type guard generated by unbox_jsval() fails. */ - if (JSTN_ERRTYPE(pendingTraceableNative) == FAIL_STATUS) { + if (JSTN_ERRTYPE(pendingSpecializedNative) == FAIL_STATUS) { /* Keep cx->bailExit null when it's invalid. */ lir->insStorei(INS_NULL(), cx_ins, (int) offsetof(JSContext, bailExit)); LIns* status = lir->insLoad(LIR_ld, lirbuf->state, (int) offsetof(InterpState, builtinStatus)); - if (pendingTraceableNative == generatedTraceableNative) { + if (pendingSpecializedNative == &generatedSpecializedNative) { LIns* ok_ins = v_ins; /* @@ -11104,7 +11106,7 @@ TraceRecorder::record_NativeCallComplete() } JSRecordingStatus ok = JSRS_CONTINUE; - if (pendingTraceableNative->flags & JSTN_UNBOX_AFTER) { + if (pendingSpecializedNative->flags & JSTN_UNBOX_AFTER) { /* * If we side exit on the unboxing code due to a type change, make sure that the boxed * value is actually currently associated with that location, and that we are talking @@ -11112,19 +11114,19 @@ TraceRecorder::record_NativeCallComplete() */ JS_ASSERT(&v == &cx->fp->regs->sp[-1] && get(&v) == v_ins); set(&v, unbox_jsval(v, v_ins, snapshot(BRANCH_EXIT))); - } else if (JSTN_ERRTYPE(pendingTraceableNative) == FAIL_NEG) { + } else if (JSTN_ERRTYPE(pendingSpecializedNative) == FAIL_NEG) { /* Already added i2f in functionCall. */ JS_ASSERT(JSVAL_IS_NUMBER(v)); } else { /* Convert the result to double if the builtin returns int32. */ if (JSVAL_IS_NUMBER(v) && - (pendingTraceableNative->builtin->_argtypes & ARGSIZE_MASK_ANY) == ARGSIZE_I) { + (pendingSpecializedNative->builtin->_argtypes & ARGSIZE_MASK_ANY) == ARGSIZE_I) { set(&v, lir->ins1(LIR_i2f, v_ins)); } } - // We'll null pendingTraceableNative in monitorRecording, on the next op cycle. - // There must be a next op since the stack is non-empty. + // We'll null pendingSpecializedNative in monitorRecording, on the next op + // cycle. There must be a next op since the stack is non-empty. return ok; } @@ -13044,11 +13046,11 @@ JS_DEFINE_TRCINFO_1(CallIteratorNext, (3, (static, JSVAL_FAIL, CallIteratorNext_tn, CONTEXT, PC, THIS, 0, 0))) static const struct BuiltinFunctionInfo { - JSTraceableNative *tn; + JSNativeTraceInfo *ti; int nargs; } builtinFunctionInfo[JSBUILTIN_LIMIT] = { - {ObjectToIterator_trcinfo, 1}, - {CallIteratorNext_trcinfo, 0}, + {&ObjectToIterator_trcinfo, 1}, + {&CallIteratorNext_trcinfo, 0}, }; JSObject * @@ -13063,9 +13065,9 @@ js_GetBuiltinFunction(JSContext *cx, uintN index) const BuiltinFunctionInfo *bfi = &builtinFunctionInfo[index]; JSFunction *fun = js_NewFunction(cx, NULL, - JS_DATA_TO_FUNC_PTR(JSNative, bfi->tn), + JS_DATA_TO_FUNC_PTR(JSNative, bfi->ti), bfi->nargs, - JSFUN_FAST_NATIVE | JSFUN_TRACEABLE, + JSFUN_FAST_NATIVE | JSFUN_TRCINFO, NULL, NULL); if (fun) { diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 82f905c05039..021b7bd09bc1 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -699,8 +699,8 @@ class TraceRecorder : public avmplus::GCObject { Queue whichTreesToTrash; Queue cfgMerges; jsval* global_dslots; - JSTraceableNative* generatedTraceableNative; - JSTraceableNative* pendingTraceableNative; + JSSpecializedNative generatedSpecializedNative; + JSSpecializedNative* pendingSpecializedNative; jsval* pendingUnboxSlot; nanojit::LIns* pendingGuardCondition; TraceRecorder* nextRecorderToAbort; @@ -926,15 +926,15 @@ class TraceRecorder : public avmplus::GCObject { uintN argc, bool constructing); JS_REQUIRES_STACK void propagateFailureToBuiltinStatus(nanojit::LIns *ok_ins, nanojit::LIns *&status_ins); - JS_REQUIRES_STACK JSRecordingStatus emitNativeCall(JSTraceableNative* known, uintN argc, + JS_REQUIRES_STACK JSRecordingStatus emitNativeCall(JSSpecializedNative* sn, uintN argc, nanojit::LIns* args[]); JS_REQUIRES_STACK void emitNativePropertyOp(JSScope* scope, JSScopeProperty* sprop, nanojit::LIns* obj_ins, bool setflag, nanojit::LIns* boxed_ins); - JS_REQUIRES_STACK JSRecordingStatus callTraceableNative(JSFunction* fun, uintN argc, - bool constructing); + JS_REQUIRES_STACK JSRecordingStatus callSpecializedNative(JSNativeTraceInfo* trcinfo, uintN argc, + bool constructing); JS_REQUIRES_STACK JSRecordingStatus callNative(uintN argc, JSOp mode); JS_REQUIRES_STACK JSRecordingStatus functionCall(uintN argc, JSOp mode); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index b39cb5ab5aed..d94712b3ea4c 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1736,7 +1736,7 @@ DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive) SHOW_FLAG(THISP_NUMBER); SHOW_FLAG(THISP_BOOLEAN); SHOW_FLAG(EXPR_CLOSURE); - SHOW_FLAG(TRACEABLE); + SHOW_FLAG(TRCINFO); #undef SHOW_FLAG diff --git a/js/src/xpconnect/src/qsgen.py b/js/src/xpconnect/src/qsgen.py index 1c92da626495..56c3346b6c32 100644 --- a/js/src/xpconnect/src/qsgen.py +++ b/js/src/xpconnect/src/qsgen.py @@ -1161,7 +1161,7 @@ def writeTraceableStub(f, customMethodCalls, method): stubName = method.iface.name + '_' + header.methodNativeName(method) writeTraceableQuickStub(f, customMethodCalls, method, stubName) fs = '{"%s", %s, %d}' % (method.name, - "JS_DATA_TO_FUNC_PTR(JSNative, %s_trcinfo)" % stubName, + "JS_DATA_TO_FUNC_PTR(JSNative, &%s_trcinfo)" % stubName, len(method.params)) return fs diff --git a/js/src/xpconnect/src/xpcquickstubs.cpp b/js/src/xpconnect/src/xpcquickstubs.cpp index 547382814a11..a340c58dd184 100644 --- a/js/src/xpconnect/src/xpcquickstubs.cpp +++ b/js/src/xpconnect/src/xpcquickstubs.cpp @@ -446,7 +446,7 @@ xpc_qsDefineQuickStubs(JSContext *cx, JSObject *proto, uintN flags, if(!JS_DefineFunction( cx, proto, ts->name, ts->native, ts->arity, flags | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS | - JSFUN_TRACEABLE)) + JSFUN_TRCINFO)) return JS_FALSE; } }