mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Add support for fast native that return jsval and wire up push/pop (453734, r=mrbkap).
This commit is contained in:
parent
9908bc1345
commit
9d7afa336a
@ -58,6 +58,8 @@ BUILTIN1(Math_log, F, F, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN2(Math_max, F, F, F, jsdouble, jsdouble, jsdouble, 1, 1)
|
||||
BUILTIN4(Array_dense_setelem, LO, LO, LO, LO, LO, bool, JSContext*, JSObject*, jsint, jsval, 0, 0)
|
||||
BUILTIN3(Array_p_join, LO, LO, LO, P, JSString*, JSContext*, JSObject*, JSString*, 0, 0)
|
||||
BUILTIN3(Array_p_push1, LO, LO, LO, LO, jsval, JSContext*, JSObject*, jsval, 0, 0)
|
||||
BUILTIN2(Array_p_pop, LO, LO, LO, jsval, JSContext*, JSObject*, 0, 0)
|
||||
BUILTIN4(String_p_substring, LO, LO, LO, LO, P, JSString*, JSContext*, JSString*, jsint, jsint, 1, 1)
|
||||
BUILTIN3(String_p_substring_1, LO, LO, LO, P, JSString*, JSContext*, JSString*, jsint, 1, 1)
|
||||
BUILTIN3(ConcatStrings, LO, LO, LO, P, JSString*, JSContext*, JSString*, JSString*, 1, 1)
|
||||
|
@ -4972,6 +4972,7 @@ js_Interpret(JSContext *cx)
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(vp[1]) ||
|
||||
PRIMITIVE_THIS_TEST(fun, vp[1]));
|
||||
ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp);
|
||||
TRACE_0(FastNativeCallComplete);
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (VALUE_IS_FUNCTION(cx, lval)) {
|
||||
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
|
||||
|
@ -4013,15 +4013,6 @@ TraceRecorder::record_JSOP_NEG()
|
||||
return false;
|
||||
}
|
||||
|
||||
enum JSTNErrType { INFALLIBLE, FAIL_NULL, FAIL_NEG, FAIL_VOID };
|
||||
struct JSTraceableNative {
|
||||
JSFastNative native;
|
||||
int builtin;
|
||||
const char *prefix;
|
||||
const char *argtypes;
|
||||
JSTNErrType errtype;
|
||||
};
|
||||
|
||||
JSBool
|
||||
js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
|
||||
|
||||
@ -4710,6 +4701,8 @@ TraceRecorder::record_JSOP_CALL()
|
||||
|
||||
static JSTraceableNative knownNatives[] = {
|
||||
{ js_array_join, F_Array_p_join, "TC", "s", FAIL_NULL },
|
||||
{ js_array_push, F_Array_p_push1, "TC", "v", FAIL_JSVAL },
|
||||
{ js_array_pop, F_Array_p_pop, "TC", "", FAIL_JSVAL },
|
||||
{ js_math_sin, F_Math_sin, "", "d", INFALLIBLE },
|
||||
{ js_math_cos, F_Math_cos, "", "d", INFALLIBLE },
|
||||
{ js_math_pow, F_Math_pow, "", "dd", INFALLIBLE },
|
||||
@ -4749,7 +4742,8 @@ TraceRecorder::record_JSOP_CALL()
|
||||
LIns* arg1_ins = NULL;
|
||||
jsval arg1 = JSVAL_VOID;
|
||||
|
||||
if ((JSFastNative)fun->u.n.native == js_fun_apply) {
|
||||
JSFastNative native = (JSFastNative)fun->u.n.native;
|
||||
if (native == js_fun_apply) {
|
||||
if (argc != 2)
|
||||
ABORT_TRACE("can't trace Function.prototype.apply with other than 2 args");
|
||||
|
||||
@ -4909,6 +4903,9 @@ TraceRecorder::record_JSOP_CALL()
|
||||
} else if (argtype == 'f') { \
|
||||
if (!VALUE_IS_FUNCTION(cx, arg)) \
|
||||
continue; /* might have another specialization for arg */ \
|
||||
} else if (argtype == 'v') { \
|
||||
if (!box_jsval(arg, *argp)) \
|
||||
return false; \
|
||||
} else { \
|
||||
continue; /* might have another specialization for arg */ \
|
||||
} \
|
||||
@ -4940,25 +4937,12 @@ TraceRecorder::record_JSOP_CALL()
|
||||
JS_ASSERT(args[0] != (LIns *)0xcdcdcdcd);
|
||||
#endif
|
||||
|
||||
LIns* res_ins = lir->insCall(known->builtin, args);
|
||||
switch (known->errtype) {
|
||||
case FAIL_NULL:
|
||||
guard(false, lir->ins_eq0(res_ins), OOM_EXIT);
|
||||
break;
|
||||
case FAIL_NEG:
|
||||
{
|
||||
res_ins = lir->ins1(LIR_i2f, res_ins);
|
||||
jsdpun u;
|
||||
u.d = 0.0;
|
||||
guard(false, lir->ins2(LIR_flt, res_ins, lir->insImmq(u.u64)), OOM_EXIT);
|
||||
break;
|
||||
}
|
||||
case FAIL_VOID:
|
||||
guard(false, lir->ins2i(LIR_eq, res_ins, JSVAL_TO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
set(&fval, res_ins);
|
||||
rval_ins = lir->insCall(known->builtin, args);
|
||||
|
||||
/* The return value will be processed by FastNativeCallComplete since we have to
|
||||
know the actual return value type for calls that return jsval (like Array_p_pop). */
|
||||
pendingTraceableNative = known;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4966,6 +4950,41 @@ TraceRecorder::record_JSOP_CALL()
|
||||
ABORT_TRACE("unknown native");
|
||||
}
|
||||
|
||||
bool
|
||||
TraceRecorder::record_FastNativeCallComplete()
|
||||
{
|
||||
JSStackFrame* fp = cx->fp;
|
||||
jsbytecode *pc = fp->regs->pc;
|
||||
uintN argc = GET_ARGC(pc);
|
||||
jsval& fval = stackval(0 - (argc + 2));
|
||||
JS_ASSERT(&fval >= StackBase(fp));
|
||||
|
||||
switch (pendingTraceableNative->errtype) {
|
||||
case FAIL_NULL:
|
||||
guard(false, lir->ins_eq0(rval_ins), OOM_EXIT);
|
||||
break;
|
||||
case FAIL_NEG:
|
||||
{
|
||||
rval_ins = lir->ins1(LIR_i2f, rval_ins);
|
||||
jsdpun u;
|
||||
u.d = 0.0;
|
||||
guard(false, lir->ins2(LIR_flt, rval_ins, lir->insImmq(u.u64)), OOM_EXIT);
|
||||
break;
|
||||
}
|
||||
case FAIL_VOID:
|
||||
guard(false, lir->ins2i(LIR_eq, rval_ins, JSVAL_TO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
|
||||
break;
|
||||
case FAIL_JSVAL:
|
||||
guard(false, lir->ins2i(LIR_eq, rval_ins, JSVAL_ERROR_COOKIE), OOM_EXIT);
|
||||
if (!unbox_jsval(fval, rval_ins))
|
||||
return false;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
set(&fval, rval_ins);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TraceRecorder::name(jsval*& vp)
|
||||
{
|
||||
|
@ -203,6 +203,15 @@ public:
|
||||
|
||||
extern struct nanojit::CallInfo builtins[];
|
||||
|
||||
enum JSTNErrType { INFALLIBLE, FAIL_NULL, FAIL_NEG, FAIL_VOID, FAIL_JSVAL };
|
||||
struct JSTraceableNative {
|
||||
JSFastNative native;
|
||||
int builtin;
|
||||
const char *prefix;
|
||||
const char *argtypes;
|
||||
JSTNErrType errtype;
|
||||
};
|
||||
|
||||
class TraceRecorder {
|
||||
JSContext* cx;
|
||||
JSTraceMonitor* traceMonitor;
|
||||
@ -238,6 +247,7 @@ class TraceRecorder {
|
||||
nanojit::Fragment* whichTreeToTrash;
|
||||
Queue<jsbytecode*> inlinedLoopEdges;
|
||||
Queue<jsbytecode*> cfgMerges;
|
||||
JSTraceableNative* pendingTraceableNative;
|
||||
|
||||
bool isGlobal(jsval* p) const;
|
||||
ptrdiff_t nativeGlobalOffset(jsval* p) const;
|
||||
@ -359,6 +369,7 @@ public:
|
||||
bool record_LeaveFrame();
|
||||
bool record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop);
|
||||
bool record_SetPropMiss(JSPropCacheEntry* entry);
|
||||
bool record_FastNativeCallComplete();
|
||||
|
||||
void deepAbort() { deepAborted = true; }
|
||||
bool wasDeepAborted() { return deepAborted; }
|
||||
@ -399,6 +410,7 @@ public:
|
||||
JS_END_MACRO
|
||||
|
||||
#define RECORD(x) RECORD_ARGS(x, ())
|
||||
#define TRACE_0(x) TRACE_ARGS(x, ())
|
||||
#define TRACE_1(x,a) TRACE_ARGS(x, (a))
|
||||
#define TRACE_2(x,a,b) TRACE_ARGS(x, (a, b))
|
||||
|
||||
|
@ -1433,6 +1433,19 @@ function testMoreArgcThanNargs()
|
||||
testMoreArgcThanNargs.expected = 4*10;
|
||||
test(testMoreArgcThanNargs);
|
||||
|
||||
function testArrayPushPop() {
|
||||
var a = [], sum1 = 0, sum2 = 0;
|
||||
for (var i = 0; i < 10; ++i)
|
||||
sum1 += a.push(i);
|
||||
for (var i = 0; i < 10; ++i)
|
||||
sum2 += a.pop();
|
||||
a.push(sum1);
|
||||
a.push(sum2);
|
||||
return a.join(",");
|
||||
}
|
||||
testArrayPushPop.expected = "55,45";
|
||||
test(testArrayPushPop);
|
||||
|
||||
/* Keep these at the end so that we can see the summary after the trace-debug spew. */
|
||||
print("\npassed:", passes.length && passes.join(","));
|
||||
print("\nFAILED:", fails.length && fails.join(","));
|
||||
|
Loading…
Reference in New Issue
Block a user