Bug 581595 - Optimize creation of RegExp.prototype.exec's return value. r=lw.

This commit is contained in:
Nicholas Nethercote 2010-09-01 16:39:56 -07:00
parent 5e9978f911
commit decf093d77
3 changed files with 46 additions and 6 deletions

View File

@ -932,14 +932,14 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, Value *argv, JSBool te
return ok;
}
static JSBool
regexp_exec(JSContext *cx, uintN argc, Value *vp)
JSBool
js_regexp_exec(JSContext *cx, uintN argc, Value *vp)
{
return regexp_exec_sub(cx, JS_THIS_OBJECT(cx, Jsvalify(vp)), argc, vp + 2, JS_FALSE, vp);
}
static JSBool
regexp_test(JSContext *cx, uintN argc, Value *vp)
JSBool
js_regexp_test(JSContext *cx, uintN argc, Value *vp)
{
if (!regexp_exec_sub(cx, JS_THIS_OBJECT(cx, Jsvalify(vp)), argc, vp + 2, JS_TRUE, vp))
return false;
@ -954,8 +954,8 @@ static JSFunctionSpec regexp_methods[] = {
#endif
JS_FN(js_toString_str, regexp_toString, 0,0),
JS_FN("compile", regexp_compile, 2,0),
JS_FN("exec", regexp_exec, 1,0),
JS_FN("test", regexp_test, 1,0),
JS_FN("exec", js_regexp_exec, 1,0),
JS_FN("test", js_regexp_test, 1,0),
JS_FS_END
};

View File

@ -123,4 +123,9 @@ js_RestoreRegExpStatics(JSContext *cx, js::RegExpStatics *res);
extern JSBool
js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp);
extern JSBool
js_regexp_exec(JSContext *cx, uintN argc, js::Value *vp);
extern JSBool
js_regexp_test(JSContext *cx, uintN argc, js::Value *vp);
#endif /* jsregexp_h___ */

View File

@ -11157,6 +11157,41 @@ TraceRecorder::callNative(uintN argc, JSOp mode)
return RECORD_CONTINUE;
}
}
} else if (vp[2].isString() && mode == JSOP_CALL) {
if (native == js_regexp_exec) {
jsbytecode *pc = cx->regs->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
*
* In either case, we call RegExp.test() because "r.exec(s) !=
* null" is equivalent to "r.test(s)". This avoids building
* the result array, which can be expensive.
*/
if (pc[0] == JSOP_CALL) {
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))
{
fun->u.n.native = js_regexp_test;
}
}
}
}
break;