зеркало из https://github.com/mozilla/gecko-dev.git
Bug 581747 - Remove JSOP_CONCATN. Good-night, sweet prince. (r=waldo)
This commit is contained in:
Родитель
9920fb0623
Коммит
e8e95b497f
|
@ -688,31 +688,6 @@
|
|||
|
||||
.end apply
|
||||
|
||||
.igroup objtostr JSOP_OBJTOSTR
|
||||
|
||||
.imacro toString # obj
|
||||
dup # obj obj
|
||||
dup # obj obj obj
|
||||
getprop valueOf # obj obj valueOf?
|
||||
ifprimtop 1 # obj obj valueOf?
|
||||
swap # obj valueOf obj
|
||||
string void # obj valueOf obj "void"
|
||||
call 1 # obj val?
|
||||
ifprimtop 3 # obj val?
|
||||
pop # obj
|
||||
dup # obj obj
|
||||
goto 2
|
||||
1: pop # obj obj
|
||||
2: callprop toString # obj toString obj
|
||||
call 0 # obj val
|
||||
primtop (JSTYPE_VOID) # obj val
|
||||
3: swap # val obj
|
||||
pop # val
|
||||
stop
|
||||
.end
|
||||
|
||||
.end objtostr
|
||||
|
||||
.igroup getprop JSOP_GETPROP
|
||||
.imacro scriptgetter # obj
|
||||
.fixup +1 # getter obj
|
||||
|
|
|
@ -364,42 +364,3 @@ js_PopInterpFrame(JSContext* cx, TracerState* state)
|
|||
return JS_TRUE;
|
||||
}
|
||||
JS_DEFINE_CALLINFO_2(extern, BOOL, js_PopInterpFrame, CONTEXT, TRACERSTATE, 0, ACCSET_STORE_ANY)
|
||||
|
||||
JSString* FASTCALL
|
||||
js_ConcatN(JSContext *cx, JSString **strArray, uint32 size)
|
||||
{
|
||||
/* Calculate total size. */
|
||||
size_t numChar = 1;
|
||||
for (uint32 i = 0; i < size; ++i) {
|
||||
size_t before = numChar;
|
||||
numChar += strArray[i]->length();
|
||||
if (numChar < before)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate buffer. */
|
||||
if (numChar & js::tl::MulOverflowMask<sizeof(jschar)>::result)
|
||||
return NULL;
|
||||
jschar *buf = (jschar *)cx->malloc(numChar * sizeof(jschar));
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
/* Fill buffer. */
|
||||
jschar *ptr = buf;
|
||||
for (uint32 i = 0; i < size; ++i) {
|
||||
const jschar *chars;
|
||||
size_t length;
|
||||
strArray[i]->getCharsAndLength(chars, length);
|
||||
js_strncpy(ptr, chars, length);
|
||||
ptr += length;
|
||||
}
|
||||
*ptr = '\0';
|
||||
|
||||
/* Create string. */
|
||||
JSString *str = js_NewString(cx, buf, numChar - 1);
|
||||
if (!str)
|
||||
cx->free(buf);
|
||||
return str;
|
||||
}
|
||||
JS_DEFINE_CALLINFO_3(extern, STRING, js_ConcatN, CONTEXT, STRINGPTR, UINT32, 0, ACCSET_STORE_ANY)
|
||||
|
|
|
@ -597,7 +597,6 @@ JS_DECLARE_CALLINFO(js_TypeOfObject)
|
|||
JS_DECLARE_CALLINFO(js_BooleanIntToString)
|
||||
JS_DECLARE_CALLINFO(js_NewNullClosure)
|
||||
JS_DECLARE_CALLINFO(js_PopInterpFrame)
|
||||
JS_DECLARE_CALLINFO(js_ConcatN)
|
||||
|
||||
/* Defined in jsfun.cpp. */
|
||||
JS_DECLARE_CALLINFO(js_AllocFlatClosure)
|
||||
|
|
|
@ -5968,47 +5968,6 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
break;
|
||||
|
||||
case TOK_PLUS:
|
||||
/* For TCF_IN_FUNCTION test, see TOK_RB concerning JSOP_NEWARRAY. */
|
||||
if (pn->pn_arity == PN_LIST && pn->pn_count < JS_BIT(16) &&
|
||||
cg->inFunction()) {
|
||||
/* Emit up to the first string literal conventionally. */
|
||||
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
||||
if (pn2->pn_type == TOK_STRING)
|
||||
break;
|
||||
if (!js_EmitTree(cx, cg, pn2))
|
||||
return JS_FALSE;
|
||||
if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!pn2)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Having seen a string literal, we know statically that the rest
|
||||
* of the additions are string concatenation, so we emit them as a
|
||||
* single concatn. First, do string conversion on the result of the
|
||||
* preceding zero or more additions so that any side effects of
|
||||
* string conversion occur before the next operand begins.
|
||||
*/
|
||||
if (pn2 == pn->pn_head) {
|
||||
index = 0;
|
||||
} else {
|
||||
if (!js_Emit1(cx, cg, JSOP_OBJTOSTR))
|
||||
return JS_FALSE;
|
||||
index = 1;
|
||||
}
|
||||
|
||||
for (; pn2; pn2 = pn2->pn_next, index++) {
|
||||
if (!js_EmitTree(cx, cg, pn2))
|
||||
return JS_FALSE;
|
||||
if (!pn2->isLiteral() && js_Emit1(cx, cg, JSOP_OBJTOSTR) < 0)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
EMIT_UINT16_IMM_OP(JSOP_CONCATN, index);
|
||||
break;
|
||||
}
|
||||
case TOK_BITOR:
|
||||
case TOK_BITXOR:
|
||||
case TOK_BITAND:
|
||||
|
|
|
@ -3487,35 +3487,6 @@ BEGIN_CASE(JSOP_ADD)
|
|||
}
|
||||
END_CASE(JSOP_ADD)
|
||||
|
||||
BEGIN_CASE(JSOP_OBJTOSTR)
|
||||
{
|
||||
const Value &ref = regs.sp[-1];
|
||||
if (ref.isObject()) {
|
||||
JSString *str = js_ValueToString(cx, ref);
|
||||
if (!str)
|
||||
goto error;
|
||||
regs.sp[-1].setString(str);
|
||||
}
|
||||
}
|
||||
END_CASE(JSOP_OBJTOSTR)
|
||||
|
||||
BEGIN_CASE(JSOP_CONCATN)
|
||||
{
|
||||
JSCharBuffer buf(cx);
|
||||
uintN argc = GET_ARGC(regs.pc);
|
||||
for (Value *vp = regs.sp - argc; vp < regs.sp; vp++) {
|
||||
JS_ASSERT(vp->isPrimitive());
|
||||
if (!js_ValueToCharBuffer(cx, *vp, buf))
|
||||
goto error;
|
||||
}
|
||||
JSString *str = js_NewStringFromCharBuffer(cx, buf);
|
||||
if (!str)
|
||||
goto error;
|
||||
regs.sp -= argc - 1;
|
||||
regs.sp[-1].setString(str);
|
||||
}
|
||||
END_CASE(JSOP_CONCATN)
|
||||
|
||||
#define BINARY_OP(OP) \
|
||||
JS_BEGIN_MACRO \
|
||||
double d1, d2; \
|
||||
|
|
|
@ -214,8 +214,6 @@ js_GetVariableStackUses(JSOp op, jsbytecode *pc)
|
|||
switch (op) {
|
||||
case JSOP_POPN:
|
||||
return GET_UINT16(pc);
|
||||
case JSOP_CONCATN:
|
||||
return GET_UINT16(pc);
|
||||
case JSOP_LEAVEBLOCK:
|
||||
return GET_UINT16(pc);
|
||||
case JSOP_LEAVEBLOCKEXPR:
|
||||
|
@ -3559,51 +3557,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
}
|
||||
break;
|
||||
|
||||
case JSOP_CONCATN:
|
||||
{
|
||||
argc = GET_UINT16(pc);
|
||||
JS_ASSERT(argc > 0);
|
||||
|
||||
js::Vector<char *> argv(cx);
|
||||
if (!argv.resize(argc))
|
||||
return NULL;
|
||||
|
||||
MUST_FLOW_THROUGH("out");
|
||||
ok = JS_FALSE;
|
||||
|
||||
for (i = argc - 1; i >= 0; i--) {
|
||||
argv[i] = JS_strdup(cx, POP_STR_PREC(cs->prec + 1));
|
||||
if (!argv[i])
|
||||
goto out;
|
||||
}
|
||||
|
||||
todo = Sprint(&ss->sprinter, "%s", argv[0]);
|
||||
if (todo < 0)
|
||||
goto out;
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (Sprint(&ss->sprinter, " + %s", argv[i]) < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* The only way that our next op could be a JSOP_ADD is
|
||||
* if we are about to concatenate at least one non-string
|
||||
* literal. Deal with that here in order to avoid extra
|
||||
* parentheses (because JSOP_ADD is left-associative).
|
||||
*/
|
||||
if (pc[len] == JSOP_ADD)
|
||||
saveop = JSOP_NOP;
|
||||
|
||||
ok = JS_TRUE;
|
||||
|
||||
out:
|
||||
for (i = 0; i < argc; i++)
|
||||
JS_free(cx, argv[i]);
|
||||
if (!ok)
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_NEW:
|
||||
case JSOP_CALL:
|
||||
case JSOP_EVAL:
|
||||
|
|
|
@ -590,23 +590,12 @@ OPDEF(JSOP_DEFFUN_DBGFC, 231,"deffun_dbgfc", NULL, 3, 0, 0, 0, JOF_
|
|||
OPDEF(JSOP_DEFLOCALFUN_DBGFC,232,"deflocalfun_dbgfc",NULL, 5, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING)
|
||||
OPDEF(JSOP_LAMBDA_DBGFC, 233,"lambda_dbgfc", NULL, 3, 0, 1, 19, JOF_OBJECT)
|
||||
|
||||
/*
|
||||
* Concatenate N values, coercing to string if necessary, where N is concatn's
|
||||
* immediate. See record_JSOP_CONCATN for recording behavior.
|
||||
*/
|
||||
OPDEF(JSOP_CONCATN, 234,"concatn", NULL, 3, -1, 1, 13, JOF_UINT16|JOF_TMPSLOT2)
|
||||
|
||||
/*
|
||||
* Joined function object as method optimization support.
|
||||
*/
|
||||
OPDEF(JSOP_SETMETHOD, 235,"setmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_INITMETHOD, 236,"initmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_UNBRAND, 237,"unbrand", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNBRANDTHIS, 238,"unbrandthis", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_SETMETHOD, 234,"setmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_INITMETHOD, 235,"initmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_UNBRAND, 236,"unbrand", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNBRANDTHIS, 237,"unbrandthis", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
OPDEF(JSOP_SHARPINIT, 239,"sharpinit", NULL, 3, 0, 0, 0, JOF_UINT16|JOF_SHARPSLOT)
|
||||
|
||||
/*
|
||||
* If the argument is an object, perform toString conversion (E-262-3 section 9.8).
|
||||
*/
|
||||
OPDEF(JSOP_OBJTOSTR, 240,"objtostr", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_SHARPINIT, 238,"sharpinit", NULL, 3, 0, 0, 0, JOF_UINT16|JOF_SHARPSLOT)
|
||||
|
|
|
@ -15933,50 +15933,6 @@ TraceRecorder::record_JSOP_TRACE()
|
|||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
static const uint32 sMaxConcatNSize = 32;
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_JSOP_OBJTOSTR()
|
||||
{
|
||||
Value &v = stackval(-1);
|
||||
JS_ASSERT_IF(cx->fp->imacpc, v.isPrimitive() &&
|
||||
*cx->fp->imacpc == JSOP_OBJTOSTR);
|
||||
if (v.isPrimitive())
|
||||
return ARECORD_CONTINUE;
|
||||
CHECK_STATUS_A(guardNativeConversion(v));
|
||||
return InjectStatus(callImacro(objtostr_imacros.toString));
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_JSOP_CONCATN()
|
||||
{
|
||||
JSFrameRegs regs = *cx->regs;
|
||||
uint32 argc = GET_ARGC(regs.pc);
|
||||
Value *argBase = regs.sp - argc;
|
||||
|
||||
/* Prevent code/alloca explosion. */
|
||||
if (argc > sMaxConcatNSize)
|
||||
return ARECORD_STOP;
|
||||
|
||||
/* Build an array of the stringified primitives. */
|
||||
int32_t bufSize = argc * sizeof(JSString *);
|
||||
LIns *buf_ins = lir->insAlloc(bufSize);
|
||||
int32_t d = 0;
|
||||
for (Value *vp = argBase; vp != regs.sp; ++vp, d += sizeof(void *)) {
|
||||
JS_ASSERT(vp->isPrimitive());
|
||||
lir->insStore(stringify(*vp), buf_ins, d, ACCSET_OTHER);
|
||||
}
|
||||
|
||||
/* Perform concatenation using a builtin. */
|
||||
LIns *args[] = { lir->insImmI(argc), buf_ins, cx_ins };
|
||||
LIns *result_ins = lir->insCall(&js_ConcatN_ci, args);
|
||||
guard(false, lir->insEqP_0(result_ins), OOM_EXIT);
|
||||
|
||||
/* Update tracker with result. */
|
||||
set(argBase, result_ins);
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_JSOP_SETMETHOD()
|
||||
{
|
||||
|
|
|
@ -205,7 +205,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
|
|||
* before deserialization of bytecode. If the saved version does not match
|
||||
* the current version, abort deserialization and invalidate the file.
|
||||
*/
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 66)
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 67)
|
||||
|
||||
/*
|
||||
* Library-private functions.
|
||||
|
|
Загрузка…
Ссылка в новой задаче