Changeset 230517 in webkit


Ignore:
Timestamp:
Apr 11, 2018 12:44:58 AM (6 years ago)
Author:
Yusuke Suzuki
Message:

[DFG] Remove duplicate 32bit code more
https://bugs.webkit.org/show_bug.cgi?id=184236

Reviewed by Mark Lam.

Remove duplicate 32bit code more aggressively part 2.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • dfg/DFGCompareSlowPathGenerator.h: Added.

(JSC::DFG::CompareSlowPathGenerator::CompareSlowPathGenerator):
Drop boxing part. Use unblessedBooleanResult in DFGSpeculativeJIT side instead.

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileOverridesHasInstance):
(JSC::DFG::SpeculativeJIT::compileLoadVarargs):
(JSC::DFG::SpeculativeJIT::compileIsObject):
(JSC::DFG::SpeculativeJIT::compileCheckNotEmpty):
(JSC::DFG::SpeculativeJIT::compilePutByIdFlush):
(JSC::DFG::SpeculativeJIT::compilePutById):
(JSC::DFG::SpeculativeJIT::compilePutByIdDirect):
(JSC::DFG::SpeculativeJIT::compileNewArrayWithSize):
(JSC::DFG::SpeculativeJIT::compileMiscStrictEq):
(JSC::DFG::SpeculativeJIT::emitInitializeButterfly):
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
(JSC::DFG::SpeculativeJIT::compileHasIndexedProperty):
(JSC::DFG::SpeculativeJIT::compileGetDirectPname):
(JSC::DFG::SpeculativeJIT::compileExtractCatchLocal):
(JSC::DFG::SpeculativeJIT::cachedPutById):
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare):
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch):
(JSC::DFG::SpeculativeJIT::nonSpeculativeCompare): Deleted.

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::selectScratchGPR): Deleted.

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::cachedPutById): Deleted.
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch): Deleted.
(JSC::DFG::CompareAndBoxBooleanSlowPathGenerator::CompareAndBoxBooleanSlowPathGenerator): Deleted.
(JSC::DFG::CompareAndBoxBooleanSlowPathGenerator::generateInternal): Deleted.
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare): Deleted.
(JSC::DFG::SpeculativeJIT::compileMiscStrictEq): Deleted.
(JSC::DFG::SpeculativeJIT::emitInitializeButterfly): Deleted.
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize): Deleted.

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::cachedPutById): Deleted.
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch): Deleted.
(JSC::DFG::CompareAndBoxBooleanSlowPathGenerator::CompareAndBoxBooleanSlowPathGenerator): Deleted.
(): Deleted.
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare): Deleted.
(JSC::DFG::SpeculativeJIT::compileMiscStrictEq): Deleted.
(JSC::DFG::SpeculativeJIT::emitInitializeButterfly): Deleted.
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize): Deleted.

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileHasIndexedProperty):
operationHasIndexedPropertyByInt starts returning unblessed boolean with size_t.

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::loadValue):
(JSC::AssemblyHelpers::selectScratchGPR):
(JSC::AssemblyHelpers::constructRegisterSet):

  • jit/RegisterSet.h:

(JSC::RegisterSet::setAny):
Clean up selectScratchGPR code to pass JSValueRegs.

Location:
trunk/Source/JavaScriptCore
Files:
1 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r230516 r230517  
     12018-04-11  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [DFG] Remove duplicate 32bit code more
     4        https://bugs.webkit.org/show_bug.cgi?id=184236
     5
     6        Reviewed by Mark Lam.
     7
     8        Remove duplicate 32bit code more aggressively part 2.
     9
     10        * JavaScriptCore.xcodeproj/project.pbxproj:
     11        * dfg/DFGCompareSlowPathGenerator.h: Added.
     12        (JSC::DFG::CompareSlowPathGenerator::CompareSlowPathGenerator):
     13        Drop boxing part. Use unblessedBooleanResult in DFGSpeculativeJIT side instead.
     14
     15        * dfg/DFGOperations.cpp:
     16        * dfg/DFGOperations.h:
     17        * dfg/DFGSpeculativeJIT.cpp:
     18        (JSC::DFG::SpeculativeJIT::compileOverridesHasInstance):
     19        (JSC::DFG::SpeculativeJIT::compileLoadVarargs):
     20        (JSC::DFG::SpeculativeJIT::compileIsObject):
     21        (JSC::DFG::SpeculativeJIT::compileCheckNotEmpty):
     22        (JSC::DFG::SpeculativeJIT::compilePutByIdFlush):
     23        (JSC::DFG::SpeculativeJIT::compilePutById):
     24        (JSC::DFG::SpeculativeJIT::compilePutByIdDirect):
     25        (JSC::DFG::SpeculativeJIT::compileNewArrayWithSize):
     26        (JSC::DFG::SpeculativeJIT::compileMiscStrictEq):
     27        (JSC::DFG::SpeculativeJIT::emitInitializeButterfly):
     28        (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
     29        (JSC::DFG::SpeculativeJIT::compileHasIndexedProperty):
     30        (JSC::DFG::SpeculativeJIT::compileGetDirectPname):
     31        (JSC::DFG::SpeculativeJIT::compileExtractCatchLocal):
     32        (JSC::DFG::SpeculativeJIT::cachedPutById):
     33        (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare):
     34        (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch):
     35        (JSC::DFG::SpeculativeJIT::nonSpeculativeCompare): Deleted.
     36        * dfg/DFGSpeculativeJIT.h:
     37        (JSC::DFG::SpeculativeJIT::selectScratchGPR): Deleted.
     38        * dfg/DFGSpeculativeJIT32_64.cpp:
     39        (JSC::DFG::SpeculativeJIT::compile):
     40        (JSC::DFG::SpeculativeJIT::cachedPutById): Deleted.
     41        (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch): Deleted.
     42        (JSC::DFG::CompareAndBoxBooleanSlowPathGenerator::CompareAndBoxBooleanSlowPathGenerator): Deleted.
     43        (JSC::DFG::CompareAndBoxBooleanSlowPathGenerator::generateInternal): Deleted.
     44        (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare): Deleted.
     45        (JSC::DFG::SpeculativeJIT::compileMiscStrictEq): Deleted.
     46        (JSC::DFG::SpeculativeJIT::emitInitializeButterfly): Deleted.
     47        (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize): Deleted.
     48        * dfg/DFGSpeculativeJIT64.cpp:
     49        (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq):
     50        (JSC::DFG::SpeculativeJIT::compile):
     51        (JSC::DFG::SpeculativeJIT::cachedPutById): Deleted.
     52        (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch): Deleted.
     53        (JSC::DFG::CompareAndBoxBooleanSlowPathGenerator::CompareAndBoxBooleanSlowPathGenerator): Deleted.
     54        (): Deleted.
     55        (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare): Deleted.
     56        (JSC::DFG::SpeculativeJIT::compileMiscStrictEq): Deleted.
     57        (JSC::DFG::SpeculativeJIT::emitInitializeButterfly): Deleted.
     58        (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize): Deleted.
     59        * ftl/FTLLowerDFGToB3.cpp:
     60        (JSC::FTL::DFG::LowerDFGToB3::compileHasIndexedProperty):
     61        operationHasIndexedPropertyByInt starts returning unblessed boolean with size_t.
     62
     63        * jit/AssemblyHelpers.h:
     64        (JSC::AssemblyHelpers::loadValue):
     65        (JSC::AssemblyHelpers::selectScratchGPR):
     66        (JSC::AssemblyHelpers::constructRegisterSet):
     67        * jit/RegisterSet.h:
     68        (JSC::RegisterSet::setAny):
     69        Clean up selectScratchGPR code to pass JSValueRegs.
     70
    1712018-04-10  Caio Lima  <ticaiolima@gmail.com>
    272
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r230488 r230517  
    17071707                E3555B8A1DAE03A500F36921 /* DOMJITCallDOMGetterSnippet.h in Headers */ = {isa = PBXBuildFile; fileRef = E3555B891DAE03A200F36921 /* DOMJITCallDOMGetterSnippet.h */; settings = {ATTRIBUTES = (Private, ); }; };
    17081708                E355F3531B7DC85300C50DC5 /* ModuleLoaderPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */; };
     1709                E356D86420728381005AC750 /* DFGCompareSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = E356D86320728381005AC750 /* DFGCompareSlowPathGenerator.h */; };
    17091710                E35CA1541DBC3A5C00F83516 /* DOMJITHeapRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1521DBC3A5600F83516 /* DOMJITHeapRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
    17101711                E35CA1561DBC3A5F00F83516 /* DOMJITAbstractHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    45564557                E355F3501B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleLoaderPrototype.cpp; sourceTree = "<group>"; };
    45574558                E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleLoaderPrototype.h; sourceTree = "<group>"; };
     4559                E356D86320728381005AC750 /* DFGCompareSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCompareSlowPathGenerator.h; path = dfg/DFGCompareSlowPathGenerator.h; sourceTree = "<group>"; };
    45584560                E35CA14F1DBC3A5600F83516 /* DOMJITAbstractHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMJITAbstractHeap.cpp; sourceTree = "<group>"; };
    45594561                E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITAbstractHeap.h; sourceTree = "<group>"; };
     
    71617163                                0FEA0A2D170D40BF00BB722C /* DFGCommonData.cpp */,
    71627164                                0FEA0A2E170D40BF00BB722C /* DFGCommonData.h */,
     7165                                E356D86320728381005AC750 /* DFGCompareSlowPathGenerator.h */,
    71637166                                0F38B01317CFE75500B144D3 /* DFGCompilationKey.cpp */,
    71647167                                0F38B01417CFE75500B144D3 /* DFGCompilationKey.h */,
     
    85108513                                0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */,
    85118514                                0FEA0A32170D40BF00BB722C /* DFGCommonData.h in Headers */,
     8515                                E356D86420728381005AC750 /* DFGCompareSlowPathGenerator.h in Headers */,
    85128516                                0F38B01817CFE75500B144D3 /* DFGCompilationKey.h in Headers */,
    85138517                                0F38B01A17CFE75500B144D3 /* DFGCompilationMode.h in Headers */,
     
    90359039                                7013CA8C1B491A9400CAE613 /* JSJob.h in Headers */,
    90369040                                BC18C4160E16F5CD00B34460 /* JSLexicalEnvironment.h in Headers */,
    9037                                 7A9774A8206B82E4008D03D0 /* JSWeakValue.h in Headers */,
    90389041                                BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */,
    90399042                                C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */,
     
    91079110                                0F0B286B1EB8E6CF000EB5D2 /* JSWeakPrivate.h in Headers */,
    91089111                                709FB8681AE335C60039D069 /* JSWeakSet.h in Headers */,
     9112                                7A9774A8206B82E4008D03D0 /* JSWeakValue.h in Headers */,
    91099113                                AD5C36EB1F75AD73000BCAAF /* JSWebAssembly.h in Headers */,
    91109114                                AD9E852F1E8A0C7C008DE39E /* JSWebAssemblyCodeBlock.h in Headers */,
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r230516 r230517  
    18981898}
    18991899
    1900 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyByInt(ExecState* exec, JSCell* baseCell, int32_t subscript, int32_t internalMethodType)
     1900size_t JIT_OPERATION operationHasIndexedPropertyByInt(ExecState* exec, JSCell* baseCell, int32_t subscript, int32_t internalMethodType)
    19011901{
    19021902    VM& vm = exec->vm();
     
    19051905    if (UNLIKELY(subscript < 0)) {
    19061906        // Go the slowest way possible because negative indices don't use indexed storage.
    1907         return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, Identifier::from(exec, subscript), static_cast<PropertySlot::InternalMethodType>(internalMethodType))));
    1908     }
    1909     return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, subscript, static_cast<PropertySlot::InternalMethodType>(internalMethodType))));
     1907        return object->hasPropertyGeneric(exec, Identifier::from(exec, subscript), static_cast<PropertySlot::InternalMethodType>(internalMethodType));
     1908    }
     1909    return object->hasPropertyGeneric(exec, subscript, static_cast<PropertySlot::InternalMethodType>(internalMethodType));
    19101910}
    19111911
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r230516 r230517  
    8181EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(ExecState*, JSObject*) WTF_INTERNAL;
    8282EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState*, EncodedJSValue, JSCell*);
    83 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyByInt(ExecState*, JSCell*, int32_t, int32_t);
     83size_t JIT_OPERATION operationHasIndexedPropertyByInt(ExecState*, JSCell*, int32_t, int32_t);
    8484JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState*, EncodedJSValue);
    8585JSCell* JIT_OPERATION operationGetPropertyEnumeratorCell(ExecState*, JSCell*);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r230516 r230517  
    3535#include "DFGCallCreateDirectArgumentsSlowPathGenerator.h"
    3636#include "DFGCapabilities.h"
     37#include "DFGCompareSlowPathGenerator.h"
    3738#include "DFGMayExit.h"
    3839#include "DFGOSRExitFuzz.h"
     
    11831184}
    11841185
    1185 bool SpeculativeJIT::nonSpeculativeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
    1186 {
    1187     unsigned branchIndexInBlock = detectPeepHoleBranch();
    1188     if (branchIndexInBlock != UINT_MAX) {
    1189         Node* branchNode = m_block->at(branchIndexInBlock);
    1190 
    1191         ASSERT(node->adjustedRefCount() == 1);
    1192        
    1193         nonSpeculativePeepholeBranch(node, branchNode, cond, helperFunction);
    1194    
    1195         m_indexInBlock = branchIndexInBlock;
    1196         m_currentNode = branchNode;
    1197        
    1198         return true;
    1199     }
    1200    
    1201     nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);
    1202    
    1203     return false;
    1204 }
    1205 
    12061186bool SpeculativeJIT::nonSpeculativeStrictEq(Node* node, bool invert)
    12071187{
     
    34653445    m_jit.exceptionCheck();
    34663446    jsValueResult(resultRegs, node);
     3447}
     3448
     3449void SpeculativeJIT::compileOverridesHasInstance(Node* node)
     3450{
     3451    Node* hasInstanceValueNode = node->child2().node();
     3452    JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value());
     3453
     3454    MacroAssembler::JumpList notDefault;
     3455    SpeculateCellOperand base(this, node->child1());
     3456    JSValueOperand hasInstanceValue(this, node->child2());
     3457    GPRTemporary result(this);
     3458
     3459    GPRReg baseGPR = base.gpr();
     3460    GPRReg resultGPR = result.gpr();
     3461
     3462    // It would be great if constant folding handled automatically the case where we knew the hasInstance function
     3463    // was a constant. Unfortunately, the folding rule for OverridesHasInstance is in the strength reduction phase
     3464    // since it relies on OSR information. https://bugs.webkit.org/show_bug.cgi?id=154832
     3465    if (!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode->asCell()) {
     3466        JSValueRegs hasInstanceValueRegs = hasInstanceValue.jsValueRegs();
     3467#if USE(JSVALUE64)
     3468        notDefault.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.gpr(), TrustedImmPtr(node->cellOperand())));
     3469#else
     3470        notDefault.append(m_jit.branchIfNotCell(hasInstanceValueRegs));
     3471        notDefault.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.payloadGPR(), TrustedImmPtr(node->cellOperand())));
     3472#endif
     3473    }
     3474
     3475    // Check that base 'ImplementsDefaultHasInstance'.
     3476    m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR);
     3477    MacroAssembler::Jump done = m_jit.jump();
     3478
     3479    if (!notDefault.empty()) {
     3480        notDefault.link(&m_jit);
     3481        m_jit.move(TrustedImm32(1), resultGPR);
     3482    }
     3483
     3484    done.link(&m_jit);
     3485    unblessedBooleanResult(resultGPR, node);
    34673486}
    34683487
     
    69256944}
    69266945
     6946void SpeculativeJIT::compileLoadVarargs(Node* node)
     6947{
     6948    LoadVarargsData* data = node->loadVarargsData();
     6949
     6950    JSValueRegs argumentsRegs;
     6951    {
     6952        JSValueOperand arguments(this, node->child1());
     6953        argumentsRegs = arguments.jsValueRegs();
     6954        flushRegisters();
     6955    }
     6956
     6957    callOperation(operationSizeOfVarargs, GPRInfo::returnValueGPR, argumentsRegs, data->offset);
     6958    m_jit.exceptionCheck();
     6959
     6960    lock(GPRInfo::returnValueGPR);
     6961    {
     6962        JSValueOperand arguments(this, node->child1());
     6963        argumentsRegs = arguments.jsValueRegs();
     6964        flushRegisters();
     6965    }
     6966    unlock(GPRInfo::returnValueGPR);
     6967
     6968    // FIXME: There is a chance that we will call an effectful length property twice. This is safe
     6969    // from the standpoint of the VM's integrity, but it's subtly wrong from a spec compliance
     6970    // standpoint. The best solution would be one where we can exit *into* the op_call_varargs right
     6971    // past the sizing.
     6972    // https://bugs.webkit.org/show_bug.cgi?id=141448
     6973
     6974    GPRReg argCountIncludingThisGPR =
     6975        JITCompiler::selectScratchGPR(GPRInfo::returnValueGPR, argumentsRegs);
     6976
     6977    m_jit.add32(TrustedImm32(1), GPRInfo::returnValueGPR, argCountIncludingThisGPR);
     6978
     6979    speculationCheck(
     6980        VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32(
     6981            MacroAssembler::Above,
     6982            GPRInfo::returnValueGPR,
     6983            argCountIncludingThisGPR));
     6984
     6985    speculationCheck(
     6986        VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32(
     6987            MacroAssembler::Above,
     6988            argCountIncludingThisGPR,
     6989            TrustedImm32(data->limit)));
     6990
     6991    m_jit.store32(argCountIncludingThisGPR, JITCompiler::payloadFor(data->machineCount));
     6992
     6993    callOperation(operationLoadVarargs, data->machineStart.offset(), argumentsRegs, data->offset, GPRInfo::returnValueGPR, data->mandatoryMinimum);
     6994    m_jit.exceptionCheck();
     6995
     6996    noResult(node);
     6997}
     6998
    69276999void SpeculativeJIT::compileForwardVarargs(Node* node)
    69287000{
     
    85108582}
    85118583
     8584void SpeculativeJIT::compileIsObject(Node* node)
     8585{
     8586    JSValueOperand value(this, node->child1());
     8587#if USE(JSVALUE64)
     8588    GPRTemporary result(this, Reuse, value);
     8589#else
     8590    GPRTemporary result(this, Reuse, value, TagWord);
     8591#endif
     8592
     8593    JSValueRegs valueRegs = value.jsValueRegs();
     8594    GPRReg resultGPR = result.gpr();
     8595
     8596    JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
     8597
     8598    m_jit.compare8(JITCompiler::AboveOrEqual,
     8599        JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
     8600        TrustedImm32(ObjectType),
     8601        resultGPR);
     8602    JITCompiler::Jump done = m_jit.jump();
     8603
     8604    isNotCell.link(&m_jit);
     8605    m_jit.move(TrustedImm32(0), resultGPR);
     8606
     8607    done.link(&m_jit);
     8608    unblessedBooleanResult(resultGPR, node);
     8609}
     8610
    85128611void SpeculativeJIT::compileIsObjectOrNull(Node* node)
    85138612{
     
    86658764    SpeculateCellOperand cell(this, node->child1());
    86668765    speculationCheck(BadCell, JSValueSource::unboxedCell(cell.gpr()), node->child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, cell.gpr(), node->cellOperand()->cell()));
     8766    noResult(node);
     8767}
     8768
     8769void SpeculativeJIT::compileCheckNotEmpty(Node* node)
     8770{
     8771    JSValueOperand operand(this, node->child1());
     8772    JSValueRegs regs = operand.jsValueRegs();
     8773    speculationCheck(TDZFailure, JSValueSource(), nullptr, m_jit.branchIfEmpty(regs));
    86678774    noResult(node);
    86688775}
     
    1155511662    m_jit.exceptionCheck();
    1155611663    cellResult(resultGPR, node);
     11664}
     11665
     11666void SpeculativeJIT::compilePutByIdFlush(Node* node)
     11667{
     11668    SpeculateCellOperand base(this, node->child1());
     11669    JSValueOperand value(this, node->child2());
     11670    GPRTemporary scratch(this);
     11671
     11672    GPRReg baseGPR = base.gpr();
     11673    JSValueRegs valueRegs = value.jsValueRegs();
     11674    GPRReg scratchGPR = scratch.gpr();
     11675    flushRegisters();
     11676
     11677    cachedPutById(node->origin.semantic, baseGPR, valueRegs, scratchGPR, node->identifierNumber(), NotDirect, MacroAssembler::Jump(), DontSpill);
     11678
     11679    noResult(node);
     11680}
     11681
     11682void SpeculativeJIT::compilePutById(Node* node)
     11683{
     11684    SpeculateCellOperand base(this, node->child1());
     11685    JSValueOperand value(this, node->child2());
     11686    GPRTemporary scratch(this);
     11687
     11688    GPRReg baseGPR = base.gpr();
     11689    JSValueRegs valueRegs = value.jsValueRegs();
     11690    GPRReg scratchGPR = scratch.gpr();
     11691
     11692    cachedPutById(node->origin.semantic, baseGPR, valueRegs, scratchGPR, node->identifierNumber(), NotDirect);
     11693
     11694    noResult(node);
     11695}
     11696
     11697void SpeculativeJIT::compilePutByIdDirect(Node* node)
     11698{
     11699    SpeculateCellOperand base(this, node->child1());
     11700    JSValueOperand value(this, node->child2());
     11701    GPRTemporary scratch(this);
     11702
     11703    GPRReg baseGPR = base.gpr();
     11704    JSValueRegs valueRegs = value.jsValueRegs();
     11705    GPRReg scratchGPR = scratch.gpr();
     11706
     11707    cachedPutById(node->origin.semantic, baseGPR, valueRegs, scratchGPR, node->identifierNumber(), Direct);
     11708
     11709    noResult(node);
    1155711710}
    1155811711
     
    1186112014    GPRFlushedCallResult result(this);
    1186212015    GPRReg resultGPR = result.gpr();
    11863     GPRReg structureGPR = selectScratchGPR(sizeGPR);
     12016    GPRReg structureGPR = AssemblyHelpers::selectScratchGPR(sizeGPR);
    1186412017    MacroAssembler::Jump bigLength = m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
    1186512018    m_jit.move(TrustedImmPtr(m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()))), structureGPR);
     
    1241012563}
    1241112564
     12565void SpeculativeJIT::compileMiscStrictEq(Node* node)
     12566{
     12567    JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
     12568    JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
     12569    GPRTemporary result(this);
     12570
     12571    if (node->child1().useKind() == MiscUse)
     12572        speculateMisc(node->child1(), op1.jsValueRegs());
     12573    if (node->child2().useKind() == MiscUse)
     12574        speculateMisc(node->child2(), op2.jsValueRegs());
     12575
     12576#if USE(JSVALUE64)
     12577    m_jit.compare64(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr());
     12578#else
     12579    m_jit.move(TrustedImm32(0), result.gpr());
     12580    JITCompiler::Jump notEqual = m_jit.branch32(JITCompiler::NotEqual, op1.tagGPR(), op2.tagGPR());
     12581    m_jit.compare32(JITCompiler::Equal, op1.payloadGPR(), op2.payloadGPR(), result.gpr());
     12582    notEqual.link(&m_jit);
     12583#endif
     12584    unblessedBooleanResult(result.gpr(), node);
     12585}
     12586
     12587void SpeculativeJIT::emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR)
     12588{
     12589    m_jit.zeroExtend32ToPtr(sizeGPR, scratchGPR);
     12590    MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
     12591    MacroAssembler::Label loop = m_jit.label();
     12592    m_jit.sub32(TrustedImm32(1), scratchGPR);
     12593    m_jit.storeValue(emptyValueRegs, MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight));
     12594    m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
     12595    done.link(&m_jit);
     12596}
     12597
     12598void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)
     12599{
     12600    GPRTemporary storage(this);
     12601    GPRTemporary scratch(this);
     12602    GPRTemporary scratch2(this);
     12603
     12604    GPRReg storageGPR = storage.gpr();
     12605    GPRReg scratchGPR = scratch.gpr();
     12606    GPRReg scratch2GPR = scratch2.gpr();
     12607
     12608    m_jit.move(TrustedImmPtr(nullptr), storageGPR);
     12609
     12610    MacroAssembler::JumpList slowCases;
     12611    if (shouldConvertLargeSizeToArrayStorage)
     12612        slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
     12613
     12614    // We can use resultGPR as a scratch right now.
     12615    emitAllocateButterfly(storageGPR, sizeGPR, scratchGPR, scratch2GPR, resultGPR, slowCases);
     12616
     12617#if USE(JSVALUE64)
     12618    JSValueRegs emptyValueRegs(scratchGPR);
     12619    if (hasDouble(indexingType))
     12620        m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), emptyValueRegs.gpr());
     12621    else
     12622        m_jit.move(TrustedImm64(JSValue::encode(JSValue())), emptyValueRegs.gpr());
     12623#else
     12624    JSValueRegs emptyValueRegs(scratchGPR, scratch2GPR);
     12625    if (hasDouble(indexingType))
     12626        m_jit.moveValue(JSValue(JSValue::EncodeAsDouble, PNaN), emptyValueRegs);
     12627    else
     12628        m_jit.moveValue(JSValue(), emptyValueRegs);
     12629#endif
     12630    emitInitializeButterfly(storageGPR, sizeGPR, emptyValueRegs, resultGPR);
     12631
     12632    RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType));
     12633
     12634    emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
     12635
     12636    m_jit.mutatorFence(*m_jit.vm());
     12637
     12638    addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
     12639        slowCases, this, operationNewArrayWithSize, resultGPR,
     12640        structure,
     12641        shouldConvertLargeSizeToArrayStorage ? m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)) : structure,
     12642        sizeGPR, storageGPR));
     12643}
     12644
     12645void SpeculativeJIT::compileHasIndexedProperty(Node* node)
     12646{
     12647    SpeculateCellOperand base(this, node->child1());
     12648    SpeculateStrictInt32Operand index(this, node->child2());
     12649    GPRTemporary result(this);
     12650
     12651    GPRReg baseGPR = base.gpr();
     12652    GPRReg indexGPR = index.gpr();
     12653    GPRReg resultGPR = result.gpr();
     12654
     12655    MacroAssembler::JumpList slowCases;
     12656    ArrayMode mode = node->arrayMode();
     12657    switch (mode.type()) {
     12658    case Array::Int32:
     12659    case Array::Contiguous: {
     12660        ASSERT(!!node->child3());
     12661        StorageOperand storage(this, node->child3());
     12662        GPRTemporary scratch(this);
     12663
     12664        GPRReg storageGPR = storage.gpr();
     12665        GPRReg scratchGPR = scratch.gpr();
     12666
     12667        MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
     12668        if (mode.isInBounds())
     12669            speculationCheck(OutOfBounds, JSValueRegs(), nullptr, outOfBounds);
     12670        else
     12671            slowCases.append(outOfBounds);
     12672
     12673#if USE(JSVALUE64)
     12674        m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchGPR);
     12675        slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR));
     12676#else
     12677        m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR);
     12678        slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag)));
     12679#endif
     12680        m_jit.move(TrustedImm32(1), resultGPR);
     12681        break;
     12682    }
     12683    case Array::Double: {
     12684        ASSERT(!!node->child3());
     12685        StorageOperand storage(this, node->child3());
     12686        FPRTemporary scratch(this);
     12687        FPRReg scratchFPR = scratch.fpr();
     12688        GPRReg storageGPR = storage.gpr();
     12689
     12690        MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
     12691        if (mode.isInBounds())
     12692            speculationCheck(OutOfBounds, JSValueRegs(), nullptr, outOfBounds);
     12693        else
     12694            slowCases.append(outOfBounds);
     12695
     12696        m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR);
     12697        slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR));
     12698        m_jit.move(TrustedImm32(1), resultGPR);
     12699        break;
     12700    }
     12701    case Array::ArrayStorage: {
     12702        ASSERT(!!node->child3());
     12703        StorageOperand storage(this, node->child3());
     12704        GPRTemporary scratch(this);
     12705
     12706        GPRReg storageGPR = storage.gpr();
     12707        GPRReg scratchGPR = scratch.gpr();
     12708
     12709        MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
     12710        if (mode.isInBounds())
     12711            speculationCheck(OutOfBounds, JSValueRegs(), nullptr, outOfBounds);
     12712        else
     12713            slowCases.append(outOfBounds);
     12714
     12715#if USE(JSVALUE64)
     12716        m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), scratchGPR);
     12717        slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR));
     12718#else
     12719        m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR);
     12720        slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag)));
     12721#endif
     12722        m_jit.move(TrustedImm32(1), resultGPR);
     12723        break;
     12724    }
     12725    default: {
     12726        slowCases.append(m_jit.jump());
     12727        break;
     12728    }
     12729    }
     12730
     12731    addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedPropertyByInt, HasPropertyPtrTag, resultGPR, baseGPR, indexGPR, static_cast<int32_t>(node->internalMethodType())));
     12732
     12733    unblessedBooleanResult(resultGPR, node);
     12734}
     12735
     12736void SpeculativeJIT::compileGetDirectPname(Node* node)
     12737{
     12738    Edge& baseEdge = m_jit.graph().varArgChild(node, 0);
     12739    Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
     12740
     12741    SpeculateCellOperand base(this, baseEdge);
     12742    SpeculateCellOperand property(this, propertyEdge);
     12743    GPRReg baseGPR = base.gpr();
     12744    GPRReg propertyGPR = property.gpr();
     12745
     12746#if CPU(X86)
     12747    // Not enough registers on X86 for this code, so always use the slow path.
     12748    flushRegisters();
     12749    JSValueRegsFlushedCallResult result(this);
     12750    JSValueRegs resultRegs = result.regs();
     12751    callOperation(operationGetByValCell, resultRegs, baseGPR, JSValue::JSCellType, propertyGPR);
     12752    m_jit.exceptionCheck();
     12753    jsValueResult(resultRegs, node);
     12754#else
     12755    Edge& indexEdge = m_jit.graph().varArgChild(node, 2);
     12756    Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3);
     12757    SpeculateStrictInt32Operand index(this, indexEdge);
     12758    SpeculateCellOperand enumerator(this, enumeratorEdge);
     12759    GPRTemporary scratch(this);
     12760    JSValueRegsTemporary result(this);
     12761
     12762    GPRReg indexGPR = index.gpr();
     12763    GPRReg enumeratorGPR = enumerator.gpr();
     12764    GPRReg scratchGPR = scratch.gpr();
     12765    JSValueRegs resultRegs = result.regs();
     12766
     12767    MacroAssembler::JumpList slowPath;
     12768
     12769    // Check the structure
     12770    m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR);
     12771    slowPath.append(
     12772        m_jit.branch32(
     12773            MacroAssembler::NotEqual,
     12774            scratchGPR,
     12775            MacroAssembler::Address(
     12776                enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset())));
     12777
     12778    // Compute the offset
     12779    // If index is less than the enumerator's cached inline storage, then it's an inline access
     12780    MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
     12781        indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
     12782
     12783    m_jit.loadValue(MacroAssembler::BaseIndex(baseGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
     12784
     12785    MacroAssembler::Jump done = m_jit.jump();
     12786
     12787    // Otherwise it's out of line
     12788    outOfLineAccess.link(&m_jit);
     12789    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), resultRegs.gpr());
     12790    m_jit.move(indexGPR, scratchGPR);
     12791    m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
     12792    m_jit.neg32(scratchGPR);
     12793    m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
     12794    int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
     12795    m_jit.loadValue(MacroAssembler::BaseIndex(resultRegs.gpr(), scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
     12796
     12797    done.link(&m_jit);
     12798
     12799#if USE(JSVALUE64)
     12800    addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByValCell, GetPropertyPtrTag, resultRegs, baseGPR, propertyGPR));
     12801#else
     12802    addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByValCell, GetPropertyPtrTag, resultRegs, baseGPR, JSValue::JSCellType, propertyGPR));
     12803#endif
     12804
     12805    jsValueResult(resultRegs, node);
     12806#endif
     12807}
     12808
     12809void SpeculativeJIT::compileExtractCatchLocal(Node* node)
     12810{
     12811    JSValueRegsTemporary result(this);
     12812    JSValueRegs resultRegs = result.regs();
     12813
     12814    JSValue* ptr = &reinterpret_cast<JSValue*>(m_jit.jitCode()->common.catchOSREntryBuffer->dataBuffer())[node->catchOSREntryIndex()];
     12815    m_jit.loadValue(ptr, resultRegs);
     12816    jsValueResult(resultRegs, node);
     12817}
     12818
     12819void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
     12820{
     12821    RegisterSet usedRegisters = this->usedRegisters();
     12822    if (spillMode == DontSpill) {
     12823        // We've already flushed registers to the stack, we don't need to spill these.
     12824        usedRegisters.set(baseGPR, false);
     12825        usedRegisters.set(valueRegs, false);
     12826    }
     12827    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
     12828    JITPutByIdGenerator gen(
     12829        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters,
     12830        JSValueRegs::payloadOnly(baseGPR), valueRegs,
     12831        scratchGPR, m_jit.ecmaModeFor(codeOrigin), putKind);
     12832
     12833    gen.generateFastPath(m_jit);
     12834
     12835    JITCompiler::JumpList slowCases;
     12836    if (slowPathTarget.isSet())
     12837        slowCases.append(slowPathTarget);
     12838    slowCases.append(gen.slowPathJump());
     12839
     12840#if USE(JSVALUE64)
     12841    auto slowPath = slowPathCall(
     12842        slowCases, this, gen.slowPathFunction(), PutPropertyPtrTag, NoResult, gen.stubInfo(), valueRegs,
     12843        baseGPR, identifierUID(identifierNumber));
     12844#else
     12845    auto slowPath = slowPathCall(
     12846        slowCases, this, gen.slowPathFunction(), PutPropertyPtrTag, NoResult, gen.stubInfo(), valueRegs,
     12847        JSValue::JSCellType, baseGPR, identifierUID(identifierNumber));
     12848#endif
     12849
     12850    m_jit.addPutById(gen, slowPath.get());
     12851    addSlowPathGenerator(WTFMove(slowPath));
     12852}
     12853
     12854void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
     12855{
     12856    ASSERT(node->isBinaryUseKind(UntypedUse));
     12857    JSValueOperand arg1(this, node->child1());
     12858    JSValueOperand arg2(this, node->child2());
     12859
     12860    JSValueRegs arg1Regs = arg1.jsValueRegs();
     12861    JSValueRegs arg2Regs = arg2.jsValueRegs();
     12862
     12863    JITCompiler::JumpList slowPath;
     12864
     12865    if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
     12866        GPRFlushedCallResult result(this);
     12867        GPRReg resultGPR = result.gpr();
     12868
     12869        arg1.use();
     12870        arg2.use();
     12871
     12872        flushRegisters();
     12873        callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs);
     12874        m_jit.exceptionCheck();
     12875
     12876        unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
     12877        return;
     12878    }
     12879
     12880#if USE(JSVALUE64)
     12881    GPRTemporary result(this, Reuse, arg1);
     12882#else
     12883    GPRTemporary result(this, Reuse, arg1, TagWord);
     12884#endif
     12885    GPRReg resultGPR = result.gpr();
     12886
     12887    arg1.use();
     12888    arg2.use();
     12889
     12890    if (!isKnownInteger(node->child1().node()))
     12891        slowPath.append(m_jit.branchIfNotInt32(arg1Regs));
     12892    if (!isKnownInteger(node->child2().node()))
     12893        slowPath.append(m_jit.branchIfNotInt32(arg2Regs));
     12894
     12895    m_jit.compare32(cond, arg1Regs.payloadGPR(), arg2Regs.payloadGPR(), resultGPR);
     12896
     12897    if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
     12898        addSlowPathGenerator(std::make_unique<CompareSlowPathGenerator<JITCompiler::JumpList>>(
     12899            slowPath, this, helperFunction, resultGPR, arg1Regs, arg2Regs));
     12900    }
     12901
     12902    unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
     12903}
     12904
     12905void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
     12906{
     12907    BasicBlock* taken = branchNode->branchData()->taken.block;
     12908    BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
     12909
     12910    JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
     12911
     12912    // The branch instruction will branch to the taken block.
     12913    // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
     12914    if (taken == nextBlock()) {
     12915        cond = JITCompiler::invert(cond);
     12916        callResultCondition = JITCompiler::Zero;
     12917        BasicBlock* tmp = taken;
     12918        taken = notTaken;
     12919        notTaken = tmp;
     12920    }
     12921
     12922    JSValueOperand arg1(this, node->child1());
     12923    JSValueOperand arg2(this, node->child2());
     12924    JSValueRegs arg1Regs = arg1.jsValueRegs();
     12925    JSValueRegs arg2Regs = arg2.jsValueRegs();
     12926
     12927    JITCompiler::JumpList slowPath;
     12928
     12929    if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
     12930        GPRFlushedCallResult result(this);
     12931        GPRReg resultGPR = result.gpr();
     12932
     12933        arg1.use();
     12934        arg2.use();
     12935
     12936        flushRegisters();
     12937        callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs);
     12938        m_jit.exceptionCheck();
     12939
     12940        branchTest32(callResultCondition, resultGPR, taken);
     12941    } else {
     12942#if USE(JSVALUE64)
     12943        GPRTemporary result(this, Reuse, arg2);
     12944#else
     12945        GPRTemporary result(this, Reuse, arg2, TagWord);
     12946#endif
     12947        GPRReg resultGPR = result.gpr();
     12948
     12949        arg1.use();
     12950        arg2.use();
     12951
     12952        if (!isKnownInteger(node->child1().node()))
     12953            slowPath.append(m_jit.branchIfNotInt32(arg1Regs));
     12954        if (!isKnownInteger(node->child2().node()))
     12955            slowPath.append(m_jit.branchIfNotInt32(arg2Regs));
     12956
     12957        branch32(cond, arg1Regs.payloadGPR(), arg2Regs.payloadGPR(), taken);
     12958
     12959        if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
     12960            jump(notTaken, ForceJump);
     12961
     12962            slowPath.link(&m_jit);
     12963
     12964            silentSpillAllRegisters(resultGPR);
     12965            callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs);
     12966            silentFillAllRegisters();
     12967            m_jit.exceptionCheck();
     12968
     12969            branchTest32(callResultCondition, resultGPR, taken);
     12970        }
     12971    }
     12972
     12973    jump(notTaken);
     12974
     12975    m_indexInBlock = m_block->size() - 1;
     12976    m_currentNode = branchNode;
     12977}
    1241212978
    1241312979} } // namespace JSC::DFG
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r230516 r230517  
    346346    void compileStoreBarrier(Node*);
    347347
    348     static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg)
    349     {
    350         return AssemblyHelpers::selectScratchGPR(preserve1, preserve2, preserve3, preserve4);
    351     }
    352 
    353348    // Called by the speculative operand types, below, to fill operand to
    354349    // machine registers, implicitly generating speculation checks as needed.
     
    726721
    727722    void cachedGetById(CodeOrigin, JSValueRegs base, JSValueRegs result, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType);
     723    void cachedPutById(CodeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
    728724
    729725#if USE(JSVALUE64)
    730726    void cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType);
    731     void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
    732727    void cachedGetByIdWithThis(CodeOrigin, GPRReg baseGPR, GPRReg thisGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget = JITCompiler::JumpList());
    733728#elif USE(JSVALUE32_64)
    734729    void cachedGetById(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType);
    735     void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
    736730    void cachedGetByIdWithThis(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg thisTagGPROrNone, GPRReg thisPayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget = JITCompiler::JumpList());
    737731#endif
     
    749743    void nonSpeculativePeepholeBranch(Node*, Node* branchNode, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction);
    750744    void nonSpeculativeNonPeepholeCompare(Node*, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction);
    751     bool nonSpeculativeCompare(Node*, MacroAssembler::RelationalCondition, S_JITOperation_EJJ helperFunction);
    752745   
    753746    void nonSpeculativePeepholeStrictEq(Node*, Node* branchNode, bool invert = false);
     
    758751    void compileInstanceOf(Node*);
    759752    void compileInstanceOfCustom(Node*);
     753    void compileOverridesHasInstance(Node*);
    760754
    761755    void compileIsCellWithType(Node*);
     
    14431437    void compileNewRegexp(Node*);
    14441438    void compileForwardVarargs(Node*);
     1439    void compileLoadVarargs(Node*);
    14451440    void compileCreateActivation(Node*);
    14461441    void compileCreateDirectArguments(Node*);
     
    14651460    void compileRegExpTest(Node*);
    14661461    void compileStringReplace(Node*);
     1462    void compileIsObject(Node*);
    14671463    void compileIsObjectOrNull(Node*);
    14681464    void compileIsFunction(Node*);
    14691465    void compileTypeOf(Node*);
    14701466    void compileCheckCell(Node*);
     1467    void compileCheckNotEmpty(Node*);
    14711468    void compileCheckStructure(Node*);
    14721469    void emitStructureCheck(Node*, GPRReg cellGPR, GPRReg tempGPR);
     
    14981495    void compileHasGenericProperty(Node*);
    14991496    void compileToIndexString(Node*);
     1497    void compilePutByIdFlush(Node*);
     1498    void compilePutById(Node*);
     1499    void compilePutByIdDirect(Node*);
    15001500    void compilePutByIdWithThis(Node*);
    15011501    void compileHasStructureProperty(Node*);
     1502    void compileGetDirectPname(Node*);
    15021503    void compileGetPropertyEnumerator(Node*);
    15031504    void compileGetEnumeratorPname(Node*);
     
    15181519    void compileLogShadowChickenPrologue(Node*);
    15191520    void compileLogShadowChickenTail(Node*);
     1521    void compileHasIndexedProperty(Node*);
     1522    void compileExtractCatchLocal(Node*);
    15201523
    15211524    void moveTrueTo(GPRReg);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r230516 r230517  
    266266}
    267267
    268 void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
    269 {
    270     RegisterSet usedRegisters = this->usedRegisters();
    271     if (spillMode == DontSpill) {
    272         // We've already flushed registers to the stack, we don't need to spill these.
    273         usedRegisters.set(basePayloadGPR, false);
    274         usedRegisters.set(JSValueRegs(valueTagGPR, valuePayloadGPR), false);
    275     }
    276     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
    277     JITPutByIdGenerator gen(
    278         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters,
    279         JSValueRegs::payloadOnly(basePayloadGPR), JSValueRegs(valueTagGPR, valuePayloadGPR),
    280         scratchGPR, m_jit.ecmaModeFor(codeOrigin), putKind);
    281    
    282     gen.generateFastPath(m_jit);
    283    
    284     JITCompiler::JumpList slowCases;
    285     if (slowPathTarget.isSet())
    286         slowCases.append(slowPathTarget);
    287     slowCases.append(gen.slowPathJump());
    288 
    289     auto slowPath = slowPathCall(
    290         slowCases, this, gen.slowPathFunction(), NoResult, gen.stubInfo(), JSValueRegs(valueTagGPR, valuePayloadGPR),
    291             JSValue::JSCellType,  basePayloadGPR, identifierUID(identifierNumber));
    292 
    293     m_jit.addPutById(gen, slowPath.get());
    294     addSlowPathGenerator(WTFMove(slowPath));
    295 }
    296 
    297268void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand)
    298269{
     
    413384}
    414385
    415 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
    416 {
    417     BasicBlock* taken = branchNode->branchData()->taken.block;
    418     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
    419 
    420     JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
    421 
    422     // The branch instruction will branch to the taken block.
    423     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
    424     if (taken == nextBlock()) {
    425         cond = JITCompiler::invert(cond);
    426         callResultCondition = JITCompiler::Zero;
    427         BasicBlock* tmp = taken;
    428         taken = notTaken;
    429         notTaken = tmp;
    430     }
    431 
    432     JSValueOperand arg1(this, node->child1());
    433     JSValueOperand arg2(this, node->child2());
    434     JSValueRegs arg1Regs = arg1.jsValueRegs();
    435     JSValueRegs arg2Regs = arg2.jsValueRegs();
    436     GPRReg arg1TagGPR = arg1.tagGPR();
    437     GPRReg arg1PayloadGPR = arg1.payloadGPR();
    438     GPRReg arg2TagGPR = arg2.tagGPR();
    439     GPRReg arg2PayloadGPR = arg2.payloadGPR();
    440    
    441     JITCompiler::JumpList slowPath;
    442    
    443     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
    444         GPRFlushedCallResult result(this);
    445         GPRReg resultGPR = result.gpr();
    446 
    447         arg1.use();
    448         arg2.use();
    449 
    450         flushRegisters();
    451         callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs);
    452         m_jit.exceptionCheck();
    453 
    454         branchTest32(callResultCondition, resultGPR, taken);
    455     } else {
    456         GPRTemporary result(this);
    457         GPRReg resultGPR = result.gpr();
    458    
    459         arg1.use();
    460         arg2.use();
    461 
    462         if (!isKnownInteger(node->child1().node()))
    463             slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
    464         if (!isKnownInteger(node->child2().node()))
    465             slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
    466    
    467         branch32(cond, arg1PayloadGPR, arg2PayloadGPR, taken);
    468    
    469         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
    470             jump(notTaken, ForceJump);
    471    
    472             slowPath.link(&m_jit);
    473    
    474             silentSpillAllRegisters(resultGPR);
    475             callOperation(helperFunction, resultGPR, arg1Regs, arg2Regs);
    476             m_jit.exceptionCheck();
    477             silentFillAllRegisters();
    478        
    479             branchTest32(callResultCondition, resultGPR, taken);
    480         }
    481     }
    482 
    483     jump(notTaken);
    484    
    485     m_indexInBlock = m_block->size() - 1;
    486     m_currentNode = branchNode;
    487 }
    488 
    489 template<typename JumpType>
    490 class CompareAndBoxBooleanSlowPathGenerator
    491     : public CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg> {
    492 public:
    493     CompareAndBoxBooleanSlowPathGenerator(
    494         JumpType from, SpeculativeJIT* jit,
    495         S_JITOperation_EJJ function, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload,
    496         GPRReg arg2Tag, GPRReg arg2Payload)
    497         : CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg>(
    498             from, jit, function, NeedToSpill, ExceptionCheckRequirement::CheckNeeded, result)
    499         , m_arg1Tag(arg1Tag)
    500         , m_arg1Payload(arg1Payload)
    501         , m_arg2Tag(arg2Tag)
    502         , m_arg2Payload(arg2Payload)
    503     {
    504     }
    505    
    506 protected:
    507     virtual void generateInternal(SpeculativeJIT* jit)
    508     {
    509         this->setUp(jit);
    510         this->recordCall(
    511             jit->callOperation(
    512                 this->m_function, this->m_result, JSValueRegs(m_arg1Tag, m_arg1Payload), JSValueRegs(m_arg2Tag, m_arg2Payload)));
    513         jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result);
    514         this->tearDown(jit);
    515     }
    516    
    517 private:
    518     GPRReg m_arg1Tag;
    519     GPRReg m_arg1Payload;
    520     GPRReg m_arg2Tag;
    521     GPRReg m_arg2Payload;
    522 };
    523 
    524 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
    525 {
    526     JSValueOperand arg1(this, node->child1());
    527     JSValueOperand arg2(this, node->child2());
    528     GPRReg arg1TagGPR = arg1.tagGPR();
    529     GPRReg arg1PayloadGPR = arg1.payloadGPR();
    530     GPRReg arg2TagGPR = arg2.tagGPR();
    531     GPRReg arg2PayloadGPR = arg2.payloadGPR();
    532    
    533     JITCompiler::JumpList slowPath;
    534    
    535     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
    536         GPRFlushedCallResult result(this);
    537         GPRReg resultPayloadGPR = result.gpr();
    538    
    539         arg1.use();
    540         arg2.use();
    541 
    542         flushRegisters();
    543         callOperation(helperFunction, resultPayloadGPR, arg1.jsValueRegs(), arg2.jsValueRegs());
    544         m_jit.exceptionCheck();
    545        
    546         booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
    547     } else {
    548         GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
    549         GPRReg resultPayloadGPR = resultPayload.gpr();
    550 
    551         arg1.use();
    552         arg2.use();
    553    
    554         if (!isKnownInteger(node->child1().node()))
    555             slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
    556         if (!isKnownInteger(node->child2().node()))
    557             slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
    558 
    559         m_jit.compare32(cond, arg1PayloadGPR, arg2PayloadGPR, resultPayloadGPR);
    560    
    561         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
    562             addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>>(
    563                     slowPath, this, helperFunction, resultPayloadGPR, arg1TagGPR,
    564                     arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR));
    565         }
    566        
    567         booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
    568     }
    569 }
    570 
    571386void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert)
    572387{
     
    667482
    668483    booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
    669 }
    670 
    671 void SpeculativeJIT::compileMiscStrictEq(Node* node)
    672 {
    673     JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
    674     JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
    675     GPRTemporary result(this);
    676    
    677     if (node->child1().useKind() == MiscUse)
    678         speculateMisc(node->child1(), op1.jsValueRegs());
    679     if (node->child2().useKind() == MiscUse)
    680         speculateMisc(node->child2(), op2.jsValueRegs());
    681    
    682     m_jit.move(TrustedImm32(0), result.gpr());
    683     JITCompiler::Jump notEqual = m_jit.branch32(JITCompiler::NotEqual, op1.tagGPR(), op2.tagGPR());
    684     m_jit.compare32(JITCompiler::Equal, op1.payloadGPR(), op2.payloadGPR(), result.gpr());
    685     notEqual.link(&m_jit);
    686     booleanResult(result.gpr(), node);
    687484}
    688485
     
    35813378
    35823379    case CheckNotEmpty: {
    3583         JSValueOperand operand(this, node->child1());
    3584         GPRReg tagGPR = operand.tagGPR();
    3585         speculationCheck(TDZFailure, JSValueSource(), nullptr, m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::EmptyValueTag)));
    3586         noResult(node);
     3380        compileCheckNotEmpty(node);
    35873381        break;
    35883382    }
     
    36923486
    36933487    case PutByIdFlush: {
    3694         SpeculateCellOperand base(this, node->child1());
    3695         JSValueOperand value(this, node->child2());
    3696         GPRTemporary scratch(this);
    3697 
    3698         GPRReg baseGPR = base.gpr();
    3699         GPRReg valueTagGPR = value.tagGPR();
    3700         GPRReg valuePayloadGPR = value.payloadGPR();
    3701         GPRReg scratchGPR = scratch.gpr();
    3702         flushRegisters();
    3703 
    3704         cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), NotDirect, MacroAssembler::Jump(), DontSpill);
    3705 
    3706         noResult(node);
    3707         break;
    3708     }
    3709        
     3488        compilePutByIdFlush(node);
     3489        break;
     3490    }
     3491
    37103492    case PutById: {
    3711         SpeculateCellOperand base(this, node->child1());
    3712         JSValueOperand value(this, node->child2());
    3713         GPRTemporary scratch(this);
    3714        
    3715         GPRReg baseGPR = base.gpr();
    3716         GPRReg valueTagGPR = value.tagGPR();
    3717         GPRReg valuePayloadGPR = value.payloadGPR();
    3718         GPRReg scratchGPR = scratch.gpr();
    3719        
    3720         cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), NotDirect);
    3721        
    3722         noResult(node);
     3493        compilePutById(node);
    37233494        break;
    37243495    }
    37253496
    37263497    case PutByIdDirect: {
    3727         SpeculateCellOperand base(this, node->child1());
    3728         JSValueOperand value(this, node->child2());
    3729         GPRTemporary scratch(this);
    3730        
    3731         GPRReg baseGPR = base.gpr();
    3732         GPRReg valueTagGPR = value.tagGPR();
    3733         GPRReg valuePayloadGPR = value.payloadGPR();
    3734         GPRReg scratchGPR = scratch.gpr();
    3735        
    3736         cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), Direct);
    3737 
    3738         noResult(node);
     3498        compilePutByIdDirect(node);
    37393499        break;
    37403500    }
     
    37993559
    38003560    case OverridesHasInstance: {
    3801 
    3802         Node* hasInstanceValueNode = node->child2().node();
    3803         JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value());
    3804 
    3805         MacroAssembler::JumpList notDefaultHasInstanceValue;
    3806         SpeculateCellOperand base(this, node->child1());
    3807         JSValueOperand hasInstanceValue(this, node->child2());
    3808         GPRTemporary result(this);
    3809 
    3810         GPRReg baseGPR = base.gpr();
    3811         GPRReg resultGPR = result.gpr();
    3812 
    3813         // It would be great if constant folding handled automatically the case where we knew the hasInstance function
    3814         // was a constant. Unfortunately, the folding rule for OverridesHasInstance is in the strength reduction phase
    3815         // since it relies on OSR information. https://bugs.webkit.org/show_bug.cgi?id=154832
    3816         if (!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode->asCell()) {
    3817             JSValueRegs hasInstanceValueRegs = hasInstanceValue.jsValueRegs();
    3818             notDefaultHasInstanceValue.append(m_jit.branchIfNotCell(hasInstanceValueRegs));
    3819             notDefaultHasInstanceValue.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.payloadGPR(), TrustedImmPtr(node->cellOperand())));
    3820         }
    3821 
    3822         // Check that constructor 'ImplementsDefaultHasInstance'.
    3823         m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR);
    3824         MacroAssembler::Jump done = m_jit.jump();
    3825 
    3826         if (!notDefaultHasInstanceValue.empty()) {
    3827             notDefaultHasInstanceValue.link(&m_jit);
    3828             moveTrueTo(resultGPR);
    3829         }
    3830 
    3831         done.link(&m_jit);
    3832         booleanResult(resultGPR, node);
     3561        compileOverridesHasInstance(node);
    38333562        break;
    38343563    }
     
    39223651
    39233652    case IsObject: {
    3924         JSValueOperand value(this, node->child1());
    3925         GPRTemporary result(this, Reuse, value, TagWord);
    3926 
    3927         JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(value.jsValueRegs());
    3928 
    3929         m_jit.compare8(JITCompiler::AboveOrEqual,
    3930             JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoTypeOffset()),
    3931             TrustedImm32(ObjectType),
    3932             result.gpr());
    3933         JITCompiler::Jump done = m_jit.jump();
    3934 
    3935         isNotCell.link(&m_jit);
    3936         m_jit.move(TrustedImm32(0), result.gpr());
    3937 
    3938         done.link(&m_jit);
    3939         booleanResult(result.gpr(), node);
     3653        compileIsObject(node);
    39403654        break;
    39413655    }
     
    40773791
    40783792    case LoadVarargs: {
    4079         LoadVarargsData* data = node->loadVarargsData();
    4080        
    4081         GPRReg argumentsTagGPR;
    4082         GPRReg argumentsPayloadGPR;
    4083         JSValueRegs argumentsRegs;
    4084         {
    4085             JSValueOperand arguments(this, node->child1());
    4086             argumentsRegs = arguments.jsValueRegs();
    4087             flushRegisters();
    4088         }
    4089        
    4090         callOperation(operationSizeOfVarargs, GPRInfo::returnValueGPR, argumentsRegs, data->offset);
    4091         m_jit.exceptionCheck();
    4092        
    4093         lock(GPRInfo::returnValueGPR);
    4094         {
    4095             JSValueOperand arguments(this, node->child1());
    4096             argumentsTagGPR = arguments.tagGPR();
    4097             argumentsPayloadGPR = arguments.payloadGPR();
    4098             argumentsRegs = arguments.jsValueRegs();
    4099             flushRegisters();
    4100         }
    4101         unlock(GPRInfo::returnValueGPR);
    4102        
    4103         // FIXME: There is a chance that we will call an effectful length property twice. This is safe
    4104         // from the standpoint of the VM's integrity, but it's subtly wrong from a spec compliance
    4105         // standpoint. The best solution would be one where we can exit *into* the op_call_varargs right
    4106         // past the sizing.
    4107         // https://bugs.webkit.org/show_bug.cgi?id=141448
    4108 
    4109         GPRReg argCountIncludingThisGPR =
    4110             JITCompiler::selectScratchGPR(GPRInfo::returnValueGPR, argumentsTagGPR, argumentsPayloadGPR);
    4111        
    4112         m_jit.add32(TrustedImm32(1), GPRInfo::returnValueGPR, argCountIncludingThisGPR);
    4113 
    4114         speculationCheck(
    4115             VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32(
    4116                 MacroAssembler::Above,
    4117                 GPRInfo::returnValueGPR,
    4118                 argCountIncludingThisGPR));
    4119 
    4120         speculationCheck(
    4121             VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32(
    4122                 MacroAssembler::Above,
    4123                 argCountIncludingThisGPR,
    4124                 TrustedImm32(data->limit)));
    4125        
    4126         m_jit.store32(argCountIncludingThisGPR, JITCompiler::payloadFor(data->machineCount));
    4127        
    4128         callOperation(operationLoadVarargs, data->machineStart.offset(), argumentsRegs, data->offset, GPRInfo::returnValueGPR, data->mandatoryMinimum);
    4129         m_jit.exceptionCheck();
    4130        
    4131         noResult(node);
     3793        compileLoadVarargs(node);
    41323794        break;
    41333795    }
     
    43414003    }
    43424004    case HasIndexedProperty: {
    4343         SpeculateCellOperand base(this, node->child1());
    4344         SpeculateInt32Operand index(this, node->child2());
    4345         GPRTemporary resultPayload(this);
    4346         GPRTemporary resultTag(this);
    4347 
    4348         GPRReg baseGPR = base.gpr();
    4349         GPRReg indexGPR = index.gpr();
    4350         GPRReg resultPayloadGPR = resultPayload.gpr();
    4351         GPRReg resultTagGPR = resultTag.gpr();
    4352 
    4353         MacroAssembler::JumpList slowCases;
    4354         ArrayMode mode = node->arrayMode();
    4355         switch (mode.type()) {
    4356         case Array::Int32:
    4357         case Array::Contiguous: {
    4358             ASSERT(!!node->child3());
    4359             StorageOperand storage(this, node->child3());
    4360             GPRTemporary scratch(this);
    4361            
    4362             GPRReg storageGPR = storage.gpr();
    4363             GPRReg scratchGPR = scratch.gpr();
    4364 
    4365             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())));
    4366             m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR);
    4367             slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag)));
    4368             break;
    4369         }
    4370         case Array::Double: {
    4371             ASSERT(!!node->child3());
    4372             StorageOperand storage(this, node->child3());
    4373             FPRTemporary scratch(this);
    4374             FPRReg scratchFPR = scratch.fpr();
    4375             GPRReg storageGPR = storage.gpr();
    4376 
    4377             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())));
    4378             m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR);
    4379             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR));
    4380             break;
    4381         }
    4382         case Array::ArrayStorage: {
    4383             ASSERT(!!node->child3());
    4384             StorageOperand storage(this, node->child3());
    4385             GPRTemporary scratch(this);
    4386 
    4387             GPRReg storageGPR = storage.gpr();
    4388             GPRReg scratchGPR = scratch.gpr();
    4389 
    4390             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
    4391             m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR);
    4392             slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag)));
    4393             break;
    4394         }
    4395         default: {
    4396             slowCases.append(m_jit.jump());
    4397             break;
    4398         }
    4399         }
    4400 
    4401         moveTrueTo(resultPayloadGPR);
    4402         MacroAssembler::Jump done = m_jit.jump();
    4403 
    4404         addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedPropertyByInt, JSValueRegs(resultTagGPR, resultPayloadGPR), baseGPR, indexGPR, static_cast<int32_t>(node->internalMethodType())));
    4405        
    4406         done.link(&m_jit);
    4407         booleanResult(resultPayloadGPR, node);
     4005        compileHasIndexedProperty(node);
    44084006        break;
    44094007    }
    44104008    case GetDirectPname: {
    4411         Edge& baseEdge = m_jit.graph().varArgChild(node, 0);
    4412         Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
    4413 
    4414         SpeculateCellOperand base(this, baseEdge);
    4415         SpeculateCellOperand property(this, propertyEdge);
    4416         GPRReg baseGPR = base.gpr();
    4417         GPRReg propertyGPR = property.gpr();
    4418 
    4419 #if CPU(X86)
    4420         GPRTemporary scratch(this);
    4421 
    4422         GPRReg scratchGPR = scratch.gpr();
    4423 
    4424         // Not enough registers on X86 for this code, so always use the slow path.
    4425         flushRegisters();
    4426         JSValueRegsFlushedCallResult result(this);
    4427         JSValueRegs resultRegs = result.regs();
    4428         m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), scratchGPR);
    4429         callOperation(operationGetByValCell, resultRegs, baseGPR, JSValueRegs(scratchGPR, propertyGPR));
    4430         m_jit.exceptionCheck();
    4431 #else
    4432         GPRTemporary scratch(this);
    4433         JSValueRegsTemporary result(this);
    4434 
    4435         GPRReg scratchGPR = scratch.gpr();
    4436         JSValueRegs resultRegs = result.regs();
    4437 
    4438         Edge& indexEdge = m_jit.graph().varArgChild(node, 2);
    4439         Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3);
    4440 
    4441         SpeculateInt32Operand index(this, indexEdge);
    4442         SpeculateCellOperand enumerator(this, enumeratorEdge);
    4443 
    4444         GPRReg indexGPR = index.gpr();
    4445         GPRReg enumeratorGPR = enumerator.gpr();
    4446 
    4447         MacroAssembler::JumpList slowPath;
    4448 
    4449         // Check the structure
    4450         m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR);
    4451         slowPath.append(
    4452             m_jit.branch32(
    4453                 MacroAssembler::NotEqual,
    4454                 scratchGPR,
    4455                 MacroAssembler::Address(
    4456                     enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset())));
    4457        
    4458         // Compute the offset
    4459         // If index is less than the enumerator's cached inline storage, then it's an inline access
    4460         MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
    4461             indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
    4462 
    4463         m_jit.move(indexGPR, scratchGPR);
    4464         m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
    4465         m_jit.load32(MacroAssembler::BaseIndex(baseGPR, scratchGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR());
    4466         m_jit.load32(MacroAssembler::BaseIndex(baseGPR, scratchGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultRegs.payloadGPR());
    4467 
    4468         MacroAssembler::Jump done = m_jit.jump();
    4469        
    4470         // Otherwise it's out of line
    4471         outOfLineAccess.link(&m_jit);
    4472         m_jit.move(indexGPR, scratchGPR);
    4473         m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
    4474         m_jit.neg32(scratchGPR);
    4475         m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
    4476         // We use resultRegs.payloadGPR() as a temporary here. We have to make sure clobber it after getting the
    4477         // value out of indexGPR and enumeratorGPR because resultRegs.payloadGPR() could reuse either of those registers.
    4478         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), resultRegs.payloadGPR());
    4479         int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
    4480         m_jit.load32(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR());
    4481         m_jit.load32(MacroAssembler::BaseIndex(resultRegs.payloadGPR(), scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultRegs.payloadGPR());
    4482 
    4483         done.link(&m_jit);
    4484 
    4485         addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByValCell, resultRegs, baseGPR, JSValue::JSCellType, propertyGPR));
    4486 #endif
    4487 
    4488         jsValueResult(resultRegs, node);
     4009        compileGetDirectPname(node);
    44894010        break;
    44904011    }
     
    46514172
    46524173    case ExtractCatchLocal: {
    4653         GPRTemporary temp(this);
    4654         GPRTemporary tag(this);
    4655         GPRTemporary payload(this);
    4656 
    4657         GPRReg tempGPR = temp.gpr();
    4658         GPRReg tagGPR = tag.gpr();
    4659         GPRReg payloadGPR = payload.gpr();
    4660 
    4661         JSValue* ptr = &reinterpret_cast<JSValue*>(m_jit.jitCode()->common.catchOSREntryBuffer->dataBuffer())[node->catchOSREntryIndex()];
    4662         m_jit.move(CCallHelpers::TrustedImmPtr(ptr), tempGPR);
    4663         m_jit.load32(CCallHelpers::Address(tempGPR, TagOffset), tagGPR);
    4664         m_jit.load32(CCallHelpers::Address(tempGPR, PayloadOffset), payloadGPR);
    4665         jsValueResult(tagGPR, payloadGPR, node);
     4174        compileExtractCatchLocal(node);
    46664175        break;
    46674176    }
     
    47954304}
    47964305
    4797 void SpeculativeJIT::emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR)
    4798 {
    4799     m_jit.move(sizeGPR, scratchGPR);
    4800     MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
    4801     MacroAssembler::Label loop = m_jit.label();
    4802     m_jit.sub32(TrustedImm32(1), scratchGPR);
    4803     m_jit.store32(emptyValueRegs.tagGPR(), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
    4804     m_jit.store32(emptyValueRegs.payloadGPR(), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
    4805     m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
    4806     done.link(&m_jit);
    4807 }
    4808 
    4809 void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)
    4810 {
    4811     GPRTemporary storage(this);
    4812     GPRTemporary scratch(this);
    4813     GPRTemporary scratch2(this);
    4814    
    4815     GPRReg storageGPR = storage.gpr();
    4816     GPRReg scratchGPR = scratch.gpr();
    4817     GPRReg scratch2GPR = scratch2.gpr();
    4818    
    4819     m_jit.move(TrustedImmPtr(nullptr), storageGPR);
    4820            
    4821     MacroAssembler::JumpList slowCases;
    4822     if (shouldConvertLargeSizeToArrayStorage)
    4823         slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
    4824 
    4825     // We can use result as a scratch for this.
    4826     emitAllocateButterfly(storageGPR, sizeGPR, scratchGPR, scratch2GPR, resultGPR, slowCases);
    4827 
    4828     JSValue hole;
    4829     if (hasDouble(indexingType))
    4830         hole = JSValue(JSValue::EncodeAsDouble, PNaN);
    4831     else
    4832         hole = JSValue();
    4833     JSValueRegs emptyValueRegs(scratchGPR, scratch2GPR);
    4834     m_jit.move(TrustedImm32(hole.tag()), emptyValueRegs.tagGPR());
    4835     m_jit.move(TrustedImm32(hole.payload()), emptyValueRegs.payloadGPR());
    4836     // We can use result as a scratch for this.
    4837     emitInitializeButterfly(storageGPR, sizeGPR, emptyValueRegs, resultGPR);
    4838            
    4839     RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType));
    4840 
    4841     emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
    4842 
    4843     addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
    4844         slowCases, this, operationNewArrayWithSize, resultGPR,
    4845         structure,
    4846         shouldConvertLargeSizeToArrayStorage ? m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)) : structure,
    4847         sizeGPR, storageGPR));
    4848 }
    4849 
    48504306#endif
    48514307
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r230516 r230517  
    217217}
    218218
    219 void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
    220 {
    221     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
    222     RegisterSet usedRegisters = this->usedRegisters();
    223     if (spillMode == DontSpill) {
    224         // We've already flushed registers to the stack, we don't need to spill these.
    225         usedRegisters.set(baseGPR, false);
    226         usedRegisters.set(valueGPR, false);
    227     }
    228 
    229     JITPutByIdGenerator gen(
    230         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, JSValueRegs(baseGPR),
    231         JSValueRegs(valueGPR), scratchGPR, m_jit.ecmaModeFor(codeOrigin), putKind);
    232 
    233     gen.generateFastPath(m_jit);
    234    
    235     JITCompiler::JumpList slowCases;
    236     if (slowPathTarget.isSet())
    237         slowCases.append(slowPathTarget);
    238     slowCases.append(gen.slowPathJump());
    239    
    240     auto slowPath = slowPathCall(
    241         slowCases, this, gen.slowPathFunction(), PutPropertyPtrTag, NoResult, gen.stubInfo(), valueGPR, baseGPR,
    242         identifierUID(identifierNumber));
    243 
    244     m_jit.addPutById(gen, slowPath.get());
    245     addSlowPathGenerator(WTFMove(slowPath));
    246 }
    247 
    248219void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand)
    249220{
     
    358329}
    359330
    360 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
    361 {
    362     BasicBlock* taken = branchNode->branchData()->taken.block;
    363     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
    364 
    365     JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
    366 
    367     // The branch instruction will branch to the taken block.
    368     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
    369     if (taken == nextBlock()) {
    370         cond = JITCompiler::invert(cond);
    371         callResultCondition = JITCompiler::Zero;
    372         BasicBlock* tmp = taken;
    373         taken = notTaken;
    374         notTaken = tmp;
    375     }
    376 
    377     JSValueOperand arg1(this, node->child1());
    378     JSValueOperand arg2(this, node->child2());
    379     GPRReg arg1GPR = arg1.gpr();
    380     GPRReg arg2GPR = arg2.gpr();
    381    
    382     JITCompiler::JumpList slowPath;
    383    
    384     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
    385         GPRFlushedCallResult result(this);
    386         GPRReg resultGPR = result.gpr();
    387    
    388         arg1.use();
    389         arg2.use();
    390    
    391         flushRegisters();
    392         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
    393         m_jit.exceptionCheck();
    394 
    395         branchTest32(callResultCondition, resultGPR, taken);
    396     } else {
    397         GPRTemporary result(this, Reuse, arg2);
    398         GPRReg resultGPR = result.gpr();
    399    
    400         arg1.use();
    401         arg2.use();
    402    
    403         if (!isKnownInteger(node->child1().node()))
    404             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
    405         if (!isKnownInteger(node->child2().node()))
    406             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
    407    
    408         branch32(cond, arg1GPR, arg2GPR, taken);
    409    
    410         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
    411             jump(notTaken, ForceJump);
    412    
    413             slowPath.link(&m_jit);
    414    
    415             silentSpillAllRegisters(resultGPR);
    416             callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
    417             silentFillAllRegisters();
    418             m_jit.exceptionCheck();
    419        
    420             branchTest32(callResultCondition, resultGPR, taken);
    421         }
    422     }
    423 
    424     jump(notTaken);
    425 
    426     m_indexInBlock = m_block->size() - 1;
    427     m_currentNode = branchNode;
    428 }
    429 
    430 template<typename JumpType>
    431 class CompareAndBoxBooleanSlowPathGenerator
    432     : public CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg> {
    433 public:
    434     CompareAndBoxBooleanSlowPathGenerator(
    435         JumpType from, SpeculativeJIT* jit,
    436         S_JITOperation_EJJ function, GPRReg result, GPRReg arg1, GPRReg arg2)
    437         : CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg>(
    438             from, jit, function, NeedToSpill, ExceptionCheckRequirement::CheckNeeded, result)
    439         , m_arg1(arg1)
    440         , m_arg2(arg2)
    441     {
    442     }
    443    
    444 protected:
    445     void generateInternal(SpeculativeJIT* jit) override
    446     {
    447         this->setUp(jit);
    448         this->recordCall(jit->callOperation(this->m_function, this->m_result, m_arg1, m_arg2));
    449         jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result);
    450         jit->m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), this->m_result);
    451         this->tearDown(jit);
    452     }
    453    
    454 private:
    455     GPRReg m_arg1;
    456     GPRReg m_arg2;
    457 };
    458 
    459 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
    460 {
    461     ASSERT(node->isBinaryUseKind(UntypedUse));
    462     JSValueOperand arg1(this, node->child1());
    463     JSValueOperand arg2(this, node->child2());
    464     GPRReg arg1GPR = arg1.gpr();
    465     GPRReg arg2GPR = arg2.gpr();
    466    
    467     JITCompiler::JumpList slowPath;
    468    
    469     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
    470         GPRFlushedCallResult result(this);
    471         GPRReg resultGPR = result.gpr();
    472    
    473         arg1.use();
    474         arg2.use();
    475    
    476         flushRegisters();
    477         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
    478         m_jit.exceptionCheck();
    479        
    480         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
    481         jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
    482     } else {
    483         GPRTemporary result(this, Reuse, arg2);
    484         GPRReg resultGPR = result.gpr();
    485 
    486         arg1.use();
    487         arg2.use();
    488    
    489         if (!isKnownInteger(node->child1().node()))
    490             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
    491         if (!isKnownInteger(node->child2().node()))
    492             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
    493    
    494         m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
    495         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
    496        
    497         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
    498             addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>>(
    499                 slowPath, this, helperFunction, resultGPR, arg1GPR, arg2GPR));
    500         }
    501 
    502         jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
    503     }
    504 }
    505 
    506331void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert)
    507332{
     
    576401    JSValueOperand arg1(this, node->child1());
    577402    JSValueOperand arg2(this, node->child2());
    578     GPRReg arg1GPR = arg1.gpr();
    579     GPRReg arg2GPR = arg2.gpr();
     403    JSValueRegs arg1Regs = arg1.jsValueRegs();
     404    JSValueRegs arg2Regs = arg2.jsValueRegs();
    580405   
    581406    GPRTemporary result(this);
     
    589414        // cell, then they must be strictly equal.
    590415        // FIXME: this should flush registers instead of silent spill/fill.
    591         JITCompiler::Jump notEqualCase = m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR);
    592        
    593         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
     416        JITCompiler::Jump notEqualCase = m_jit.branch64(JITCompiler::NotEqual, arg1Regs.gpr(), arg2Regs.gpr());
     417       
     418        m_jit.move(JITCompiler::TrustedImm64(!invert), resultGPR);
    594419       
    595420        JITCompiler::Jump done = m_jit.jump();
     
    598423       
    599424        silentSpillAllRegisters(resultGPR);
    600         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
     425        callOperation(operationCompareStrictEqCell, resultGPR, arg1Regs, arg2Regs);
    601426        silentFillAllRegisters();
    602427        m_jit.exceptionCheck();
    603428       
    604         m_jit.and64(JITCompiler::TrustedImm32(1), resultGPR);
    605         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
    606        
    607429        done.link(&m_jit);
    608     } else {
    609         m_jit.or64(arg1GPR, arg2GPR, resultGPR);
    610        
    611         JITCompiler::JumpList slowPathCases;
    612        
    613         JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
    614        
    615         JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
    616         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister));
    617         leftOK.link(&m_jit);
    618         JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
    619         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister));
    620         rightOK.link(&m_jit);
    621        
    622         m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
    623         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
    624        
    625         JITCompiler::Jump done = m_jit.jump();
    626        
    627         twoCellsCase.link(&m_jit);
    628         slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR));
    629        
    630         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
    631        
    632         addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<MacroAssembler::JumpList>>(
    633                     slowPathCases, this, operationCompareStrictEq, resultGPR, arg1GPR,
    634                     arg2GPR));
    635        
    636         done.link(&m_jit);
    637     }
    638    
    639     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
    640 }
    641 
    642 void SpeculativeJIT::compileMiscStrictEq(Node* node)
    643 {
    644     JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
    645     JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
    646     GPRTemporary result(this);
    647    
    648     if (node->child1().useKind() == MiscUse)
    649         speculateMisc(node->child1(), op1.jsValueRegs());
    650     if (node->child2().useKind() == MiscUse)
    651         speculateMisc(node->child2(), op2.jsValueRegs());
    652    
    653     m_jit.compare64(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr());
    654     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
    655     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
     430        unblessedBooleanResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly);
     431        return;
     432    }
     433
     434    m_jit.or64(arg1Regs.gpr(), arg2Regs.gpr(), resultGPR);
     435
     436    JITCompiler::JumpList slowPathCases;
     437
     438    JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
     439
     440    JITCompiler::Jump leftOK = m_jit.branchIfInt32(arg1Regs);
     441    slowPathCases.append(m_jit.branchIfNumber(arg1Regs, InvalidGPRReg));
     442    leftOK.link(&m_jit);
     443    JITCompiler::Jump rightOK = m_jit.branchIfInt32(arg2Regs);
     444    slowPathCases.append(m_jit.branchIfNumber(arg2Regs, InvalidGPRReg));
     445    rightOK.link(&m_jit);
     446
     447    m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1Regs.gpr(), arg2Regs.gpr(), resultGPR);
     448
     449    JITCompiler::Jump done = m_jit.jump();
     450
     451    twoCellsCase.link(&m_jit);
     452    slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1Regs.gpr(), arg2Regs.gpr()));
     453
     454    m_jit.move(JITCompiler::TrustedImm64(!invert), resultGPR);
     455
     456    addSlowPathGenerator(std::make_unique<CompareSlowPathGenerator<MacroAssembler::JumpList>>(
     457        slowPathCases, this, operationCompareStrictEq, resultGPR, arg1Regs, arg2Regs));
     458
     459    done.link(&m_jit);
     460
     461    unblessedBooleanResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly);
    656462}
    657463
     
    37973603
    37983604    case CheckNotEmpty: {
    3799         JSValueOperand operand(this, node->child1());
    3800         GPRReg gpr = operand.gpr();
    3801         speculationCheck(TDZFailure, JSValueSource(), nullptr, m_jit.branchTest64(JITCompiler::Zero, gpr));
    3802         noResult(node);
     3605        compileCheckNotEmpty(node);
    38033606        break;
    38043607    }
     
    39223725
    39233726    case PutByIdFlush: {
    3924         SpeculateCellOperand base(this, node->child1());
    3925         JSValueOperand value(this, node->child2());
    3926         GPRTemporary scratch(this);
    3927 
    3928         GPRReg baseGPR = base.gpr();
    3929         GPRReg valueGPR = value.gpr();
    3930         GPRReg scratchGPR = scratch.gpr();
    3931         flushRegisters();
    3932 
    3933         cachedPutById(node->origin.semantic, baseGPR, valueGPR, scratchGPR, node->identifierNumber(), NotDirect, MacroAssembler::Jump(), DontSpill);
    3934 
    3935         noResult(node);
     3727        compilePutByIdFlush(node);
    39363728        break;
    39373729    }
    39383730       
    39393731    case PutById: {
    3940         SpeculateCellOperand base(this, node->child1());
    3941         JSValueOperand value(this, node->child2());
    3942         GPRTemporary scratch(this);
    3943        
    3944         GPRReg baseGPR = base.gpr();
    3945         GPRReg valueGPR = value.gpr();
    3946         GPRReg scratchGPR = scratch.gpr();
    3947        
    3948         cachedPutById(node->origin.semantic, baseGPR, valueGPR, scratchGPR, node->identifierNumber(), NotDirect);
    3949 
    3950         noResult(node);
     3732        compilePutById(node);
    39513733        break;
    39523734    }
     
    39763758
    39773759    case PutByIdDirect: {
    3978         SpeculateCellOperand base(this, node->child1());
    3979         JSValueOperand value(this, node->child2());
    3980         GPRTemporary scratch(this);
    3981        
    3982         GPRReg baseGPR = base.gpr();
    3983         GPRReg valueGPR = value.gpr();
    3984         GPRReg scratchGPR = scratch.gpr();
    3985        
    3986         cachedPutById(node->origin.semantic, baseGPR, valueGPR, scratchGPR, node->identifierNumber(), Direct);
    3987 
    3988         noResult(node);
     3760        compilePutByIdDirect(node);
    39893761        break;
    39903762    }
     
    40643836
    40653837    case OverridesHasInstance: {
    4066 
    4067         Node* hasInstanceValueNode = node->child2().node();
    4068         JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value());
    4069 
    4070         MacroAssembler::Jump notDefault;
    4071         SpeculateCellOperand base(this, node->child1());
    4072         JSValueOperand hasInstanceValue(this, node->child2());
    4073         GPRTemporary result(this);
    4074 
    4075         GPRReg resultGPR = result.gpr();
    4076         GPRReg baseGPR = base.gpr();
    4077 
    4078         // It would be great if constant folding handled automatically the case where we knew the hasInstance function
    4079         // was a constant. Unfortunately, the folding rule for OverridesHasInstance is in the strength reduction phase
    4080         // since it relies on OSR information. https://bugs.webkit.org/show_bug.cgi?id=154832
    4081         if (!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode->asCell()) {
    4082             GPRReg hasInstanceValueGPR = hasInstanceValue.gpr();
    4083             notDefault = m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueGPR, TrustedImmPtr(node->cellOperand()));
    4084         }
    4085 
    4086         // Check that base 'ImplementsDefaultHasInstance'.
    4087         m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR);
    4088         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
    4089         MacroAssembler::Jump done = m_jit.jump();
    4090 
    4091         if (notDefault.isSet()) {
    4092             notDefault.link(&m_jit);
    4093             moveTrueTo(resultGPR);
    4094         }
    4095 
    4096         done.link(&m_jit);
    4097         jsValueResult(resultGPR, node, DataFormatJSBoolean);
     3838        compileOverridesHasInstance(node);
    40983839        break;
    40993840    }
     
    41093850    }
    41103851
    4111     case IsEmpty: {       
     3852    case IsEmpty: {
    41123853        JSValueOperand value(this, node->child1());
    41133854        GPRTemporary result(this, Reuse, value);
     
    45304271
    45314272    case IsObject: {
    4532         JSValueOperand value(this, node->child1());
    4533         GPRTemporary result(this, Reuse, value);
    4534 
    4535         JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(value.jsValueRegs());
    4536 
    4537         m_jit.compare8(JITCompiler::AboveOrEqual,
    4538             JITCompiler::Address(value.gpr(), JSCell::typeInfoTypeOffset()),
    4539             TrustedImm32(ObjectType),
    4540             result.gpr());
    4541         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
    4542         JITCompiler::Jump done = m_jit.jump();
    4543 
    4544         isNotCell.link(&m_jit);
    4545         m_jit.move(TrustedImm32(ValueFalse), result.gpr());
    4546 
    4547         done.link(&m_jit);
    4548         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
     4273        compileIsObject(node);
    45494274        break;
    45504275    }
     
    45994324
    46004325    case LoadVarargs: {
    4601         LoadVarargsData* data = node->loadVarargsData();
    4602        
    4603         GPRReg argumentsGPR;
    4604         {
    4605             JSValueOperand arguments(this, node->child1());
    4606             argumentsGPR = arguments.gpr();
    4607             flushRegisters();
    4608         }
    4609        
    4610         callOperation(operationSizeOfVarargs, GPRInfo::returnValueGPR, argumentsGPR, data->offset);
    4611         m_jit.exceptionCheck();
    4612        
    4613         lock(GPRInfo::returnValueGPR);
    4614         {
    4615             JSValueOperand arguments(this, node->child1());
    4616             argumentsGPR = arguments.gpr();
    4617             flushRegisters();
    4618         }
    4619         unlock(GPRInfo::returnValueGPR);
    4620        
    4621         // FIXME: There is a chance that we will call an effectful length property twice. This is safe
    4622         // from the standpoint of the VM's integrity, but it's subtly wrong from a spec compliance
    4623         // standpoint. The best solution would be one where we can exit *into* the op_call_varargs right
    4624         // past the sizing.
    4625         // https://bugs.webkit.org/show_bug.cgi?id=141448
    4626 
    4627         GPRReg argCountIncludingThisGPR =
    4628             JITCompiler::selectScratchGPR(GPRInfo::returnValueGPR, argumentsGPR);
    4629        
    4630         m_jit.add32(TrustedImm32(1), GPRInfo::returnValueGPR, argCountIncludingThisGPR);
    4631 
    4632         speculationCheck(
    4633             VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32(
    4634                 MacroAssembler::Above,
    4635                 GPRInfo::returnValueGPR,
    4636                 argCountIncludingThisGPR));
    4637 
    4638         speculationCheck(
    4639             VarargsOverflow, JSValueSource(), Edge(), m_jit.branch32(
    4640                 MacroAssembler::Above,
    4641                 argCountIncludingThisGPR,
    4642                 TrustedImm32(data->limit)));
    4643        
    4644         m_jit.store32(argCountIncludingThisGPR, JITCompiler::payloadFor(data->machineCount));
    4645        
    4646         callOperation(operationLoadVarargs, data->machineStart.offset(), argumentsGPR, data->offset, GPRInfo::returnValueGPR, data->mandatoryMinimum);
    4647         m_jit.exceptionCheck();
    4648        
    4649         noResult(node);
     4326        compileLoadVarargs(node);
    46504327        break;
    46514328    }
     
    48794556    }
    48804557    case HasIndexedProperty: {
    4881         SpeculateCellOperand base(this, node->child1());
    4882         SpeculateStrictInt32Operand index(this, node->child2());
    4883         GPRTemporary result(this);
    4884 
    4885         GPRReg baseGPR = base.gpr();
    4886         GPRReg indexGPR = index.gpr();
    4887         GPRReg resultGPR = result.gpr();
    4888 
    4889         MacroAssembler::JumpList slowCases;
    4890         ArrayMode mode = node->arrayMode();
    4891         switch (mode.type()) {
    4892         case Array::Int32:
    4893         case Array::Contiguous: {
    4894             ASSERT(!!node->child3());
    4895             StorageOperand storage(this, node->child3());
    4896             GPRTemporary scratch(this);
    4897            
    4898             GPRReg storageGPR = storage.gpr();
    4899             GPRReg scratchGPR = scratch.gpr();
    4900 
    4901             MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
    4902             if (mode.isInBounds())
    4903                 speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
    4904             else
    4905                 slowCases.append(outOfBounds);
    4906 
    4907             m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchGPR);
    4908             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR));
    4909             moveTrueTo(resultGPR);
    4910             break;
    4911         }
    4912         case Array::Double: {
    4913             ASSERT(!!node->child3());
    4914             StorageOperand storage(this, node->child3());
    4915             FPRTemporary scratch(this);
    4916             FPRReg scratchFPR = scratch.fpr();
    4917             GPRReg storageGPR = storage.gpr();
    4918 
    4919             MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
    4920             if (mode.isInBounds())
    4921                 speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
    4922             else
    4923                 slowCases.append(outOfBounds);
    4924 
    4925             m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR);
    4926             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR));
    4927             moveTrueTo(resultGPR);
    4928             break;
    4929         }
    4930         case Array::ArrayStorage: {
    4931             ASSERT(!!node->child3());
    4932             StorageOperand storage(this, node->child3());
    4933             GPRTemporary scratch(this);
    4934 
    4935             GPRReg storageGPR = storage.gpr();
    4936             GPRReg scratchGPR = scratch.gpr();
    4937 
    4938             MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
    4939             if (mode.isInBounds())
    4940                 speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
    4941             else   
    4942                 slowCases.append(outOfBounds);
    4943 
    4944             m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), scratchGPR);
    4945             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR));
    4946             moveTrueTo(resultGPR);
    4947             break;
    4948         }
    4949         default: {
    4950             slowCases.append(m_jit.jump());
    4951             break;
    4952         }
    4953         }
    4954 
    4955         addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedPropertyByInt, HasPropertyPtrTag, resultGPR, baseGPR, indexGPR, static_cast<int32_t>(node->internalMethodType())));
    4956        
    4957         jsValueResult(resultGPR, node, DataFormatJSBoolean);
     4558        compileHasIndexedProperty(node);
    49584559        break;
    49594560    }
    49604561    case GetDirectPname: {
    4961         Edge& baseEdge = m_jit.graph().varArgChild(node, 0);
    4962         Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
    4963         Edge& indexEdge = m_jit.graph().varArgChild(node, 2);
    4964         Edge& enumeratorEdge = m_jit.graph().varArgChild(node, 3);
    4965 
    4966         SpeculateCellOperand base(this, baseEdge);
    4967         SpeculateCellOperand property(this, propertyEdge);
    4968         SpeculateStrictInt32Operand index(this, indexEdge);
    4969         SpeculateCellOperand enumerator(this, enumeratorEdge);
    4970         GPRTemporary result(this);
    4971         GPRTemporary scratch1(this);
    4972         GPRTemporary scratch2(this);
    4973 
    4974         GPRReg baseGPR = base.gpr();
    4975         GPRReg propertyGPR = property.gpr();
    4976         GPRReg indexGPR = index.gpr();
    4977         GPRReg enumeratorGPR = enumerator.gpr();
    4978         GPRReg resultGPR = result.gpr();
    4979         GPRReg scratch1GPR = scratch1.gpr();
    4980         GPRReg scratch2GPR = scratch2.gpr();
    4981 
    4982         MacroAssembler::JumpList slowPath;
    4983 
    4984         // Check the structure
    4985         m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratch1GPR);
    4986         slowPath.append(
    4987             m_jit.branch32(
    4988                 MacroAssembler::NotEqual,
    4989                 scratch1GPR,
    4990                 MacroAssembler::Address(
    4991                     enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset())));
    4992        
    4993         // Compute the offset
    4994         // If index is less than the enumerator's cached inline storage, then it's an inline access
    4995         MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
    4996             indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
    4997 
    4998         m_jit.load64(MacroAssembler::BaseIndex(baseGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultGPR);
    4999 
    5000         MacroAssembler::Jump done = m_jit.jump();
    5001        
    5002         // Otherwise it's out of line
    5003         outOfLineAccess.link(&m_jit);
    5004         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratch2GPR);
    5005         m_jit.move(indexGPR, scratch1GPR);
    5006         m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratch1GPR);
    5007         m_jit.neg32(scratch1GPR);
    5008         m_jit.signExtend32ToPtr(scratch1GPR, scratch1GPR);
    5009         int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
    5010         m_jit.load64(MacroAssembler::BaseIndex(scratch2GPR, scratch1GPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultGPR);
    5011 
    5012         done.link(&m_jit);
    5013 
    5014         addSlowPathGenerator(slowPathCall(slowPath, this, operationGetByVal, GetPropertyPtrTag, resultGPR, baseGPR, propertyGPR));
    5015 
    5016         jsValueResult(resultGPR, node);
     4562        compileGetDirectPname(node);
    50174563        break;
    50184564    }
     
    51354681
    51364682    case ExtractCatchLocal: {
    5137         JSValue* ptr = &reinterpret_cast<JSValue*>(m_jit.jitCode()->common.catchOSREntryBuffer->dataBuffer())[node->catchOSREntryIndex()];
    5138         GPRTemporary temp(this);
    5139         GPRReg tempGPR = temp.gpr();
    5140         m_jit.move(CCallHelpers::TrustedImmPtr(ptr), tempGPR);
    5141         m_jit.load64(CCallHelpers::Address(tempGPR), tempGPR);
    5142         jsValueResult(tempGPR, node);
     4683        compileExtractCatchLocal(node);
    51434684        break;
    51444685    }
     
    53684909}
    53694910
    5370 void SpeculativeJIT::emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR)
    5371 {
    5372     m_jit.zeroExtend32ToPtr(sizeGPR, scratchGPR);
    5373     MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
    5374     MacroAssembler::Label loop = m_jit.label();
    5375     m_jit.sub32(TrustedImm32(1), scratchGPR);
    5376     m_jit.store64(emptyValueRegs.gpr(), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight));
    5377     m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
    5378     done.link(&m_jit);
    5379 }
    5380 
    53814911void SpeculativeJIT::compileBigIntEquality(Node* node)
    53824912{
     
    54164946}
    54174947
    5418 void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)
    5419 {
    5420     GPRTemporary storage(this);
    5421     GPRTemporary scratch(this);
    5422     GPRTemporary scratch2(this);
    5423    
    5424     GPRReg storageGPR = storage.gpr();
    5425     GPRReg scratchGPR = scratch.gpr();
    5426     GPRReg scratch2GPR = scratch2.gpr();
    5427    
    5428     m_jit.move(TrustedImmPtr(nullptr), storageGPR);
    5429    
    5430     MacroAssembler::JumpList slowCases;
    5431     if (shouldConvertLargeSizeToArrayStorage)
    5432         slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
    5433            
    5434     // We can use resultGPR as a scratch right now.
    5435     emitAllocateButterfly(storageGPR, sizeGPR, resultGPR, scratchGPR, scratch2GPR, slowCases);
    5436 
    5437     if (hasDouble(indexingType))
    5438         m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), scratchGPR);
    5439     else
    5440         m_jit.move(TrustedImm64(JSValue::encode(JSValue())), scratchGPR);
    5441     emitInitializeButterfly(storageGPR, sizeGPR, JSValueRegs(scratchGPR), scratch2GPR);
    5442 
    5443     RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType));
    5444 
    5445     emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
    5446    
    5447     m_jit.mutatorFence(*m_jit.vm());
    5448    
    5449     addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
    5450         slowCases, this, operationNewArrayWithSize, resultGPR,
    5451         structure,
    5452         shouldConvertLargeSizeToArrayStorage ? m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)) : structure,
    5453         sizeGPR, storageGPR));
    5454 }
    5455 
    54564948#endif
    54574949
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r230516 r230517  
    1002410024
    1002510025            m_out.appendTo(slowCase, continuation);
    10026             ValueFromBlock slowResult = m_out.anchor(m_out.equal(
    10027                 m_out.constInt64(JSValue::encode(jsBoolean(true))),
    10028                 vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType)));
     10026            ValueFromBlock slowResult = m_out.anchor(
     10027                m_out.notZero64(vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType)));
    1002910028            m_out.jump(continuation);
    1003010029
     
    1006110060           
    1006210061            m_out.appendTo(slowCase, continuation);
    10063             ValueFromBlock slowResult = m_out.anchor(m_out.equal(
    10064                 m_out.constInt64(JSValue::encode(jsBoolean(true))),
    10065                 vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType)));
     10062            ValueFromBlock slowResult = m_out.anchor(
     10063                m_out.notZero64(vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType)));
    1006610064            m_out.jump(continuation);
    1006710065           
     
    1009710095
    1009810096            m_out.appendTo(slowCase, continuation);
    10099             ValueFromBlock slowResult = m_out.anchor(m_out.equal(
    10100                 m_out.constInt64(JSValue::encode(jsBoolean(true))),
    10101                 vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType)));
     10097            ValueFromBlock slowResult = m_out.anchor(
     10098                m_out.notZero64(vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType)));
    1010210099            m_out.jump(continuation);
    1010310100
     
    1011110108            LValue index = lowInt32(m_node->child2());
    1011210109            LValue internalMethodType = m_out.constInt32(static_cast<int32_t>(m_node->internalMethodType()));
    10113             setBoolean(m_out.equal(
    10114                 m_out.constInt64(JSValue::encode(jsBoolean(true))),
    10115                 vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType)));
     10110            setBoolean(m_out.notZero64(vmCall(Int64, m_out.operation(operationHasIndexedPropertyByInt), m_callFrame, base, index, internalMethodType)));
    1011610111            break;
    1011710112        }
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r230516 r230517  
    165165        load64(address, regs.gpr());
    166166#else
    167         load32(bitwise_cast<void*>(bitwise_cast<uintptr_t>(address) + PayloadOffset), regs.payloadGPR());
    168         load32(bitwise_cast<void*>(bitwise_cast<uintptr_t>(address) + TagOffset), regs.tagGPR());
     167        move(TrustedImmPtr(address), regs.payloadGPR());
     168        loadValue(Address(regs.payloadGPR()), regs);
    169169#endif
    170170    }
     
    10121012    }
    10131013
    1014     static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg, GPRReg preserve5 = InvalidGPRReg)
    1015     {
    1016         if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0 && preserve5 != GPRInfo::regT0)
    1017             return GPRInfo::regT0;
    1018 
    1019         if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1 && preserve5 != GPRInfo::regT1)
    1020             return GPRInfo::regT1;
    1021 
    1022         if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2 && preserve5 != GPRInfo::regT2)
    1023             return GPRInfo::regT2;
    1024 
    1025         if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3 && preserve5 != GPRInfo::regT3)
    1026             return GPRInfo::regT3;
    1027 
    1028         if (preserve1 != GPRInfo::regT4 && preserve2 != GPRInfo::regT4 && preserve3 != GPRInfo::regT4 && preserve4 != GPRInfo::regT4 && preserve5 != GPRInfo::regT4)
    1029             return GPRInfo::regT4;
    1030 
    1031         return GPRInfo::regT5;
     1014    static GPRReg selectScratchGPR(RegisterSet preserved)
     1015    {
     1016        GPRReg registers[] = {
     1017            GPRInfo::regT0,
     1018            GPRInfo::regT1,
     1019            GPRInfo::regT2,
     1020            GPRInfo::regT3,
     1021            GPRInfo::regT4,
     1022            GPRInfo::regT5,
     1023        };
     1024
     1025        for (GPRReg reg : registers) {
     1026            if (!preserved.contains(reg))
     1027                return reg;
     1028        }
     1029        RELEASE_ASSERT_NOT_REACHED();
     1030        return InvalidGPRReg;
     1031    }
     1032
     1033    template<typename... Regs>
     1034    static GPRReg selectScratchGPR(Regs... args)
     1035    {
     1036        RegisterSet set;
     1037        constructRegisterSet(set, args...);
     1038        return selectScratchGPR(set);
     1039    }
     1040
     1041    static void constructRegisterSet(RegisterSet&)
     1042    {
     1043    }
     1044
     1045    template<typename... Regs>
     1046    static void constructRegisterSet(RegisterSet& set, JSValueRegs regs, Regs... args)
     1047    {
     1048        if (regs.tagGPR() != InvalidGPRReg)
     1049            set.set(regs.tagGPR());
     1050        if (regs.payloadGPR() != InvalidGPRReg)
     1051            set.set(regs.payloadGPR());
     1052        constructRegisterSet(set, args...);
     1053    }
     1054
     1055    template<typename... Regs>
     1056    static void constructRegisterSet(RegisterSet& set, GPRReg reg, Regs... args)
     1057    {
     1058        if (reg != InvalidGPRReg)
     1059            set.set(reg);
     1060        constructRegisterSet(set, args...);
    10321061    }
    10331062
  • trunk/Source/JavaScriptCore/jit/RegisterSet.h

    r229391 r230517  
    208208private:
    209209    void setAny(Reg reg) { set(reg); }
     210    void setAny(JSValueRegs regs) { set(regs); }
    210211    void setAny(const RegisterSet& set) { merge(set); }
    211212    void setMany() { }
Note: See TracChangeset for help on using the changeset viewer.