mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Backed out changesets fabe232e8be9 and c84b0156ae03 (bug 793860) for Linux mochitest-2 timeouts.
This commit is contained in:
parent
bd668d0af6
commit
28a5b72edd
@ -1978,6 +1978,22 @@ EmitNameOp(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool callC
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
EmitElemOpBase(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
|
||||
{
|
||||
if (Emit1(cx, bce, op) < 0)
|
||||
return false;
|
||||
CheckTypeSet(cx, bce, op);
|
||||
|
||||
if (op == JSOP_CALLELEM) {
|
||||
if (Emit1(cx, bce, JSOP_SWAP) < 0)
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_NOTEARG) < 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitPropLHS(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
|
||||
{
|
||||
@ -2125,39 +2141,45 @@ EmitNameIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM
|
||||
* opcode onto the stack in the right order. In the case of SETELEM, the
|
||||
* value to be assigned must already be pushed.
|
||||
*/
|
||||
static bool
|
||||
EmitElemOperands(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
|
||||
{
|
||||
JS_ASSERT(pn->isArity(PN_BINARY));
|
||||
if (!EmitTree(cx, bce, pn->pn_left))
|
||||
ParseNode *left, *right;
|
||||
|
||||
if (pn->isArity(PN_NAME)) {
|
||||
/*
|
||||
* Set left and right so pn appears to be a PNK_ELEM node, instead of
|
||||
* a PNK_DOT node. See the PNK_FOR/IN case in EmitTree, and
|
||||
* EmitDestructuringOps nearer below. In the destructuring case, the
|
||||
* base expression (pn_expr) of the name may be null, which means we
|
||||
* have to emit a JSOP_BINDNAME.
|
||||
*/
|
||||
left = pn->maybeExpr();
|
||||
if (!left) {
|
||||
left = bce->parser->handler.new_<NullaryNode>(
|
||||
PNK_STRING, JSOP_BINDNAME, pn->pn_pos, pn->pn_atom);
|
||||
if (!left)
|
||||
return false;
|
||||
}
|
||||
right = bce->parser->handler.new_<NullaryNode>(
|
||||
PNK_STRING, JSOP_STRING, pn->pn_pos, pn->pn_atom);
|
||||
if (!right)
|
||||
return false;
|
||||
} else {
|
||||
JS_ASSERT(pn->isArity(PN_BINARY));
|
||||
left = pn->pn_left;
|
||||
right = pn->pn_right;
|
||||
}
|
||||
|
||||
if (!EmitTree(cx, bce, left))
|
||||
return false;
|
||||
|
||||
if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_DUP) < 0)
|
||||
return false;
|
||||
if (!EmitTree(cx, bce, pn->pn_right))
|
||||
return false;
|
||||
if (op == JSOP_SETELEM && Emit2(cx, bce, JSOP_PICK, (jsbytecode)2) < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
EmitElemOpBase(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
|
||||
{
|
||||
if (Emit1(cx, bce, op) < 0)
|
||||
if (!EmitTree(cx, bce, right))
|
||||
return false;
|
||||
CheckTypeSet(cx, bce, op);
|
||||
|
||||
if (op == JSOP_CALLELEM) {
|
||||
if (Emit1(cx, bce, JSOP_SWAP) < 0)
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_NOTEARG) < 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2831,16 +2853,20 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
{
|
||||
JS_ASSERT(emitOption != DefineVars);
|
||||
|
||||
// Now emit the lvalue opcode sequence. If the lvalue is a nested
|
||||
// destructuring initialiser-form, call ourselves to handle it, then pop
|
||||
// the matched value. Otherwise emit an lvalue bytecode sequence followed
|
||||
// by an assignment op.
|
||||
/*
|
||||
* Now emit the lvalue opcode sequence. If the lvalue is a nested
|
||||
* destructuring initialiser-form, call ourselves to handle it, then
|
||||
* pop the matched value. Otherwise emit an lvalue bytecode sequence
|
||||
* ending with a JSOP_ENUMELEM or equivalent op.
|
||||
*/
|
||||
if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) {
|
||||
if (!EmitDestructuringOpsHelper(cx, bce, pn, emitOption))
|
||||
return false;
|
||||
if (emitOption == InitializeVars) {
|
||||
// Per its post-condition, EmitDestructuringOpsHelper has left the
|
||||
// to-be-destructured value on top of the stack.
|
||||
/*
|
||||
* Per its post-condition, EmitDestructuringOpsHelper has left the
|
||||
* to-be-destructured value on top of the stack.
|
||||
*/
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0)
|
||||
return false;
|
||||
}
|
||||
@ -2850,6 +2876,8 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
JS_ASSERT(pn->getOp() == JSOP_GETLOCAL);
|
||||
JS_ASSERT(pn->pn_dflags & PND_BOUND);
|
||||
} else {
|
||||
// All paths below must pop after assigning to the lhs.
|
||||
|
||||
switch (pn->getKind()) {
|
||||
case PNK_NAME:
|
||||
if (!BindNameToSlot(cx, bce, pn))
|
||||
@ -2862,7 +2890,6 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
switch (pn->getOp()) {
|
||||
case JSOP_SETNAME:
|
||||
case JSOP_SETGNAME:
|
||||
case JSOP_SETCONST: {
|
||||
// This is like ordinary assignment, but with one difference.
|
||||
//
|
||||
// In `a = b`, we first determine a binding for `a` (using
|
||||
@ -2872,28 +2899,27 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
// In `[a] = [b]`, per spec, `b` is evaluated first, then we
|
||||
// determine a binding for `a`. Then we need to do assignment--
|
||||
// but the operands are on the stack in the wrong order for
|
||||
// JSOP_SETPROP, so we have to add a JSOP_SWAP.
|
||||
jsatomid atomIndex;
|
||||
if (!bce->makeAtomIndex(pn->pn_atom, &atomIndex))
|
||||
return false;
|
||||
|
||||
if (!pn->isOp(JSOP_SETCONST)) {
|
||||
JSOp bindOp = pn->isOp(JSOP_SETNAME) ? JSOP_BINDNAME : JSOP_BINDGNAME;
|
||||
if (!EmitIndex32(cx, bindOp, atomIndex, bce))
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_SWAP) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EmitIndexOp(cx, pn->getOp(), atomIndex, bce))
|
||||
// JSOP_SETPROP, so we use JSOP_ENUMELEM instead.
|
||||
//
|
||||
// EmitElemOp ordinarily works with PNK_ELEM nodes, naturally,
|
||||
// but it has special code to handle PNK_NAME nodes in this one
|
||||
// case.
|
||||
if (!EmitElemOp(cx, pn, JSOP_ENUMELEM, bce))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case JSOP_SETCONST:
|
||||
// As above.
|
||||
if (!EmitElemOp(cx, pn, JSOP_ENUMCONSTELEM, bce))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_SETLOCAL:
|
||||
case JSOP_SETARG:
|
||||
if (!EmitVarOp(cx, pn, pn->getOp(), bce))
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0)
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2902,6 +2928,7 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
break;
|
||||
|
||||
case PNK_DOT:
|
||||
case PNK_ELEM:
|
||||
// See the (PNK_NAME, JSOP_SETNAME) case above.
|
||||
//
|
||||
// In `a.x = b`, `a` is evaluated first, then `b`, then a
|
||||
@ -2909,20 +2936,11 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
//
|
||||
// In `[a.x] = [b]`, per spec, `b` is evaluated before `a`. Then we
|
||||
// need a property set -- but the operands are on the stack in the
|
||||
// wrong order for JSOP_SETPROP, so we have to add a JSOP_SWAP.
|
||||
if (!EmitTree(cx, bce, pn->pn_expr))
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_SWAP) < 0)
|
||||
return false;
|
||||
if (!EmitAtomOp(cx, pn, JSOP_SETPROP, bce))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case PNK_ELEM:
|
||||
// See the comment at `case PNK_DOT:` above. This case,
|
||||
// `[a[x]] = [b]`, is handled much the same way. The JSOP_SWAP
|
||||
// is emitted by EmitElemOperands.
|
||||
if (!EmitElemOp(cx, pn, JSOP_SETELEM, bce))
|
||||
// wrong order for JSOP_SETPROP, so we use JSOP_ENUMELEM instead.
|
||||
//
|
||||
// EmitElemOp has special code to handle PNK_DOT nodes in this one
|
||||
// case.
|
||||
if (!EmitElemOp(cx, pn, JSOP_ENUMELEM, bce))
|
||||
return false;
|
||||
break;
|
||||
|
||||
@ -2931,11 +2949,13 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
if (!EmitTree(cx, bce, pn))
|
||||
return false;
|
||||
|
||||
// Pop the call return value. Below, we pop the RHS too, balancing
|
||||
// the stack --- presumably for the benefit of bytecode
|
||||
// analysis. (The interpreter will never reach these instructions
|
||||
// since we just emitted JSOP_SETCALL, which always throws. It's
|
||||
// possible no analyses actually depend on this either.)
|
||||
// Pop the call return value and the RHS, presumably for the
|
||||
// benefit of bytecode analysis. (The interpreter will never reach
|
||||
// these instructions since we just emitted JSOP_SETCALL, which
|
||||
// always throws. It's possible no analyses actually depend on this
|
||||
// either.)
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0)
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0)
|
||||
return false;
|
||||
break;
|
||||
@ -2943,10 +2963,6 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("EmitDestructuringLHS: bad lhs kind");
|
||||
}
|
||||
|
||||
// Pop the assigned value.
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1717,6 +1717,25 @@ BaselineCompiler::emit_JSOP_SETELEM()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_ENUMELEM()
|
||||
{
|
||||
// ENUMELEM is a SETELEM with a different stack arrangement.
|
||||
// Instead of: OBJ ID RHS
|
||||
// The stack is: RHS OBJ ID
|
||||
|
||||
// Keep object and index in R0 and R1, and keep RHS on the stack.
|
||||
frame.popRegsAndSync(2);
|
||||
|
||||
// Call IC.
|
||||
ICSetElem_Fallback::Compiler stubCompiler(cx);
|
||||
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
|
||||
return false;
|
||||
|
||||
frame.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*DeleteElementFn)(JSContext *, HandleValue, HandleValue, bool *);
|
||||
static const VMFunction DeleteElementStrictInfo = FunctionInfo<DeleteElementFn>(DeleteElement<true>);
|
||||
static const VMFunction DeleteElementNonStrictInfo = FunctionInfo<DeleteElementFn>(DeleteElement<false>);
|
||||
|
@ -97,6 +97,7 @@ namespace jit {
|
||||
_(JSOP_GETELEM) \
|
||||
_(JSOP_SETELEM) \
|
||||
_(JSOP_CALLELEM) \
|
||||
_(JSOP_ENUMELEM) \
|
||||
_(JSOP_DELELEM) \
|
||||
_(JSOP_IN) \
|
||||
_(JSOP_GETGNAME) \
|
||||
|
@ -4888,6 +4888,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
|
||||
FallbackICSpew(cx, stub, "SetElem(%s)", js_CodeName[JSOp(*pc)]);
|
||||
|
||||
JS_ASSERT(op == JSOP_SETELEM ||
|
||||
op == JSOP_ENUMELEM ||
|
||||
op == JSOP_INITELEM ||
|
||||
op == JSOP_INITELEM_ARRAY);
|
||||
|
||||
|
@ -273,7 +273,11 @@ OPDEF(JSOP_DEFAULT, 122,"default", NULL, 5, 1, 0, JOF_JUMP)
|
||||
*/
|
||||
OPDEF(JSOP_EVAL, 123,"eval", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
|
||||
|
||||
OPDEF(JSOP_UNUSED124, 124, "unused124", NULL, 1, 0, 0, JOF_BYTE)
|
||||
/*
|
||||
* ECMA-compliant helper for 'for (x[i] in o)' loops.
|
||||
*/
|
||||
OPDEF(JSOP_ENUMELEM, 124,"enumelem", NULL, 1, 3, 0, JOF_BYTE |JOF_SET|JOF_TMPSLOT)
|
||||
|
||||
OPDEF(JSOP_UNUSED125, 125, "unused125", NULL, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED126, 126, "unused126", NULL, 1, 0, 0, JOF_BYTE)
|
||||
|
||||
@ -446,8 +450,15 @@ OPDEF(JSOP_GENERATOR, 202,"generator", NULL, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_YIELD, 203,"yield", NULL, 1, 1, 1, JOF_BYTE)
|
||||
OPDEF(JSOP_ARRAYPUSH, 204,"arraypush", NULL, 3, 1, 0, JOF_LOCAL)
|
||||
|
||||
OPDEF(JSOP_UNUSED205, 205, "unused205", NULL, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED206, 206, "unused206", NULL, 1, 0, 0, JOF_BYTE)
|
||||
/*
|
||||
* Get the built-in function::foo namespace and push it.
|
||||
*/
|
||||
OPDEF(JSOP_GETFUNNS, 205,"getfunns", NULL, 1, 0, 1, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Variant of JSOP_ENUMELEM for destructuring const (const [a, b] = ...).
|
||||
*/
|
||||
OPDEF(JSOP_ENUMCONSTELEM, 206,"enumconstelem",NULL, 1, 3, 0, JOF_BYTE|JOF_SET)
|
||||
|
||||
/*
|
||||
* Variant of JSOP_LEAVEBLOCK has a result on the stack above the locals,
|
||||
|
@ -1489,7 +1489,6 @@ CASE(JSOP_UNUSED102)
|
||||
CASE(JSOP_UNUSED103)
|
||||
CASE(JSOP_UNUSED104)
|
||||
CASE(JSOP_UNUSED107)
|
||||
CASE(JSOP_UNUSED124)
|
||||
CASE(JSOP_UNUSED125)
|
||||
CASE(JSOP_UNUSED126)
|
||||
CASE(JSOP_UNUSED132)
|
||||
@ -1536,8 +1535,7 @@ CASE(JSOP_UNUSED194)
|
||||
CASE(JSOP_UNUSED196)
|
||||
CASE(JSOP_UNUSED200)
|
||||
CASE(JSOP_UNUSED201)
|
||||
CASE(JSOP_UNUSED205)
|
||||
CASE(JSOP_UNUSED206)
|
||||
CASE(JSOP_GETFUNNS)
|
||||
CASE(JSOP_UNUSED208)
|
||||
CASE(JSOP_UNUSED209)
|
||||
CASE(JSOP_UNUSED210)
|
||||
@ -1883,6 +1881,26 @@ CASE(JSOP_SETCONST)
|
||||
}
|
||||
END_CASE(JSOP_SETCONST);
|
||||
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
CASE(JSOP_ENUMCONSTELEM)
|
||||
{
|
||||
RootedValue &rval = rootValue0;
|
||||
rval = REGS.sp[-3];
|
||||
|
||||
RootedObject &obj = rootObject0;
|
||||
FETCH_OBJECT(cx, -2, obj);
|
||||
RootedId &id = rootId0;
|
||||
FETCH_ELEMENT_ID(-1, id);
|
||||
if (!JSObject::defineGeneric(cx, obj, id, rval,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
|
||||
goto error;
|
||||
}
|
||||
REGS.sp -= 3;
|
||||
}
|
||||
END_CASE(JSOP_ENUMCONSTELEM)
|
||||
#endif
|
||||
|
||||
CASE(JSOP_BINDGNAME)
|
||||
PUSH_OBJECT(REGS.fp()->global());
|
||||
END_CASE(JSOP_BINDGNAME)
|
||||
@ -2347,6 +2365,22 @@ CASE(JSOP_SETELEM)
|
||||
}
|
||||
END_CASE(JSOP_SETELEM)
|
||||
|
||||
CASE(JSOP_ENUMELEM)
|
||||
{
|
||||
RootedObject &obj = rootObject0;
|
||||
RootedValue &rval = rootValue0;
|
||||
|
||||
/* Funky: the value to set is under the [obj, id] pair. */
|
||||
FETCH_OBJECT(cx, -2, obj);
|
||||
RootedId &id = rootId0;
|
||||
FETCH_ELEMENT_ID(-1, id);
|
||||
rval = REGS.sp[-3];
|
||||
if (!JSObject::setGeneric(cx, obj, obj, id, &rval, script->strict))
|
||||
goto error;
|
||||
REGS.sp -= 3;
|
||||
}
|
||||
END_CASE(JSOP_ENUMELEM)
|
||||
|
||||
CASE(JSOP_EVAL)
|
||||
{
|
||||
CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp);
|
||||
|
@ -22,7 +22,7 @@ namespace js {
|
||||
* and saved versions. If deserialization fails, the data should be
|
||||
* invalidated if possible.
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 157);
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 156);
|
||||
|
||||
class XDRBuffer {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user