зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset e01d0f7a3c6f (bug 1135708) for spidermonkey errors CLOSED TREE
This commit is contained in:
Родитель
f29d04329b
Коммит
9c5c217c21
|
@ -47,7 +47,7 @@ enum AssignmentOperator {
|
|||
/* assign */
|
||||
AOP_ASSIGN = 0,
|
||||
/* operator-assign */
|
||||
AOP_PLUS, AOP_MINUS, AOP_STAR, AOP_DIV, AOP_MOD, AOP_POW,
|
||||
AOP_PLUS, AOP_MINUS, AOP_STAR, AOP_DIV, AOP_MOD,
|
||||
/* shift-assign */
|
||||
AOP_LSH, AOP_RSH, AOP_URSH,
|
||||
/* binary */
|
||||
|
@ -66,7 +66,7 @@ enum BinaryOperator {
|
|||
/* shift */
|
||||
BINOP_LSH, BINOP_RSH, BINOP_URSH,
|
||||
/* arithmetic */
|
||||
BINOP_ADD, BINOP_SUB, BINOP_STAR, BINOP_DIV, BINOP_MOD, BINOP_POW,
|
||||
BINOP_ADD, BINOP_SUB, BINOP_STAR, BINOP_DIV, BINOP_MOD,
|
||||
/* binary */
|
||||
BINOP_BITOR, BINOP_BITXOR, BINOP_BITAND,
|
||||
/* misc */
|
||||
|
@ -113,7 +113,6 @@ static const char* const aopNames[] = {
|
|||
"*=", /* AOP_STAR */
|
||||
"/=", /* AOP_DIV */
|
||||
"%=", /* AOP_MOD */
|
||||
"**=", /* AOP_POW */
|
||||
"<<=", /* AOP_LSH */
|
||||
">>=", /* AOP_RSH */
|
||||
">>>=", /* AOP_URSH */
|
||||
|
@ -139,7 +138,6 @@ static const char* const binopNames[] = {
|
|||
"*", /* BINOP_STAR */
|
||||
"/", /* BINOP_DIV */
|
||||
"%", /* BINOP_MOD */
|
||||
"**", /* BINOP_POW */
|
||||
"|", /* BINOP_BITOR */
|
||||
"^", /* BINOP_BITXOR */
|
||||
"&", /* BINOP_BITAND */
|
||||
|
@ -1860,7 +1858,6 @@ class ASTSerializer
|
|||
bool statements(ParseNode* pn, NodeVector& elts);
|
||||
bool expressions(ParseNode* pn, NodeVector& elts);
|
||||
bool leftAssociate(ParseNode* pn, MutableHandleValue dst);
|
||||
bool rightAssociate(ParseNode* pn, MutableHandleValue dst);
|
||||
bool functionArgs(ParseNode* pn, ParseNode* pnargs, ParseNode* pnbody,
|
||||
NodeVector& args, NodeVector& defaults, MutableHandleValue rest);
|
||||
|
||||
|
@ -1977,8 +1974,6 @@ ASTSerializer::aop(JSOp op)
|
|||
return AOP_DIV;
|
||||
case JSOP_MOD:
|
||||
return AOP_MOD;
|
||||
case JSOP_POW:
|
||||
return AOP_POW;
|
||||
case JSOP_LSH:
|
||||
return AOP_LSH;
|
||||
case JSOP_RSH:
|
||||
|
@ -2057,8 +2052,6 @@ ASTSerializer::binop(ParseNodeKind kind, JSOp op)
|
|||
return BINOP_DIV;
|
||||
case PNK_MOD:
|
||||
return BINOP_MOD;
|
||||
case PNK_POW:
|
||||
return BINOP_POW;
|
||||
case PNK_BITOR:
|
||||
return BINOP_BITOR;
|
||||
case PNK_BITXOR:
|
||||
|
@ -2793,49 +2786,6 @@ ASTSerializer::leftAssociate(ParseNode* pn, MutableHandleValue dst)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::rightAssociate(ParseNode* pn, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->pn_count >= 1);
|
||||
|
||||
// First, we need to reverse the list, so that we can traverse it in the right order.
|
||||
// It's OK to destructively reverse the list, because there are no other consumers.
|
||||
|
||||
ParseNode* head = pn->pn_head;
|
||||
ParseNode* prev = nullptr;
|
||||
ParseNode* current = head;
|
||||
ParseNode* next;
|
||||
while (current != nullptr) {
|
||||
next = current->pn_next;
|
||||
current->pn_next = prev;
|
||||
prev = current;
|
||||
current = next;
|
||||
}
|
||||
|
||||
head = prev;
|
||||
|
||||
RootedValue right(cx);
|
||||
if (!expression(head, &right))
|
||||
return false;
|
||||
for (ParseNode* next = head->pn_next; next; next = next->pn_next) {
|
||||
RootedValue left(cx);
|
||||
if (!expression(next, &left))
|
||||
return false;
|
||||
|
||||
TokenPos subpos(pn->pn_pos.begin, next->pn_pos.end);
|
||||
|
||||
BinaryOperator op = binop(pn->getKind(), pn->getOp());
|
||||
LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
|
||||
|
||||
if (!builder.binaryExpression(op, left, right, &subpos, &right))
|
||||
return false;
|
||||
}
|
||||
|
||||
dst.set(right);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ASTSerializer::comprehensionBlock(ParseNode* pn, MutableHandleValue dst)
|
||||
{
|
||||
|
@ -3024,7 +2974,6 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_MULASSIGN:
|
||||
case PNK_DIVASSIGN:
|
||||
case PNK_MODASSIGN:
|
||||
case PNK_POWASSIGN:
|
||||
{
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
|
||||
|
@ -3061,9 +3010,6 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_INSTANCEOF:
|
||||
return leftAssociate(pn, dst);
|
||||
|
||||
case PNK_POW:
|
||||
return rightAssociate(pn, dst);
|
||||
|
||||
case PNK_DELETENAME:
|
||||
case PNK_DELETEPROP:
|
||||
case PNK_DELETESUPERPROP:
|
||||
|
|
|
@ -2039,7 +2039,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
case PNK_MULASSIGN:
|
||||
case PNK_DIVASSIGN:
|
||||
case PNK_MODASSIGN:
|
||||
case PNK_POWASSIGN:
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
*answer = true;
|
||||
return true;
|
||||
|
@ -2092,7 +2091,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
case PNK_STAR:
|
||||
case PNK_DIV:
|
||||
case PNK_MOD:
|
||||
case PNK_POW:
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pn->pn_count >= 2);
|
||||
*answer = true;
|
||||
|
@ -7732,7 +7730,6 @@ BytecodeEmitter::emitTree(ParseNode* pn)
|
|||
case PNK_MULASSIGN:
|
||||
case PNK_DIVASSIGN:
|
||||
case PNK_MODASSIGN:
|
||||
case PNK_POWASSIGN:
|
||||
if (!emitAssignment(pn->pn_left, pn->getOp(), pn->pn_right))
|
||||
return false;
|
||||
break;
|
||||
|
@ -7782,20 +7779,6 @@ BytecodeEmitter::emitTree(ParseNode* pn)
|
|||
break;
|
||||
}
|
||||
|
||||
case PNK_POW: {
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
/* Right-associative operator chain. */
|
||||
for (ParseNode* subexpr = pn->pn_head; subexpr; subexpr = subexpr->pn_next) {
|
||||
if (!emitTree(subexpr))
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < pn->pn_count - 1; i++) {
|
||||
if (!emit1(JSOP_POW))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PNK_TYPEOFNAME:
|
||||
ok = emitTypeof(pn, JSOP_TYPEOF);
|
||||
break;
|
||||
|
|
|
@ -363,7 +363,6 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
case PNK_STAR:
|
||||
case PNK_DIV:
|
||||
case PNK_MOD:
|
||||
case PNK_POW:
|
||||
case PNK_ASSIGN:
|
||||
case PNK_ADDASSIGN:
|
||||
case PNK_SUBASSIGN:
|
||||
|
@ -376,7 +375,6 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
case PNK_MULASSIGN:
|
||||
case PNK_DIVASSIGN:
|
||||
case PNK_MODASSIGN:
|
||||
case PNK_POWASSIGN:
|
||||
case PNK_COMMA:
|
||||
case PNK_ARRAY:
|
||||
case PNK_OBJECT:
|
||||
|
@ -532,10 +530,6 @@ FoldBinaryNumeric(ExclusiveContext* cx, JSOp op, ParseNode* pn1, ParseNode* pn2,
|
|||
}
|
||||
break;
|
||||
|
||||
case JSOP_POW:
|
||||
d = ecmaPow(d, d2);
|
||||
break;
|
||||
|
||||
default:;
|
||||
}
|
||||
|
||||
|
@ -1404,7 +1398,6 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
case PNK_URSH:
|
||||
case PNK_DIV:
|
||||
case PNK_MOD:
|
||||
case PNK_POW:
|
||||
MOZ_ASSERT(pn->getArity() == PN_LIST);
|
||||
MOZ_ASSERT(pn->pn_count >= 2);
|
||||
for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
|
||||
|
@ -1416,12 +1409,6 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
if (!pn2->isKind(PNK_NUMBER))
|
||||
break;
|
||||
}
|
||||
|
||||
// No constant-folding for (2**3**5), because (**) is right-
|
||||
// associative. We would have to reverse the list. It's not worth it.
|
||||
if (pn->getKind() == PNK_POW && pn->pn_count > 2)
|
||||
break;
|
||||
|
||||
if (!pn2) {
|
||||
JSOp op = pn->getOp();
|
||||
|
||||
|
|
|
@ -439,7 +439,6 @@ class NameResolver
|
|||
case PNK_MULASSIGN:
|
||||
case PNK_DIVASSIGN:
|
||||
case PNK_MODASSIGN:
|
||||
case PNK_POWASSIGN:
|
||||
case PNK_ELEM:
|
||||
case PNK_COLON:
|
||||
case PNK_CASE:
|
||||
|
@ -660,7 +659,6 @@ class NameResolver
|
|||
case PNK_STAR:
|
||||
case PNK_DIV:
|
||||
case PNK_MOD:
|
||||
case PNK_POW:
|
||||
case PNK_COMMA:
|
||||
case PNK_NEW:
|
||||
case PNK_CALL:
|
||||
|
|
|
@ -272,7 +272,6 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
case PNK_MULASSIGN:
|
||||
case PNK_DIVASSIGN:
|
||||
case PNK_MODASSIGN:
|
||||
case PNK_POWASSIGN:
|
||||
// ...and a few others.
|
||||
case PNK_ELEM:
|
||||
case PNK_IMPORT_SPEC:
|
||||
|
@ -479,7 +478,6 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
case PNK_STAR:
|
||||
case PNK_DIV:
|
||||
case PNK_MOD:
|
||||
case PNK_POW:
|
||||
case PNK_COMMA:
|
||||
case PNK_NEW:
|
||||
case PNK_CALL:
|
||||
|
@ -613,18 +611,7 @@ ParseNode::appendOrCreateList(ParseNodeKind kind, JSOp op, ParseNode* left, Pars
|
|||
// processing such a tree, exactly implemented that way, would blow the
|
||||
// the stack. We use a list node that uses O(1) stack to represent
|
||||
// such operations: (+ a b c).
|
||||
//
|
||||
// (**) is right-associative; per spec |a ** b ** c| parses as
|
||||
// (** a (** b c)). But we treat this the same way, creating a list
|
||||
// node: (** a b c). All consumers must understand that this must be
|
||||
// processed with a right fold, whereas the list (+ a b c) must be
|
||||
// processed with a left fold because (+) is left-associative.
|
||||
//
|
||||
if (left->isKind(kind) &&
|
||||
left->isOp(op) &&
|
||||
(js_CodeSpec[op].format & JOF_LEFTASSOC ||
|
||||
(kind == PNK_POW && !left->pn_parens)))
|
||||
{
|
||||
if (left->isKind(kind) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC)) {
|
||||
ListNode* list = &left->as<ListNode>();
|
||||
|
||||
list->append(right);
|
||||
|
|
|
@ -197,7 +197,6 @@ class UpvarCookie
|
|||
F(STAR) \
|
||||
F(DIV) \
|
||||
F(MOD) \
|
||||
F(POW) \
|
||||
\
|
||||
/* Assignment operators (= += -= etc.). */ \
|
||||
/* ParseNode::isAssignment assumes all these are consecutive. */ \
|
||||
|
@ -212,8 +211,7 @@ class UpvarCookie
|
|||
F(URSHASSIGN) \
|
||||
F(MULASSIGN) \
|
||||
F(DIVASSIGN) \
|
||||
F(MODASSIGN) \
|
||||
F(POWASSIGN)
|
||||
F(MODASSIGN)
|
||||
|
||||
/*
|
||||
* Parsing builds a tree of nodes that directs code generation. This tree is
|
||||
|
@ -232,9 +230,9 @@ enum ParseNodeKind
|
|||
#undef EMIT_ENUM
|
||||
PNK_LIMIT, /* domain size */
|
||||
PNK_BINOP_FIRST = PNK_OR,
|
||||
PNK_BINOP_LAST = PNK_POW,
|
||||
PNK_BINOP_LAST = PNK_MOD,
|
||||
PNK_ASSIGNMENT_START = PNK_ASSIGN,
|
||||
PNK_ASSIGNMENT_LAST = PNK_POWASSIGN
|
||||
PNK_ASSIGNMENT_LAST = PNK_MODASSIGN
|
||||
};
|
||||
|
||||
inline bool
|
||||
|
@ -371,34 +369,31 @@ IsDeleteKind(ParseNodeKind kind)
|
|||
* PNK_URSHASSIGN,
|
||||
* PNK_MULASSIGN,
|
||||
* PNK_DIVASSIGN,
|
||||
* PNK_MODASSIGN,
|
||||
* PNK_POWASSIGN
|
||||
* PNK_MODASSIGN
|
||||
* PNK_CONDITIONAL ternary (cond ? trueExpr : falseExpr)
|
||||
* pn_kid1: cond, pn_kid2: then, pn_kid3: else
|
||||
* PNK_OR, list pn_head; list of pn_count subexpressions
|
||||
* PNK_AND, All of these operators are left-associative except (**).
|
||||
* PNK_BITOR,
|
||||
* PNK_BITXOR,
|
||||
* PNK_BITAND,
|
||||
* PNK_EQ,
|
||||
* PNK_OR binary pn_left: first in || chain, pn_right: rest of chain
|
||||
* PNK_AND binary pn_left: first in && chain, pn_right: rest of chain
|
||||
* PNK_BITOR binary pn_left: left-assoc | expr, pn_right: ^ expr
|
||||
* PNK_BITXOR binary pn_left: left-assoc ^ expr, pn_right: & expr
|
||||
* PNK_BITAND binary pn_left: left-assoc & expr, pn_right: EQ expr
|
||||
*
|
||||
* PNK_EQ, binary pn_left: left-assoc EQ expr, pn_right: REL expr
|
||||
* PNK_NE,
|
||||
* PNK_STRICTEQ,
|
||||
* PNK_STRICTNE,
|
||||
* PNK_LT,
|
||||
* PNK_STRICTNE
|
||||
* PNK_LT, binary pn_left: left-assoc REL expr, pn_right: SH expr
|
||||
* PNK_LE,
|
||||
* PNK_GT,
|
||||
* PNK_GE,
|
||||
* PNK_LSH,
|
||||
* PNK_GE
|
||||
* PNK_LSH, binary pn_left: left-assoc SH expr, pn_right: ADD expr
|
||||
* PNK_RSH,
|
||||
* PNK_URSH,
|
||||
* PNK_ADD,
|
||||
* PNK_SUB,
|
||||
* PNK_STAR,
|
||||
* PNK_DIV,
|
||||
* PNK_MOD,
|
||||
* PNK_POW (**) is right-associative, but forms a list
|
||||
* nonetheless. Special hacks everywhere.
|
||||
*
|
||||
* PNK_URSH
|
||||
* PNK_ADD, binary pn_left: left-assoc ADD expr, pn_right: MUL expr
|
||||
* PNK_SUB
|
||||
* PNK_STAR, binary pn_left: left-assoc MUL expr, pn_right: UNARY expr
|
||||
* PNK_DIV, pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
|
||||
* PNK_MOD
|
||||
* PNK_POS, unary pn_kid: UNARY expr
|
||||
* PNK_NEG
|
||||
* PNK_VOID, unary pn_kid: UNARY expr
|
||||
|
|
|
@ -6351,8 +6351,7 @@ static const JSOp ParseNodeKindToJSOp[] = {
|
|||
JSOP_SUB,
|
||||
JSOP_MUL,
|
||||
JSOP_DIV,
|
||||
JSOP_MOD,
|
||||
JSOP_POW
|
||||
JSOP_MOD
|
||||
};
|
||||
|
||||
static inline JSOp
|
||||
|
@ -6393,11 +6392,10 @@ static const int PrecedenceTable[] = {
|
|||
9, /* PNK_SUB */
|
||||
10, /* PNK_STAR */
|
||||
10, /* PNK_DIV */
|
||||
10, /* PNK_MOD */
|
||||
11 /* PNK_POW */
|
||||
10 /* PNK_MOD */
|
||||
};
|
||||
|
||||
static const int PRECEDENCE_CLASSES = 11;
|
||||
static const int PRECEDENCE_CLASSES = 10;
|
||||
|
||||
static int
|
||||
Precedence(ParseNodeKind pnk) {
|
||||
|
@ -6417,8 +6415,8 @@ MOZ_ALWAYS_INLINE typename ParseHandler::Node
|
|||
Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling,
|
||||
InvokedPrediction invoked)
|
||||
{
|
||||
// Shift-reduce parser for the binary operator part of the JS expression
|
||||
// syntax.
|
||||
// Shift-reduce parser for the left-associative binary operator part of
|
||||
// the JS syntax.
|
||||
|
||||
// Conceptually there's just one stack, a stack of pairs (lhs, op).
|
||||
// It's implemented using two separate arrays, though.
|
||||
|
@ -6450,9 +6448,10 @@ Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling
|
|||
// stack, reduce. This combines nodes on the stack until we form the
|
||||
// actual lhs of pnk.
|
||||
//
|
||||
// The >= in this condition works because it is appendOrCreateList's
|
||||
// job to decide if the operator in question is left- or
|
||||
// right-associative, and build the corresponding tree.
|
||||
// The >= in this condition works because all the operators in question
|
||||
// are left-associative; if any were not, the case where two operators
|
||||
// have equal precedence would need to be handled specially, and the
|
||||
// stack would need to be a Vector.
|
||||
while (depth > 0 && Precedence(kindStack[depth - 1]) >= Precedence(pnk)) {
|
||||
depth--;
|
||||
ParseNodeKind combiningPnk = kindStack[depth];
|
||||
|
@ -6614,7 +6613,6 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
|
|||
case TOK_MULASSIGN: kind = PNK_MULASSIGN; op = JSOP_MUL; break;
|
||||
case TOK_DIVASSIGN: kind = PNK_DIVASSIGN; op = JSOP_DIV; break;
|
||||
case TOK_MODASSIGN: kind = PNK_MODASSIGN; op = JSOP_MOD; break;
|
||||
case TOK_POWASSIGN: kind = PNK_POWASSIGN; op = JSOP_POW; break;
|
||||
|
||||
case TOK_ARROW: {
|
||||
// A line terminator between ArrowParameters and the => should trigger a SyntaxError.
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
* range-testing. \
|
||||
*/ \
|
||||
/* \
|
||||
* Binary operators tokens, TOK_OR thru TOK_POW. These must be in the same \
|
||||
* Binary operators tokens, TOK_OR thru TOK_MOD. These must be in the same \
|
||||
* order as F(OR) and friends in FOR_EACH_PARSE_NODE_KIND in ParseNode.h. \
|
||||
*/ \
|
||||
macro(OR, "'||'") /* logical or */ \
|
||||
|
@ -163,8 +163,7 @@
|
|||
macro(MUL, "'*'") \
|
||||
macro(DIV, "'/'") \
|
||||
macro(MOD, "'%'") \
|
||||
macro(POW, "'**'") \
|
||||
range(BINOP_LAST, POW) \
|
||||
range(BINOP_LAST, MOD) \
|
||||
\
|
||||
/* Unary operation tokens. */ \
|
||||
macro(TYPEOF, "keyword 'typeof'") \
|
||||
|
@ -188,8 +187,7 @@
|
|||
macro(MULASSIGN, "'*='") \
|
||||
macro(DIVASSIGN, "'/='") \
|
||||
macro(MODASSIGN, "'%='") \
|
||||
macro(POWASSIGN, "'**='") \
|
||||
range(ASSIGNMENT_LAST, POWASSIGN)
|
||||
range(ASSIGNMENT_LAST, MODASSIGN)
|
||||
|
||||
#define TOKEN_KIND_RANGE_EMIT_NONE(name, value)
|
||||
#define FOR_EACH_TOKEN_KIND(macro) \
|
||||
|
|
|
@ -1509,10 +1509,7 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
goto out;
|
||||
|
||||
case '*':
|
||||
if (matchChar('*'))
|
||||
tp->type = matchChar('=') ? TOK_POWASSIGN : TOK_POW;
|
||||
else
|
||||
tp->type = matchChar('=') ? TOK_MULASSIGN : TOK_MUL;
|
||||
tp->type = matchChar('=') ? TOK_MULASSIGN : TOK_MUL;
|
||||
goto out;
|
||||
|
||||
case '/':
|
||||
|
|
|
@ -1598,12 +1598,6 @@ BaselineCompiler::emit_JSOP_MOD()
|
|||
return emitBinaryArith();
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_POW()
|
||||
{
|
||||
return emitBinaryArith();
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emitBinaryArith()
|
||||
{
|
||||
|
|
|
@ -80,7 +80,6 @@ namespace jit {
|
|||
_(JSOP_MUL) \
|
||||
_(JSOP_DIV) \
|
||||
_(JSOP_MOD) \
|
||||
_(JSOP_POW) \
|
||||
_(JSOP_LT) \
|
||||
_(JSOP_LE) \
|
||||
_(JSOP_GT) \
|
||||
|
|
|
@ -1905,10 +1905,6 @@ DoBinaryArithFallback(JSContext* cx, BaselineFrame* frame, ICBinaryArith_Fallbac
|
|||
if (!ModValues(cx, &lhsCopy, &rhsCopy, ret))
|
||||
return false;
|
||||
break;
|
||||
case JSOP_POW:
|
||||
if (!math_pow_handle(cx, lhsCopy, rhsCopy, ret))
|
||||
return false;
|
||||
break;
|
||||
case JSOP_BITOR: {
|
||||
int32_t result;
|
||||
if (!BitOr(cx, lhs, rhs, &result))
|
||||
|
@ -2042,7 +2038,7 @@ DoBinaryArithFallback(JSContext* cx, BaselineFrame* frame, ICBinaryArith_Fallbac
|
|||
}
|
||||
}
|
||||
|
||||
if (lhs.isInt32() && rhs.isInt32() && op != JSOP_POW) {
|
||||
if (lhs.isInt32() && rhs.isInt32()) {
|
||||
bool allowDouble = ret.isDouble();
|
||||
if (allowDouble)
|
||||
stub->unlinkStubsWithKind(cx, ICStub::BinaryArith_Int32);
|
||||
|
@ -10028,7 +10024,7 @@ ICCallStubCompiler::pushSpreadCallArguments(MacroAssembler& masm,
|
|||
masm.unboxObject(Address(masm.getStackPointer(),
|
||||
(isConstructing * sizeof(Value)) + STUB_FRAME_SIZE), startReg);
|
||||
masm.loadPtr(Address(startReg, NativeObject::offsetOfElements()), startReg);
|
||||
|
||||
|
||||
// Align the stack such that the JitFrameLayout is aligned on the
|
||||
// JitStackAlignment.
|
||||
if (isJitCall) {
|
||||
|
@ -10278,18 +10274,18 @@ ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
|
|||
// Use BaselineFrameReg instead of BaselineStackReg, because
|
||||
// BaselineFrameReg and BaselineStackReg hold the same value just after
|
||||
// calling enterStubFrame.
|
||||
|
||||
|
||||
// newTarget
|
||||
if (isConstructing_)
|
||||
masm.pushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE));
|
||||
|
||||
|
||||
// array
|
||||
uint32_t valueOffset = isConstructing_;
|
||||
masm.pushValue(Address(BaselineFrameReg, valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
|
||||
|
||||
|
||||
// this
|
||||
masm.pushValue(Address(BaselineFrameReg, valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
|
||||
|
||||
|
||||
// callee
|
||||
masm.pushValue(Address(BaselineFrameReg, valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
|
||||
|
||||
|
|
|
@ -1657,9 +1657,6 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
case JSOP_MOD:
|
||||
return jsop_binary(op);
|
||||
|
||||
case JSOP_POW:
|
||||
return jsop_pow();
|
||||
|
||||
case JSOP_POS:
|
||||
return jsop_pos();
|
||||
|
||||
|
@ -4600,25 +4597,6 @@ IonBuilder::jsop_binary(JSOp op, MDefinition* left, MDefinition* right)
|
|||
return maybeInsertResume();
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_pow()
|
||||
{
|
||||
MDefinition* exponent = current->pop();
|
||||
MDefinition* base = current->pop();
|
||||
|
||||
if (inlineMathPowHelper(base, exponent, MIRType_Double) == InliningStatus_Inlined) {
|
||||
base->setImplicitlyUsedUnchecked();
|
||||
exponent->setImplicitlyUsedUnchecked();
|
||||
return true;
|
||||
}
|
||||
|
||||
// For now, use MIRType_Double, as a safe cover-all. See bug 1188079.
|
||||
MPow* pow = MPow::New(alloc(), base, exponent, MIRType_Double);
|
||||
current->add(pow);
|
||||
current->push(pow);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_binary(JSOp op)
|
||||
{
|
||||
|
|
|
@ -624,7 +624,6 @@ class IonBuilder
|
|||
bool jsop_bitop(JSOp op);
|
||||
bool jsop_binary(JSOp op);
|
||||
bool jsop_binary(JSOp op, MDefinition* left, MDefinition* right);
|
||||
bool jsop_pow();
|
||||
bool jsop_pos();
|
||||
bool jsop_neg();
|
||||
bool jsop_setarg(uint32_t arg);
|
||||
|
@ -757,7 +756,6 @@ class IonBuilder
|
|||
InliningStatus inlineMathHypot(CallInfo& callInfo);
|
||||
InliningStatus inlineMathMinMax(CallInfo& callInfo, bool max);
|
||||
InliningStatus inlineMathPow(CallInfo& callInfo);
|
||||
InliningStatus inlineMathPowHelper(MDefinition* lhs, MDefinition* rhs, MIRType outputType);
|
||||
InliningStatus inlineMathRandom(CallInfo& callInfo);
|
||||
InliningStatus inlineMathImul(CallInfo& callInfo);
|
||||
InliningStatus inlineMathFRound(CallInfo& callInfo);
|
||||
|
|
|
@ -1347,11 +1347,17 @@ IonBuilder::inlineMathHypot(CallInfo& callInfo)
|
|||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineMathPowHelper(MDefinition* lhs, MDefinition* rhs, MIRType outputType)
|
||||
IonBuilder::inlineMathPow(CallInfo& callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 2 || callInfo.constructing()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
// Typechecking.
|
||||
MIRType baseType = lhs->type();
|
||||
MIRType powerType = rhs->type();
|
||||
MIRType baseType = callInfo.getArg(0)->type();
|
||||
MIRType powerType = callInfo.getArg(1)->type();
|
||||
MIRType outputType = getInlineReturnType();
|
||||
|
||||
if (outputType != MIRType_Int32 && outputType != MIRType_Double)
|
||||
return InliningStatus_NotInlined;
|
||||
|
@ -1360,13 +1366,17 @@ IonBuilder::inlineMathPowHelper(MDefinition* lhs, MDefinition* rhs, MIRType outp
|
|||
if (!IsNumberType(powerType))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* base = lhs;
|
||||
MDefinition* power = rhs;
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MDefinition* base = callInfo.getArg(0);
|
||||
MDefinition* power = callInfo.getArg(1);
|
||||
MDefinition* output = nullptr;
|
||||
|
||||
// Optimize some constant powers.
|
||||
if (rhs->isConstantValue() && rhs->constantValue().isNumber()) {
|
||||
double pow = rhs->constantValue().toNumber();
|
||||
if (callInfo.getArg(1)->isConstantValue() &&
|
||||
callInfo.getArg(1)->constantValue().isNumber())
|
||||
{
|
||||
double pow = callInfo.getArg(1)->constantValue().toNumber();
|
||||
|
||||
// Math.pow(x, 0.5) is a sqrt with edge-case detection.
|
||||
if (pow == 0.5) {
|
||||
|
@ -1441,23 +1451,6 @@ IonBuilder::inlineMathPowHelper(MDefinition* lhs, MDefinition* rhs, MIRType outp
|
|||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineMathPow(CallInfo& callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 2 || callInfo.constructing()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus status =
|
||||
inlineMathPowHelper(callInfo.getArg(0), callInfo.getArg(1), getInlineReturnType());
|
||||
|
||||
if (status == IonBuilder::InliningStatus_Inlined)
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineMathRandom(CallInfo& callInfo)
|
||||
{
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var BUGNUMBER = 1135708;
|
||||
var summary = "Implement the exponentiation operator";
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
// Constant folding
|
||||
assertEq(2 ** 2 ** 3, 256);
|
||||
assertEq(1 ** 1 ** 4, 1);
|
||||
|
||||
// No folding
|
||||
var two = 2;
|
||||
var three = 3;
|
||||
var four = 4;
|
||||
assertEq(two ** two ** three, 256);
|
||||
assertEq(1 ** 1 ** four, 1);
|
||||
|
||||
// Operator precedence
|
||||
assertEq(2 ** 3 / 2 ** 3, 1);
|
||||
assertEq(2 ** 3 * 2 ** 3, 64);
|
||||
assertEq(2 ** 3 + 2 ** 3, 16);
|
||||
|
||||
// With parentheses
|
||||
assertEq((2 ** 3) ** 2, 64);
|
||||
assertEq(2 ** (3 ** 2), 512);
|
||||
|
||||
// Assignment operator
|
||||
var x = 2;
|
||||
assertEq(x **= 2 ** 3, 256);
|
||||
assertEq(x, 256);
|
||||
|
||||
// Loop to test baseline and ION
|
||||
for (var i=0; i<10000; i++) {
|
||||
assertEq((2 ** 3) ** 2, 64);
|
||||
assertEq(2 ** (3 ** 2), 512);
|
||||
var x = 2;
|
||||
assertEq(x **= 2 ** 3, 256);
|
||||
assertEq(x, 256);
|
||||
}
|
||||
|
||||
// Comments should not be confused with exp operator
|
||||
var a, c, e;
|
||||
a = c = e = 2;
|
||||
assertEq(a**/**b**/c/**/**/**d**/e, 16);
|
||||
|
||||
// Two stars separated should not parse as exp operator
|
||||
assertThrows(function() { return Reflect.parse("2 * * 3"); }, SyntaxError);
|
||||
|
||||
// Check if error propagation works
|
||||
var thrower = {
|
||||
get value() {
|
||||
throw new Error();
|
||||
}
|
||||
};
|
||||
|
||||
assertThrowsInstanceOf(function() { return thrower.value ** 2; }, Error);
|
||||
assertThrowsInstanceOf(function() { return 2 ** thrower.value; }, Error);
|
||||
assertThrowsInstanceOf(function() { return 2 ** thrower.value ** 2; }, Error);
|
||||
|
||||
var convertibleToPrimitive = {
|
||||
valueOf: function() {
|
||||
throw new Error("oops");
|
||||
}
|
||||
};
|
||||
|
||||
assertThrowsInstanceOf(function() { return convertibleToPrimitive ** 3; }, Error);
|
||||
assertThrowsInstanceOf(function() { return 3 ** convertibleToPrimitive; }, Error);
|
||||
|
||||
assertEq(NaN ** 2, NaN);
|
||||
assertEq(2 ** NaN, NaN);
|
||||
assertEq(2 ** "3", 8);
|
||||
assertEq("2" ** 3, 8);
|
||||
|
||||
// Reflect.parse generates a correct parse tree for simplest case
|
||||
var parseTree = Reflect.parse("a ** b");
|
||||
assertEq(parseTree.body[0].type, "ExpressionStatement");
|
||||
assertEq(parseTree.body[0].expression.operator, "**");
|
||||
assertEq(parseTree.body[0].expression.left.name, "a");
|
||||
assertEq(parseTree.body[0].expression.right.name, "b");
|
||||
|
||||
// Reflect.parse generates a tree following the right-associativity rule
|
||||
var parseTree = Reflect.parse("a ** b ** c");
|
||||
assertEq(parseTree.body[0].type, "ExpressionStatement");
|
||||
assertEq(parseTree.body[0].expression.left.name, "a");
|
||||
assertEq(parseTree.body[0].expression.right.operator, "**");
|
||||
assertEq(parseTree.body[0].expression.right.left.name, "b");
|
||||
assertEq(parseTree.body[0].expression.right.right.name, "c");
|
||||
|
||||
|
||||
function assertTrue(v) {
|
||||
assertEq(v, true);
|
||||
}
|
||||
|
||||
function assertFalse(v) {
|
||||
assertEq(v, false);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -2052,6 +2052,7 @@ CASE(EnableInterruptsPseudoOpcode)
|
|||
CASE(JSOP_NOP)
|
||||
CASE(JSOP_UNUSED2)
|
||||
CASE(JSOP_BACKPATCH)
|
||||
CASE(JSOP_UNUSED150)
|
||||
CASE(JSOP_UNUSED161)
|
||||
CASE(JSOP_UNUSED162)
|
||||
CASE(JSOP_UNUSED163)
|
||||
|
@ -2654,17 +2655,6 @@ CASE(JSOP_MOD)
|
|||
}
|
||||
END_CASE(JSOP_MOD)
|
||||
|
||||
CASE(JSOP_POW)
|
||||
{
|
||||
ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
|
||||
ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
|
||||
MutableHandleValue res = REGS.stackHandleAt(-2);
|
||||
if (!math_pow_handle(cx, lval, rval, res))
|
||||
goto error;
|
||||
REGS.sp--;
|
||||
}
|
||||
END_CASE(JSOP_POW)
|
||||
|
||||
CASE(JSOP_NOT)
|
||||
{
|
||||
bool cond = ToBoolean(REGS.stackHandleAt(-1));
|
||||
|
|
|
@ -1533,15 +1533,7 @@
|
|||
* Stack: =>
|
||||
*/ \
|
||||
macro(JSOP_BACKPATCH, 149,"backpatch", NULL, 5, 0, 0, JOF_JUMP) \
|
||||
/*
|
||||
* Pops the top two values 'lval' and 'rval' from the stack, then pushes
|
||||
* the result of 'Math.pow(lval, rval)'.
|
||||
* Category: Operators
|
||||
* Type: Arithmetic Operators
|
||||
* Operands:
|
||||
* Stack: lval, rval => (lval ** rval)
|
||||
*/ \
|
||||
macro(JSOP_POW, 150, "pow", "**", 1, 2, 1, JOF_BYTE|JOF_ARITH) \
|
||||
macro(JSOP_UNUSED150, 150,"unused150", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
\
|
||||
/*
|
||||
* Pops the top of stack value as 'v', sets pending exception as 'v',
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace js {
|
|||
*
|
||||
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 299;
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 298;
|
||||
static const uint32_t XDR_BYTECODE_VERSION =
|
||||
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче