Changeset 194113 in webkit


Ignore:
Timestamp:
Dec 15, 2015, 1:19:31 PM (9 years ago)
Author:
mark.lam@apple.com
Message:

Polymorphic operand types for DFG and FTL bit operators.
https://bugs.webkit.org/show_bug.cgi?id=152191

Reviewed by Saam Barati.

Source/JavaScriptCore:

  • bytecode/SpeculatedType.h:

(JSC::isUntypedSpeculationForBitOps):

  • dfg/DFGAbstractInterpreterInlines.h:

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

  • dfg/DFGNode.h:

(JSC::DFG::Node::shouldSpeculateUntypedForBitOps):

  • Added check for types not supported by ValueToInt32, and therefore should be treated as untyped for bitops.
  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • Handled untyped operands.
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • Added DFG slow path functions for bitops.
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::emitUntypedBitOp):
(JSC::DFG::SpeculativeJIT::compileBitwiseOp):
(JSC::DFG::SpeculativeJIT::emitUntypedRightShiftBitOp):
(JSC::DFG::SpeculativeJIT::compileShiftOp):

  • dfg/DFGSpeculativeJIT.h:
  • Added DFG backend support untyped operands for bitops.
  • dfg/DFGStrengthReductionPhase.cpp:

(JSC::DFG::StrengthReductionPhase::handleNode):

  • Limit bitops strength reduction only to when we don't have untyped operands. This is because values that are not int32s need to be converted to int32. Without untyped operands, the ValueToInt32 node takes care of this. With untyped operands, we cannot use ValueToInt32, and need to do the conversion in the code emitted for the bitop node itself. For example:

5.5 | 0; yields 5 because ValueToInt32 converts the 5.5 to a 5.
"abc" | 0;
would yield "abc" instead of the expected 0 if we let

strength reduction do its thing.

  • ftl/FTLCompileBinaryOp.cpp:

(JSC::FTL::generateBinaryBitOpFastPath):
(JSC::FTL::generateRightShiftFastPath):
(JSC::FTL::generateBinaryOpFastPath):

  • ftl/FTLInlineCacheDescriptor.h:

(JSC::FTL::BitAndDescriptor::BitAndDescriptor):
(JSC::FTL::BitAndDescriptor::icSize):
(JSC::FTL::BitAndDescriptor::nodeType):
(JSC::FTL::BitAndDescriptor::opName):
(JSC::FTL::BitAndDescriptor::slowPathFunction):
(JSC::FTL::BitAndDescriptor::nonNumberSlowPathFunction):
(JSC::FTL::BitOrDescriptor::BitOrDescriptor):
(JSC::FTL::BitOrDescriptor::icSize):
(JSC::FTL::BitOrDescriptor::nodeType):
(JSC::FTL::BitOrDescriptor::opName):
(JSC::FTL::BitOrDescriptor::slowPathFunction):
(JSC::FTL::BitOrDescriptor::nonNumberSlowPathFunction):
(JSC::FTL::BitXorDescriptor::BitXorDescriptor):
(JSC::FTL::BitXorDescriptor::icSize):
(JSC::FTL::BitXorDescriptor::nodeType):
(JSC::FTL::BitXorDescriptor::opName):
(JSC::FTL::BitXorDescriptor::slowPathFunction):
(JSC::FTL::BitXorDescriptor::nonNumberSlowPathFunction):
(JSC::FTL::BitLShiftDescriptor::BitLShiftDescriptor):
(JSC::FTL::BitLShiftDescriptor::icSize):
(JSC::FTL::BitLShiftDescriptor::nodeType):
(JSC::FTL::BitLShiftDescriptor::opName):
(JSC::FTL::BitLShiftDescriptor::slowPathFunction):
(JSC::FTL::BitLShiftDescriptor::nonNumberSlowPathFunction):
(JSC::FTL::BitRShiftDescriptor::BitRShiftDescriptor):
(JSC::FTL::BitRShiftDescriptor::icSize):
(JSC::FTL::BitRShiftDescriptor::nodeType):
(JSC::FTL::BitRShiftDescriptor::opName):
(JSC::FTL::BitRShiftDescriptor::slowPathFunction):
(JSC::FTL::BitRShiftDescriptor::nonNumberSlowPathFunction):
(JSC::FTL::BitURShiftDescriptor::BitURShiftDescriptor):
(JSC::FTL::BitURShiftDescriptor::icSize):
(JSC::FTL::BitURShiftDescriptor::nodeType):
(JSC::FTL::BitURShiftDescriptor::opName):
(JSC::FTL::BitURShiftDescriptor::slowPathFunction):
(JSC::FTL::BitURShiftDescriptor::nonNumberSlowPathFunction):

  • Added support for bitop ICs.
  • ftl/FTLInlineCacheSize.cpp:

(JSC::FTL::sizeOfBitAnd):
(JSC::FTL::sizeOfBitOr):
(JSC::FTL::sizeOfBitXor):
(JSC::FTL::sizeOfBitLShift):
(JSC::FTL::sizeOfBitRShift):
(JSC::FTL::sizeOfBitURShift):

  • ftl/FTLInlineCacheSize.h:
  • Added new bitop IC sizes. These are just estimates for now that work adequately, and are shown to not impact performance on benchmarks. We will re-tune these sizes values later in another patch once all snippet ICs have been added.
  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::DFG::LowerDFGToLLVM::compileBitAnd):
(JSC::FTL::DFG::LowerDFGToLLVM::compileBitOr):
(JSC::FTL::DFG::LowerDFGToLLVM::compileBitXor):
(JSC::FTL::DFG::LowerDFGToLLVM::compileBitRShift):
(JSC::FTL::DFG::LowerDFGToLLVM::compileBitLShift):
(JSC::FTL::DFG::LowerDFGToLLVM::compileBitURShift):

  • Added support for bitop ICs.
  • jit/JITLeftShiftGenerator.cpp:

(JSC::JITLeftShiftGenerator::generateFastPath):

  • jit/JITLeftShiftGenerator.h:

(JSC::JITLeftShiftGenerator::JITLeftShiftGenerator):

  • jit/JITRightShiftGenerator.cpp:

(JSC::JITRightShiftGenerator::generateFastPath):

  • The shift MASM operatons need to ensure that the shiftAmount is not in the same register as the destination register. With the baselineJIT and DFG, this is ensured in how we allocate these registers, and hence, the bug does not manifest. With the FTL, these registers are not guaranteed to be unique. Hence, we need to fix the shift op snippet code to compensate for this.

LayoutTests:

  • js/regress/ftl-polymorphic-bitand-expected.txt: Added.
  • js/regress/ftl-polymorphic-bitand.html: Added.
  • js/regress/ftl-polymorphic-bitor-expected.txt: Added.
  • js/regress/ftl-polymorphic-bitor.html: Added.
  • js/regress/ftl-polymorphic-bitxor-expected.txt: Added.
  • js/regress/ftl-polymorphic-bitxor.html: Added.
  • js/regress/ftl-polymorphic-lshift-expected.txt: Added.
  • js/regress/ftl-polymorphic-lshift.html: Added.
  • js/regress/ftl-polymorphic-rshift-expected.txt: Added.
  • js/regress/ftl-polymorphic-rshift.html: Added.
  • js/regress/ftl-polymorphic-urshift-expected.txt: Added.
  • js/regress/ftl-polymorphic-urshift.html: Added.
  • js/regress/script-tests/ftl-polymorphic-bitand.js: Added.

(o1.valueOf):
(foo):

  • js/regress/script-tests/ftl-polymorphic-bitor.js: Added.

(o1.valueOf):
(foo):

  • js/regress/script-tests/ftl-polymorphic-bitxor.js: Added.

(o1.valueOf):
(foo):

  • js/regress/script-tests/ftl-polymorphic-lshift.js: Added.

(o1.valueOf):
(foo):

  • js/regress/script-tests/ftl-polymorphic-rshift.js: Added.

(o1.valueOf):
(foo):

  • js/regress/script-tests/ftl-polymorphic-urshift.js: Added.

(o1.valueOf):
(foo):

Location:
trunk
Files:
18 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r194112 r194113  
     12015-12-15  Mark Lam  <mark.lam@apple.com>
     2
     3        Polymorphic operand types for DFG and FTL bit operators.
     4        https://bugs.webkit.org/show_bug.cgi?id=152191
     5
     6        Reviewed by Saam Barati.
     7
     8        * js/regress/ftl-polymorphic-bitand-expected.txt: Added.
     9        * js/regress/ftl-polymorphic-bitand.html: Added.
     10        * js/regress/ftl-polymorphic-bitor-expected.txt: Added.
     11        * js/regress/ftl-polymorphic-bitor.html: Added.
     12        * js/regress/ftl-polymorphic-bitxor-expected.txt: Added.
     13        * js/regress/ftl-polymorphic-bitxor.html: Added.
     14        * js/regress/ftl-polymorphic-lshift-expected.txt: Added.
     15        * js/regress/ftl-polymorphic-lshift.html: Added.
     16        * js/regress/ftl-polymorphic-rshift-expected.txt: Added.
     17        * js/regress/ftl-polymorphic-rshift.html: Added.
     18        * js/regress/ftl-polymorphic-urshift-expected.txt: Added.
     19        * js/regress/ftl-polymorphic-urshift.html: Added.
     20        * js/regress/script-tests/ftl-polymorphic-bitand.js: Added.
     21        (o1.valueOf):
     22        (foo):
     23        * js/regress/script-tests/ftl-polymorphic-bitor.js: Added.
     24        (o1.valueOf):
     25        (foo):
     26        * js/regress/script-tests/ftl-polymorphic-bitxor.js: Added.
     27        (o1.valueOf):
     28        (foo):
     29        * js/regress/script-tests/ftl-polymorphic-lshift.js: Added.
     30        (o1.valueOf):
     31        (foo):
     32        * js/regress/script-tests/ftl-polymorphic-rshift.js: Added.
     33        (o1.valueOf):
     34        (foo):
     35        * js/regress/script-tests/ftl-polymorphic-urshift.js: Added.
     36        (o1.valueOf):
     37        (foo):
     38
    1392015-12-15  Adam Bergkvist  <adam.bergkvist@ericsson.com>
    240
  • trunk/Source/JavaScriptCore/ChangeLog

    r194107 r194113  
     12015-12-15  Mark Lam  <mark.lam@apple.com>
     2
     3        Polymorphic operand types for DFG and FTL bit operators.
     4        https://bugs.webkit.org/show_bug.cgi?id=152191
     5
     6        Reviewed by Saam Barati.
     7
     8        * bytecode/SpeculatedType.h:
     9        (JSC::isUntypedSpeculationForBitOps):
     10        * dfg/DFGAbstractInterpreterInlines.h:
     11        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     12        * dfg/DFGNode.h:
     13        (JSC::DFG::Node::shouldSpeculateUntypedForBitOps):
     14        - Added check for types not supported by ValueToInt32, and therefore should be
     15          treated as untyped for bitops.
     16
     17        * dfg/DFGClobberize.h:
     18        (JSC::DFG::clobberize):
     19        * dfg/DFGFixupPhase.cpp:
     20        (JSC::DFG::FixupPhase::fixupNode):
     21        - Handled untyped operands.
     22
     23        * dfg/DFGOperations.cpp:
     24        * dfg/DFGOperations.h:
     25        - Added DFG slow path functions for bitops.
     26
     27        * dfg/DFGSpeculativeJIT.cpp:
     28        (JSC::DFG::SpeculativeJIT::emitUntypedBitOp):
     29        (JSC::DFG::SpeculativeJIT::compileBitwiseOp):
     30        (JSC::DFG::SpeculativeJIT::emitUntypedRightShiftBitOp):
     31        (JSC::DFG::SpeculativeJIT::compileShiftOp):
     32        * dfg/DFGSpeculativeJIT.h:
     33        - Added DFG backend support untyped operands for bitops.
     34
     35        * dfg/DFGStrengthReductionPhase.cpp:
     36        (JSC::DFG::StrengthReductionPhase::handleNode):
     37        - Limit bitops strength reduction only to when we don't have untyped operands.
     38          This is because values that are not int32s need to be converted to int32.
     39          Without untyped operands, the ValueToInt32 node takes care of this.
     40          With untyped operands, we cannot use ValueToInt32, and need to do the conversion
     41          in the code emitted for the bitop node itself.  For example:
     42
     43              5.5 | 0; // yields 5 because ValueToInt32 converts the 5.5 to a 5.
     44              "abc" | 0; // would yield "abc" instead of the expected 0 if we let
     45                         // strength reduction do its thing.
     46
     47        * ftl/FTLCompileBinaryOp.cpp:
     48        (JSC::FTL::generateBinaryBitOpFastPath):
     49        (JSC::FTL::generateRightShiftFastPath):
     50        (JSC::FTL::generateBinaryOpFastPath):
     51
     52        * ftl/FTLInlineCacheDescriptor.h:
     53        (JSC::FTL::BitAndDescriptor::BitAndDescriptor):
     54        (JSC::FTL::BitAndDescriptor::icSize):
     55        (JSC::FTL::BitAndDescriptor::nodeType):
     56        (JSC::FTL::BitAndDescriptor::opName):
     57        (JSC::FTL::BitAndDescriptor::slowPathFunction):
     58        (JSC::FTL::BitAndDescriptor::nonNumberSlowPathFunction):
     59        (JSC::FTL::BitOrDescriptor::BitOrDescriptor):
     60        (JSC::FTL::BitOrDescriptor::icSize):
     61        (JSC::FTL::BitOrDescriptor::nodeType):
     62        (JSC::FTL::BitOrDescriptor::opName):
     63        (JSC::FTL::BitOrDescriptor::slowPathFunction):
     64        (JSC::FTL::BitOrDescriptor::nonNumberSlowPathFunction):
     65        (JSC::FTL::BitXorDescriptor::BitXorDescriptor):
     66        (JSC::FTL::BitXorDescriptor::icSize):
     67        (JSC::FTL::BitXorDescriptor::nodeType):
     68        (JSC::FTL::BitXorDescriptor::opName):
     69        (JSC::FTL::BitXorDescriptor::slowPathFunction):
     70        (JSC::FTL::BitXorDescriptor::nonNumberSlowPathFunction):
     71        (JSC::FTL::BitLShiftDescriptor::BitLShiftDescriptor):
     72        (JSC::FTL::BitLShiftDescriptor::icSize):
     73        (JSC::FTL::BitLShiftDescriptor::nodeType):
     74        (JSC::FTL::BitLShiftDescriptor::opName):
     75        (JSC::FTL::BitLShiftDescriptor::slowPathFunction):
     76        (JSC::FTL::BitLShiftDescriptor::nonNumberSlowPathFunction):
     77        (JSC::FTL::BitRShiftDescriptor::BitRShiftDescriptor):
     78        (JSC::FTL::BitRShiftDescriptor::icSize):
     79        (JSC::FTL::BitRShiftDescriptor::nodeType):
     80        (JSC::FTL::BitRShiftDescriptor::opName):
     81        (JSC::FTL::BitRShiftDescriptor::slowPathFunction):
     82        (JSC::FTL::BitRShiftDescriptor::nonNumberSlowPathFunction):
     83        (JSC::FTL::BitURShiftDescriptor::BitURShiftDescriptor):
     84        (JSC::FTL::BitURShiftDescriptor::icSize):
     85        (JSC::FTL::BitURShiftDescriptor::nodeType):
     86        (JSC::FTL::BitURShiftDescriptor::opName):
     87        (JSC::FTL::BitURShiftDescriptor::slowPathFunction):
     88        (JSC::FTL::BitURShiftDescriptor::nonNumberSlowPathFunction):
     89        - Added support for bitop ICs.
     90
     91        * ftl/FTLInlineCacheSize.cpp:
     92        (JSC::FTL::sizeOfBitAnd):
     93        (JSC::FTL::sizeOfBitOr):
     94        (JSC::FTL::sizeOfBitXor):
     95        (JSC::FTL::sizeOfBitLShift):
     96        (JSC::FTL::sizeOfBitRShift):
     97        (JSC::FTL::sizeOfBitURShift):
     98        * ftl/FTLInlineCacheSize.h:
     99        - Added new bitop IC sizes.  These are just estimates for now that work adequately,
     100          and are shown to not impact performance on benchmarks.  We will re-tune these
     101          sizes values later in another patch once all snippet ICs have been added.
     102
     103        * ftl/FTLLowerDFGToLLVM.cpp:
     104        (JSC::FTL::DFG::LowerDFGToLLVM::compileBitAnd):
     105        (JSC::FTL::DFG::LowerDFGToLLVM::compileBitOr):
     106        (JSC::FTL::DFG::LowerDFGToLLVM::compileBitXor):
     107        (JSC::FTL::DFG::LowerDFGToLLVM::compileBitRShift):
     108        (JSC::FTL::DFG::LowerDFGToLLVM::compileBitLShift):
     109        (JSC::FTL::DFG::LowerDFGToLLVM::compileBitURShift):
     110        - Added support for bitop ICs.
     111
     112        * jit/JITLeftShiftGenerator.cpp:
     113        (JSC::JITLeftShiftGenerator::generateFastPath):
     114        * jit/JITLeftShiftGenerator.h:
     115        (JSC::JITLeftShiftGenerator::JITLeftShiftGenerator):
     116        * jit/JITRightShiftGenerator.cpp:
     117        (JSC::JITRightShiftGenerator::generateFastPath):
     118        - The shift MASM operatons need to ensure that the shiftAmount is not in the same
     119          register as the destination register.  With the baselineJIT and DFG, this is
     120          ensured in how we allocate these registers, and hence, the bug does not manifest.
     121          With the FTL, these registers are not guaranteed to be unique.  Hence, we need
     122          to fix the shift op snippet code to compensate for this.
     123
    11242015-12-15  Caitlin Potter  <caitp@igalia.com>
    2125
     
    16061729        * runtime/CommonIdentifiers.h:
    16071730
    1608 >>>>>>> .r193940
    160917312015-12-08  Filip Pizlo  <fpizlo@apple.com>
    16101732
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h

    r192034 r194113  
    391391}
    392392
     393inline bool isUntypedSpeculationForBitOps(SpeculatedType value)
     394{
     395    return !(value & (SpecFullNumber | SpecBoolean | SpecOther));
     396}
     397
    393398void dumpSpeculation(PrintStream&, SpeculatedType);
    394399void dumpSpeculationAbbreviated(PrintStream&, SpeculatedType);
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r194087 r194113  
    234234    case BitLShift:
    235235    case BitURShift: {
     236        if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
     237            clobberWorld(node->origin.semantic, clobberLimit);
     238            forNode(node).setType(m_graph, SpecInt32);
     239            break;
     240        }
     241
    236242        JSValue left = forNode(node->child1()).value();
    237243        JSValue right = forNode(node->child2()).value();
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r194087 r194113  
    122122        return;
    123123       
    124     case BitAnd:
    125     case BitOr:
    126     case BitXor:
    127     case BitLShift:
    128     case BitRShift:
    129     case BitURShift:
    130124    case ArithIMul:
    131125    case ArithAbs:
     
    165159        return;
    166160
     161    case BitAnd:
     162    case BitOr:
     163    case BitXor:
     164    case BitLShift:
     165    case BitRShift:
     166    case BitURShift:
     167        if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
     168            read(World);
     169            write(Heap);
     170            return;
     171        }
     172        def(PureValue(node));
     173        return;
     174
    167175    case ArithRandom:
    168176        read(MathDotRandomState);
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r194087 r194113  
    106106        case BitLShift:
    107107        case BitURShift: {
     108            if (Node::shouldSpeculateUntypedForBitOps(node->child1().node(), node->child2().node())
     109                && m_graph.hasExitSite(node->origin.semantic, BadType)) {
     110                fixEdge<UntypedUse>(node->child1());
     111                fixEdge<UntypedUse>(node->child2());
     112                break;
     113            }
    108114            fixIntConvertingEdge(node->child1());
    109115            fixIntConvertingEdge(node->child2());
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r194036 r194113  
    20342034    }
    20352035   
     2036    bool shouldSpeculateUntypedForBitOps()
     2037    {
     2038        return isUntypedSpeculationForBitOps(prediction());
     2039    }
     2040   
     2041    static bool shouldSpeculateUntypedForBitOps(Node* op1, Node* op2)
     2042    {
     2043        return op1->shouldSpeculateUntypedForBitOps() || op2->shouldSpeculateUntypedForBitOps();
     2044    }
     2045   
    20362046    static bool shouldSpeculateBoolean(Node* op1, Node* op2)
    20372047    {
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r194087 r194113  
    174174}
    175175
     176EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     177{
     178    VM* vm = &exec->vm();
     179    NativeCallFrameTracer tracer(vm, exec);
     180
     181    JSValue op1 = JSValue::decode(encodedOp1);
     182    JSValue op2 = JSValue::decode(encodedOp2);
     183
     184    int32_t a = op1.toInt32(exec);
     185    int32_t b = op2.toInt32(exec);
     186    return JSValue::encode(jsNumber(a & b));
     187}
     188
     189EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     190{
     191    VM* vm = &exec->vm();
     192    NativeCallFrameTracer tracer(vm, exec);
     193
     194    JSValue op1 = JSValue::decode(encodedOp1);
     195    JSValue op2 = JSValue::decode(encodedOp2);
     196
     197    int32_t a = op1.toInt32(exec);
     198    int32_t b = op2.toInt32(exec);
     199    return JSValue::encode(jsNumber(a | b));
     200}
     201
     202EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     203{
     204    VM* vm = &exec->vm();
     205    NativeCallFrameTracer tracer(vm, exec);
     206
     207    JSValue op1 = JSValue::decode(encodedOp1);
     208    JSValue op2 = JSValue::decode(encodedOp2);
     209
     210    int32_t a = op1.toInt32(exec);
     211    int32_t b = op2.toInt32(exec);
     212    return JSValue::encode(jsNumber(a ^ b));
     213}
     214
     215EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     216{
     217    VM* vm = &exec->vm();
     218    NativeCallFrameTracer tracer(vm, exec);
     219
     220    JSValue op1 = JSValue::decode(encodedOp1);
     221    JSValue op2 = JSValue::decode(encodedOp2);
     222
     223    int32_t a = op1.toInt32(exec);
     224    uint32_t b = op2.toUInt32(exec);
     225    return JSValue::encode(jsNumber(a << (b & 0x1f)));
     226}
     227
     228EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     229{
     230    VM* vm = &exec->vm();
     231    NativeCallFrameTracer tracer(vm, exec);
     232
     233    JSValue op1 = JSValue::decode(encodedOp1);
     234    JSValue op2 = JSValue::decode(encodedOp2);
     235
     236    int32_t a = op1.toInt32(exec);
     237    uint32_t b = op2.toUInt32(exec);
     238    return JSValue::encode(jsNumber(a >> (b & 0x1f)));
     239}
     240
     241EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     242{
     243    VM* vm = &exec->vm();
     244    NativeCallFrameTracer tracer(vm, exec);
     245
     246    JSValue op1 = JSValue::decode(encodedOp1);
     247    JSValue op2 = JSValue::decode(encodedOp2);
     248
     249    uint32_t a = op1.toUInt32(exec);
     250    uint32_t b = op2.toUInt32(exec);
     251    return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
     252}
     253
    176254EncodedJSValue JIT_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
    177255{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r194087 r194113  
    4444EncodedJSValue JIT_OPERATION operationToThis(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
    4545EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
     46EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
     47EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
     48EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
     49EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
     50EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
     51EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
    4652EncodedJSValue JIT_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
    4753EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r194042 r194113  
    4040#include "DirectArguments.h"
    4141#include "JITAddGenerator.h"
     42#include "JITBitAndGenerator.h"
     43#include "JITBitOrGenerator.h"
     44#include "JITBitXorGenerator.h"
    4245#include "JITDivGenerator.h"
     46#include "JITLeftShiftGenerator.h"
    4347#include "JITMulGenerator.h"
     48#include "JITRightShiftGenerator.h"
    4449#include "JITSubGenerator.h"
    4550#include "JSArrowFunction.h"
     
    27872792}
    27882793
     2794template<typename SnippetGenerator, J_JITOperation_EJJ snippetSlowPathFunction>
     2795void SpeculativeJIT::emitUntypedBitOp(Node* node)
     2796{
     2797    Edge& leftChild = node->child1();
     2798    Edge& rightChild = node->child2();
     2799
     2800    if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
     2801        JSValueOperand left(this, leftChild);
     2802        JSValueOperand right(this, rightChild);
     2803        JSValueRegs leftRegs = left.jsValueRegs();
     2804        JSValueRegs rightRegs = right.jsValueRegs();
     2805#if USE(JSVALUE64)
     2806        GPRTemporary result(this);
     2807        JSValueRegs resultRegs = JSValueRegs(result.gpr());
     2808#else
     2809        GPRTemporary resultTag(this);
     2810        GPRTemporary resultPayload(this);
     2811        JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
     2812#endif
     2813        flushRegisters();
     2814        callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
     2815        m_jit.exceptionCheck();
     2816
     2817        jsValueResult(resultRegs, node);
     2818        return;
     2819    }
     2820
     2821    Optional<JSValueOperand> left;
     2822    Optional<JSValueOperand> right;
     2823
     2824    JSValueRegs leftRegs;
     2825    JSValueRegs rightRegs;
     2826
     2827#if USE(JSVALUE64)
     2828    GPRTemporary result(this);
     2829    JSValueRegs resultRegs = JSValueRegs(result.gpr());
     2830    GPRTemporary scratch(this);
     2831    GPRReg scratchGPR = scratch.gpr();
     2832#else
     2833    GPRTemporary resultTag(this);
     2834    GPRTemporary resultPayload(this);
     2835    JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
     2836    GPRReg scratchGPR = resultTag.gpr();
     2837#endif
     2838
     2839    SnippetOperand leftOperand;
     2840    SnippetOperand rightOperand;
     2841
     2842    // The snippet generator does not support both operands being constant. If the left
     2843    // operand is already const, we'll ignore the right operand's constness.
     2844    if (leftChild->isInt32Constant())
     2845        leftOperand.setConstInt32(leftChild->asInt32());
     2846    else if (rightChild->isInt32Constant())
     2847        rightOperand.setConstInt32(rightChild->asInt32());
     2848
     2849    RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
     2850
     2851    if (!leftOperand.isConst()) {
     2852        left = JSValueOperand(this, leftChild);
     2853        leftRegs = left->jsValueRegs();
     2854    }
     2855    if (!rightOperand.isConst()) {
     2856        right = JSValueOperand(this, rightChild);
     2857        rightRegs = right->jsValueRegs();
     2858    }
     2859
     2860    SnippetGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, scratchGPR);
     2861    gen.generateFastPath(m_jit);
     2862
     2863    ASSERT(gen.didEmitFastPath());
     2864    gen.endJumpList().append(m_jit.jump());
     2865
     2866    gen.slowPathJumpList().link(&m_jit);
     2867    silentSpillAllRegisters(resultRegs);
     2868
     2869    if (leftOperand.isConst()) {
     2870        leftRegs = resultRegs;
     2871        m_jit.moveValue(leftChild->asJSValue(), leftRegs);
     2872    } else if (rightOperand.isConst()) {
     2873        rightRegs = resultRegs;
     2874        m_jit.moveValue(rightChild->asJSValue(), rightRegs);
     2875    }
     2876
     2877    callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
     2878
     2879    silentFillAllRegisters(resultRegs);
     2880    m_jit.exceptionCheck();
     2881
     2882    gen.endJumpList().link(&m_jit);
     2883    jsValueResult(resultRegs, node);
     2884}
     2885
    27892886void SpeculativeJIT::compileBitwiseOp(Node* node)
    27902887{
     
    27922889    Edge& leftChild = node->child1();
    27932890    Edge& rightChild = node->child2();
     2891
     2892    if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
     2893        switch (op) {
     2894        case BitAnd:
     2895            emitUntypedBitOp<JITBitAndGenerator, operationValueBitAnd>(node);
     2896            return;
     2897        case BitOr:
     2898            emitUntypedBitOp<JITBitOrGenerator, operationValueBitOr>(node);
     2899            return;
     2900        case BitXor:
     2901            emitUntypedBitOp<JITBitXorGenerator, operationValueBitXor>(node);
     2902            return;
     2903        default:
     2904            RELEASE_ASSERT_NOT_REACHED();
     2905        }
     2906    }
    27942907
    27952908    if (leftChild->isInt32Constant()) {
     
    28222935}
    28232936
     2937void SpeculativeJIT::emitUntypedRightShiftBitOp(Node* node)
     2938{
     2939    J_JITOperation_EJJ snippetSlowPathFunction = node->op() == BitRShift
     2940        ? operationValueBitRShift : operationValueBitURShift;
     2941    JITRightShiftGenerator::ShiftType shiftType = node->op() == BitRShift
     2942        ? JITRightShiftGenerator::SignedShift : JITRightShiftGenerator::UnsignedShift;
     2943
     2944    Edge& leftChild = node->child1();
     2945    Edge& rightChild = node->child2();
     2946
     2947    if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
     2948        JSValueOperand left(this, leftChild);
     2949        JSValueOperand right(this, rightChild);
     2950        JSValueRegs leftRegs = left.jsValueRegs();
     2951        JSValueRegs rightRegs = right.jsValueRegs();
     2952#if USE(JSVALUE64)
     2953        GPRTemporary result(this);
     2954        JSValueRegs resultRegs = JSValueRegs(result.gpr());
     2955#else
     2956        GPRTemporary resultTag(this);
     2957        GPRTemporary resultPayload(this);
     2958        JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
     2959#endif
     2960        flushRegisters();
     2961        callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
     2962        m_jit.exceptionCheck();
     2963
     2964        jsValueResult(resultRegs, node);
     2965        return;
     2966    }
     2967
     2968    Optional<JSValueOperand> left;
     2969    Optional<JSValueOperand> right;
     2970
     2971    JSValueRegs leftRegs;
     2972    JSValueRegs rightRegs;
     2973
     2974    FPRTemporary leftNumber(this);
     2975    FPRReg leftFPR = leftNumber.fpr();
     2976
     2977#if USE(JSVALUE64)
     2978    GPRTemporary result(this);
     2979    JSValueRegs resultRegs = JSValueRegs(result.gpr());
     2980    GPRTemporary scratch(this);
     2981    GPRReg scratchGPR = scratch.gpr();
     2982    FPRReg scratchFPR = InvalidFPRReg;
     2983#else
     2984    GPRTemporary resultTag(this);
     2985    GPRTemporary resultPayload(this);
     2986    JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
     2987    GPRReg scratchGPR = resultTag.gpr();
     2988    FPRTemporary fprScratch(this);
     2989    FPRReg scratchFPR = fprScratch.fpr();
     2990#endif
     2991
     2992    SnippetOperand leftOperand;
     2993    SnippetOperand rightOperand;
     2994
     2995    // The snippet generator does not support both operands being constant. If the left
     2996    // operand is already const, we'll ignore the right operand's constness.
     2997    if (leftChild->isInt32Constant())
     2998        leftOperand.setConstInt32(leftChild->asInt32());
     2999    else if (rightChild->isInt32Constant())
     3000        rightOperand.setConstInt32(rightChild->asInt32());
     3001
     3002    RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
     3003
     3004    if (!leftOperand.isConst()) {
     3005        left = JSValueOperand(this, leftChild);
     3006        leftRegs = left->jsValueRegs();
     3007    }
     3008    if (!rightOperand.isConst()) {
     3009        right = JSValueOperand(this, rightChild);
     3010        rightRegs = right->jsValueRegs();
     3011    }
     3012
     3013    JITRightShiftGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
     3014        leftFPR, scratchGPR, scratchFPR, shiftType);
     3015    gen.generateFastPath(m_jit);
     3016
     3017    ASSERT(gen.didEmitFastPath());
     3018    gen.endJumpList().append(m_jit.jump());
     3019
     3020    gen.slowPathJumpList().link(&m_jit);
     3021    silentSpillAllRegisters(resultRegs);
     3022
     3023    if (leftOperand.isConst()) {
     3024        leftRegs = resultRegs;
     3025        m_jit.moveValue(leftChild->asJSValue(), leftRegs);
     3026    } else if (rightOperand.isConst()) {
     3027        rightRegs = resultRegs;
     3028        m_jit.moveValue(rightChild->asJSValue(), rightRegs);
     3029    }
     3030
     3031    callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
     3032
     3033    silentFillAllRegisters(resultRegs);
     3034    m_jit.exceptionCheck();
     3035
     3036    gen.endJumpList().link(&m_jit);
     3037    jsValueResult(resultRegs, node);
     3038    return;
     3039}
     3040
    28243041void SpeculativeJIT::compileShiftOp(Node* node)
    28253042{
     
    28273044    Edge& leftChild = node->child1();
    28283045    Edge& rightChild = node->child2();
     3046
     3047    if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
     3048        switch (op) {
     3049        case BitLShift:
     3050            emitUntypedBitOp<JITLeftShiftGenerator, operationValueBitLShift>(node);
     3051            return;
     3052        case BitRShift:
     3053        case BitURShift:
     3054            emitUntypedRightShiftBitOp(node);
     3055            return;
     3056        default:
     3057            RELEASE_ASSERT_NOT_REACHED();
     3058        }
     3059    }
    28293060
    28303061    if (rightChild->isInt32Constant()) {
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r194087 r194113  
    22182218    void compileUInt32ToNumber(Node*);
    22192219    void compileDoubleAsInt32(Node*);
     2220
     2221    template<typename SnippetGenerator, J_JITOperation_EJJ slowPathFunction>
     2222    void emitUntypedBitOp(Node*);
    22202223    void compileBitwiseOp(Node*);
     2224
     2225    void emitUntypedRightShiftBitOp(Node*);
    22212226    void compileShiftOp(Node*);
     2227
    22222228    void compileValueAdd(Node*);
    22232229    void compileArithAdd(Node*);
  • trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp

    r188519 r194113  
    7575            handleCommutativity();
    7676
    77             if (m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
     77            if (m_node->child1().useKind() != UntypedUse && m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
    7878                convertToIdentityOverChild1();
    7979                break;
     
    8989        case BitRShift:
    9090        case BitURShift:
    91             if (m_node->child2()->isInt32Constant() && !(m_node->child2()->asInt32() & 0x1f)) {
     91            if (m_node->child1().useKind() != UntypedUse && m_node->child2()->isInt32Constant() && !(m_node->child2()->asInt32() & 0x1f)) {
    9292                convertToIdentityOverChild1();
    9393                break;
  • trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.cpp

    r193985 r194113  
    3333#include "GPRInfo.h"
    3434#include "JITAddGenerator.h"
     35#include "JITBitAndGenerator.h"
     36#include "JITBitOrGenerator.h"
     37#include "JITBitXorGenerator.h"
    3538#include "JITDivGenerator.h"
     39#include "JITLeftShiftGenerator.h"
    3640#include "JITMulGenerator.h"
     41#include "JITRightShiftGenerator.h"
    3742#include "JITSubGenerator.h"
    3843#include "ScratchRegisterAllocator.h"
     
    160165};
    161166
     167template<typename SnippetGenerator>
     168void generateBinaryBitOpFastPath(BinaryOpDescriptor& ic, CCallHelpers& jit,
     169    GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
     170    CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart)
     171{
     172    ScratchRegisterAllocator allocator(usedRegisters);
     173
     174    BinarySnippetRegisterContext context(allocator, result, left, right);
     175
     176    GPRReg scratchGPR = allocator.allocateScratchGPR();
     177
     178    SnippetGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
     179        JSValueRegs(left), JSValueRegs(right), scratchGPR);
     180
     181    unsigned numberOfBytesUsedToPreserveReusedRegisters =
     182        allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
     183
     184    context.initializeRegisters(jit);
     185    gen.generateFastPath(jit);
     186
     187    ASSERT(gen.didEmitFastPath());
     188    gen.endJumpList().link(&jit);
     189
     190    context.restoreRegisters(jit);
     191    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
     192        ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
     193    done = jit.jump();
     194
     195    gen.slowPathJumpList().link(&jit);
     196    context.restoreRegisters(jit);
     197    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
     198        ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
     199    slowPathStart = jit.jump();
     200}
     201
     202static void generateRightShiftFastPath(BinaryOpDescriptor& ic, CCallHelpers& jit,
     203    GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
     204    CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart,
     205    JITRightShiftGenerator::ShiftType shiftType)
     206{
     207    ScratchRegisterAllocator allocator(usedRegisters);
     208
     209    BinarySnippetRegisterContext context(allocator, result, left, right);
     210
     211    FPRReg leftFPR = allocator.allocateScratchFPR();
     212    GPRReg scratchGPR = allocator.allocateScratchGPR();
     213
     214    JITRightShiftGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
     215        JSValueRegs(left), JSValueRegs(right), leftFPR, scratchGPR, InvalidFPRReg, shiftType);
     216
     217    unsigned numberOfBytesUsedToPreserveReusedRegisters =
     218        allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
     219
     220    context.initializeRegisters(jit);
     221    gen.generateFastPath(jit);
     222
     223    ASSERT(gen.didEmitFastPath());
     224    gen.endJumpList().link(&jit);
     225    context.restoreRegisters(jit);
     226    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
     227        ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
     228    done = jit.jump();
     229
     230    gen.slowPathJumpList().link(&jit);
     231    context.restoreRegisters(jit);
     232    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
     233        ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
     234    slowPathStart = jit.jump();
     235}
     236
    162237template<typename BinaryArithOpGenerator, ScratchFPRUsage scratchFPRUsage = DontNeedScratchFPR>
    163238void generateBinaryArithOpFastPath(BinaryOpDescriptor& ic, CCallHelpers& jit,
     
    179254        JSValueRegs(left), JSValueRegs(right), leftFPR, rightFPR, scratchGPR, scratchFPR);
    180255
    181     auto numberOfBytesUsedToPreserveReusedRegisters =
     256    unsigned numberOfBytesUsedToPreserveReusedRegisters =
    182257        allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
    183258
     
    189264    context.restoreRegisters(jit);
    190265    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
    191         ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);
     266        ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
    192267    done = jit.jump();
    193268
     
    195270    context.restoreRegisters(jit);
    196271    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
    197         ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);
     272        ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
    198273    slowPathStart = jit.jump();
    199274}
     
    204279{
    205280    switch (ic.nodeType()) {
     281    case BitAnd:
     282        generateBinaryBitOpFastPath<JITBitAndGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
     283        break;
     284    case BitOr:
     285        generateBinaryBitOpFastPath<JITBitOrGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
     286        break;
     287    case BitXor:
     288        generateBinaryBitOpFastPath<JITBitXorGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
     289        break;
     290    case BitLShift:
     291        generateBinaryBitOpFastPath<JITLeftShiftGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
     292        break;
     293    case BitRShift:
     294        generateRightShiftFastPath(ic, jit, result, left, right, usedRegisters, done, slowPathStart, JITRightShiftGenerator::SignedShift);
     295        break;
     296    case BitURShift:
     297        generateRightShiftFastPath(ic, jit, result, left, right, usedRegisters, done, slowPathStart, JITRightShiftGenerator::UnsignedShift);
     298        break;
    206299    case ArithDiv:
    207300        generateBinaryArithOpFastPath<JITDivGenerator, NeedScratchFPR>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h

    r193985 r194113  
    165165};
    166166
     167class BitAndDescriptor : public BinaryOpDescriptor {
     168public:
     169    BitAndDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
     170        : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
     171    { }
     172
     173    static size_t icSize() { return sizeOfBitAnd(); }
     174    static unsigned nodeType() { return DFG::BitAnd; }
     175    static const char* opName() { return "BitAnd"; }
     176    static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitAnd; }
     177    static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
     178};
     179
     180class BitOrDescriptor : public BinaryOpDescriptor {
     181public:
     182    BitOrDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
     183        : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
     184    { }
     185
     186    static size_t icSize() { return sizeOfBitOr(); }
     187    static unsigned nodeType() { return DFG::BitOr; }
     188    static const char* opName() { return "BitOr"; }
     189    static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitOr; }
     190    static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
     191};
     192
     193class BitXorDescriptor : public BinaryOpDescriptor {
     194public:
     195    BitXorDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
     196        : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
     197    { }
     198
     199    static size_t icSize() { return sizeOfBitXor(); }
     200    static unsigned nodeType() { return DFG::BitXor; }
     201    static const char* opName() { return "BitXor"; }
     202    static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitXor; }
     203    static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
     204};
     205
     206class BitLShiftDescriptor : public BinaryOpDescriptor {
     207public:
     208    BitLShiftDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
     209        : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
     210    { }
     211
     212    static size_t icSize() { return sizeOfBitLShift(); }
     213    static unsigned nodeType() { return DFG::BitLShift; }
     214    static const char* opName() { return "BitLShift"; }
     215    static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitLShift; }
     216    static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
     217};
     218
     219class BitRShiftDescriptor : public BinaryOpDescriptor {
     220public:
     221    BitRShiftDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
     222        : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
     223    { }
     224
     225    static size_t icSize() { return sizeOfBitRShift(); }
     226    static unsigned nodeType() { return DFG::BitRShift; }
     227    static const char* opName() { return "BitRShift"; }
     228    static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitRShift; }
     229    static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
     230};
     231
     232class BitURShiftDescriptor : public BinaryOpDescriptor {
     233public:
     234    BitURShiftDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
     235        : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
     236    { }
     237
     238    static size_t icSize() { return sizeOfBitURShift(); }
     239    static unsigned nodeType() { return DFG::BitURShift; }
     240    static const char* opName() { return "BitURShift"; }
     241    static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitURShift; }
     242    static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
     243};
     244
    167245class ArithDivDescriptor : public BinaryOpDescriptor {
    168246public:
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp

    r193781 r194113  
    126126#else
    127127    return 5;
     128#endif
     129}
     130
     131size_t sizeOfBitAnd()
     132{
     133#if CPU(ARM64)
     134#ifdef NDEBUG
     135return 180; // ARM64 release.
     136#else
     137return 276; // ARM64 debug.
     138#endif
     139#else // CPU(X86_64)
     140#ifdef NDEBUG
     141return 199; // X86_64 release.
     142#else
     143return 286; // X86_64 debug.
     144#endif
     145#endif
     146}
     147
     148size_t sizeOfBitOr()
     149{
     150#if CPU(ARM64)
     151#ifdef NDEBUG
     152    return 180; // ARM64 release.
     153#else
     154    return 276; // ARM64 debug.
     155#endif
     156#else // CPU(X86_64)
     157#ifdef NDEBUG
     158    return 199; // X86_64 release.
     159#else
     160    return 286; // X86_64 debug.
     161#endif
     162#endif
     163}
     164
     165size_t sizeOfBitXor()
     166{
     167#if CPU(ARM64)
     168#ifdef NDEBUG
     169    return 180; // ARM64 release.
     170#else
     171    return 276; // ARM64 debug.
     172#endif
     173#else // CPU(X86_64)
     174#ifdef NDEBUG
     175    return 199; // X86_64 release.
     176#else
     177    return 286; // X86_64 debug.
     178#endif
     179#endif
     180}
     181
     182size_t sizeOfBitLShift()
     183{
     184#if CPU(ARM64)
     185#ifdef NDEBUG
     186    return 180; // ARM64 release.
     187#else
     188    return 276; // ARM64 debug.
     189#endif
     190#else // CPU(X86_64)
     191#ifdef NDEBUG
     192    return 199; // X86_64 release.
     193#else
     194    return 286; // X86_64 debug.
     195#endif
     196#endif
     197}
     198
     199size_t sizeOfBitRShift()
     200{
     201#if CPU(ARM64)
     202#ifdef NDEBUG
     203    return 180; // ARM64 release.
     204#else
     205    return 276; // ARM64 debug.
     206#endif
     207#else // CPU(X86_64)
     208#ifdef NDEBUG
     209    return 199; // X86_64 release.
     210#else
     211    return 286; // X86_64 debug.
     212#endif
     213#endif
     214}
     215
     216size_t sizeOfBitURShift()
     217{
     218#if CPU(ARM64)
     219#ifdef NDEBUG
     220    return 180; // ARM64 release.
     221#else
     222    return 276; // ARM64 debug.
     223#endif
     224#else // CPU(X86_64)
     225#ifdef NDEBUG
     226    return 199; // X86_64 release.
     227#else
     228    return 286; // X86_64 debug.
     229#endif
    128230#endif
    129231}
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h

    r193781 r194113  
    4747size_t sizeOfConstructForwardVarargs();
    4848size_t sizeOfIn();
     49size_t sizeOfBitAnd();
     50size_t sizeOfBitOr();
     51size_t sizeOfBitXor();
     52size_t sizeOfBitLShift();
     53size_t sizeOfBitRShift();
     54size_t sizeOfBitURShift();
    4955size_t sizeOfArithDiv();
    5056size_t sizeOfArithMul();
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r194092 r194113  
    22642264    void compileBitAnd()
    22652265    {
     2266        if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
     2267            compileUntypedBinaryOp<BitAndDescriptor>();
     2268            return;
     2269        }
    22662270        setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
    22672271    }
     
    22692273    void compileBitOr()
    22702274    {
     2275        if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
     2276            compileUntypedBinaryOp<BitOrDescriptor>();
     2277            return;
     2278        }
    22712279        setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
    22722280    }
     
    22742282    void compileBitXor()
    22752283    {
     2284        if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
     2285            compileUntypedBinaryOp<BitXorDescriptor>();
     2286            return;
     2287        }
    22762288        setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
    22772289    }
     
    22792291    void compileBitRShift()
    22802292    {
     2293        if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
     2294            compileUntypedBinaryOp<BitRShiftDescriptor>();
     2295            return;
     2296        }
    22812297        setInt32(m_out.aShr(
    22822298            lowInt32(m_node->child1()),
     
    22862302    void compileBitLShift()
    22872303    {
     2304        if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
     2305            compileUntypedBinaryOp<BitLShiftDescriptor>();
     2306            return;
     2307        }
    22882308        setInt32(m_out.shl(
    22892309            lowInt32(m_node->child1()),
     
    22932313    void compileBitURShift()
    22942314    {
     2315        if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
     2316            compileUntypedBinaryOp<BitURShiftDescriptor>();
     2317            return;
     2318        }
    22952319        setInt32(m_out.lShr(
    22962320            lowInt32(m_node->child1()),
  • trunk/Source/JavaScriptCore/jit/JITLeftShiftGenerator.cpp

    r193788 r194113  
    3333void JITLeftShiftGenerator::generateFastPath(CCallHelpers& jit)
    3434{
     35    ASSERT(m_scratchGPR != InvalidGPRReg);
     36    ASSERT(m_scratchGPR != m_left.payloadGPR());
     37    ASSERT(m_scratchGPR != m_right.payloadGPR());
     38#if USE(JSVALUE32_64)
     39    ASSERT(m_scratchGPR != m_left.tagGPR());
     40    ASSERT(m_scratchGPR != m_right.tagGPR());
     41#endif
     42
    3543    ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
    3644
     
    4856        m_slowPathJumpList.append(jit.branchIfNotInt32(m_right));
    4957
     58        GPRReg rightOperandGPR = m_right.payloadGPR();
     59        if (rightOperandGPR == m_result.payloadGPR()) {
     60            jit.move(rightOperandGPR, m_scratchGPR);
     61            rightOperandGPR = m_scratchGPR;
     62        }
     63
    5064        if (m_leftOperand.isConstInt32()) {
    5165#if USE(JSVALUE32_64)
     
    5872        }
    5973
    60         jit.lshift32(m_right.payloadGPR(), m_result.payloadGPR());
     74        jit.lshift32(rightOperandGPR, m_result.payloadGPR());
    6175    }
    6276
  • trunk/Source/JavaScriptCore/jit/JITLeftShiftGenerator.h

    r193788 r194113  
    3636public:
    3737    JITLeftShiftGenerator(const SnippetOperand& leftOperand, const SnippetOperand& rightOperand,
    38         JSValueRegs result, JSValueRegs left, JSValueRegs right, GPRReg unused = InvalidGPRReg)
    39         : JITBitBinaryOpGenerator(leftOperand, rightOperand, result, left, right, unused)
     38        JSValueRegs result, JSValueRegs left, JSValueRegs right, GPRReg scratchGPR)
     39        : JITBitBinaryOpGenerator(leftOperand, rightOperand, result, left, right, scratchGPR)
    4040    { }
    4141
  • trunk/Source/JavaScriptCore/jit/JITRightShiftGenerator.cpp

    r194042 r194113  
    8888        m_slowPathJumpList.append(jit.branchIfNotInt32(m_right));
    8989
     90        GPRReg rightOperandGPR = m_right.payloadGPR();
     91        if (rightOperandGPR == m_result.payloadGPR())
     92            rightOperandGPR = m_scratchGPR;
     93
    9094        CCallHelpers::Jump leftNotInt;
    9195        if (m_leftOperand.isConstInt32()) {
     96            jit.move(m_right.payloadGPR(), rightOperandGPR);
    9297#if USE(JSVALUE32_64)
    9398            jit.move(m_right.tagGPR(), m_result.tagGPR());
     
    96101        } else {
    97102            leftNotInt = jit.branchIfNotInt32(m_left);
     103            jit.move(m_right.payloadGPR(), rightOperandGPR);
    98104            jit.moveValueRegs(m_left, m_result);
    99105        }
    100106
    101107        if (m_shiftType == SignedShift)
    102             jit.rshift32(m_right.payloadGPR(), m_result.payloadGPR());
     108            jit.rshift32(rightOperandGPR, m_result.payloadGPR());
    103109        else
    104             jit.urshift32(m_right.payloadGPR(), m_result.payloadGPR());
     110            jit.urshift32(rightOperandGPR, m_result.payloadGPR());
    105111#if USE(JSVALUE64)
    106112        jit.or64(GPRInfo::tagTypeNumberRegister, m_result.payloadGPR());
Note: See TracChangeset for help on using the changeset viewer.