зеркало из https://github.com/mozilla/gecko-dev.git
Transform RegExp.exec to RegExp.test in native call IC, bug 645889. r=dmandelin
This commit is contained in:
Родитель
95aaffbddc
Коммит
92e44bf5eb
|
@ -5553,3 +5553,39 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
|
||||||
|
|
||||||
#undef LOCAL_ASSERT
|
#undef LOCAL_ASSERT
|
||||||
#undef LOCAL_ASSERT_RV
|
#undef LOCAL_ASSERT_RV
|
||||||
|
|
||||||
|
namespace js {
|
||||||
|
|
||||||
|
bool
|
||||||
|
CallResultEscapes(jsbytecode *pc)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If we see any of these sequences, the result is unused:
|
||||||
|
* - call / pop
|
||||||
|
* - call / trace / pop
|
||||||
|
*
|
||||||
|
* If we see any of these sequences, the result is only tested for nullness:
|
||||||
|
* - call / ifeq
|
||||||
|
* - call / trace / ifeq
|
||||||
|
* - call / not / ifeq
|
||||||
|
* - call / trace / not / ifeq
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (*pc != JSOP_CALL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
pc += JSOP_CALL_LENGTH;
|
||||||
|
|
||||||
|
if (*pc == JSOP_TRACE)
|
||||||
|
pc += JSOP_TRACE_LENGTH;
|
||||||
|
|
||||||
|
if (*pc == JSOP_POP)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (*pc == JSOP_NOT)
|
||||||
|
pc += JSOP_NOT_LENGTH;
|
||||||
|
|
||||||
|
return (*pc != JSOP_IFEQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace js
|
||||||
|
|
|
@ -516,6 +516,9 @@ SprintString(Sprinter *sp, JSString *str);
|
||||||
extern ptrdiff_t
|
extern ptrdiff_t
|
||||||
Sprint(Sprinter *sp, const char *format, ...);
|
Sprint(Sprinter *sp, const char *format, ...);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
CallResultEscapes(jsbytecode *pc);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -11440,37 +11440,15 @@ TraceRecorder::callNative(uintN argc, JSOp mode)
|
||||||
}
|
}
|
||||||
} else if (vp[2].isString() && mode == JSOP_CALL) {
|
} else if (vp[2].isString() && mode == JSOP_CALL) {
|
||||||
if (native == js_regexp_exec) {
|
if (native == js_regexp_exec) {
|
||||||
jsbytecode *pc = cx->regs->pc;
|
|
||||||
/*
|
/*
|
||||||
* If we see any of these sequences, the result is unused:
|
* If the result of the call will be unused or only tested against
|
||||||
* - call / pop
|
* nullness, we replace the call to RegExp.exec() on the
|
||||||
* - call / trace / pop
|
|
||||||
*
|
|
||||||
* If we see any of these sequences, the result is only tested for nullness:
|
|
||||||
* - call / ifeq
|
|
||||||
* - call / trace / ifeq
|
|
||||||
* - call / not / ifeq
|
|
||||||
* - call / trace / not / ifeq
|
|
||||||
*
|
|
||||||
* In either case, we replace the call to RegExp.exec() on the
|
|
||||||
* stack with a call to RegExp.test() because "r.exec(s) !=
|
* stack with a call to RegExp.test() because "r.exec(s) !=
|
||||||
* null" is equivalent to "r.test(s)". This avoids building
|
* null" is equivalent to "r.test(s)". This avoids building
|
||||||
* the result array, which can be expensive. This requires
|
* the result array, which can be expensive. This requires
|
||||||
* that RegExp.prototype.test() hasn't been changed; we check this.
|
* that RegExp.prototype.test() hasn't been changed; we check this.
|
||||||
*/
|
*/
|
||||||
if (pc[0] == JSOP_CALL) {
|
if (!CallResultEscapes(cx->regs->pc)) {
|
||||||
if ((pc[JSOP_CALL_LENGTH] == JSOP_POP) ||
|
|
||||||
(pc[JSOP_CALL_LENGTH] == JSOP_TRACE &&
|
|
||||||
pc[JSOP_CALL_LENGTH + JSOP_TRACE_LENGTH] == JSOP_POP) ||
|
|
||||||
(pc[JSOP_CALL_LENGTH] == JSOP_IFEQ) ||
|
|
||||||
(pc[JSOP_CALL_LENGTH] == JSOP_TRACE &&
|
|
||||||
pc[JSOP_CALL_LENGTH + JSOP_TRACE_LENGTH] == JSOP_IFEQ) ||
|
|
||||||
(pc[JSOP_CALL_LENGTH] == JSOP_NOT &&
|
|
||||||
pc[JSOP_CALL_LENGTH + JSOP_NOT_LENGTH] == JSOP_IFEQ) ||
|
|
||||||
(pc[JSOP_CALL_LENGTH] == JSOP_TRACE &&
|
|
||||||
pc[JSOP_CALL_LENGTH + JSOP_TRACE_LENGTH] == JSOP_NOT &&
|
|
||||||
pc[JSOP_CALL_LENGTH + JSOP_TRACE_LENGTH + JSOP_NOT_LENGTH] == JSOP_IFEQ))
|
|
||||||
{
|
|
||||||
JSObject* proto;
|
JSObject* proto;
|
||||||
jsid id = ATOM_TO_JSID(cx->runtime->atomState.testAtom);
|
jsid id = ATOM_TO_JSID(cx->runtime->atomState.testAtom);
|
||||||
/* Get RegExp.prototype.test() and check it hasn't been changed. */
|
/* Get RegExp.prototype.test() and check it hasn't been changed. */
|
||||||
|
@ -11485,7 +11463,6 @@ TraceRecorder::callNative(uintN argc, JSOp mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
|
|
@ -900,7 +900,17 @@ class CallCompiler : public BaseCompiler
|
||||||
else
|
else
|
||||||
masm.storeArg(1, argcReg.reg());
|
masm.storeArg(1, argcReg.reg());
|
||||||
masm.storeArg(0, cxReg);
|
masm.storeArg(0, cxReg);
|
||||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, fun->u.n.native), false);
|
|
||||||
|
js::Native native = fun->u.n.native;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call RegExp.test instead of exec if the result will not be used or
|
||||||
|
* will only be used to test for existence.
|
||||||
|
*/
|
||||||
|
if (native == js_regexp_exec && !CallResultEscapes(f.regs.pc))
|
||||||
|
native = js_regexp_test;
|
||||||
|
|
||||||
|
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, native), false);
|
||||||
|
|
||||||
Jump hasException = masm.branchTest32(Assembler::Zero, Registers::ReturnReg,
|
Jump hasException = masm.branchTest32(Assembler::Zero, Registers::ReturnReg,
|
||||||
Registers::ReturnReg);
|
Registers::ReturnReg);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче