Backed out changeset e01d0f7a3c6f (bug 1135708) for spidermonkey errors CLOSED TREE

This commit is contained in:
Wes Kocher 2015-07-27 15:22:40 -07:00
Родитель f29d04329b
Коммит 9c5c217c21
19 изменённых файлов: 63 добавлений и 337 удалений

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

@ -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);