Title: [203499] trunk/Source/_javascript_Core
Revision
203499
Author
[email protected]
Date
2016-07-21 00:33:28 -0700 (Thu, 21 Jul 2016)

Log Message

[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:

Modified Paths

Added Paths

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
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to