bug 450529 - pass pc to String.prototype.match so we can avoid unnecessary object creation when tracing. r=brendan

This commit is contained in:
Blake Kaplan 2008-08-15 09:29:03 -07:00
parent 7bbee60c81
commit 5aa5360905
6 changed files with 45 additions and 20 deletions

View File

@ -57,7 +57,7 @@ BUILTIN3(String_getelem, LO, LO, LO, LO, JSString*, JSContext*, JSString*
BUILTIN2(String_fromCharCode, LO, LO, LO, JSString*, JSContext*, jsint, 1, 1)
BUILTIN2(String_p_charCodeAt, LO, LO, LO, jsint, JSString*, jsint, 1, 1)
BUILTIN3(String_p_concat_1int, LO, LO, LO, LO, JSString*, JSContest*, JSString*, jsint, 1, 1)
BUILTIN3(String_p_match, LO, LO, LO, LO, JSObject*, JSContext*, JSString*, JSObject*, 1, 1)
BUILTIN4(String_p_match, LO, LO, LO, LO, LO, JSObject*, JSContext*, JSString*, jsbytecode*, JSObject*, 1, 1)
BUILTIN4(String_p_replace_fun, LO, LO, LO, LO, LO, JSString*, JSContext*, JSString*, JSObject*, JSObject*, 1, 1)
BUILTIN4(String_p_replace_str, LO, LO, LO, LO, LO, JSString*, JSContext*, JSString*, JSObject*, JSString*, 1, 1)
BUILTIN5(String_p_replace_str3, LO, LO, LO, LO, LO, LO, JSString*, JSContext*, JSString*, JSString*, JSString*, JSString*, 1, 1)

View File

@ -267,10 +267,10 @@ js_String_p_concat_1int(JSContext* cx, JSString* str, jsint i)
}
JSObject* FASTCALL
js_String_p_match(JSContext* cx, JSString* str, JSObject* regexp)
js_String_p_match(JSContext* cx, JSString* str, jsbytecode *pc, JSObject* regexp)
{
jsval vp[4] = { JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
if (!js_str_match(cx, 1, vp))
jsval vp[3] = { JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
if (!js_StringMatchHelper(cx, 1, vp, pc))
return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
(!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));

View File

@ -1131,6 +1131,7 @@ str_lastIndexOf(JSContext *cx, uintN argc, jsval *vp)
* Perl-inspired string functions.
*/
typedef struct GlobData {
jsbytecode *pc; /* in: program counter resulting in us matching */
uintN flags; /* inout: mode and flag bits, see below */
uintN optarg; /* in: index of optional flags argument */
JSString *str; /* out: 'this' parameter object as string */
@ -1234,20 +1235,14 @@ match_or_replace(JSContext *cx,
* a scripted function. If the caller cares only about testing null
* vs. non-null return value, optimize away the array object that
* would normally be returned in *vp.
*
* Assume a full array result is required, then prove otherwise.
*/
JSStackFrame *fp;
/* Skip Function.prototype.call and .apply frames. */
for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
JS_ASSERT(!fp->script);
/* Assume a full array result is required, then prove otherwise. */
test = JS_FALSE;
if (fp) {
JS_ASSERT(*fp->regs->pc == JSOP_CALL ||
*fp->regs->pc == JSOP_NEW);
JS_ASSERT(js_CodeSpec[*fp->regs->pc].length == 3);
switch (fp->regs->pc[3]) {
if (data->pc) {
JS_ASSERT(*data->pc == JSOP_CALL || *data->pc == JSOP_NEW);
JS_ASSERT(js_CodeSpec[*data->pc].length == 3);
switch (data->pc[3]) {
case JSOP_POP:
case JSOP_IFEQ:
case JSOP_IFNE:
@ -1307,13 +1302,14 @@ match_glob(JSContext *cx, jsint count, GlobData *data)
}
JSBool
js_str_match(JSContext *cx, uintN argc, jsval *vp)
js_StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc)
{
JSTempValueRooter tvr;
MatchData mdata;
JSBool ok;
JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
mdata.base.pc = pc;
mdata.base.flags = MODE_MATCH;
mdata.base.optarg = 1;
mdata.arrayval = &tvr.u.value;
@ -1324,6 +1320,16 @@ js_str_match(JSContext *cx, uintN argc, jsval *vp)
return ok;
}
JSBool
js_str_match(JSContext *cx, uintN argc, jsval *vp)
{
JSStackFrame *fp;
for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
JS_ASSERT(!fp->script);
return js_StringMatchHelper(cx, argc, vp, fp ? fp->regs->pc : NULL);
}
static JSBool
str_search(JSContext *cx, uintN argc, jsval *vp)
{

View File

@ -613,6 +613,9 @@ extern JSBool
js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
extern JSBool
js_StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc);
extern JSBool
js_str_match(JSContext *cx, uintN argc, jsval *vp);

View File

@ -3508,7 +3508,8 @@ js_math_floor(JSContext* cx, uintN argc, jsval* vp);
bool
TraceRecorder::record_JSOP_CALL()
{
uintN argc = GET_ARGC(cx->fp->regs->pc);
jsbytecode *pc = cx->fp->regs->pc;
uintN argc = GET_ARGC(pc);
jsval& fval = stackval(0 - (argc + 2));
/*
@ -3551,7 +3552,7 @@ TraceRecorder::record_JSOP_CALL()
{ js_str_fromCharCode, F_String_fromCharCode, "C", "i", FAIL_NULL, NULL },
{ js_str_charCodeAt, F_String_p_charCodeAt, "T", "i", FAIL_NEG, NULL },
{ js_str_charAt, F_String_getelem, "TC", "i", FAIL_NULL, NULL },
{ js_str_match, F_String_p_match, "TC", "r", FAIL_VOID, NULL },
{ js_str_match, F_String_p_match, "PTC", "r", FAIL_VOID, NULL },
{ js_str_replace, F_String_p_replace_str3,"TC","sss", FAIL_NULL, NULL },
{ js_str_replace, F_String_p_replace_str, "TC", "sr", FAIL_NULL, NULL },
{ js_str_replace, F_String_p_replace_fun, "TC", "fr", FAIL_NULL, NULL },
@ -3581,7 +3582,7 @@ TraceRecorder::record_JSOP_CALL()
char argtype;
#if defined _DEBUG
memset(args, 0xCD, sizeof(args));
memset(args, 0xCD, sizeof(args));
#endif
jsval& thisval = stackval(0 - (argc + 1));
@ -3601,6 +3602,8 @@ TraceRecorder::record_JSOP_CALL()
*argp = thisval_ins; \
} else if (argtype == 'R') { \
*argp = lir->insImmPtr((void*)cx->runtime); \
} else if (argtype == 'P') { \
*argp = lir->insImmPtr(pc); \
} else { \
JS_NOT_REACHED("unknown prefix arg type"); \
} \
@ -3608,6 +3611,9 @@ TraceRecorder::record_JSOP_CALL()
JS_END_MACRO
switch (prefixc) {
case 3:
HANDLE_PREFIX(2);
/* FALL THROUGH */
case 2:
HANDLE_PREFIX(1);
/* FALL THROUGH */

View File

@ -758,6 +758,16 @@ function parsingNumbers() {
parsingNumbers.expected = "ok";
test(parsingNumbers);
function matchInLoop() {
var k = "hi";
for (var i = 0; i < 10; i++) {
var result = k.match(/hi/) != null;
}
return result;
}
matchInLoop.expected = true;
test(matchInLoop);
/* 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(","));