Bug 460904 - rename/tweak JSTraceableFunction (r=jorendorff)

This commit is contained in:
Luke Wagner 2009-09-03 11:57:14 -07:00
parent 02a5869681
commit 52d822b6d2
15 changed files with 162 additions and 148 deletions

View File

@ -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;

View File

@ -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),

View File

@ -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

View File

@ -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
};

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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
};

View File

@ -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),

View File

@ -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),

View File

@ -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;

View File

@ -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
};

View File

@ -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) {

View File

@ -699,8 +699,8 @@ class TraceRecorder : public avmplus::GCObject {
Queue<nanojit::Fragment*> whichTreesToTrash;
Queue<jsbytecode*> 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);

View File

@ -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