Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (203498 => 203499)
--- trunk/Source/_javascript_Core/ChangeLog 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-07-21 07:33:28 UTC (rev 203499)
@@ -1,3 +1,228 @@
+2016-07-20 Yusuke Suzuki <[email protected]>
+
+ [ES7] Introduce exponentiation _expression_
+ https://bugs.webkit.org/show_bug.cgi?id=159969
+
+ Reviewed by Saam Barati.
+
+ This patch implements the exponentiation _expression_, e.g. `x ** y`.
+ The exponentiation _expression_ is introduced in ECMA262 2016 and ECMA262 2016
+ is already released. So this is not the draft spec.
+
+ The exponentiation _expression_ has 2 interesting points.
+
+ 1. Right associative
+
+ To follow the Math _expression_, ** operator is right associative.
+ When we execute `x ** y ** z`, this is handled as `x ** (y ** z)`, not `(x ** y) ** z`.
+ This patch introduces the right associativity to the binary operator and handles it
+ in the operator precedence parser in Parser.cpp.
+
+ 2. LHS of the exponentiation _expression_ is UpdateExpression
+
+ ExponentiationExpression[Yield]:
+ UnaryExpression[?Yield]
+ UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
+
+ As we can see, the left hand side of the ExponentiationExpression is UpdateExpression, not UnaryExpression.
+ It means that `+x ** y` becomes a syntax error. This is intentional. Without superscript in JS,
+ `-x**y` is confusing between `-(x ** y)` and `(-x) ** y`. So ECMA262 intentionally avoids UnaryExpression here.
+ If we need to use a negated value, we need to write parentheses explicitly e.g. `(-x) ** y`.
+ In this patch, we ensure that the left hand side is not an unary _expression_ by checking an operator in
+ parseBinaryExpression. This works since `**` has the highest operator precedence in the binary operators.
+
+ We introduce a new bytecode, op_pow. That simply works as similar as the other binary operators.
+ And it is converted to ArithPow in DFG and handled in DFG and FTL.
+ In this patch, we take the approach just introducing a new bytecode instead of calling Math.pow.
+ This is because we would like to execute ToNumber in the caller side, not in the callee (Math.pow) side.
+ And we don't want to compile ** into the following.
+
+ lhsNumber = to_number (lhs)
+ rhsNumber = to_number (rhs)
+ call Math.pow(lhsNumber, rhsNumber)
+
+ We ensure that this patch passes all the test262 tests related to the exponentiation _expression_.
+
+ The only sensitive part to the performance is the parser changes.
+ So we measured the code-load performance and it is neutral in my x64 Linux box (hanayamata).
+
+ Collected 30 samples per benchmark/VM, with 30 VM invocations per benchmark. Emitted a call to
+ gc() between sample measurements. Used 1 benchmark iteration per VM invocation for warm-up. Used
+ the jsc-specific preciseTime() function to get microsecond-level timing. Reporting benchmark
+ execution times with 95% confidence intervals in milliseconds.
+
+ baseline patched
+
+ closure 0.60499+-0.00250 0.60180+-0.00244
+ jquery 7.89175+-0.02433 ? 7.91287+-0.04759 ?
+
+ <geometric> 2.18499+-0.00523 2.18207+-0.00689 might be 1.0013x faster
+
+ * bytecode/BytecodeList.json:
+ * bytecode/BytecodeUseDef.h:
+ (JSC::computeUsesForBytecodeOffset):
+ (JSC::computeDefsForBytecodeOffset):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dumpBytecode):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::emitReadModifyAssignment):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ * jit/JITArithmetic.cpp:
+ (JSC::JIT::emit_op_pow):
+ * llint/LowLevelInterpreter.asm:
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::operatorStackShouldReduce):
+ (JSC::ASTBuilder::makePowNode):
+ (JSC::ASTBuilder::makeMultNode):
+ (JSC::ASTBuilder::makeDivNode):
+ (JSC::ASTBuilder::makeModNode):
+ (JSC::ASTBuilder::makeSubNode):
+ (JSC::ASTBuilder::makeBinaryNode):
+ (JSC::ASTBuilder::operatorStackHasHigherPrecedence): Deleted.
+ * parser/Lexer.cpp:
+ (JSC::Lexer<T>::lex):
+ * parser/NodeConstructors.h:
+ (JSC::PowNode::PowNode):
+ * parser/Nodes.h:
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseAssignmentExpression):
+ (JSC::isUnaryOpExcludingUpdateOp):
+ (JSC::Parser<LexerType>::parseBinaryExpression):
+ (JSC::isUnaryOp): Deleted.
+ * parser/ParserTokens.h:
+ (JSC::isUpdateOp):
+ (JSC::isUnaryOp):
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::operatorStackPop):
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::SLOW_PATH_DECL):
+ * runtime/CommonSlowPaths.h:
+ * tests/stress/pow-basics.js: Added.
+ (valuesAreClose):
+ (mathPowDoubleDouble1):
+ (mathPowDoubleInt1):
+ (test1):
+ (mathPowDoubleDouble2):
+ (mathPowDoubleInt2):
+ (test2):
+ (mathPowDoubleDouble3):
+ (mathPowDoubleInt3):
+ (test3):
+ (mathPowDoubleDouble4):
+ (mathPowDoubleInt4):
+ (test4):
+ (mathPowDoubleDouble5):
+ (mathPowDoubleInt5):
+ (test5):
+ (mathPowDoubleDouble6):
+ (mathPowDoubleInt6):
+ (test6):
+ (mathPowDoubleDouble7):
+ (mathPowDoubleInt7):
+ (test7):
+ (mathPowDoubleDouble8):
+ (mathPowDoubleInt8):
+ (test8):
+ (mathPowDoubleDouble9):
+ (mathPowDoubleInt9):
+ (test9):
+ (mathPowDoubleDouble10):
+ (mathPowDoubleInt10):
+ (test10):
+ (mathPowDoubleDouble11):
+ (mathPowDoubleInt11):
+ (test11):
+ * tests/stress/pow-coherency.js: Added.
+ (pow42):
+ (build42AsDouble.opaqueAdd):
+ (build42AsDouble):
+ (powDouble42):
+ (clobber):
+ (pow42NoConstantFolding):
+ (powDouble42NoConstantFolding):
+ * tests/stress/pow-evaluation-order.js: Added.
+ (shouldBe):
+ (throw.new.Error):
+ * tests/stress/pow-expects-update-_expression_-on-lhs.js: Added.
+ (testSyntax):
+ (testSyntaxError):
+ (throw.new.Error):
+ (let.token.of.tokens.testSyntax.pow):
+ (testSyntax.pow):
+ * tests/stress/pow-integer-exponent-fastpath.js: Added.
+ (valuesAreClose):
+ (mathPowDoubleDoubleTestExponentFifty):
+ (mathPowDoubleIntTestExponentFifty):
+ (testExponentFifty):
+ (mathPowDoubleDoubleTestExponentTenThousands):
+ (mathPowDoubleIntTestExponentTenThousands):
+ (testExponentTenThousands):
+ * tests/stress/pow-nan-behaviors.js: Added.
+ (testIntegerBaseWithNaNExponentStatic):
+ (mathPowIntegerBaseWithNaNExponentDynamic):
+ (testIntegerBaseWithNaNExponentDynamic):
+ (testFloatingPointBaseWithNaNExponentStatic):
+ (mathPowFloatingPointBaseWithNaNExponentDynamic):
+ (testFloatingPointBaseWithNaNExponentDynamic):
+ (testNaNBaseStatic):
+ (mathPowNaNBaseDynamic1):
+ (mathPowNaNBaseDynamic2):
+ (mathPowNaNBaseDynamic3):
+ (mathPowNaNBaseDynamic4):
+ (testNaNBaseDynamic):
+ (infiniteExponentsStatic):
+ (mathPowInfiniteExponentsDynamic1):
+ (mathPowInfiniteExponentsDynamic2):
+ (mathPowInfiniteExponentsDynamic3):
+ (mathPowInfiniteExponentsDynamic4):
+ (infiniteExponentsDynamic):
+ * tests/stress/pow-simple.js: Added.
+ (shouldBe):
+ (throw.new.Error):
+ * tests/stress/pow-stable-results.js: Added.
+ (opaquePow):
+ (isIdentical):
+ * tests/stress/pow-to-number-should-be-executed-in-code-side.js: Added.
+ (shouldBe):
+ (throw.new.Error):
+ * tests/stress/pow-with-constants.js: Added.
+ (exponentIsZero):
+ (testExponentIsZero):
+ (exponentIsOne):
+ (testExponentIsOne):
+ (powUsedAsSqrt):
+ (testPowUsedAsSqrt):
+ (powUsedAsOneOverSqrt):
+ (testPowUsedAsOneOverSqrt):
+ (powUsedAsSquare):
+ (testPowUsedAsSquare):
+ (intIntConstantsSmallNumbers):
+ (intIntConstantsLargeNumbers):
+ (intIntSmallConstants):
+ (intDoubleConstants):
+ (doubleDoubleConstants):
+ (doubleIntConstants):
+ (testBaseAndExponentConstantLiterals):
+ (exponentIsIntegerConstant):
+ (testExponentIsIntegerConstant):
+ (exponentIsDoubleConstant):
+ (testExponentIsDoubleConstant):
+ (exponentIsInfinityConstant):
+ (testExponentIsInfinityConstant):
+ (exponentIsNegativeInfinityConstant):
+ (testExponentIsNegativeInfinityConstant):
+ * tests/stress/pow-with-never-NaN-exponent.js: Added.
+ (exponentIsNonNanDouble1):
+ (exponentIsNonNanDouble2):
+ (testExponentIsDoubleConstant):
+ * tests/test262.yaml:
+
2016-07-18 Filip Pizlo <[email protected]>
Switching on symbols should be fast
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (203498 => 203499)
--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2016-07-21 07:33:28 UTC (rev 203499)
@@ -39,6 +39,7 @@
{ "name" : "op_div", "length" : 5 },
{ "name" : "op_mod", "length" : 4 },
{ "name" : "op_sub", "length" : 5 },
+ { "name" : "op_pow", "length" : 4 },
{ "name" : "op_lshift", "length" : 4 },
{ "name" : "op_rshift", "length" : 4 },
{ "name" : "op_urshift", "length" : 4 },
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (203498 => 203499)
--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2016-07-21 07:33:28 UTC (rev 203499)
@@ -208,6 +208,7 @@
case op_div:
case op_mod:
case op_sub:
+ case op_pow:
case op_lshift:
case op_rshift:
case op_urshift:
@@ -431,6 +432,7 @@
case op_div:
case op_mod:
case op_sub:
+ case op_pow:
case op_lshift:
case op_rshift:
case op_urshift:
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (203498 => 203499)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2016-07-21 07:33:28 UTC (rev 203499)
@@ -1024,6 +1024,10 @@
printBinaryOp(out, exec, location, it, "mod");
break;
}
+ case op_pow: {
+ printBinaryOp(out, exec, location, it, "pow");
+ break;
+ }
case op_sub: {
printBinaryOp(out, exec, location, it, "sub");
++it;
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (203498 => 203499)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2016-07-21 07:33:28 UTC (rev 203499)
@@ -1993,6 +1993,9 @@
case OpModEq:
opcodeID = op_mod;
break;
+ case OpPowEq:
+ opcodeID = op_pow;
+ break;
default:
RELEASE_ASSERT_NOT_REACHED();
return dst;
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (203498 => 203499)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-07-21 07:33:28 UTC (rev 203499)
@@ -3819,6 +3819,15 @@
NEXT_OPCODE(op_mod);
}
+ case op_pow: {
+ // FIXME: ArithPow(Untyped, Untyped) should be supported as the same to ArithMul, ArithSub etc.
+ // https://bugs.webkit.org/show_bug.cgi?id=160012
+ Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+ Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
+ set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ArithPow, op1, op2));
+ NEXT_OPCODE(op_pow);
+ }
+
case op_div: {
Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (203498 => 203499)
--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2016-07-21 07:33:28 UTC (rev 203499)
@@ -123,6 +123,7 @@
case op_negate:
case op_mul:
case op_mod:
+ case op_pow:
case op_div:
case op_debug:
case op_profile_type:
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (203498 => 203499)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2016-07-21 07:33:28 UTC (rev 203499)
@@ -300,6 +300,7 @@
DEFINE_OP(op_nstricteq)
DEFINE_OP(op_dec)
DEFINE_OP(op_inc)
+ DEFINE_OP(op_pow)
DEFINE_OP(op_profile_type)
DEFINE_OP(op_profile_control_flow)
DEFINE_OP(op_push_with_scope)
Modified: trunk/Source/_javascript_Core/jit/JIT.h (203498 => 203499)
--- trunk/Source/_javascript_Core/jit/JIT.h 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2016-07-21 07:33:28 UTC (rev 203499)
@@ -566,6 +566,7 @@
void emit_op_nstricteq(Instruction*);
void emit_op_dec(Instruction*);
void emit_op_inc(Instruction*);
+ void emit_op_pow(Instruction*);
void emit_op_profile_type(Instruction*);
void emit_op_profile_control_flow(Instruction*);
void emit_op_push_with_scope(Instruction*);
Modified: trunk/Source/_javascript_Core/jit/JITArithmetic.cpp (203498 => 203499)
--- trunk/Source/_javascript_Core/jit/JITArithmetic.cpp 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/jit/JITArithmetic.cpp 2016-07-21 07:33:28 UTC (rev 203499)
@@ -1032,8 +1032,14 @@
}
}
-/* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
+void JIT::emit_op_pow(Instruction* currentInstruction)
+{
+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_pow);
+ slowPathCall.call();
+}
+/* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL, OP_POW ------------------------------ */
+
} // namespace JSC
#endif // ENABLE(JIT)
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (203498 => 203499)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-07-21 07:33:28 UTC (rev 203499)
@@ -1320,6 +1320,12 @@
dispatch(4)
+_llint_op_pow:
+ traceExecution()
+ callOpcodeSlowPath(_slow_path_pow)
+ dispatch(4)
+
+
_llint_op_typeof:
traceExecution()
callOpcodeSlowPath(_slow_path_typeof)
Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (203498 => 203499)
--- trunk/Source/_javascript_Core/parser/ASTBuilder.h 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h 2016-07-21 07:33:28 UTC (rev 203499)
@@ -28,6 +28,7 @@
#include "BuiltinNames.h"
#include "BytecodeIntrinsicRegistry.h"
+#include "MathCommon.h"
#include "NodeConstructors.h"
#include "SyntaxChecker.h"
#include "VariableEnvironment.h"
@@ -143,6 +144,7 @@
ExpressionNode* makeDeleteNode(const JSTokenLocation&, ExpressionNode*, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end);
ExpressionNode* makeNegateNode(const JSTokenLocation&, ExpressionNode*);
ExpressionNode* makeBitwiseNotNode(const JSTokenLocation&, ExpressionNode*);
+ ExpressionNode* makePowNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
ExpressionNode* makeMultNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
ExpressionNode* makeDivNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
ExpressionNode* makeModNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
@@ -784,9 +786,14 @@
operatorStackDepth--;
m_binaryOperatorStack.removeLast();
}
- bool operatorStackHasHigherPrecedence(int&, int precedence)
+ bool operatorStackShouldReduce(int precedence)
{
- return precedence <= m_binaryOperatorStack.last().second;
+ // If the current precedence of the operator stack is the same to the one of the given operator,
+ // it depends on the associative whether we reduce the stack.
+ // If the operator is right associative, we should not reduce the stack right now.
+ if (precedence == m_binaryOperatorStack.last().second)
+ return !(m_binaryOperatorStack.last().first & RightAssociativeBinaryOpTokenFlag);
+ return precedence < m_binaryOperatorStack.last().second;
}
const BinaryOperand& getFromOperandStack(int i) { return m_binaryOperandStack[m_binaryOperandStack.size() + i]; }
void shrinkOperandStackBy(int& operandStackDepth, int amount)
@@ -1044,8 +1051,29 @@
return new (m_parserArena) BitwiseNotNode(location, expr);
}
+ExpressionNode* ASTBuilder::makePowNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ auto* strippedExpr1 = expr1->stripUnaryPlus();
+ auto* strippedExpr2 = expr2->stripUnaryPlus();
+
+ if (strippedExpr1->isNumber() && strippedExpr2->isNumber()) {
+ const NumberNode& numberExpr1 = static_cast<NumberNode&>(*strippedExpr1);
+ const NumberNode& numberExpr2 = static_cast<NumberNode&>(*strippedExpr2);
+ return createNumberFromBinaryOperation(location, operationMathPow(numberExpr1.value(), numberExpr2.value()), numberExpr1, numberExpr2);
+ }
+
+ if (strippedExpr1->isNumber())
+ expr1 = strippedExpr1;
+ if (strippedExpr2->isNumber())
+ expr2 = strippedExpr2;
+
+ return new (m_parserArena) PowNode(location, expr1, expr2, rightHasAssignments);
+}
+
ExpressionNode* ASTBuilder::makeMultNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
{
+ // FIXME: Unary + change the evaluation order.
+ // https://bugs.webkit.org/show_bug.cgi?id=159968
expr1 = expr1->stripUnaryPlus();
expr2 = expr2->stripUnaryPlus();
@@ -1066,6 +1094,8 @@
ExpressionNode* ASTBuilder::makeDivNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
{
+ // FIXME: Unary + change the evaluation order.
+ // https://bugs.webkit.org/show_bug.cgi?id=159968
expr1 = expr1->stripUnaryPlus();
expr2 = expr2->stripUnaryPlus();
@@ -1082,6 +1112,8 @@
ExpressionNode* ASTBuilder::makeModNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
{
+ // FIXME: Unary + change the evaluation order.
+ // https://bugs.webkit.org/show_bug.cgi?id=159968
expr1 = expr1->stripUnaryPlus();
expr2 = expr2->stripUnaryPlus();
@@ -1106,6 +1138,8 @@
ExpressionNode* ASTBuilder::makeSubNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
{
+ // FIXME: Unary + change the evaluation order.
+ // https://bugs.webkit.org/show_bug.cgi?id=159968
expr1 = expr1->stripUnaryPlus();
expr2 = expr2->stripUnaryPlus();
@@ -1295,6 +1329,9 @@
case MOD:
return makeModNode(location, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+ case POW:
+ return makePowNode(location, lhs.first, rhs.first, rhs.second.hasAssignment);
}
CRASH();
return 0;
Modified: trunk/Source/_javascript_Core/parser/Lexer.cpp (203498 => 203499)
--- trunk/Source/_javascript_Core/parser/Lexer.cpp 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/parser/Lexer.cpp 2016-07-21 07:33:28 UTC (rev 203499)
@@ -1956,6 +1956,16 @@
token = MULTEQUAL;
break;
}
+ if (m_current == '*') {
+ shift();
+ if (m_current == '=') {
+ shift();
+ token = POWEQUAL;
+ break;
+ }
+ token = POW;
+ break;
+ }
token = TIMES;
break;
case CharacterSlash:
Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (203498 => 203499)
--- trunk/Source/_javascript_Core/parser/NodeConstructors.h 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h 2016-07-21 07:33:28 UTC (rev 203499)
@@ -497,6 +497,11 @@
{
}
+ inline PowNode::PowNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_pow, rightHasAssignments)
+ {
+ }
+
inline MultNode::MultNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
: BinaryOpNode(location, ResultType::numberType(), expr1, expr2, op_mul, rightHasAssignments)
{
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (203498 => 203499)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2016-07-21 07:33:28 UTC (rev 203499)
@@ -67,6 +67,7 @@
OpXOrEq,
OpOrEq,
OpModEq,
+ OpPowEq,
OpLShift,
OpRShift,
OpURShift
@@ -1039,6 +1040,11 @@
bool m_rightHasAssignments;
};
+ class PowNode : public BinaryOpNode {
+ public:
+ PowNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
class MultNode : public BinaryOpNode {
public:
MultNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (203498 => 203499)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2016-07-21 07:33:28 UTC (rev 203499)
@@ -3126,6 +3126,7 @@
case XOREQUAL: op = OpXOrEq; break;
case OREQUAL: op = OpOrEq; break;
case MODEQUAL: op = OpModEq; break;
+ case POWEQUAL: op = OpPowEq; break;
default:
goto end;
}
@@ -3218,9 +3219,11 @@
return context.createConditionalExpr(location, cond, lhs, rhs);
}
-ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
+ALWAYS_INLINE static bool isUnaryOpExcludingUpdateOp(JSTokenType token)
{
- return token & UnaryOpTokenFlag;
+ if (isUpdateOp(token))
+ return false;
+ return isUnaryOp(token);
}
template <typename LexerType>
@@ -3241,10 +3244,35 @@
while (true) {
JSTextPosition exprStart = tokenStartPosition();
int initialAssignments = m_parserState.assignmentCount;
+ JSTokenType leadingTokenTypeForUnaryExpression = m_token.m_type;
TreeExpression current = parseUnaryExpression(context);
failIfFalse(current, "Cannot parse _expression_");
context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_parserState.assignmentCount);
+
+ // 12.6 https://tc39.github.io/ecma262/#sec-exp-operator
+ // ExponentiationExpresion is described as follows.
+ //
+ // ExponentiationExpression[Yield]:
+ // UnaryExpression[?Yield]
+ // UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
+ //
+ // As we can see, the left hand side of the ExponentiationExpression is UpdateExpression, not UnaryExpression.
+ // So placing UnaryExpression not included in UpdateExpression here is a syntax error.
+ // This is intentional. For example, if UnaryExpression is allowed, we can have the code like `-x**y`.
+ // But this is confusing: `-(x**y)` OR `(-x)**y`, which interpretation is correct?
+ // To avoid this problem, ECMA262 makes unparenthesized exponentiation _expression_ as operand of unary operators an early error.
+ // More rationale: https://mail.mozilla.org/pipermail/es-discuss/2015-September/044232.html
+ //
+ // Here, we guarantee that the left hand side of this _expression_ is not unary _expression_ by checking the leading operator of the parseUnaryExpression.
+ // This check just works. Let's consider the example,
+ // y <> -x ** z
+ // ^
+ // Check this.
+ // If the binary operator <> has higher precedence than one of "**", this check does not work.
+ // But it's OK for ** because the operator "**" has the highest operator precedence in the binary operators.
+ failIfTrue(match(POW) && isUnaryOpExcludingUpdateOp(leadingTokenTypeForUnaryExpression), "Unparenthesized unary _expression_ found on the left hand side of an exponentiation _expression_");
+
int precedence = isBinaryOperator(m_token.m_type);
if (!precedence)
break;
@@ -3253,7 +3281,7 @@
int operatorToken = m_token.m_type;
next(TreeBuilder::DontBuildStrings);
- while (operatorStackDepth && context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
+ while (operatorStackDepth && context.operatorStackShouldReduce(precedence)) {
ASSERT(operandStackDepth > 1);
typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
Modified: trunk/Source/_javascript_Core/parser/ParserTokens.h (203498 => 203499)
--- trunk/Source/_javascript_Core/parser/ParserTokens.h 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/parser/ParserTokens.h 2016-07-21 07:33:28 UTC (rev 203499)
@@ -41,7 +41,8 @@
BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4,
BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift,
ErrorTokenFlag = 1 << (BinaryOpTokenAllowsInPrecedenceAdditionalShift + BinaryOpTokenPrecedenceShift + 7),
- UnterminatedErrorTokenFlag = ErrorTokenFlag << 1
+ UnterminatedErrorTokenFlag = ErrorTokenFlag << 1,
+ RightAssociativeBinaryOpTokenFlag = UnterminatedErrorTokenFlag << 1
};
#define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift)))
@@ -109,6 +110,7 @@
URSHIFTEQUAL,
ANDEQUAL,
MODEQUAL,
+ POWEQUAL,
XOREQUAL,
OREQUAL,
DOTDOTDOT,
@@ -118,10 +120,10 @@
// Begin tagged tokens
PLUSPLUS = 0 | UnaryOpTokenFlag,
MINUSMINUS = 1 | UnaryOpTokenFlag,
- EXCLAMATION = 2 | UnaryOpTokenFlag,
- TILDE = 3 | UnaryOpTokenFlag,
- AUTOPLUSPLUS = 4 | UnaryOpTokenFlag,
- AUTOMINUSMINUS = 5 | UnaryOpTokenFlag,
+ AUTOPLUSPLUS = 2 | UnaryOpTokenFlag,
+ AUTOMINUSMINUS = 3 | UnaryOpTokenFlag,
+ EXCLAMATION = 4 | UnaryOpTokenFlag,
+ TILDE = 5 | UnaryOpTokenFlag,
TYPEOF = 6 | UnaryOpTokenFlag | KeywordTokenFlag,
VOIDTOKEN = 7 | UnaryOpTokenFlag | KeywordTokenFlag,
DELETETOKEN = 8 | UnaryOpTokenFlag | KeywordTokenFlag,
@@ -148,6 +150,7 @@
TIMES = 20 | BINARY_OP_PRECEDENCE(10),
DIVIDE = 21 | BINARY_OP_PRECEDENCE(10),
MOD = 22 | BINARY_OP_PRECEDENCE(10),
+ POW = 23 | BINARY_OP_PRECEDENCE(11) | RightAssociativeBinaryOpTokenFlag, // Make sure that POW has the highest operator precedence.
ERRORTOK = 0 | ErrorTokenFlag,
UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK = 0 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
INVALID_IDENTIFIER_ESCAPE_ERRORTOK = 1 | ErrorTokenFlag,
@@ -222,6 +225,16 @@
JSTextPosition m_endPosition;
};
+ALWAYS_INLINE bool isUpdateOp(JSTokenType token)
+{
+ return token >= PLUSPLUS && token <= AUTOMINUSMINUS;
+}
+
+ALWAYS_INLINE bool isUnaryOp(JSTokenType token)
+{
+ return token & UnaryOpTokenFlag;
+}
+
} // namespace JSC
#endif // ParserTokens_h
Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (203498 => 203499)
--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2016-07-21 07:33:28 UTC (rev 203499)
@@ -301,7 +301,7 @@
// Logic to handle datastructures used during parsing of binary expressions
void operatorStackPop(int& operatorStackDepth) { operatorStackDepth--; }
- bool operatorStackHasHigherPrecedence(int&, int) { return true; }
+ bool operatorStackShouldReduce(int) { return true; }
BinaryOperand getFromOperandStack(int) { return m_topBinaryExpr; }
void shrinkOperandStackBy(int& operandStackDepth, int amount) { operandStackDepth -= amount; }
void appendBinaryOperation(const JSTokenLocation&, int& operandStackDepth, int&, BinaryOperand, BinaryOperand) { operandStackDepth++; }
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (203498 => 203499)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2016-07-21 07:33:28 UTC (rev 203499)
@@ -470,6 +470,14 @@
RETURN(jsNumber(jsMod(a, b)));
}
+SLOW_PATH_DECL(slow_path_pow)
+{
+ BEGIN();
+ double a = OP_C(2).jsValue().toNumber(exec);
+ double b = OP_C(3).jsValue().toNumber(exec);
+ RETURN(jsNumber(operationMathPow(a, b)));
+}
+
SLOW_PATH_DECL(slow_path_lshift)
{
BEGIN();
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (203498 => 203499)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2016-07-21 07:33:28 UTC (rev 203499)
@@ -219,6 +219,7 @@
SLOW_PATH_HIDDEN_DECL(slow_path_sub);
SLOW_PATH_HIDDEN_DECL(slow_path_div);
SLOW_PATH_HIDDEN_DECL(slow_path_mod);
+SLOW_PATH_HIDDEN_DECL(slow_path_pow);
SLOW_PATH_HIDDEN_DECL(slow_path_lshift);
SLOW_PATH_HIDDEN_DECL(slow_path_rshift);
SLOW_PATH_HIDDEN_DECL(slow_path_urshift);
Modified: trunk/Source/_javascript_Core/tests/stress/math-pow-basics.js (203498 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/math-pow-basics.js 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/tests/stress/math-pow-basics.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -181,7 +181,7 @@
}
}
noInline(test7);
-test6(-37.676522764377296, -1.0, -0.026541727490454296, -0.026541727490454296);
+test7(-37.676522764377296, -1.0, -0.026541727490454296, -0.026541727490454296);
// Let's square things.
function mathPowDoubleDouble8(x, y) {
@@ -207,7 +207,7 @@
}
}
noInline(test8);
-test7(-37.676522764377296, 2.0, 1419.5203676146407, 1419.5203676146407);
+test8(-37.676522764377296, 2.0, 1419.5203676146407, 1419.5203676146407);
function mathPowDoubleDouble9(x, y) {
return Math.pow(x, y)
@@ -232,7 +232,7 @@
}
}
noInline(test9);
-test8(37.676522764377296, 2.0, 1419.5203676146407, 1419.5203676146407);
+test9(37.676522764377296, 2.0, 1419.5203676146407, 1419.5203676146407);
// Let's cube things.
function mathPowDoubleDouble10(x, y) {
@@ -257,8 +257,8 @@
throw "Error: bad result, mathPowDoubleInt(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
}
}
-noInline(test9);
-test9(-37.676522764377296, 3.0, -53482.591444930236, -53482.591444930236);
+noInline(test10);
+test10(-37.676522764377296, 3.0, -53482.591444930236, -53482.591444930236);
function mathPowDoubleDouble11(x, y) {
return Math.pow(x, y)
@@ -282,5 +282,5 @@
throw "Error: bad result, mathPowDoubleInt(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
}
}
-noInline(test10);
-test10(37.676522764377296, 3.0, 53482.591444930236, 53482.591444930236);
+noInline(test11);
+test11(37.676522764377296, 3.0, 53482.591444930236, 53482.591444930236);
Modified: trunk/Source/_javascript_Core/tests/stress/math-pow-nan-behaviors.js (203498 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/math-pow-nan-behaviors.js 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/tests/stress/math-pow-nan-behaviors.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -1,4 +1,4 @@
-// If y is NaN, the result is NaN.
+// If an argument is NaN, the result of Math.pow(x, y) is NaN.
function testIntegerBaseWithNaNExponentStatic() {
for (var i = 0; i < 10000; ++i) {
var result = Math.pow(5, NaN);
@@ -72,7 +72,7 @@
testFloatingPointBaseWithNaNExponentDynamic();
// If y is +0, the result is 1, even if x is NaN.
-// If y is −0, the result is 1, even if x is NaN.
+// If y is -0, the result is 1, even if x is NaN.
// If x is NaN and y is nonzero, the result is NaN.
function testNaNBaseStatic() {
for (var i = 0; i < 10000; ++i) {
@@ -140,8 +140,8 @@
noInline(testNaNBaseDynamic);
testNaNBaseDynamic();
-// If abs(x) is 1 and y is +∞, the result is NaN.
-// If abs(x) is 1 and y is −∞, the result is NaN.
+// If abs(x) is 1 and y is +Inf the result is NaN.
+// If abs(x) is 1 and y is −Inf the result is NaN.
function infiniteExponentsStatic() {
for (var i = 0; i < 10000; ++i) {
var result = Math.pow(1, Number.POSITIVE_INFINITY);
@@ -206,4 +206,4 @@
}
}
noInline(infiniteExponentsDynamic);
-infiniteExponentsDynamic();
\ No newline at end of file
+infiniteExponentsDynamic();
Copied: trunk/Source/_javascript_Core/tests/stress/pow-basics.js (from rev 203498, trunk/Source/_javascript_Core/tests/stress/math-pow-basics.js) (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-basics.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-basics.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,286 @@
+function valuesAreClose(a, b) {
+ return Math.abs(a / b) - 1 < 1e-10;
+}
+
+// Some random values.
+function mathPowDoubleDouble1(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble1);
+
+function mathPowDoubleInt1(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt1);
+
+function test1(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble1(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble1(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt1(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt1(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test1);
+test1(376.76522764377296, 10.81699226051569, 7.333951929109252e+27, 5.76378989575089e+25);
+
+function mathPowDoubleDouble2(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble2);
+
+function mathPowDoubleInt2(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt2);
+function test2(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble2(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble2(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt2(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt2(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test2);
+test2(376.76522764377296, -5.81699226051569, 1.035180331187579e-15, 1.3171824310400265e-13);
+
+function mathPowDoubleDouble3(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble3);
+
+function mathPowDoubleInt3(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt3);
+function test3(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble3(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble3(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt3(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt3(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test3);
+test3(-37.676522764377296, 10.0, 5763789895750892, 5763789895750892);
+
+// Exponent zero.
+function mathPowDoubleDouble4(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble4);
+
+function mathPowDoubleInt4(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt4);
+function test4(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble4(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble4(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt4(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt4(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test4);
+test4(-37.676522764377296, 0, 1, 1);
+
+// Exponent minus zero.
+function mathPowDoubleDouble5(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble5);
+
+function mathPowDoubleInt5(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt5);
+function test5(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble5(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble5(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt5(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test5);
+test5(-37.676522764377296, -0, 1, 1);
+
+// Exponent 1.
+function mathPowDoubleDouble6(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble6);
+
+function mathPowDoubleInt6(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt6);
+function test6(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble6(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble6(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt6(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt6(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test6);
+test6(-37.676522764377296, 1.0, -37.676522764377296, -37.676522764377296);
+
+// Exponent -1.
+function mathPowDoubleDouble7(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble7);
+
+function mathPowDoubleInt7(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt7);
+function test7(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble7(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble7(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble7(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleDouble7(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test7);
+test7(-37.676522764377296, -1.0, -0.026541727490454296, -0.026541727490454296);
+
+// Let's square things.
+function mathPowDoubleDouble8(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble8);
+
+function mathPowDoubleInt8(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt8);
+function test8(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble8(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble8(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt8(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt8(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test8);
+test8(-37.676522764377296, 2.0, 1419.5203676146407, 1419.5203676146407);
+
+function mathPowDoubleDouble9(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble9);
+
+function mathPowDoubleInt9(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt9);
+function test9(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble9(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble9(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt9(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt9(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test9);
+test9(37.676522764377296, 2.0, 1419.5203676146407, 1419.5203676146407);
+
+// Let's cube things.
+function mathPowDoubleDouble10(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble10);
+
+function mathPowDoubleInt10(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt10);
+function test10(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble10(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt10(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test10);
+test10(-37.676522764377296, 3.0, -53482.591444930236, -53482.591444930236);
+
+function mathPowDoubleDouble11(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleDouble11);
+
+function mathPowDoubleInt11(x, y) {
+ return x ** y;
+}
+noInline(mathPowDoubleInt11);
+function test11(x, y, expected1, expected2) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDouble11(x, y);
+ if (!valuesAreClose(result, expected1))
+ throw "Error: bad result, mathPowDoubleDouble(" + x + ", " + y + ") = " + result + " expected a value close to " + expected1;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleInt11(x, integerY);
+ if (!valuesAreClose(result, expected2))
+ throw "Error: bad result, mathPowDoubleInt(" + x + ", " + integerY + ") = " + result + " expected a value close to " + expected2;
+ }
+}
+noInline(test11);
+test11(37.676522764377296, 3.0, 53482.591444930236, 53482.591444930236);
Added: trunk/Source/_javascript_Core/tests/stress/pow-coherency.js (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-coherency.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-coherency.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,95 @@
+//@ skip
+
+// This test checks that the pow function returns coherent results:
+// (a) Across different compilation tiers
+// (b) With integer exponents represented as int32 or as double
+
+function pow42() {
+ return { value: 2.1 ** 42, ftl: isFinalTier() };
+}
+
+function build42AsDouble() {
+ function opaqueAdd(x, y) { return x + y; }
+ return opaqueAdd(42 - 0.123, 0.123);
+}
+
+var double42 = build42AsDouble();
+
+if (double42 !== 42)
+ throw new Error("42 (as double) should be === to 42 (as int)");
+
+function powDouble42() {
+ return { value: 2.1 ** double42, ftl: isFinalTier() };
+}
+
+function clobber() { }
+noInline(clobber);
+
+function pow42NoConstantFolding() {
+ var obj = { x: 2.1, y: 42 };
+ clobber(obj);
+ return { value: obj.x ** obj.y, ftl: isFinalTier() };
+}
+
+function powDouble42NoConstantFolding() {
+ var obj = { x: 2.1, y: double42 };
+ clobber(obj);
+ return { value: obj.x ** obj.y, ftl: isFinalTier() };
+}
+
+var results = { 'jit': {}, 'dfg': {}, 'ftl': {} };
+var funs = [
+ [ 'pow42', pow42 ],
+ [ 'powDouble42', powDouble42 ],
+ [ 'pow42NoConstantFolding', pow42NoConstantFolding ],
+ [ 'powDouble42NoConstantFolding', powDouble42NoConstantFolding ]
+];
+var tiers = ['jit', 'dfg', 'ftl'];
+
+for (var i = 0; i < 100000; ++i) {
+ for (var j in funs) {
+ var name = funs[j][0];
+ var fun = funs[j][1];
+ var result = fun();
+ if (result.ftl)
+ results['ftl'][name] = result.value;
+ else if (numberOfDFGCompiles(fun) > 0)
+ results['dfg'][name] = result.value;
+ else
+ results['jit'][name] = result.value;
+ }
+}
+
+var errors = [];
+var valuesFor = {};
+for (var i in tiers) {
+ var tier = tiers[i];
+ var result = results[tier];
+ // We don't have this tier
+ if (Object.keys(result).length === 0)
+ continue;
+
+ for (var j in funs) {
+ var name = funs[j][0];
+ if (!(name in result))
+ errors.push(name + " was not compiled to " + tier);
+ else if (!(name in valuesFor))
+ valuesFor[name] = { value: result[name], tiers: [tier] };
+ else if (result[name] !== valuesFor[name].value)
+ errors.push(name + " has different results in " + tier + " (" + result[name] + ") and " + valuesFor[name].tiers + " (" + valuesFor[name].value + ")");
+ else
+ valuesFor[name].tiers.push(tier);
+ }
+}
+
+var reference = funs[0][0];
+var result = valuesFor[reference].value;
+
+for (var j in funs) {
+ var name = funs[j][0];
+ if (valuesFor[name].value !== result)
+ errors.push(name + " (" + valuesFor[name].value + ") and " + reference + " (" + result + ") have different results");
+}
+
+if (errors.length > 0)
+ throw new Error(errors.join('\n'));
Added: trunk/Source/_javascript_Core/tests/stress/pow-evaluation-order.js (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-evaluation-order.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-evaluation-order.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,40 @@
+// Copyright (C) 2016 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+function shouldBe(actual, expected)
+{
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+{
+ let capture = [];
+ let leftValue = { valueOf() { capture.push("leftValue"); return 3; }};
+ let rightValue = { valueOf() { capture.push("rightValue"); return 2; }};
+
+ (capture.push("left"), leftValue) ** +(capture.push("right"), rightValue);
+// ^
+// Changes the order
+
+ // Expected per operator evaluation order: "left", "right", "rightValue", "leftValue"
+ shouldBe(capture[0], "left");
+ shouldBe(capture[1], "right");
+ shouldBe(capture[2], "rightValue");
+ shouldBe(capture[3], "leftValue");
+}
+
+{
+ let capture = [];
+ let leftValue = { valueOf() { capture.push("leftValue"); return 3; }};
+ let rightValue = { valueOf() { capture.push("rightValue"); return 2; }};
+
+ (+(capture.push("left"), leftValue)) ** (capture.push("right"), rightValue);
+// ^
+// Changes the order
+
+ // Expected per operator evaluation order: "left", "right", "rightValue", "leftValue"
+ shouldBe(capture[0], "left");
+ shouldBe(capture[1], "leftValue");
+ shouldBe(capture[2], "right");
+ shouldBe(capture[3], "rightValue");
+}
Added: trunk/Source/_javascript_Core/tests/stress/pow-expects-update-_expression_-on-lhs.js (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-expects-update-_expression_-on-lhs.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-expects-update-_expression_-on-lhs.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,96 @@
+function testSyntax(script) {
+ try {
+ eval(script);
+ } catch (error) {
+ if (error instanceof SyntaxError)
+ throw new Error("Bad error: " + String(error));
+ }
+}
+
+function testSyntaxError(script, message) {
+ var error = null;
+ try {
+ eval(script);
+ } catch (e) {
+ error = e;
+ }
+ if (!error)
+ throw new Error("Expected syntax error not thrown");
+
+ if (String(error) !== message)
+ throw new Error("Bad error: " + String(error));
+}
+
+{
+ let tokens = [
+ '-',
+ '+',
+ '~',
+ '!',
+ 'typeof',
+ 'void',
+ 'delete',
+ ];
+
+ for (let token of tokens) {
+ testSyntaxError(`
+ function pow(a, b)
+ {
+ return ${token} a ** b;
+ }
+ `, `SyntaxError: Unexpected token '**'. Unparenthesized unary _expression_ found on the left hand side of an exponentiation _expression_.`);
+ }
+}
+
+{
+ let tokens = [
+ '-',
+ '+',
+ '~',
+ '!',
+ 'typeof',
+ 'void',
+ 'delete',
+ ];
+
+ for (let token of tokens) {
+ testSyntax(`
+ function pow(a, b)
+ {
+ return (${token} a) ** b;
+ }
+ `);
+ }
+}
+
+{
+ let tokens = [
+ '++',
+ '--',
+ ];
+
+ for (let token of tokens) {
+ testSyntax(`
+ function pow(a, b)
+ {
+ return ${token} a ** b;
+ }
+ `);
+ }
+}
+
+{
+ let tokens = [
+ '++',
+ '--',
+ ];
+
+ for (let token of tokens) {
+ testSyntax(`
+ function pow(a, b)
+ {
+ return a ${token} ** b;
+ }
+ `);
+ }
+}
Added: trunk/Source/_javascript_Core/tests/stress/pow-integer-exponent-fastpath.js (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-integer-exponent-fastpath.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-integer-exponent-fastpath.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,56 @@
+function valuesAreClose(a, b) {
+ return Math.abs(a / b) - 1 < 1e-10;
+}
+
+// Small exponent values are handled through a simpler inline loop. Test that it is not observable.
+function mathPowDoubleDoubleTestExponentFifty(x, y) {
+ return x ** y
+}
+noInline(mathPowDoubleDoubleTestExponentFifty);
+
+function mathPowDoubleIntTestExponentFifty(x, y) {
+ return x ** y
+}
+noInline(mathPowDoubleIntTestExponentFifty);
+function testExponentFifty(x, y, expected) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDoubleTestExponentFifty(x, y);
+ if (!valuesAreClose(result, expected))
+ throw "Error: bad result, (" + x + ") ** (" + y + ") = " + result + " expected value close to " + expected;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleIntTestExponentFifty(x, integerY);
+ if (!valuesAreClose(result, expected))
+ throw "Error: bad result, (" + x + ") ** (" + integerY + ") = " + result + " expected value close to " + expected;
+ }
+}
+noInline(testExponentFifty);
+testExponentFifty(53.70901164133102, 50.0, 3.179494118120144e+86);
+testExponentFifty(53.70901164133102, -10.0, 5.006432842621192e-18);
+
+function mathPowDoubleDoubleTestExponentTenThousands(x, y) {
+ return x ** y
+}
+noInline(mathPowDoubleDoubleTestExponentTenThousands);
+
+function mathPowDoubleIntTestExponentTenThousands(x, y) {
+ return x ** y
+}
+noInline(mathPowDoubleIntTestExponentTenThousands);
+function testExponentTenThousands(x, y, expected) {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleDoubleTestExponentTenThousands(x, y);
+ if (!valuesAreClose(result, expected))
+ throw "Error: bad result, (" + x + ") ** (" + y + ") = " + result + " expected value close to " + expected;
+ }
+ var integerY = y | 0;
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowDoubleIntTestExponentTenThousands(x, integerY);
+ if (!valuesAreClose(result, expected))
+ throw "Error: bad result, (" + x + ") ** (" + integerY + ") = " + result + " expected value close to " + expected;
+ }
+}
+noInline(testExponentTenThousands);
+testExponentTenThousands(1.001, 10000.0, 21916.681339048373);
+testExponentTenThousands(1.001, -1.0, 0.9990009990009991);
Copied: trunk/Source/_javascript_Core/tests/stress/pow-nan-behaviors.js (from rev 203498, trunk/Source/_javascript_Core/tests/stress/math-pow-nan-behaviors.js) (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-nan-behaviors.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-nan-behaviors.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,209 @@
+// If an argument is NaN, the result of x ** y is NaN.
+function testIntegerBaseWithNaNExponentStatic() {
+ for (var i = 0; i < 10000; ++i) {
+ var result = 5 ** NaN;
+ if (!isNaN(result))
+ throw "Error: bad result, 5 ** NaN = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = i ** NaN;
+ if (!isNaN(result))
+ throw "Error: bad result, i ** NaN = " + result + " with i = " + i;
+ }
+}
+noInline(testIntegerBaseWithNaNExponentStatic);
+testIntegerBaseWithNaNExponentStatic();
+
+function mathPowIntegerBaseWithNaNExponentDynamic(x, y) {
+ return x ** y;
+}
+noInline(mathPowIntegerBaseWithNaNExponentDynamic);
+function testIntegerBaseWithNaNExponentDynamic() {
+ // Warm up with 2 integers.
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowIntegerBaseWithNaNExponentDynamic(2, 5);
+ if (result !== 32)
+ throw "Error: bad result, mathPowIntegerBaseWithNaNExponentDynamic(2, 5) = " + result + ", expected 32."
+ }
+
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowIntegerBaseWithNaNExponentDynamic(i, NaN);
+ if (!isNaN(result))
+ throw "Error: bad result, mathPowIntegerBaseWithNaNExponentDynamic(i, NaN) = " + result + " with i = " + i + ", expected NaN";
+ }
+}
+noInline(testIntegerBaseWithNaNExponentDynamic);
+testIntegerBaseWithNaNExponentDynamic();
+
+function testFloatingPointBaseWithNaNExponentStatic() {
+ for (var i = 0; i < 10000; ++i) {
+ var result = 5.5 ** NaN;
+ if (!isNaN(result))
+ throw "Error: bad result, 5.5 ** NaN = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = (i + 0.5) ** NaN;
+ if (!isNaN(result))
+ throw "Error: bad result, (i + 0.5) ** NaN = " + result + " with i = " + i;
+ }
+}
+noInline(testFloatingPointBaseWithNaNExponentStatic);
+testFloatingPointBaseWithNaNExponentStatic();
+
+function mathPowFloatingPointBaseWithNaNExponentDynamic(x, y) {
+ return x ** y;
+}
+noInline(mathPowFloatingPointBaseWithNaNExponentDynamic);
+function testFloatingPointBaseWithNaNExponentDynamic() {
+ // Warm up with 2 double.
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowFloatingPointBaseWithNaNExponentDynamic(2.5, 5.1);
+ if (result !== 107.02717054543135)
+ throw "Error: bad result, mathPowFloatingPointBaseWithNaNExponentDynamic(2.5, 5.1) = " + result + ", expected 107.02717054543135."
+ }
+
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowFloatingPointBaseWithNaNExponentDynamic(i + 0.5, NaN);
+ if (!isNaN(result))
+ throw "Error: bad result, mathPowFloatingPointBaseWithNaNExponentDynamic(i + 0.5, NaN) = " + result + " with i = " + i + ", expected NaN";
+ }
+}
+noInline(testFloatingPointBaseWithNaNExponentDynamic);
+testFloatingPointBaseWithNaNExponentDynamic();
+
+// If y is +0, the result is 1, even if x is NaN.
+// If y is -0, the result is 1, even if x is NaN.
+// If x is NaN and y is nonzero, the result is NaN.
+function testNaNBaseStatic() {
+ for (var i = 0; i < 10000; ++i) {
+ var result = NaN ** (i + 1);
+ if (!isNaN(result))
+ throw "Error: bad result, NaN ** (i + 1) = " + result + " with i = " + i;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = NaN ** (i + 1.5);
+ if (!isNaN(result))
+ throw "Error: bad result, NaN ** (i + 1.5) = " + result + " with i = " + i;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = NaN ** 0;
+ if (result !== 1)
+ throw "Error: bad result, NaN ** 0 = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = NaN ** -0;
+ if (result !== 1)
+ throw "Error: bad result, NaN ** -0 = " + result;
+ }
+}
+noInline(testNaNBaseStatic);
+testNaNBaseStatic();
+
+function mathPowNaNBaseDynamic1(x, y) {
+ return x ** y;
+}
+function mathPowNaNBaseDynamic2(x, y) {
+ return x ** y;
+}
+function mathPowNaNBaseDynamic3(x, y) {
+ return x ** y;
+}
+function mathPowNaNBaseDynamic4(x, y) {
+ return x ** y;
+}
+noInline(mathPowNaNBaseDynamic1);
+noInline(mathPowNaNBaseDynamic2);
+noInline(mathPowNaNBaseDynamic3);
+noInline(mathPowNaNBaseDynamic4);
+function testNaNBaseDynamic() {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowNaNBaseDynamic1(NaN, i + 1);
+ if (!isNaN(result))
+ throw "Error: bad result, mathPowNaNBaseDynamic1(NaN, i + 1) = " + result + " with i = " + i;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowNaNBaseDynamic2(NaN, i + 1.5);
+ if (!isNaN(result))
+ throw "Error: bad result, mathPowNaNBaseDynamic2(NaN, i + 1.5) = " + result + " with i = " + i;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowNaNBaseDynamic3(NaN, 0);
+ if (result !== 1)
+ throw "Error: bad result, mathPowNaNBaseDynamic3(NaN, 0) = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowNaNBaseDynamic4(NaN, -0);
+ if (result !== 1)
+ throw "Error: bad result, mathPowNaNBaseDynamic4(NaN, -0) = " + result;
+ }
+}
+noInline(testNaNBaseDynamic);
+testNaNBaseDynamic();
+
+// If abs(x) is 1 and y is +Inf the result is NaN.
+// If abs(x) is 1 and y is −Inf the result is NaN.
+function infiniteExponentsStatic() {
+ for (var i = 0; i < 10000; ++i) {
+ var result = 1 ** Number.POSITIVE_INFINITY;
+ if (!isNaN(result))
+ throw "Error: bad result, 1 ** Number.POSITIVE_INFINITY = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = (-1) ** Number.POSITIVE_INFINITY;
+ if (!isNaN(result))
+ throw "Error: bad result, -1 ** Number.POSITIVE_INFINITY = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = 1 ** Number.NEGATIVE_INFINITY;
+ if (!isNaN(result))
+ throw "Error: bad result, 1 ** Number.NEGATIVE_INFINITY = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = (-1) ** Number.NEGATIVE_INFINITY;
+ if (!isNaN(result))
+ throw "Error: bad result, -1 ** Number.NEGATIVE_INFINITY = " + result;
+ }
+}
+noInline(infiniteExponentsStatic);
+infiniteExponentsStatic();
+
+function mathPowInfiniteExponentsDynamic1(x, y) {
+ return x ** y;
+}
+function mathPowInfiniteExponentsDynamic2(x, y) {
+ return x ** y;
+}
+function mathPowInfiniteExponentsDynamic3(x, y) {
+ return x ** y;
+}
+function mathPowInfiniteExponentsDynamic4(x, y) {
+ return x ** y;
+}
+noInline(mathPowInfiniteExponentsDynamic1);
+noInline(mathPowInfiniteExponentsDynamic2);
+noInline(mathPowInfiniteExponentsDynamic3);
+noInline(mathPowInfiniteExponentsDynamic4);
+function infiniteExponentsDynamic() {
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowInfiniteExponentsDynamic1(1, Number.POSITIVE_INFINITY);
+ if (!isNaN(result))
+ throw "Error: bad result, mathPowInfiniteExponentsDynamic1(1, Number.POSITIVE_INFINITY) = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowInfiniteExponentsDynamic2(-1, Number.POSITIVE_INFINITY);
+ if (!isNaN(result))
+ throw "Error: bad result, mathPowInfiniteExponentsDynamic2(-1, Number.POSITIVE_INFINITY) = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowInfiniteExponentsDynamic3(1, Number.NEGATIVE_INFINITY);
+ if (!isNaN(result))
+ throw "Error: bad result, mathPowInfiniteExponentsDynamic3(1, Number.NEGATIVE_INFINITY) = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = mathPowInfiniteExponentsDynamic4(-1, Number.NEGATIVE_INFINITY);
+ if (!isNaN(result))
+ throw "Error: bad result, mathPowInfiniteExponentsDynamic4(-1, Number.NEGATIVE_INFINITY) = " + result;
+ }
+}
+noInline(infiniteExponentsDynamic);
+infiniteExponentsDynamic();
Added: trunk/Source/_javascript_Core/tests/stress/pow-simple.js (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-simple.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-simple.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,39 @@
+function shouldBe(actual, expected)
+{
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+{
+ let i = 2;
+ let j = 3;
+ shouldBe(2 ** 3, 8);
+ shouldBe(i ** 3, 8);
+ shouldBe(2 ** j, 8);
+ shouldBe(i ** j, 8);
+}
+
+{
+ shouldBe(2 ** 3 ** 3, 134217728);
+ shouldBe(2 ** 3 + 3, 11);
+ shouldBe(2 ** 3 + 3 ** 3, 35);
+ shouldBe(2 ** 3 * 3, 24);
+ shouldBe(2 ** 3 * 3 ** 3, 216);
+
+ shouldBe(2 + 3 ** 3, 29);
+ shouldBe(2 * 3 ** 3, 54);
+}
+
+{
+ let i = 2;
+ i **= 4;
+ shouldBe(i, 16);
+ i **= 1 + 1;
+ shouldBe(i, 256);
+}
+
+for (let i = 0; i < 1e4; ++i) {
+ let a = Math.random();
+ let b = Math.random();
+ shouldBe(a ** b, Math.pow(a, b));
+}
Added: trunk/Source/_javascript_Core/tests/stress/pow-stable-results.js (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-stable-results.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-stable-results.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,85 @@
+// This test verify the results of `**` do not change as we change optimization tier.
+
+function opaquePow(a, b)
+{
+ return a ** b;
+}
+noInline(opaquePow);
+
+
+let caseStrings = [
+ "0",
+ "-0.",
+ "0.5",
+ "1",
+ "2",
+ "-0.5",
+ "-1",
+ "999",
+ "1000",
+ "1001",
+ "NaN",
+ "Infinity",
+ "-Infinity",
+ "Math.PI",
+ "Math.LN2",
+ "Math.LN10",
+ "Math.E",
+ "Math.LOG10E",
+ "Math.LOG2E",
+ "Math.SQRT2"
+];
+let cases = [];
+for (let caseString of caseStrings) {
+ cases.push(eval(caseString));
+}
+
+let expectedResults = [];
+let constantBaseFunctions = [];
+let constantExponentFunctions = [];
+for (let i = 0; i < cases.length; ++i) {
+ let base = cases[i];
+
+ expectedResults[i] = [];
+ for (let j = 0; j < cases.length; ++j) {
+ let exponent = cases[j];
+ expectedResults[i][j] = base ** exponent;
+ }
+
+ eval("constantBaseFunctions[i] = function (exponent) { return (" + caseStrings[i] + ") ** exponent; }");
+ eval("constantExponentFunctions[i] = function (base) { return base ** (" + caseStrings[i] + "); }");
+}
+
+function isIdentical(result, expected)
+{
+ if (expected === expected) {
+ if (result !== expected)
+ return false;
+ if (!expected && 1 / expected === -Infinity && 1 / result !== -Infinity)
+ return false;
+
+ return true;
+ }
+ return result !== result;
+}
+
+for (let tierUpLoopCounter = 0; tierUpLoopCounter < 1e3; ++tierUpLoopCounter) {
+ for (let i = 0; i < cases.length; ++i) {
+ let base = cases[i];
+ for (let j = 0; j < cases.length; ++j) {
+ let exponent = cases[j];
+ let expectedResult = expectedResults[i][j];
+ let result = opaquePow(base, exponent);
+ if (!isIdentical(result, expectedResult))
+ throw `Failed opaquePow with base = ${base} exponent = ${exponent} expected (${expectedResult}) got (${result})`;
+
+ result = constantBaseFunctions[i](exponent);
+ if (!isIdentical(result, expectedResult))
+ throw `Failed constantBaseFunctions with base = ${base} exponent = ${exponent} expected (${expectedResult}) got (${result})`;
+
+ result = constantExponentFunctions[j](base);
+ if (!isIdentical(result, expectedResult))
+ throw `Failed constantExponentFunctions with base = ${base} exponent = ${exponent} expected (${expectedResult}) got (${result})`;
+ }
+ }
+}
Added: trunk/Source/_javascript_Core/tests/stress/pow-to-number-should-be-executed-in-code-side.js (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-to-number-should-be-executed-in-code-side.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-to-number-should-be-executed-in-code-side.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,77 @@
+function shouldBe(actual, expected)
+{
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+{
+ let value = {
+ valueOf()
+ {
+ throw new Error("NG");
+ }
+ };
+ let error = null;
+
+ try {
+ 2 ** value;
+ } catch (e) {
+ error = e;
+ }
+ // global, and valueOf.
+ shouldBe(error.stack.split("\n").length, 2);
+}
+
+{
+ let value = {
+ valueOf()
+ {
+ throw new Error("NG");
+ }
+ };
+ let error = null;
+
+ try {
+ value ** 2;
+ } catch (e) {
+ error = e;
+ }
+ // global, and valueOf.
+ shouldBe(error.stack.split("\n").length, 2);
+}
+
+{
+ let value = {
+ valueOf()
+ {
+ throw new Error("NG");
+ }
+ };
+ let error = null;
+
+ try {
+ Math.pow(value, 2);
+ } catch (e) {
+ error = e;
+ }
+ // global, Math.pow, and valueOf.
+ shouldBe(error.stack.split("\n").length, 3);
+}
+
+{
+ let value = {
+ valueOf()
+ {
+ throw new Error("NG");
+ }
+ };
+ let error = null;
+
+ try {
+ Math.pow(2, value);
+ } catch (e) {
+ error = e;
+ }
+ // global, Math.pow, and valueOf.
+ shouldBe(error.stack.split("\n").length, 3);
+}
Added: trunk/Source/_javascript_Core/tests/stress/pow-with-constants.js (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-with-constants.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-with-constants.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,285 @@
+function exponentIsZero(x) {
+ return x ** 0;
+}
+noInline(exponentIsZero);
+
+function testExponentIsZero() {
+ for (var i = 0; i < 10000; ++i) {
+ var result = exponentIsZero(5);
+ if (result !== 1)
+ throw "Error: zeroExponent(5) should be 1, was = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = exponentIsZero(5.5);
+ if (result !== 1)
+ throw "Error: zeroExponent(5.5) should be 1, was = " + result;
+ }
+}
+testExponentIsZero();
+
+
+function exponentIsOne(x) {
+ return x ** 1;
+}
+noInline(exponentIsOne);
+
+function testExponentIsOne() {
+ for (var i = 0; i < 10000; ++i) {
+ var result = exponentIsOne(5);
+ if (result !== 5)
+ throw "Error: exponentIsOne(5) should be 5, was = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = exponentIsOne(5.5);
+ if (result !== 5.5)
+ throw "Error: exponentIsOne(5.5) should be 5.5, was = " + result;
+ }
+}
+testExponentIsOne();
+
+
+function powUsedAsSqrt(x) {
+ return x ** 0.5;
+}
+noInline(powUsedAsSqrt);
+
+function testPowUsedAsSqrt() {
+ for (let i = 0; i < 1e4; ++i) {
+ let result = powUsedAsSqrt(4);
+ if (result !== Math.sqrt(4))
+ throw "Error: powUsedAsSqrt(4) should be 2, was = " + result;
+ result = powUsedAsSqrt(4.4);
+ if (result !== Math.sqrt(4.4))
+ throw "Error: powUsedAsSqrt(4) should be " + Math.sqrt(4.4) + ", was = " + result;
+ if (powUsedAsSqrt(Infinity) !== Infinity)
+ throw "Failed powUsedAsSqrt(Infinity)";
+ if (powUsedAsSqrt(-Infinity) !== Infinity)
+ throw "Failed powUsedAsSqrt(-Infinity)";
+ let nanResult = powUsedAsSqrt(NaN)
+ if (nanResult === nanResult)
+ throw "Failed powUsedAsSqrt(NaN)";
+ let zeroResult = powUsedAsSqrt(0.)
+ if (zeroResult || (1 / zeroResult) !== Infinity)
+ throw "Failed powUsedAsSqrt(0.)";
+ let negativeZeroResult = powUsedAsSqrt(-0)
+ if (negativeZeroResult || (1 / negativeZeroResult) !== Infinity)
+ throw "Failed powUsedAsSqrt(-0)";
+ }
+}
+testPowUsedAsSqrt();
+
+function powUsedAsOneOverSqrt(x) {
+ return x ** -0.5;
+}
+noInline(powUsedAsOneOverSqrt);
+
+function testPowUsedAsOneOverSqrt() {
+ for (let i = 0; i < 1e4; ++i) {
+ let result = powUsedAsOneOverSqrt(4);
+ if (result !== 0.5)
+ throw "Error: powUsedAsOneOverSqrt(4) should be 0.5, was = " + result;
+ result = powUsedAsOneOverSqrt(4.4);
+ if (result !== 1/Math.sqrt(4.4))
+ throw "Error: powUsedAsOneOverSqrt(4) should be " + 1/Math.sqrt(4.4) + ", was = " + result;
+ if (powUsedAsOneOverSqrt(Infinity) !== 0)
+ throw "Failed powUsedAsOneOverSqrt(Infinity)";
+ if (powUsedAsOneOverSqrt(-Infinity) !== 0)
+ throw "Failed powUsedAsOneOverSqrt(-Infinity)";
+ let nanResult = powUsedAsOneOverSqrt(NaN)
+ if (nanResult === nanResult)
+ throw "Failed powUsedAsOneOverSqrt(NaN)";
+ if (powUsedAsOneOverSqrt(0) !== Infinity)
+ throw "Failed powUsedAsOneOverSqrt(0)";
+ if (powUsedAsOneOverSqrt(-0.) !== Infinity)
+ throw "Failed powUsedAsOneOverSqrt(-0.)";
+ }
+}
+testPowUsedAsOneOverSqrt();
+
+function powUsedAsSquare(x) {
+ return x ** 2;
+}
+noInline(powUsedAsSquare);
+
+function testPowUsedAsSquare() {
+ for (let i = 0; i < 1e4; ++i) {
+ let result = powUsedAsSquare(2);
+ if (result !== 4)
+ throw "Error: powUsedAsSquare(4) should be 2, was = " + result;
+ result = powUsedAsSquare(4.4);
+ if (result !== 19.360000000000003)
+ throw "Error: powUsedAsSquare(4) should be " + 19.360000000000003 + ", was = " + result;
+ result = powUsedAsSquare(Math.PI);
+ if (result !== 9.869604401089358)
+ throw "Error: powUsedAsSquare(4) should be " + 9.869604401089358 + ", was = " + result;
+ if (powUsedAsSquare(Infinity) !== Infinity)
+ throw "Failed powUsedAsSquare(Infinity)";
+ if (powUsedAsSquare(-Infinity) !== Infinity)
+ throw "Failed powUsedAsSquare(-Infinity)";
+ let nanResult = powUsedAsSquare(NaN)
+ if (nanResult === nanResult)
+ throw "Failed powUsedAsSquare(NaN)";
+ let zeroResult = powUsedAsSquare(0.)
+ if (zeroResult || (1 / zeroResult) !== Infinity)
+ throw "Failed powUsedAsSquare(0.)";
+ let negativeZeroResult = powUsedAsSquare(-0)
+ if (negativeZeroResult || (1 / negativeZeroResult) !== Infinity)
+ throw "Failed powUsedAsSquare(-0)";
+ }
+}
+testPowUsedAsSquare();
+
+function intIntConstantsSmallNumbers() {
+ return 42 ** 3;
+}
+function intIntConstantsLargeNumbers() {
+ // The result does not fit in a integer.
+ return 42 ** 42;
+}
+function intIntSmallConstants() {
+ return 42 ** 3;
+}
+function intDoubleConstants() {
+ return 14 ** 42.5;
+}
+function doubleDoubleConstants() {
+ return 13.5 ** 42.5;
+}
+function doubleIntConstants() {
+ return 13.5 ** 52;
+}
+noInline(intIntConstantsSmallNumbers);
+noInline(intIntConstantsLargeNumbers);
+noInline(intDoubleConstants);
+noInline(doubleDoubleConstants);
+noInline(doubleIntConstants);
+
+function testBaseAndExponentConstantLiterals()
+{
+ for (var i = 0; i < 10000; ++i) {
+ var result = intIntConstantsSmallNumbers();
+ if (result !== 74088)
+ throw "Error: intIntConstantsSmallNumbers() should be 74088, was = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = intIntConstantsLargeNumbers();
+ if (result !== 1.5013093754529656e+68)
+ throw "Error: intIntConstantsLargeNumbers() should be 1.5013093754529656e+68, was = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = intDoubleConstants();
+ if (result !== 5.1338303882015765e+48)
+ throw "Error: intDoubleConstants() should be 5.1338303882015765e+48, was = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = doubleDoubleConstants();
+ if (result !== 1.0944228729647829e+48)
+ throw "Error: doubleDoubleConstants() should be 1.0944228729647829e+48, was = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = doubleIntConstants();
+ if (result !== 5.989022735311158e+58)
+ throw "Error: doubleIntConstants() should be 5.989022735311158e+58, was = " + result;
+ }
+}
+testBaseAndExponentConstantLiterals();
+
+
+function exponentIsIntegerConstant(x) {
+ return x ** 42;
+}
+noInline(exponentIsIntegerConstant);
+
+function testExponentIsIntegerConstant() {
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsIntegerConstant(2);
+ if (result !== 4398046511104)
+ throw "Error: exponentIsIntegerConstant(2) should be 4398046511104, was = " + result;
+ }
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsIntegerConstant(5);
+ if (result !== 2.2737367544323207e+29)
+ throw "Error: exponentIsIntegerConstant(5) should be 2.2737367544323207e+29, was = " + result;
+ }
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsIntegerConstant(2.1);
+ if (result !== 34135823067412.42)
+ throw "Error: exponentIsIntegerConstant(2.1) should be 34135823067412.42, was = " + result;
+ }
+}
+testExponentIsIntegerConstant();
+
+
+function exponentIsDoubleConstant(x) {
+ return x ** 42.5;
+}
+noInline(exponentIsDoubleConstant);
+
+function testExponentIsDoubleConstant() {
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsDoubleConstant(2);
+ if (result !== 6219777023950.95)
+ throw "Error: exponentIsDoubleConstant(2) should be 6219777023950.95, was = " + result;
+ }
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsDoubleConstant(5);
+ if (result !== 5.084229945850415e+29)
+ throw "Error: exponentIsDoubleConstant(5) should be 5.084229945850415e+29, was = " + result;
+ }
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsDoubleConstant(2.1);
+ if (result !== 49467507261113.805)
+ throw "Error: exponentIsDoubleConstant(2.1) should be 49467507261113.805, was = " + result;
+ }
+}
+testExponentIsDoubleConstant();
+
+
+function exponentIsInfinityConstant(x) {
+ return x ** Infinity;
+}
+noInline(exponentIsInfinityConstant);
+
+function testExponentIsInfinityConstant() {
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsInfinityConstant(2);
+ if (result !== Infinity)
+ throw "Error: exponentIsInfinityConstant(2) should be Infinity, was = " + result;
+ }
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsInfinityConstant(5);
+ if (result !== Infinity)
+ throw "Error: exponentIsInfinityConstant(5) should be Infinity, was = " + result;
+ }
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsInfinityConstant(2.1);
+ if (result !== Infinity)
+ throw "Error: exponentIsInfinityConstant(2.1) should be Infinity, was = " + result;
+ }
+}
+testExponentIsInfinityConstant();
+
+
+function exponentIsNegativeInfinityConstant(x) {
+ return x ** -Infinity;
+}
+noInline(exponentIsNegativeInfinityConstant);
+
+function testExponentIsNegativeInfinityConstant() {
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsNegativeInfinityConstant(2);
+ if (result !== 0)
+ throw "Error: exponentIsNegativeInfinityConstant(2) should be zero, was = " + result;
+ }
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsNegativeInfinityConstant(5);
+ if (result !== 0)
+ throw "Error: exponentIsNegativeInfinityConstant(5) should be zero, was = " + result;
+ }
+ for (var i = 0; i < 1000; ++i) {
+ var result = exponentIsNegativeInfinityConstant(2.1);
+ if (result !== 0)
+ throw "Error: exponentIsNegativeInfinityConstant(2.1) should be zero, was = " + result;
+ }
+}
+testExponentIsNegativeInfinityConstant();
Added: trunk/Source/_javascript_Core/tests/stress/pow-with-never-NaN-exponent.js (0 => 203499)
--- trunk/Source/_javascript_Core/tests/stress/pow-with-never-NaN-exponent.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/pow-with-never-NaN-exponent.js 2016-07-21 07:33:28 UTC (rev 203499)
@@ -0,0 +1,24 @@
+function exponentIsNonNanDouble1(x, doubleArrayIndex) {
+ var doubleArray = [4.4];
+ return x ** doubleArray[doubleArrayIndex];
+}
+noInline(exponentIsNonNanDouble1);
+
+function exponentIsNonNanDouble2(x, doubleArray) {
+ return x ** doubleArray[0];
+}
+noInline(exponentIsNonNanDouble2);
+
+function testExponentIsDoubleConstant() {
+ for (var i = 0; i < 10000; ++i) {
+ var result = exponentIsNonNanDouble1(2, 0);
+ if (result !== 21.112126572366314)
+ throw "Error: exponentIsNonNanDouble1(2, 0) should be 21.112126572366314, was = " + result;
+ }
+ for (var i = 0; i < 10000; ++i) {
+ var result = exponentIsNonNanDouble2(3, [-1.5]);
+ if (result !== 0.19245008972987526)
+ throw "Error: exponentIsNonNanDouble2(3, [-1.5]) should be 0.19245008972987526, was = " + result;
+ }
+}
+testExponentIsDoubleConstant();
Modified: trunk/Source/_javascript_Core/tests/test262.yaml (203498 => 203499)
--- trunk/Source/_javascript_Core/tests/test262.yaml 2016-07-21 07:29:39 UTC (rev 203498)
+++ trunk/Source/_javascript_Core/tests/test262.yaml 2016-07-21 07:33:28 UTC (rev 203499)
@@ -60822,113 +60822,113 @@
- path: test262/test/language/expressions/equals/symbol-strict-equality-comparison.js
cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A1.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A1.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A10.js
cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A10.js
cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A11.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A11.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A12.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A12.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A13.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A13.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A14.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A14.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A15.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A15.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A16.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A16.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A17.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A17.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A18.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A18.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A19.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A19.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A2.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A2.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A20.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A20.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A21.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A21.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A22.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A22.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A23.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A23.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A3.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A3.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A4.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A4.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A5.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A5.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A6.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A6.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A7.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A7.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A8.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A8.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A9.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/applying-the-exp-operator_A9.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/exp-assignment-operator.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/exp-assignment-operator.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/exp-operator-evaluation-order.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/exp-operator-evaluation-order.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/exp-operator-precedence-unary-_expression_-semantics.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/exp-operator-precedence-unary-_expression_-semantics.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/exp-operator-precedence-update-_expression_-semantics.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/exp-operator-precedence-update-_expression_-semantics.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/exp-operator-syntax-error-bitnot-unary-_expression_-base.js
cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/exp-operator-syntax-error-bitnot-unary-_expression_-base.js
@@ -60958,9 +60958,9 @@
- path: test262/test/language/expressions/exponentiation/exp-operator-syntax-error-void-unary-_expression_-base.js
cmd: runTest262 :normal, "SyntaxError", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/exponentiation/exp-operator.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/exponentiation/exp-operator.js
- cmd: runTest262 :fail, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
+ cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], [:strict]
- path: test262/test/language/expressions/function/S10.1.1_A1_T2.js
cmd: runTest262 :normal, "NoException", ["../../../../harness/assert.js", "../../../../harness/sta.js"], []
- path: test262/test/language/expressions/function/S10.1.1_A1_T2.js