Changeset 206134 in webkit


Ignore:
Timestamp:
Sep 19, 2016 5:48:39 PM (8 years ago)
Author:
commit-queue@webkit.org
Message:

[JSC] Make the rounding-related nodes support any type
https://bugs.webkit.org/show_bug.cgi?id=161895

Patch by Benjamin Poulain <bpoulain@apple.com> on 2016-09-19
Reviewed by Geoffrey Garen.

JSTests:

  • stress/arith-ceil-on-various-types.js: Added.
  • stress/arith-floor-on-various-types.js: Added.
  • stress/arith-round-on-various-types.js: Added.
  • stress/arith-trunc-on-various-types.js: Added.

Source/JavaScriptCore:

This patch changes ArithRound, ArithFloor, ArithCeil and ArithTrunc
to support polymorphic input without exiting on entry.

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
The 4 functions ignore any input past the first argument. It is okay
to use the nodes with the first argument and let the Phantoms keep
the remaining arguments live.

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):
Our fixup had the issue we have seen on previous nodes: unaryArithShouldSpeculateInt32()
prevents us from picking a good type if we do not see any double.

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

Prediction propagation of those nodes are fully determined
from their flags and results's prediction. They are moved
to the invariant processing.

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileArithRounding):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileArithRound):
(JSC::FTL::DFG::LowerDFGToB3::compileArithFloor):
(JSC::FTL::DFG::LowerDFGToB3::compileArithCeil):
(JSC::FTL::DFG::LowerDFGToB3::compileArithTrunc):

Location:
trunk
Files:
4 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r206082 r206134  
     12016-09-19  Benjamin Poulain  <bpoulain@apple.com>
     2
     3        [JSC] Make the rounding-related nodes support any type
     4        https://bugs.webkit.org/show_bug.cgi?id=161895
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * stress/arith-ceil-on-various-types.js: Added.
     9        * stress/arith-floor-on-various-types.js: Added.
     10        * stress/arith-round-on-various-types.js: Added.
     11        * stress/arith-trunc-on-various-types.js: Added.
     12
    1132016-09-18  Yusuke Suzuki  <utatane.tea@gmail.com>
    214
  • trunk/Source/JavaScriptCore/ChangeLog

    r206128 r206134  
     12016-09-19  Benjamin Poulain  <bpoulain@apple.com>
     2
     3        [JSC] Make the rounding-related nodes support any type
     4        https://bugs.webkit.org/show_bug.cgi?id=161895
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch changes ArithRound, ArithFloor, ArithCeil and ArithTrunc
     9        to support polymorphic input without exiting on entry.
     10
     11        * dfg/DFGAbstractInterpreterInlines.h:
     12        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     13        * dfg/DFGByteCodeParser.cpp:
     14        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
     15        The 4 functions ignore any input past the first argument. It is okay
     16        to use the nodes with the first argument and let the Phantoms keep
     17        the remaining arguments live.
     18
     19        * dfg/DFGClobberize.h:
     20        (JSC::DFG::clobberize):
     21        * dfg/DFGFixupPhase.cpp:
     22        (JSC::DFG::FixupPhase::fixupNode):
     23        Our fixup had the issue we have seen on previous nodes: unaryArithShouldSpeculateInt32()
     24        prevents us from picking a good type if we do not see any double.
     25
     26        * dfg/DFGNodeType.h:
     27        * dfg/DFGOperations.cpp:
     28        * dfg/DFGOperations.h:
     29        * dfg/DFGPredictionPropagationPhase.cpp:
     30        Prediction propagation of those nodes are fully determined
     31        from their flags and results's prediction. They are moved
     32        to the invariant processing.
     33
     34        * dfg/DFGSpeculativeJIT.cpp:
     35        (JSC::DFG::SpeculativeJIT::compileArithRounding):
     36        * ftl/FTLLowerDFGToB3.cpp:
     37        (JSC::FTL::DFG::LowerDFGToB3::compileArithRound):
     38        (JSC::FTL::DFG::LowerDFGToB3::compileArithFloor):
     39        (JSC::FTL::DFG::LowerDFGToB3::compileArithCeil):
     40        (JSC::FTL::DFG::LowerDFGToB3::compileArithTrunc):
     41
    1422016-09-19  Yusuke Suzuki  <utatane.tea@gmail.com>
    243
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r206098 r206134  
    906906    case ArithTrunc: {
    907907        JSValue operand = forNode(node->child1()).value();
    908         if (operand && operand.isNumber()) {
     908        if (Optional<double> number = operand.toNumberFromPrimitive()) {
    909909            double roundedValue = 0;
    910910            if (node->op() == ArithRound)
    911                 roundedValue = jsRound(operand.asNumber());
     911                roundedValue = jsRound(*number);
    912912            else if (node->op() == ArithFloor)
    913                 roundedValue = floor(operand.asNumber());
     913                roundedValue = floor(*number);
    914914            else if (node->op() == ArithCeil)
    915                 roundedValue = ceil(operand.asNumber());
     915                roundedValue = ceil(*number);
    916916            else {
    917917                ASSERT(node->op() == ArithTrunc);
    918                 roundedValue = trunc(operand.asNumber());
    919             }
    920 
     918                roundedValue = trunc(*number);
     919            }
     920
     921            if (node->child1().useKind() == UntypedUse) {
     922                setConstant(node, jsNumber(roundedValue));
     923                break;
     924            }
    921925            if (producesInteger(node->arithRoundingMode())) {
    922926                int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
     
    937941            }
    938942        }
    939         if (producesInteger(node->arithRoundingMode()))
    940             forNode(node).setType(SpecInt32Only);
    941         else
    942             forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
     943        if (node->child1().useKind() == DoubleRepUse) {
     944            if (producesInteger(node->arithRoundingMode()))
     945                forNode(node).setType(SpecInt32Only);
     946            else if (node->child1().useKind() == DoubleRepUse)
     947                forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
     948        } else {
     949            DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse);
     950            forNode(node).setType(SpecFullNumber);
     951        }
    943952        break;
    944953    }
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r206104 r206134  
    24422442            return true;
    24432443        }
    2444         if (argumentCountIncludingThis == 2) {
    2445             insertChecks();
    2446             Node* operand = get(virtualRegisterForArgument(1, registerOffset));
    2447             NodeType op;
    2448             if (intrinsic == RoundIntrinsic)
    2449                 op = ArithRound;
    2450             else if (intrinsic == FloorIntrinsic)
    2451                 op = ArithFloor;
    2452             else if (intrinsic == CeilIntrinsic)
    2453                 op = ArithCeil;
    2454             else {
    2455                 ASSERT(intrinsic == TruncIntrinsic);
    2456                 op = ArithTrunc;
    2457             }
    2458             Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
    2459             set(VirtualRegister(resultOperand), roundNode);
    2460             return true;
    2461         }
    2462         return false;
     2444        insertChecks();
     2445        Node* operand = get(virtualRegisterForArgument(1, registerOffset));
     2446        NodeType op;
     2447        if (intrinsic == RoundIntrinsic)
     2448            op = ArithRound;
     2449        else if (intrinsic == FloorIntrinsic)
     2450            op = ArithFloor;
     2451        else if (intrinsic == CeilIntrinsic)
     2452            op = ArithCeil;
     2453        else {
     2454            ASSERT(intrinsic == TruncIntrinsic);
     2455            op = ArithTrunc;
     2456        }
     2457        Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
     2458        set(VirtualRegister(resultOperand), roundNode);
     2459        return true;
    24632460    }
    24642461    case IMulIntrinsic: {
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r206098 r206134  
    360360    case ArithCeil:
    361361    case ArithTrunc:
    362         def(PureValue(node, static_cast<uintptr_t>(node->arithRoundingMode())));
     362        if (node->child1().useKind() == DoubleRepUse)
     363            def(PureValue(node, static_cast<uintptr_t>(node->arithRoundingMode())));
     364        else {
     365            read(World);
     366            write(Heap);
     367        }
    363368        return;
    364369
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r206098 r206134  
    377377        case ArithCeil:
    378378        case ArithTrunc: {
    379             if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
     379            if (node->child1()->shouldSpeculateInt32OrBoolean() && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
    380380                fixIntOrBooleanEdge(node->child1());
    381381                insertCheck<Int32Use>(m_indexInBlock, node->child1().node());
     
    383383                break;
    384384            }
    385             fixDoubleOrBooleanEdge(node->child1());
    386 
    387             if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
    388                 node->setResult(NodeResultInt32);
    389                 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
    390                     node->setArithRoundingMode(Arith::RoundingMode::Int32);
    391                 else
    392                     node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
    393             } else {
    394                 node->setResult(NodeResultDouble);
    395                 node->setArithRoundingMode(Arith::RoundingMode::Double);
    396             }
     385            if (node->child1()->shouldSpeculateNotCell()) {
     386                fixDoubleOrBooleanEdge(node->child1());
     387
     388                if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
     389                    node->setResult(NodeResultInt32);
     390                    if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
     391                        node->setArithRoundingMode(Arith::RoundingMode::Int32);
     392                    else
     393                        node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
     394                } else {
     395                    node->setResult(NodeResultDouble);
     396                    node->setArithRoundingMode(Arith::RoundingMode::Double);
     397                }
     398                node->clearFlags(NodeMustGenerate);
     399            } else
     400                fixEdge<UntypedUse>(node->child1());
    397401            break;
    398402        }
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r206098 r206134  
    156156    macro(ArithPow, NodeResultDouble) \
    157157    macro(ArithRandom, NodeResultDouble | NodeMustGenerate) \
    158     macro(ArithRound, NodeResultNumber) \
    159     macro(ArithFloor, NodeResultNumber) \
    160     macro(ArithCeil, NodeResultNumber) \
    161     macro(ArithTrunc, NodeResultNumber) \
     158    macro(ArithRound, NodeResultNumber | NodeMustGenerate) \
     159    macro(ArithFloor, NodeResultNumber | NodeMustGenerate) \
     160    macro(ArithCeil, NodeResultNumber | NodeMustGenerate) \
     161    macro(ArithTrunc, NodeResultNumber | NodeMustGenerate) \
    162162    macro(ArithSqrt, NodeResultDouble | NodeMustGenerate) \
    163163    macro(ArithSin, NodeResultDouble | NodeMustGenerate) \
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r205974 r206134  
    443443}
    444444
     445EncodedJSValue JIT_OPERATION operationArithRound(ExecState* exec, EncodedJSValue encodedArgument)
     446{
     447    VM* vm = &exec->vm();
     448    NativeCallFrameTracer tracer(vm, exec);
     449    auto scope = DECLARE_THROW_SCOPE(*vm);
     450
     451    JSValue argument = JSValue::decode(encodedArgument);
     452    double valueOfArgument = argument.toNumber(exec);
     453    if (UNLIKELY(scope.exception()))
     454        return JSValue::encode(JSValue());
     455    return JSValue::encode(jsNumber(jsRound(valueOfArgument)));
     456}
     457
     458EncodedJSValue JIT_OPERATION operationArithFloor(ExecState* exec, EncodedJSValue encodedArgument)
     459{
     460    VM* vm = &exec->vm();
     461    NativeCallFrameTracer tracer(vm, exec);
     462    auto scope = DECLARE_THROW_SCOPE(*vm);
     463
     464    JSValue argument = JSValue::decode(encodedArgument);
     465    double valueOfArgument = argument.toNumber(exec);
     466    if (UNLIKELY(scope.exception()))
     467        return JSValue::encode(JSValue());
     468    return JSValue::encode(jsNumber(floor(valueOfArgument)));
     469}
     470
     471EncodedJSValue JIT_OPERATION operationArithCeil(ExecState* exec, EncodedJSValue encodedArgument)
     472{
     473    VM* vm = &exec->vm();
     474    NativeCallFrameTracer tracer(vm, exec);
     475    auto scope = DECLARE_THROW_SCOPE(*vm);
     476
     477    JSValue argument = JSValue::decode(encodedArgument);
     478    double valueOfArgument = argument.toNumber(exec);
     479    if (UNLIKELY(scope.exception()))
     480        return JSValue::encode(JSValue());
     481    return JSValue::encode(jsNumber(ceil(valueOfArgument)));
     482}
     483
     484EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState* exec, EncodedJSValue encodedArgument)
     485{
     486    VM* vm = &exec->vm();
     487    NativeCallFrameTracer tracer(vm, exec);
     488    auto scope = DECLARE_THROW_SCOPE(*vm);
     489
     490    JSValue argument = JSValue::decode(encodedArgument);
     491    double truncatedValueOfArgument = argument.toIntegerPreserveNaN(exec);
     492    if (UNLIKELY(scope.exception()))
     493        return JSValue::encode(JSValue());
     494    return JSValue::encode(jsNumber(truncatedValueOfArgument));
     495}
     496
    445497static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
    446498{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r205974 r206134  
    11/*
    2  * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    6262double JIT_OPERATION operationArithSin(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
    6363double JIT_OPERATION operationArithSqrt(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
     64EncodedJSValue JIT_OPERATION operationArithRound(ExecState*, EncodedJSValue) WTF_INTERNAL;
     65EncodedJSValue JIT_OPERATION operationArithFloor(ExecState*, EncodedJSValue) WTF_INTERNAL;
     66EncodedJSValue JIT_OPERATION operationArithCeil(ExecState*, EncodedJSValue) WTF_INTERNAL;
     67EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState*, EncodedJSValue) WTF_INTERNAL;
    6468EncodedJSValue JIT_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL;
    6569EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r206098 r206134  
    316316                    changed |= mergePrediction(SpecInt32Only | SpecBytecodeDouble);
    317317            }
    318             break;
    319         }
    320 
    321         case ArithRound:
    322         case ArithFloor:
    323         case ArithCeil:
    324         case ArithTrunc: {
    325             if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, m_pass))
    326                 changed |= setPrediction(SpecInt32Only);
    327             else
    328                 changed |= setPrediction(SpecBytecodeDouble);
    329318            break;
    330319        }
     
    777766        }
    778767
     768        case ArithRound:
     769        case ArithFloor:
     770        case ArithCeil:
     771        case ArithTrunc: {
     772            if (isInt32OrBooleanSpeculation(m_currentNode->getHeapPrediction())
     773                && m_graph.roundShouldSpeculateInt32(m_currentNode, m_pass))
     774                setPrediction(SpecInt32Only);
     775            else
     776                setPrediction(SpecBytecodeDouble);
     777            break;
     778        }
     779
    779780        case ArithRandom: {
    780781            setPrediction(SpecDoubleReal);
     
    949950        case ArithDiv:
    950951        case ArithMod:
    951         case ArithRound:
    952         case ArithFloor:
    953         case ArithCeil:
    954         case ArithTrunc:
    955952        case ArithAbs:
    956953        case GetByVal:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r206065 r206134  
    49164916void SpeculativeJIT::compileArithRounding(Node* node)
    49174917{
    4918     ASSERT(node->child1().useKind() == DoubleRepUse);
    4919 
    4920     SpeculateDoubleOperand value(this, node->child1());
    4921     FPRReg valueFPR = value.fpr();
    4922 
    4923     auto setResult = [&] (FPRReg resultFPR) {
    4924         if (producesInteger(node->arithRoundingMode())) {
    4925             GPRTemporary roundedResultAsInt32(this);
    4926             FPRTemporary scratch(this);
    4927             FPRReg scratchFPR = scratch.fpr();
    4928             GPRReg resultGPR = roundedResultAsInt32.gpr();
    4929             JITCompiler::JumpList failureCases;
    4930             m_jit.branchConvertDoubleToInt32(resultFPR, resultGPR, failureCases, scratchFPR, shouldCheckNegativeZero(node->arithRoundingMode()));
    4931             speculationCheck(Overflow, JSValueRegs(), node, failureCases);
    4932 
    4933             int32Result(resultGPR, node);
    4934         } else
    4935             doubleResult(resultFPR, node);
    4936     };
    4937 
    4938     if (m_jit.supportsFloatingPointRounding()) {
    4939         switch (node->op()) {
    4940         case ArithRound: {
    4941             FPRTemporary result(this);
    4942             FPRReg resultFPR = result.fpr();
    4943             if (producesInteger(node->arithRoundingMode()) && !shouldCheckNegativeZero(node->arithRoundingMode())) {
    4944                 static const double halfConstant = 0.5;
    4945                 m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), resultFPR);
    4946                 m_jit.addDouble(valueFPR, resultFPR);
    4947                 m_jit.floorDouble(resultFPR, resultFPR);
    4948             } else {
    4949                 m_jit.ceilDouble(valueFPR, resultFPR);
    4950                 FPRTemporary realPart(this);
    4951                 FPRReg realPartFPR = realPart.fpr();
    4952                 m_jit.subDouble(resultFPR, valueFPR, realPartFPR);
    4953 
     4918    if (node->child1().useKind() == DoubleRepUse) {
     4919        SpeculateDoubleOperand value(this, node->child1());
     4920        FPRReg valueFPR = value.fpr();
     4921
     4922        auto setResult = [&] (FPRReg resultFPR) {
     4923            if (producesInteger(node->arithRoundingMode())) {
     4924                GPRTemporary roundedResultAsInt32(this);
    49544925                FPRTemporary scratch(this);
    49554926                FPRReg scratchFPR = scratch.fpr();
    4956                 static const double halfConstant = 0.5;
    4957                 m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), scratchFPR);
    4958 
    4959                 JITCompiler::Jump shouldUseCeiled = m_jit.branchDouble(JITCompiler::DoubleLessThanOrEqual, realPartFPR, scratchFPR);
    4960                 static const double oneConstant = -1.0;
    4961                 m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&oneConstant), scratchFPR);
    4962                 m_jit.addDouble(scratchFPR, resultFPR);
    4963                 shouldUseCeiled.link(&m_jit);
     4927                GPRReg resultGPR = roundedResultAsInt32.gpr();
     4928                JITCompiler::JumpList failureCases;
     4929                m_jit.branchConvertDoubleToInt32(resultFPR, resultGPR, failureCases, scratchFPR, shouldCheckNegativeZero(node->arithRoundingMode()));
     4930                speculationCheck(Overflow, JSValueRegs(), node, failureCases);
     4931
     4932                int32Result(resultGPR, node);
     4933            } else
     4934                doubleResult(resultFPR, node);
     4935        };
     4936
     4937        if (m_jit.supportsFloatingPointRounding()) {
     4938            switch (node->op()) {
     4939            case ArithRound: {
     4940                FPRTemporary result(this);
     4941                FPRReg resultFPR = result.fpr();
     4942                if (producesInteger(node->arithRoundingMode()) && !shouldCheckNegativeZero(node->arithRoundingMode())) {
     4943                    static const double halfConstant = 0.5;
     4944                    m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), resultFPR);
     4945                    m_jit.addDouble(valueFPR, resultFPR);
     4946                    m_jit.floorDouble(resultFPR, resultFPR);
     4947                } else {
     4948                    m_jit.ceilDouble(valueFPR, resultFPR);
     4949                    FPRTemporary realPart(this);
     4950                    FPRReg realPartFPR = realPart.fpr();
     4951                    m_jit.subDouble(resultFPR, valueFPR, realPartFPR);
     4952
     4953                    FPRTemporary scratch(this);
     4954                    FPRReg scratchFPR = scratch.fpr();
     4955                    static const double halfConstant = 0.5;
     4956                    m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&halfConstant), scratchFPR);
     4957
     4958                    JITCompiler::Jump shouldUseCeiled = m_jit.branchDouble(JITCompiler::DoubleLessThanOrEqual, realPartFPR, scratchFPR);
     4959                    static const double oneConstant = -1.0;
     4960                    m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&oneConstant), scratchFPR);
     4961                    m_jit.addDouble(scratchFPR, resultFPR);
     4962                    shouldUseCeiled.link(&m_jit);
     4963                }
     4964                setResult(resultFPR);
     4965                return;
     4966            }
     4967
     4968            case ArithFloor: {
     4969                FPRTemporary rounded(this);
     4970                FPRReg resultFPR = rounded.fpr();
     4971                m_jit.floorDouble(valueFPR, resultFPR);
     4972                setResult(resultFPR);
     4973                return;
     4974            }
     4975
     4976            case ArithCeil: {
     4977                FPRTemporary rounded(this);
     4978                FPRReg resultFPR = rounded.fpr();
     4979                m_jit.ceilDouble(valueFPR, resultFPR);
     4980                setResult(resultFPR);
     4981                return;
     4982            }
     4983
     4984            case ArithTrunc: {
     4985                FPRTemporary rounded(this);
     4986                FPRReg resultFPR = rounded.fpr();
     4987                m_jit.roundTowardZeroDouble(valueFPR, resultFPR);
     4988                setResult(resultFPR);
     4989                return;
     4990            }
     4991
     4992            default:
     4993                RELEASE_ASSERT_NOT_REACHED();
     4994            }
     4995        } else {
     4996            flushRegisters();
     4997            FPRResult roundedResultAsDouble(this);
     4998            FPRReg resultFPR = roundedResultAsDouble.fpr();
     4999            if (node->op() == ArithRound)
     5000                callOperation(jsRound, resultFPR, valueFPR);
     5001            else if (node->op() == ArithFloor)
     5002                callOperation(floor, resultFPR, valueFPR);
     5003            else if (node->op() == ArithCeil)
     5004                callOperation(ceil, resultFPR, valueFPR);
     5005            else {
     5006                ASSERT(node->op() == ArithTrunc);
     5007                callOperation(trunc, resultFPR, valueFPR);
    49645008            }
    49655009            setResult(resultFPR);
    4966             return;
    4967         }
    4968 
    4969         case ArithFloor: {
    4970             FPRTemporary rounded(this);
    4971             FPRReg resultFPR = rounded.fpr();
    4972             m_jit.floorDouble(valueFPR, resultFPR);
    4973             setResult(resultFPR);
    4974             return;
    4975         }
    4976 
    4977         case ArithCeil: {
    4978             FPRTemporary rounded(this);
    4979             FPRReg resultFPR = rounded.fpr();
    4980             m_jit.ceilDouble(valueFPR, resultFPR);
    4981             setResult(resultFPR);
    4982             return;
    4983         }
    4984 
    4985         case ArithTrunc: {
    4986             FPRTemporary rounded(this);
    4987             FPRReg resultFPR = rounded.fpr();
    4988             m_jit.roundTowardZeroDouble(valueFPR, resultFPR);
    4989             setResult(resultFPR);
    4990             return;
    4991         }
    4992 
    4993         default:
    4994             RELEASE_ASSERT_NOT_REACHED();
    4995         }
    4996     } else {
    4997         flushRegisters();
    4998         FPRResult roundedResultAsDouble(this);
    4999         FPRReg resultFPR = roundedResultAsDouble.fpr();
    5000         if (node->op() == ArithRound)
    5001             callOperation(jsRound, resultFPR, valueFPR);
    5002         else if (node->op() == ArithFloor)
    5003             callOperation(floor, resultFPR, valueFPR);
    5004         else if (node->op() == ArithCeil)
    5005             callOperation(ceil, resultFPR, valueFPR);
    5006         else {
    5007             ASSERT(node->op() == ArithTrunc);
    5008             callOperation(trunc, resultFPR, valueFPR);
    5009         }
    5010         m_jit.exceptionCheck();
    5011         setResult(resultFPR);
    5012     }
     5010        }
     5011        return;
     5012    }
     5013
     5014    DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse);
     5015
     5016    JSValueOperand argument(this, node->child1());
     5017    JSValueRegs argumentRegs = argument.jsValueRegs();
     5018#if USE(JSVALUE64)
     5019    GPRTemporary result(this);
     5020    JSValueRegs resultRegs = JSValueRegs(result.gpr());
     5021#else
     5022    GPRTemporary resultTag(this);
     5023    GPRTemporary resultPayload(this);
     5024    JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
     5025#endif
     5026    flushRegisters();
     5027    J_JITOperation_EJ operation = nullptr;
     5028    if (node->op() == ArithRound)
     5029        operation = operationArithRound;
     5030    else if (node->op() == ArithFloor)
     5031        operation = operationArithFloor;
     5032    else if (node->op() == ArithCeil)
     5033        operation = operationArithCeil;
     5034    else {
     5035        ASSERT(node->op() == ArithTrunc);
     5036        operation = operationArithTrunc;
     5037    }
     5038    callOperation(operation, resultRegs, argumentRegs);
     5039    m_jit.exceptionCheck();
     5040    jsValueResult(resultRegs, node);
    50135041}
    50145042
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r206098 r206134  
    22612261    void compileArithRound()
    22622262    {
    2263         LValue result = nullptr;
    2264 
    2265         if (producesInteger(m_node->arithRoundingMode()) && !shouldCheckNegativeZero(m_node->arithRoundingMode())) {
     2263        if (m_node->child1().useKind() == DoubleRepUse) {
     2264            LValue result = nullptr;
     2265            if (producesInteger(m_node->arithRoundingMode()) && !shouldCheckNegativeZero(m_node->arithRoundingMode())) {
     2266                LValue value = lowDouble(m_node->child1());
     2267                result = m_out.doubleFloor(m_out.doubleAdd(value, m_out.constDouble(0.5)));
     2268            } else {
     2269                LBasicBlock realPartIsMoreThanHalf = m_out.newBlock();
     2270                LBasicBlock continuation = m_out.newBlock();
     2271
     2272                LValue value = lowDouble(m_node->child1());
     2273                LValue integerValue = m_out.doubleCeil(value);
     2274                ValueFromBlock integerValueResult = m_out.anchor(integerValue);
     2275
     2276                LValue realPart = m_out.doubleSub(integerValue, value);
     2277
     2278                m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation));
     2279
     2280                LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation);
     2281                LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1));
     2282                ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown);
     2283                m_out.jump(continuation);
     2284                m_out.appendTo(continuation, lastNext);
     2285
     2286                result = m_out.phi(Double, integerValueResult, integerValueRoundedDownResult);
     2287            }
     2288
     2289            if (producesInteger(m_node->arithRoundingMode())) {
     2290                LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()));
     2291                setInt32(integerValue);
     2292            } else
     2293                setDouble(result);
     2294            return;
     2295        }
     2296
     2297        DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
     2298        LValue argument = lowJSValue(m_node->child1());
     2299        setJSValue(vmCall(Int64, m_out.operation(operationArithRound), m_callFrame, argument));
     2300    }
     2301
     2302    void compileArithFloor()
     2303    {
     2304        if (m_node->child1().useKind() == DoubleRepUse) {
    22662305            LValue value = lowDouble(m_node->child1());
    2267             result = m_out.doubleFloor(m_out.doubleAdd(value, m_out.constDouble(0.5)));
    2268         } else {
    2269             LBasicBlock realPartIsMoreThanHalf = m_out.newBlock();
    2270             LBasicBlock continuation = m_out.newBlock();
    2271 
     2306            LValue integerValue = m_out.doubleFloor(value);
     2307            if (producesInteger(m_node->arithRoundingMode()))
     2308                setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
     2309            else
     2310                setDouble(integerValue);
     2311            return;
     2312        }
     2313        DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
     2314        LValue argument = lowJSValue(m_node->child1());
     2315        setJSValue(vmCall(Int64, m_out.operation(operationArithFloor), m_callFrame, argument));
     2316    }
     2317
     2318    void compileArithCeil()
     2319    {
     2320        if (m_node->child1().useKind() == DoubleRepUse) {
    22722321            LValue value = lowDouble(m_node->child1());
    22732322            LValue integerValue = m_out.doubleCeil(value);
    2274             ValueFromBlock integerValueResult = m_out.anchor(integerValue);
    2275 
    2276             LValue realPart = m_out.doubleSub(integerValue, value);
    2277 
    2278             m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation));
    2279 
    2280             LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation);
    2281             LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1));
    2282             ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown);
    2283             m_out.jump(continuation);
    2284             m_out.appendTo(continuation, lastNext);
    2285 
    2286             result = m_out.phi(Double, integerValueResult, integerValueRoundedDownResult);
    2287         }
    2288 
    2289         if (producesInteger(m_node->arithRoundingMode())) {
    2290             LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()));
    2291             setInt32(integerValue);
    2292         } else
    2293             setDouble(result);
    2294     }
    2295 
    2296     void compileArithFloor()
    2297     {
    2298         LValue value = lowDouble(m_node->child1());
    2299         LValue integerValue = m_out.doubleFloor(value);
    2300         if (producesInteger(m_node->arithRoundingMode()))
    2301             setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
    2302         else
    2303             setDouble(integerValue);
    2304     }
    2305 
    2306     void compileArithCeil()
    2307     {
    2308         LValue value = lowDouble(m_node->child1());
    2309         LValue integerValue = m_out.doubleCeil(value);
    2310         if (producesInteger(m_node->arithRoundingMode()))
    2311             setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
    2312         else
    2313             setDouble(integerValue);
     2323            if (producesInteger(m_node->arithRoundingMode()))
     2324                setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
     2325            else
     2326                setDouble(integerValue);
     2327            return;
     2328        }
     2329        DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
     2330        LValue argument = lowJSValue(m_node->child1());
     2331        setJSValue(vmCall(Int64, m_out.operation(operationArithCeil), m_callFrame, argument));
    23142332    }
    23152333
    23162334    void compileArithTrunc()
    23172335    {
    2318         LValue value = lowDouble(m_node->child1());
    2319         LValue result = m_out.doubleTrunc(value);
    2320         if (producesInteger(m_node->arithRoundingMode()))
    2321             setInt32(convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode())));
    2322         else
    2323             setDouble(result);
     2336        if (m_node->child1().useKind() == DoubleRepUse) {
     2337            LValue value = lowDouble(m_node->child1());
     2338            LValue result = m_out.doubleTrunc(value);
     2339            if (producesInteger(m_node->arithRoundingMode()))
     2340                setInt32(convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode())));
     2341            else
     2342                setDouble(result);
     2343            return;
     2344        }
     2345        DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
     2346        LValue argument = lowJSValue(m_node->child1());
     2347        setJSValue(vmCall(Int64, m_out.operation(operationArithTrunc), m_callFrame, argument));
    23242348    }
    23252349
  • trunk/Source/JavaScriptCore/jsc.cpp

    r206065 r206134  
    5353#include "JSWASMModule.h"
    5454#include "LLIntData.h"
     55#include "ObjectConstructor.h"
    5556#include "ParserError.h"
    5657#include "ProfilerDatabase.h"
     
    6970#include <string.h>
    7071#include <thread>
     72#include <type_traits>
    7173#include <wtf/CurrentTime.h>
    7274#include <wtf/MainThread.h>
     
    613615static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
    614616static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
     617static EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState*);
    615618static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
    616619static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
     
    818821        addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1);
    819822        addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
     823        addFunction(vm, "jscOptions", functionJSCOptions, 0);
    820824        addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
    821825        addFunction(vm, "reoptimizationRetryCount", functionReoptimizationRetryCount, 1);
     
    17161720}
    17171721
     1722template<typename ValueType>
     1723typename std::enable_if<!std::is_fundamental<ValueType>::value>::type addOption(VM&, JSObject*, Identifier, ValueType) { }
     1724
     1725template<typename ValueType>
     1726typename std::enable_if<std::is_fundamental<ValueType>::value>::type addOption(VM& vm, JSObject* optionsObject, Identifier identifier, ValueType value)
     1727{
     1728    optionsObject->putDirect(vm, identifier, JSValue(value));
     1729}
     1730
     1731EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState* exec)
     1732{
     1733    JSObject* optionsObject = constructEmptyObject(exec);
     1734#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
     1735    addOption(exec->vm(), optionsObject, Identifier::fromString(exec, #name_), Options::name_());
     1736    JSC_OPTIONS(FOR_EACH_OPTION)
     1737#undef FOR_EACH_OPTION
     1738    return JSValue::encode(optionsObject);
     1739}
     1740
    17181741EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState* exec)
    17191742{
Note: See TracChangeset for help on using the changeset viewer.