Backout bug 468782. Confirmed to leak.

This commit is contained in:
Andreas Gal 2009-01-25 16:38:31 -08:00
Родитель b014d7265b
Коммит f3bca92387
12 изменённых файлов: 130 добавлений и 295 удалений

Просмотреть файл

@ -81,6 +81,8 @@ BUILTIN3(extern, JSVAL, js_Any_getprop, CONTEXT, OBJECT, STRING,
BUILTIN4(extern, BOOL, js_Any_setprop, CONTEXT, OBJECT, STRING, JSVAL, 0, 0) BUILTIN4(extern, BOOL, js_Any_setprop, CONTEXT, OBJECT, STRING, JSVAL, 0, 0)
BUILTIN3(extern, JSVAL, js_Any_getelem, CONTEXT, OBJECT, INT32, 0, 0) BUILTIN3(extern, JSVAL, js_Any_getelem, CONTEXT, OBJECT, INT32, 0, 0)
BUILTIN4(extern, BOOL, js_Any_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, 0) BUILTIN4(extern, BOOL, js_Any_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, 0)
BUILTIN3(extern, OBJECT, js_FastValueToIterator, CONTEXT, UINT32, JSVAL, 0, 0)
BUILTIN2(extern, JSVAL, js_FastCallIteratorNext, CONTEXT, OBJECT, 0, 0)
BUILTIN2(FRIEND, BOOL, js_CloseIterator, CONTEXT, JSVAL, 0, 0) BUILTIN2(FRIEND, BOOL, js_CloseIterator, CONTEXT, JSVAL, 0, 0)
BUILTIN2(extern, SIDEEXIT, js_CallTree, INTERPSTATE, FRAGMENT, 0, 0) BUILTIN2(extern, SIDEEXIT, js_CallTree, INTERPSTATE, FRAGMENT, 0, 0)
BUILTIN2(extern, OBJECT, js_FastNewObject, CONTEXT, OBJECT, 0, 0) BUILTIN2(extern, OBJECT, js_FastNewObject, CONTEXT, OBJECT, 0, 0)

Просмотреть файл

@ -109,24 +109,11 @@ function immediate(op) {
info.flags.indexOf("JOF_INT8") >= 0) { info.flags.indexOf("JOF_INT8") >= 0) {
return (op.imm1 & 0xff); return (op.imm1 & 0xff);
} }
if (info.flags.indexOf("JOF_UINT16") >= 0) { if (info.flags.indexOf("JOF_UINT16") >= 0)
if (/^\(/.test(op.imm1))
return '(_ & 0xff00) >> 8, (_ & 0xff)'.replace(/_/g, op.imm1);
return ((op.imm1 & 0xff00) >> 8) + ", " + (op.imm1 & 0xff); return ((op.imm1 & 0xff00) >> 8) + ", " + (op.imm1 & 0xff);
}
throw new Error(info.jsop + " format not yet implemented"); throw new Error(info.jsop + " format not yet implemented");
} }
const line_regexp_parts = [
"^(?:(\\w+):)?",
"\\s*(\\.?\\w+)",
"(?:\\s+(\\w+|\\([^)]*\\)))?",
"(?:\\s+([\\w-]+|\\([^)]*\\)))?",
"(?:\\s*(?:#.*))?$"
];
const line_regexp = new RegExp(line_regexp_parts.join(""));
/* /*
* Syntax (spaces are significant only to delimit tokens): * Syntax (spaces are significant only to delimit tokens):
* *
@ -134,13 +121,10 @@ const line_regexp = new RegExp(line_regexp_parts.join(""));
* Directive ::= (name ':')? Operation * Directive ::= (name ':')? Operation
* Operation ::= opname Operands? * Operation ::= opname Operands?
* Operands ::= Operand (',' Operand)* * Operands ::= Operand (',' Operand)*
* Operand ::= name | number | '(' Expr ')' * Operand ::= name | number
* Expr ::= a constant-expression in the C++ language
* containing no parentheses
* *
* We simplify given line structure and the maximum of one immediate operand, * We simplify given line structure and the maximum of one immediate operand,
* by parsing using split and regexps. For ease of parsing, parentheses are * by parsing using split and regexps.
* banned in an Expr for now, even in quotes or a C++ comment.
* *
* Pseudo-ops start with . and include .igroup and .imacro, terminated by .end. * Pseudo-ops start with . and include .igroup and .imacro, terminated by .end.
* .imacro must nest in .igroup, neither nests in itself. See imacros.jsasm for * .imacro must nest in .igroup, neither nests in itself. See imacros.jsasm for
@ -157,7 +141,7 @@ function assemble(filename) {
for (let i = 0; i < a.length; i++) { for (let i = 0; i < a.length; i++) {
if (/^\s*(?:#.*)?$/.test(a[i])) if (/^\s*(?:#.*)?$/.test(a[i]))
continue; continue;
let m = line_regexp.exec(a[i]); let m = /(?:(\w+):)?\s*(\.?\w+)(?:\s+(\w+))?(?:\s+([\w-]+))?(?:\s*(?:#.*))?$/.exec(a[i]);
if (!m) if (!m)
throw new Error(a[i]); throw new Error(a[i]);
@ -224,6 +208,7 @@ function assemble(filename) {
print(" {"); print(" {");
for (let k = 0; k < imacro.code.length; k++) { for (let k = 0; k < imacro.code.length; k++) {
let op = imacro.code[k]; let op = imacro.code[k];
print("/*" + formatoffset(op.offset,2) + "*/ " + op.info.jsop + print("/*" + formatoffset(op.offset,2) + "*/ " + op.info.jsop +
(op.imm1 ? ", " + immediate(op) : "") + ","); (op.imm1 ? ", " + immediate(op) : "") + ",");

Просмотреть файл

@ -536,64 +536,6 @@ static struct {
/* 6*/ JSOP_STOP, /* 6*/ JSOP_STOP,
}, },
}; };
static struct {
jsbytecode for_in[10];
jsbytecode for_each[10];
jsbytecode for_in_native[10];
jsbytecode for_each_native[10];
} iter_imacros = {
{
/* 0*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
/* 3*/ JSOP_INT8, 0,
/* 5*/ JSOP_CALL, 0, 1,
/* 8*/ JSOP_PUSH,
/* 9*/ JSOP_STOP,
},
{
/* 0*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
/* 3*/ JSOP_INT8, 0,
/* 5*/ JSOP_CALL, 0, 1,
/* 8*/ JSOP_PUSH,
/* 9*/ JSOP_STOP,
},
{
/* 0*/ JSOP_CALLBUILTIN, ((JSBUILTIN_ObjectToIterator) & 0xff00) >> 8, ((JSBUILTIN_ObjectToIterator) & 0xff),
/* 3*/ JSOP_INT8, 0,
/* 5*/ JSOP_CALL, 0, 1,
/* 8*/ JSOP_PUSH,
/* 9*/ JSOP_STOP,
},
{
/* 0*/ JSOP_CALLBUILTIN, ((JSBUILTIN_ObjectToIterator) & 0xff00) >> 8, ((JSBUILTIN_ObjectToIterator) & 0xff),
/* 3*/ JSOP_INT8, 0,
/* 5*/ JSOP_CALL, 0, 1,
/* 8*/ JSOP_PUSH,
/* 9*/ JSOP_STOP,
},
};
static struct {
jsbytecode custom_iter_next[10];
jsbytecode native_iter_next[12];
} nextiter_imacros = {
{
/* 0*/ JSOP_POP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(next),
/* 5*/ JSOP_CALL, 0, 0,
/* 8*/ JSOP_TRUE,
/* 9*/ JSOP_STOP,
},
{
/* 0*/ JSOP_POP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_CALLBUILTIN, ((JSBUILTIN_CallIteratorNext) & 0xff00) >> 8, ((JSBUILTIN_CallIteratorNext) & 0xff),
/* 5*/ JSOP_CALL, 0, 0,
/* 8*/ JSOP_DUP,
/* 9*/ JSOP_HOLE,
/*10*/ JSOP_STRICTNE,
/*11*/ JSOP_STOP,
},
};
uint8 js_opcode2extra[JSOP_LIMIT] = { uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_NOP */ 0, /* JSOP_NOP */
0, /* JSOP_PUSH */ 0, /* JSOP_PUSH */
@ -670,8 +612,8 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_STRICTEQ */ 0, /* JSOP_STRICTEQ */
0, /* JSOP_STRICTNE */ 0, /* JSOP_STRICTNE */
0, /* JSOP_NULLTHIS */ 0, /* JSOP_NULLTHIS */
3, /* JSOP_ITER */ 0, /* JSOP_ITER */
2, /* JSOP_NEXTITER */ 0, /* JSOP_NEXTITER */
0, /* JSOP_ENDITER */ 0, /* JSOP_ENDITER */
7, /* JSOP_APPLY */ 7, /* JSOP_APPLY */
0, /* JSOP_SWAP */ 0, /* JSOP_SWAP */
@ -821,7 +763,7 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_CALLGVAR */ 0, /* JSOP_CALLGVAR */
0, /* JSOP_CALLLOCAL */ 0, /* JSOP_CALLLOCAL */
0, /* JSOP_CALLARG */ 0, /* JSOP_CALLARG */
0, /* JSOP_CALLBUILTIN */ 0, /* JSOP_UNUSED226 */
0, /* JSOP_INT8 */ 0, /* JSOP_INT8 */
0, /* JSOP_INT32 */ 0, /* JSOP_INT32 */
0, /* JSOP_LENGTH */ 0, /* JSOP_LENGTH */

Просмотреть файл

@ -575,63 +575,3 @@
.end # .end #
.end .end
.igroup iter JSOP_ITER
.imacro for_in # obj
callprop iterator # fun obj
int8 (JSITER_ENUMERATE) # fun obj flags
call 1 # iterobj
push # iterobj undef
stop
.end
.imacro for_each # obj
callprop iterator # fun obj
int8 (JSITER_ENUMERATE|JSITER_FOREACH) # fun obj flags
call 1 # iterobj
push # iterobj undef
stop
.end
.imacro for_in_native # obj
callbuiltin (JSBUILTIN_ObjectToIterator) # fun obj
int8 JSITER_ENUMERATE # fun obj flags
call 1 # iterobj
push # iterobj undef
stop
.end
.imacro for_each_native # obj
callbuiltin (JSBUILTIN_ObjectToIterator) # fun obj
int8 (JSITER_ENUMERATE|JSITER_FOREACH) # fun obj flags
call 1 # iterobj
push # iterobj undef
stop
.end
.end
.igroup nextiter JSOP_NEXTITER
.imacro custom_iter_next # iterobj prevval
pop # iterobj
dup # iterobj iterobj
callprop next # iterobj fun iterobj
call 0 # iterobj nextval
true # iterobj nextval true
stop
.end
.imacro native_iter_next # iterobj prevval
pop # iterobj
dup # iterobj iterobj
callbuiltin (JSBUILTIN_CallIteratorNext) # iterobj fun iterobj
call 0 # iterobj nextval?
dup # iterobj nextval? nextval?
hole # iterobj nextval? nextval? hole
strictne # iterobj nextval? boolean
stop
.end
.end

Просмотреть файл

@ -243,6 +243,23 @@ js_Any_setelem(JSContext* cx, JSObject* obj, int32 index, jsval v)
return OBJ_SET_PROPERTY(cx, obj, id, &v); return OBJ_SET_PROPERTY(cx, obj, id, &v);
} }
JSObject* FASTCALL
js_FastValueToIterator(JSContext* cx, jsuint flags, jsval v)
{
if (!js_ValueToIterator(cx, flags, &v))
return NULL;
return JSVAL_TO_OBJECT(v);
}
jsval FASTCALL
js_FastCallIteratorNext(JSContext* cx, JSObject* iterobj)
{
jsval v;
if (!js_CallIteratorNext(cx, iterobj, &v))
return JSVAL_ERROR_COOKIE;
return v;
}
SideExit* FASTCALL SideExit* FASTCALL
js_CallTree(InterpState* state, Fragment* f) js_CallTree(InterpState* state, Fragment* f)
{ {

Просмотреть файл

@ -227,12 +227,6 @@ typedef enum JSRuntimeState {
JSRTS_LANDING JSRTS_LANDING
} JSRuntimeState; } JSRuntimeState;
typedef enum JSBuiltinFunctionId {
JSBUILTIN_ObjectToIterator,
JSBUILTIN_CallIteratorNext,
JSBUILTIN_LIMIT
} JSBuiltinFunctionId;
typedef struct JSPropertyTreeEntry { typedef struct JSPropertyTreeEntry {
JSDHashEntryHdr hdr; JSDHashEntryHdr hdr;
JSScopeProperty *child; JSScopeProperty *child;
@ -341,14 +335,6 @@ struct JSRuntime {
JSString *emptyString; JSString *emptyString;
JSString **unitStrings; JSString **unitStrings;
/*
* Builtin functions, lazily created and held for use by the trace recorder.
*
* This field would be #ifdef JS_TRACER, but XPConnect is compiled without
* -DJS_TRACER and includes this header.
*/
JSObject *builtinFunctions[JSBUILTIN_LIMIT];
/* List of active contexts sharing this runtime; protected by gcLock. */ /* List of active contexts sharing this runtime; protected by gcLock. */
JSCList contextList; JSCList contextList;

Просмотреть файл

@ -3105,11 +3105,6 @@ js_TraceRuntime(JSTracer *trc, JSBool allAtoms)
rt->gcExtraRootsTraceOp(trc, rt->gcExtraRootsData); rt->gcExtraRootsTraceOp(trc, rt->gcExtraRootsData);
#ifdef JS_TRACER #ifdef JS_TRACER
for (int i = 0; i < JSBUILTIN_LIMIT; i++) {
if (rt->builtinFunctions[i])
JS_CALL_OBJECT_TRACER(trc, rt->builtinFunctions[i], "builtin function");
}
#ifdef JS_THREADSAFE #ifdef JS_THREADSAFE
/* Trace the loop table(s) which can contain pointers to code objects. */ /* Trace the loop table(s) which can contain pointers to code objects. */
while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) { while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {

Просмотреть файл

@ -3227,6 +3227,7 @@ js_Interpret(JSContext *cx)
CHECK_INTERRUPT_HANDLER(); CHECK_INTERRUPT_HANDLER();
rval = BOOLEAN_TO_JSVAL(regs.sp[-1] != JSVAL_HOLE); rval = BOOLEAN_TO_JSVAL(regs.sp[-1] != JSVAL_HOLE);
PUSH(rval); PUSH(rval);
TRACE_0(IteratorNextComplete);
END_CASE(JSOP_NEXTITER) END_CASE(JSOP_NEXTITER)
BEGIN_CASE(JSOP_ENDITER) BEGIN_CASE(JSOP_ENDITER)
@ -6731,19 +6732,6 @@ js_Interpret(JSContext *cx)
} }
END_CASE(JSOP_LEAVEBLOCK) END_CASE(JSOP_LEAVEBLOCK)
BEGIN_CASE(JSOP_CALLBUILTIN)
#ifdef JS_TRACER
obj = js_GetBuiltinFunction(cx, GET_INDEX(regs.pc));
if (!obj)
goto error;
rval = FETCH_OPND(-1);
PUSH_OPND(rval);
STORE_OPND(-2, OBJECT_TO_JSVAL(obj));
#else
goto bad_opcode; /* This is an imacro-only opcode. */
#endif
END_CASE(JSOP_CALLBUILTIN)
#if JS_HAS_GENERATORS #if JS_HAS_GENERATORS
BEGIN_CASE(JSOP_GENERATOR) BEGIN_CASE(JSOP_GENERATOR)
ASSERT_NOT_THROWING(cx); ASSERT_NOT_THROWING(cx);
@ -6853,12 +6841,10 @@ js_Interpret(JSContext *cx)
L_JSOP_UNUSED208: L_JSOP_UNUSED208:
L_JSOP_UNUSED209: L_JSOP_UNUSED209:
L_JSOP_UNUSED219: L_JSOP_UNUSED219:
L_JSOP_UNUSED226:
#else /* !JS_THREADED_INTERP */ #else /* !JS_THREADED_INTERP */
default: default:
#endif
#ifndef JS_TRACER
bad_opcode:
#endif #endif
{ {
char numBuf[12]; char numBuf[12];
@ -6877,8 +6863,7 @@ js_Interpret(JSContext *cx)
if (fp->imacpc && cx->throwing) { if (fp->imacpc && cx->throwing) {
// To keep things simple, we hard-code imacro exception handlers here. // To keep things simple, we hard-code imacro exception handlers here.
if (*fp->imacpc == JSOP_NEXTITER) { if (*fp->imacpc == JSOP_NEXTITER) {
// pc may point to JSOP_DUP here due to bug 474854. JS_ASSERT(*regs.pc == JSOP_CALL);
JS_ASSERT(*regs.pc == JSOP_CALL || *regs.pc == JSOP_DUP);
if (js_ValueIsStopIteration(cx->exception)) { if (js_ValueIsStopIteration(cx->exception)) {
cx->throwing = JS_FALSE; cx->throwing = JS_FALSE;
cx->exception = JSVAL_VOID; cx->exception = JSVAL_VOID;

Просмотреть файл

@ -545,7 +545,7 @@ OPDEF(JSOP_INDEXBASE3, 222,"atombase3", NULL, 1, 0, 0, 0, JOF_BYTE |
OPDEF(JSOP_CALLGVAR, 223, "callgvar", NULL, 3, 0, 2, 19, JOF_ATOM|JOF_NAME|JOF_CALLOP) OPDEF(JSOP_CALLGVAR, 223, "callgvar", NULL, 3, 0, 2, 19, JOF_ATOM|JOF_NAME|JOF_CALLOP)
OPDEF(JSOP_CALLLOCAL, 224, "calllocal", NULL, 3, 0, 2, 19, JOF_LOCAL|JOF_NAME|JOF_CALLOP) OPDEF(JSOP_CALLLOCAL, 224, "calllocal", NULL, 3, 0, 2, 19, JOF_LOCAL|JOF_NAME|JOF_CALLOP)
OPDEF(JSOP_CALLARG, 225, "callarg", NULL, 3, 0, 2, 19, JOF_QARG |JOF_NAME|JOF_CALLOP) OPDEF(JSOP_CALLARG, 225, "callarg", NULL, 3, 0, 2, 19, JOF_QARG |JOF_NAME|JOF_CALLOP)
OPDEF(JSOP_CALLBUILTIN, 226, "callbuiltin", NULL, 3, 0, 2, 0, JOF_UINT16) OPDEF(JSOP_UNUSED226, 226, "unused226", NULL, 1, 0, 1, 1, JOF_BYTE)
/* /*
* Opcodes to hold 8-bit and 32-bit immediate integer operands. * Opcodes to hold 8-bit and 32-bit immediate integer operands.

Просмотреть файл

@ -1995,7 +1995,7 @@ TraceRecorder::snapshot(ExitType exitType)
bool resumeAfter = (pendingTraceableNative && bool resumeAfter = (pendingTraceableNative &&
JSTN_ERRTYPE(pendingTraceableNative) == FAIL_JSVAL); JSTN_ERRTYPE(pendingTraceableNative) == FAIL_JSVAL);
if (resumeAfter) { if (resumeAfter) {
JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY); JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEXTITER);
pc += cs.length; pc += cs.length;
regs->pc = pc; regs->pc = pc;
MUST_FLOW_THROUGH("restore_pc"); MUST_FLOW_THROUGH("restore_pc");
@ -2022,10 +2022,11 @@ TraceRecorder::snapshot(ExitType exitType)
); );
JS_ASSERT(unsigned(m - typemap) == ngslots + stackSlots); JS_ASSERT(unsigned(m - typemap) == ngslots + stackSlots);
/* If we are capturing the stack state on a specific instruction, the value on /* If we are capturing the stack state on a specific instruction, the value on or near
the top of the stack is a boxed value. */ the top of the stack is a boxed value. Either pc[-cs.length] is JSOP_NEXTITER and we
want one below top of stack, or else it's JSOP_CALL and we want top of stack. */
if (resumeAfter) { if (resumeAfter) {
typemap[stackSlots - 1] = JSVAL_BOXED; typemap[stackSlots + ((pc[-cs.length] == JSOP_NEXTITER) ? -2 : -1)] = JSVAL_BOXED;
/* Now restore the the original pc (after which early returns are ok). */ /* Now restore the the original pc (after which early returns are ok). */
MUST_FLOW_LABEL(restore_pc); MUST_FLOW_LABEL(restore_pc);
@ -7532,40 +7533,114 @@ TraceRecorder::record_JSOP_IMACOP()
return true; return true;
} }
static struct {
jsbytecode for_in[10];
jsbytecode for_each[10];
} iter_imacros = {
{
JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
JSOP_INT8, JSITER_ENUMERATE,
JSOP_CALL, 0, 1,
JSOP_PUSH,
JSOP_STOP
},
{
JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
JSOP_INT8, JSITER_ENUMERATE | JSITER_FOREACH,
JSOP_CALL, 0, 1,
JSOP_PUSH,
JSOP_STOP
}
};
JS_STATIC_ASSERT(sizeof(iter_imacros) < IMACRO_PC_ADJ_LIMIT);
JS_REQUIRES_STACK bool JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_ITER() TraceRecorder::record_JSOP_ITER()
{ {
jsval& v = stackval(-1); jsval& v = stackval(-1);
if (JSVAL_IS_PRIMITIVE(v)) if (!JSVAL_IS_PRIMITIVE(v)) {
ABORT_TRACE("for-in on a primitive value"); jsuint flags = cx->fp->regs->pc[1];
jsuint flags = cx->fp->regs->pc[1]; if (!hasIteratorMethod(JSVAL_TO_OBJECT(v))) {
LIns* args[] = { get(&v), INS_CONST(flags), cx_ins };
LIns* v_ins = lir->insCall(&js_FastValueToIterator_ci, args);
guard(false, lir->ins_eq0(v_ins), MISMATCH_EXIT);
set(&v, v_ins);
LIns* void_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
stack(0, void_ins);
return true;
}
if (hasIteratorMethod(JSVAL_TO_OBJECT(v))) {
if (flags == JSITER_ENUMERATE) if (flags == JSITER_ENUMERATE)
return call_imacro(iter_imacros.for_in); return call_imacro(iter_imacros.for_in);
if (flags == (JSITER_ENUMERATE | JSITER_FOREACH)) if (flags == (JSITER_ENUMERATE | JSITER_FOREACH))
return call_imacro(iter_imacros.for_each); return call_imacro(iter_imacros.for_each);
} else { ABORT_TRACE("unimplemented JSITER_* flags");
if (flags == JSITER_ENUMERATE)
return call_imacro(iter_imacros.for_in_native);
if (flags == (JSITER_ENUMERATE | JSITER_FOREACH))
return call_imacro(iter_imacros.for_each_native);
} }
ABORT_TRACE("unimplemented JSITER_* flags");
ABORT_TRACE("for-in on a primitive value");
} }
static JSTraceableNative js_FastCallIteratorNext_tn = {
NULL, // JSFastNative native;
&js_FastCallIteratorNext_ci, // const nanojit::CallInfo *builtin;
"C", // const char *prefix;
"o", // const char *argtypes;
FAIL_JSVAL // uintN flags;
};
static jsbytecode nextiter_imacro[] = {
JSOP_POP,
JSOP_DUP,
JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(next),
JSOP_CALL, 0, 0,
JSOP_TRUE,
JSOP_STOP
};
JS_STATIC_ASSERT(sizeof(nextiter_imacro) < IMACRO_PC_ADJ_LIMIT);
JS_REQUIRES_STACK bool JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_NEXTITER() TraceRecorder::record_JSOP_NEXTITER()
{ {
jsval& iterobj_val = stackval(-2); jsval& iterobj_val = stackval(-2);
if (JSVAL_IS_PRIMITIVE(iterobj_val)) if (!JSVAL_IS_PRIMITIVE(iterobj_val)) {
ABORT_TRACE("for-in on a primitive value"); LIns* iterobj_ins = get(&iterobj_val);
LIns* iterobj_ins = get(&iterobj_val); if (guardClass(JSVAL_TO_OBJECT(iterobj_val), iterobj_ins, &js_IteratorClass, BRANCH_EXIT)) {
if (guardClass(JSVAL_TO_OBJECT(iterobj_val), iterobj_ins, &js_IteratorClass, BRANCH_EXIT)) LIns* args[] = { iterobj_ins, cx_ins };
return call_imacro(nextiter_imacros.native_iter_next); LIns* v_ins = lir->insCall(&js_FastCallIteratorNext_ci, args);
return call_imacro(nextiter_imacros.custom_iter_next); guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), OOM_EXIT);
LIns* flag_ins = lir->ins_eq0(lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_HOLE)));
stack(-1, v_ins);
stack(0, flag_ins);
pendingTraceableNative = &js_FastCallIteratorNext_tn;
return true;
}
// Custom iterator, possibly a generator.
return call_imacro(nextiter_imacro);
}
ABORT_TRACE("for-in on a primitive value");
}
JS_REQUIRES_STACK bool
TraceRecorder::record_IteratorNextComplete()
{
JS_ASSERT(*cx->fp->regs->pc == JSOP_NEXTITER);
JS_ASSERT(pendingTraceableNative == &js_FastCallIteratorNext_tn);
jsval& v = stackval(-2);
LIns* v_ins = get(&v);
unbox_jsval(v, v_ins);
set(&v, v_ins);
return true;
} }
JS_REQUIRES_STACK bool JS_REQUIRES_STACK bool
@ -8594,86 +8669,6 @@ TraceRecorder::record_JSOP_CALLARG()
return true; return true;
} }
/* Functions for use with JSOP_CALLBUILTIN. */
static JSBool
ObjectToIterator(JSContext *cx, uintN argc, jsval *vp)
{
jsval *argv = JS_ARGV(cx, vp);
JS_ASSERT(JSVAL_IS_INT(argv[0]));
JS_SET_RVAL(cx, vp, JS_THIS(cx, vp));
return js_ValueToIterator(cx, JSVAL_TO_INT(argv[0]), &JS_RVAL(cx, vp));
}
static JSObject* FASTCALL
ObjectToIterator_tn(JSContext* cx, JSObject *obj, int32 flags)
{
jsval v = OBJECT_TO_JSVAL(obj);
if (!js_ValueToIterator(cx, flags, &v))
return NULL;
return JSVAL_TO_OBJECT(v);
}
static JSBool
CallIteratorNext(JSContext *cx, uintN argc, jsval *vp)
{
return js_CallIteratorNext(cx, JS_THIS_OBJECT(cx, vp), &JS_RVAL(cx, vp));
}
static jsval FASTCALL
CallIteratorNext_tn(JSContext* cx, JSObject* iterobj)
{
jsval v;
if (!js_CallIteratorNext(cx, iterobj, &v))
return JSVAL_ERROR_COOKIE;
return v;
}
JS_DEFINE_TRCINFO_1(ObjectToIterator,
(3, (static, OBJECT_FAIL_NULL, ObjectToIterator_tn, CONTEXT, THIS, INT32, 0, 0)))
JS_DEFINE_TRCINFO_1(CallIteratorNext,
(2, (static, JSVAL_FAIL, CallIteratorNext_tn, CONTEXT, THIS, 0, 0)))
static const struct BuiltinFunctionInfo {
JSTraceableNative *tn;
int nargs;
} builtinFunctionInfo[JSBUILTIN_LIMIT] = {
{ObjectToIterator_trcinfo, 1},
{CallIteratorNext_trcinfo, 0}
};
JSObject *
js_GetBuiltinFunction(JSContext *cx, uintN index)
{
JSRuntime *rt = cx->runtime;
JSObject *funobj = rt->builtinFunctions[index];
if (!funobj) {
/* Use NULL parent and atom. Builtin functions never escape to scripts. */
JSFunction *fun = js_NewFunction(cx,
NULL,
(JSNative) builtinFunctionInfo[index].tn,
builtinFunctionInfo[index].nargs,
JSFUN_FAST_NATIVE | JSFUN_TRACEABLE,
NULL,
NULL);
if (fun)
rt->builtinFunctions[index] = funobj = FUN_OBJECT(fun);
}
return funobj;
}
JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_CALLBUILTIN()
{
JSObject *obj = js_GetBuiltinFunction(cx, GET_INDEX(cx->fp->regs->pc));
if (!obj)
return false;
stack(0, get(&stackval(-1)));
stack(-1, INS_CONSTPTR(obj));
return true;
}
JS_REQUIRES_STACK bool JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_NULLTHIS() TraceRecorder::record_JSOP_NULLTHIS()
{ {
@ -8832,7 +8827,7 @@ static void
InitIMacroCode() InitIMacroCode()
{ {
if (imacro_code[JSOP_NEXTITER]) { if (imacro_code[JSOP_NEXTITER]) {
JS_ASSERT(imacro_code[JSOP_NEXTITER] == (jsbytecode*)&nextiter_imacros - 1); JS_ASSERT(imacro_code[JSOP_NEXTITER] == nextiter_imacro - 1);
return; return;
} }
@ -8843,7 +8838,7 @@ InitIMacroCode()
imacro_code[JSOP_ADD] = (jsbytecode*)&add_imacros - 1; imacro_code[JSOP_ADD] = (jsbytecode*)&add_imacros - 1;
imacro_code[JSOP_ITER] = (jsbytecode*)&iter_imacros - 1; imacro_code[JSOP_ITER] = (jsbytecode*)&iter_imacros - 1;
imacro_code[JSOP_NEXTITER] = (jsbytecode*)&nextiter_imacros - 1; imacro_code[JSOP_NEXTITER] = nextiter_imacro - 1;
imacro_code[JSOP_APPLY] = (jsbytecode*)&apply_imacros - 1; imacro_code[JSOP_APPLY] = (jsbytecode*)&apply_imacros - 1;
imacro_code[JSOP_NEG] = (jsbytecode*)&unary_imacros - 1; imacro_code[JSOP_NEG] = (jsbytecode*)&unary_imacros - 1;
@ -8869,3 +8864,4 @@ UNUSED(207)
UNUSED(208) UNUSED(208)
UNUSED(209) UNUSED(209)
UNUSED(219) UNUSED(219)
UNUSED(226)

Просмотреть файл

@ -518,6 +518,7 @@ public:
JS_REQUIRES_STACK bool record_SetPropMiss(JSPropCacheEntry* entry); JS_REQUIRES_STACK bool record_SetPropMiss(JSPropCacheEntry* entry);
JS_REQUIRES_STACK bool record_DefLocalFunSetSlot(uint32 slot, JSObject* obj); JS_REQUIRES_STACK bool record_DefLocalFunSetSlot(uint32 slot, JSObject* obj);
JS_REQUIRES_STACK bool record_FastNativeCallComplete(); JS_REQUIRES_STACK bool record_FastNativeCallComplete();
JS_REQUIRES_STACK bool record_IteratorNextComplete();
nanojit::Fragment* getOuterToBlacklist() { return outerToBlacklist; } nanojit::Fragment* getOuterToBlacklist() { return outerToBlacklist; }
void deepAbort() { deepAborted = true; } void deepAbort() { deepAborted = true; }
@ -574,9 +575,6 @@ js_FlushJITCache(JSContext* cx);
extern void extern void
js_FlushJITOracle(JSContext* cx); js_FlushJITOracle(JSContext* cx);
extern JSObject *
js_GetBuiltinFunction(JSContext *cx, uintN index);
#else /* !JS_TRACER */ #else /* !JS_TRACER */
#define TRACE_0(x) ((void)0) #define TRACE_0(x) ((void)0)

Просмотреть файл

@ -2545,17 +2545,6 @@ function testApply() {
testApply.expected = "5,5,5,5,5,5,5,5,5,5"; testApply.expected = "5,5,5,5,5,5,5,5,5,5";
test(testApply); test(testApply);
function testNestedForIn() {
var a = {x: 1, y: 2, z: 3};
var s = '';
for (var p1 in a)
for (var p2 in a)
s += p1 + p2 + ' ';
return s;
}
testNestedForIn.expected = 'xx xy xz yx yy yz zx zy zz ';
test(testNestedForIn);
function testComparisons() function testComparisons()
{ {
// All the special values from each of the types in // All the special values from each of the types in