⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 284700 in webkit


Ignore:
Timestamp:
Oct 22, 2021, 11:31:50 AM (5 years ago)
Author:
commit-queue@webkit.org
Message:

[JSC][32bit] Re-enable compileEnumeratorGetByVal fast path
https://bugs.webkit.org/show_bug.cgi?id=232052

Patch by Mikhail R. Gadelha <Mikhail R. Gadelha> on 2021-10-22
Reviewed by Yusuke Suzuki.

In https://bugs.webkit.org/show_bug.cgi?id=229543, the compileEnumeratorGetByVal
fast path had to be disabled in 32 bits due to not having enough registers.
There are enough registers available now, so we can re-enable the fast path and
removed the speculation that the baseEdge of both enumeratorGetByVal and
getByVal is a Cell in 32 bits.

I've also updated the 32 bits version of compileGetByVal to be closer to the 64
bits version: using DFG_CRASH instead of RELEASE_ASSERT_NOT_REACHED, using nullptr
instead of 0, and removed some whitespaces.

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGOperations.cpp:

(JSC::DFG::JSC_DEFINE_JIT_OPERATION):

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

(JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compileGetByVal):
(JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): Deleted.

  • dfg/DFGSpeculativeJIT64.cpp:

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

Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r284699 r284700  
     12021-10-22  Mikhail R. Gadelha  <mikhail@igalia.com>
     2
     3        [JSC][32bit] Re-enable compileEnumeratorGetByVal fast path
     4        https://bugs.webkit.org/show_bug.cgi?id=232052
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        In https://bugs.webkit.org/show_bug.cgi?id=229543, the compileEnumeratorGetByVal
     9        fast path had to be disabled in 32 bits due to not having enough registers.
     10        There are enough registers available now, so we can re-enable the fast path and
     11        removed the speculation that the baseEdge of both enumeratorGetByVal and
     12        getByVal is a Cell in 32 bits.
     13
     14        I've also updated the 32 bits version of compileGetByVal to be closer to the 64
     15        bits version: using DFG_CRASH instead of RELEASE_ASSERT_NOT_REACHED, using nullptr
     16        instead of 0, and removed some whitespaces.
     17
     18        * dfg/DFGFixupPhase.cpp:
     19        (JSC::DFG::FixupPhase::fixupNode):
     20        * dfg/DFGOperations.cpp:
     21        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
     22        * dfg/DFGOperations.h:
     23        * dfg/DFGSpeculativeJIT.cpp:
     24        (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal):
     25        * dfg/DFGSpeculativeJIT32_64.cpp:
     26        (JSC::DFG::SpeculativeJIT::compileGetByVal):
     27        (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): Deleted.
     28        * dfg/DFGSpeculativeJIT64.cpp:
     29        (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): Deleted.
     30
    1312021-10-22  Saam Barati  <sbarati@apple.com>
    232
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r284646 r284700  
    11251125                    }
    11261126                }
    1127 #if USE(JSVALUE32_64)
    1128                 fixEdge<CellUse>(m_graph.varArgChild(node, 0)); // Speculating cell due to register pressure on 32-bit.
    1129 #endif
    11301127                break;
    11311128            case Array::ForceExit:
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r284330 r284700  
    750750}
    751751
    752 JSC_DEFINE_JIT_OPERATION(operationGetByValCell, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, EncodedJSValue encodedProperty))
    753 {
    754     VM& vm = globalObject->vm();
    755     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
    756     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    757     auto scope = DECLARE_THROW_SCOPE(vm);
    758 
    759     JSValue property = JSValue::decode(encodedProperty);
    760 
    761     if (std::optional<uint32_t> index = property.tryGetAsUint32Index())
    762         RELEASE_AND_RETURN(scope, getByValWithIndex(globalObject, base, *index));
    763 
    764     if (property.isString()) {
    765         Structure& structure = *base->structure(vm);
    766         if (JSCell::canUseFastGetOwnProperty(structure)) {
    767             RefPtr<AtomStringImpl> existingAtomString = asString(property)->toExistingAtomString(globalObject);
    768             RETURN_IF_EXCEPTION(scope, encodedJSValue());
    769             if (existingAtomString) {
    770                 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomString.get()))
    771                     return JSValue::encode(result);
    772             }
    773         }
    774     }
    775 
    776     auto propertyName = property.toPropertyKey(globalObject);
    777     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    778     RELEASE_AND_RETURN(scope, JSValue::encode(JSValue(base).get(globalObject, propertyName)));
    779 }
    780 
    781752ALWAYS_INLINE EncodedJSValue getByValCellInt(JSGlobalObject* globalObject, VM& vm, JSCell* base, int32_t index)
    782753{
     
    25082479}
    25092480
    2510 JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, uint32_t index, JSPropertyNameEnumerator* enumerator))
     2481JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, uint32_t index, JSPropertyNameEnumerator* enumerator))
    25112482{
    25122483    VM& vm = globalObject->vm();
     
    25192490    // This should only really return for TerminationException since we know string is backed by a UUID.
    25202491    RETURN_IF_EXCEPTION(scope, { });
    2521     JSObject* object = base->toObject(globalObject);
     2492    JSValue base = JSValue::decode(baseValue);
     2493    JSObject* object = base.toObject(globalObject);
    25222494    RETURN_IF_EXCEPTION(scope, { });
    25232495
     
    25382510    JSString* propertyName = jsSecureCast<JSString*>(vm, JSValue::decode(propertyNameValue));
    25392511    RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, base, propertyName))));
    2540 }
    2541 
    2542 JSC_DEFINE_JIT_OPERATION(operationEnumeratorGetByValGeneric, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
    2543 {
    2544     VM& vm = globalObject->vm();
    2545     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
    2546     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    2547     auto scope = DECLARE_THROW_SCOPE(vm);
    2548 
    2549     JSValue property = JSValue::decode(propertyNameValue);
    2550     JSPropertyNameEnumerator::Flag mode = static_cast<JSPropertyNameEnumerator::Flag>(modeNumber);
    2551     JSValue base = JSValue::decode(baseValue);
    2552     RELEASE_AND_RETURN(scope, JSValue::encode(CommonSlowPaths::opEnumeratorGetByVal(globalObject, base, property, index, mode, enumerator)));
    25532512}
    25542513
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r284330 r284700  
    9191JSC_DECLARE_JIT_OPERATION(operationArithCeil, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
    9292JSC_DECLARE_JIT_OPERATION(operationArithTrunc, EncodedJSValue, (JSGlobalObject*, EncodedJSValue));
    93 JSC_DECLARE_JIT_OPERATION(operationGetByValCell, EncodedJSValue, (JSGlobalObject*, JSCell*, EncodedJSValue encodedProperty));
    9493JSC_DECLARE_JIT_OPERATION(operationGetByValObjectInt, EncodedJSValue, (JSGlobalObject*, JSObject*, int32_t));
    9594JSC_DECLARE_JIT_OPERATION(operationGetByValStringInt, EncodedJSValue, (JSGlobalObject*, JSString*, int32_t));
     
    112111JSC_DECLARE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
    113112JSC_DECLARE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
    114 JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, JSCell*, uint32_t, JSPropertyNameEnumerator*));
    115 JSC_DECLARE_JIT_OPERATION(operationEnumeratorGetByValGeneric, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t, JSPropertyNameEnumerator*));
     113JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uint32_t, JSPropertyNameEnumerator*));
    116114
    117115JSC_DECLARE_JIT_OPERATION(operationNewRegexpWithLastIndex, JSCell*, (JSGlobalObject*, JSCell*, EncodedJSValue));
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r284590 r284700  
    1585515855}
    1585615856
     15857void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
     15858{
     15859    Edge baseEdge = m_graph.varArgChild(node, 0);
     15860    auto generate = [&] (JSValueRegs baseRegs) {
     15861        MacroAssembler::JumpList doneCases;
     15862        JSValueRegsTemporary result;
     15863        JSValueRegs resultRegs;
     15864        GPRReg indexGPR;
     15865        GPRReg enumeratorGPR;
     15866        MacroAssembler::Jump badStructureSlowPath;
     15867
     15868        compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) {
     15869            Edge storageEdge = m_graph.varArgChild(node, 2);
     15870            StorageOperand storage;
     15871            if (storageEdge)
     15872                storage.emplace(this, storageEdge);
     15873            SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
     15874            SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
     15875            SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
     15876
     15877            GPRReg modeGPR = mode.gpr();
     15878            indexGPR = index.gpr();
     15879            enumeratorGPR = enumerator.gpr();
     15880
     15881            bool haveStorage = !!storageEdge;
     15882            GPRTemporary storageTemporary;
     15883            GPRReg storageGPR;
     15884            if (!haveStorage) {
     15885                storageTemporary = GPRTemporary(this, Reuse, enumerator);
     15886                storageGPR = storageTemporary.gpr();
     15887            } else
     15888                storageGPR = storage.gpr();
     15889
     15890            result = JSValueRegsTemporary(this);
     15891            resultRegs = result.regs();
     15892            GPRReg scratchGPR = resultRegs.payloadGPR();
     15893
     15894            MacroAssembler::JumpList notFastNamedCases;
     15895
     15896            // FIXME: We shouldn't generate this code if we know base is not an object.
     15897            notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)));
     15898            {
     15899                if (!m_state.forNode(baseEdge).isType(SpecCell))
     15900                    notFastNamedCases.append(m_jit.branchIfNotCell(baseRegs));
     15901
     15902                // Check the structure
     15903                // FIXME: If we know there's only one structure for base we can just embed it here.
     15904                m_jit.load32(MacroAssembler::Address(baseRegs.payloadGPR(), JSCell::structureIDOffset()), scratchGPR);
     15905
     15906                auto badStructure = m_jit.branch32(
     15907                    MacroAssembler::NotEqual,
     15908                    scratchGPR,
     15909                    MacroAssembler::Address(
     15910                        enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
     15911
     15912                // FIXME: Maybe we should have a better way to represent Indexed+Named?
     15913                if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node())
     15914                    badStructureSlowPath = badStructure;
     15915                else
     15916                    notFastNamedCases.append(badStructure);
     15917
     15918                // Compute the offset
     15919                // If index is less than the enumerator's cached inline storage, then it's an inline access
     15920                MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
     15921                    indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
     15922
     15923                m_jit.loadValue(MacroAssembler::BaseIndex(baseRegs.payloadGPR(), indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
     15924
     15925                doneCases.append(m_jit.jump());
     15926
     15927                // Otherwise it's out of line
     15928                outOfLineAccess.link(&m_jit);
     15929                m_jit.move(indexGPR, scratchGPR);
     15930                m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
     15931                m_jit.neg32(scratchGPR);
     15932                m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
     15933                if (!haveStorage)
     15934                    m_jit.loadPtr(MacroAssembler::Address(baseRegs.payloadGPR(), JSObject::butterflyOffset()), storageGPR);
     15935                constexpr intptr_t offsetOfFirstProperty = offsetInButterfly(firstOutOfLineOffset) * static_cast<intptr_t>(sizeof(EncodedJSValue));
     15936                m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
     15937                doneCases.append(m_jit.jump());
     15938            }
     15939
     15940            notFastNamedCases.link(&m_jit);
     15941            return std::make_pair(resultRegs, DataFormatJS);
     15942        }));
     15943
     15944        // We rely on compileGetByVal to call jsValueResult for us.
     15945        // FIXME: This is kinda hacky...
     15946        ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
     15947
     15948        if (badStructureSlowPath.isSet()) {
     15949            if (baseRegs.tagGPR() == InvalidGPRReg)
     15950                addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), CCallHelpers::CellValue(baseRegs.payloadGPR()), indexGPR, enumeratorGPR));
     15951            else
     15952                addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, indexGPR, enumeratorGPR));
     15953        }
     15954
     15955        doneCases.link(&m_jit);
     15956    };
     15957
     15958    if (isCell(baseEdge.useKind())) {
     15959        // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
     15960        SpeculateCellOperand base(this, baseEdge, ManualOperandSpeculation);
     15961        speculate(node, baseEdge);
     15962        generate(JSValueRegs::payloadOnly(base.gpr()));
     15963    } else {
     15964        JSValueOperand base(this, baseEdge);
     15965        generate(base.regs());
     15966    }
     15967}
     15968
    1585715969} } // namespace JSC::DFG
    1585815970
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r284330 r284700  
    18191819{
    18201820    switch (node->arrayMode().type()) {
     1821    case Array::AnyTypedArray:
     1822    case Array::ForceExit:
     1823    case Array::SelectUsingArguments:
    18211824    case Array::SelectUsingPredictions:
    1822     case Array::ForceExit:
    1823         RELEASE_ASSERT_NOT_REACHED();
    1824 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
    1825         terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
    1826 #endif
     1825    case Array::Unprofiled:
     1826    case Array::BigInt64Array:
     1827    case Array::BigUint64Array:
     1828        DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
    18271829        break;
    18281830    case Array::Undecided: {
     
    18471849                if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
    18481850                    compileGetByValForObjectWithString(node, prefix);
    1849                     break;
     1851                    return;
    18501852                }
    18511853
    18521854                if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
    18531855                    compileGetByValForObjectWithSymbol(node, prefix);
    1854                     break;
     1856                    return;
    18551857                }
    18561858            }
    18571859
    1858             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right.
     1860            JSValueOperand base(this, m_graph.varArgChild(node, 0));
    18591861            JSValueOperand property(this, m_graph.varArgChild(node, 1));
    1860             GPRReg baseGPR = base.gpr();
     1862            JSValueRegs baseGPR = base.jsValueRegs();
    18611863            JSValueRegs propertyRegs = property.jsValueRegs();
    18621864
     
    18651867
    18661868            flushRegisters();
    1867             callOperation(operationGetByValCell, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs);
     1869            callOperation(operationGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs);
    18681870            m_jit.exceptionCheck();
    18691871
    18701872            jsValueResult(resultRegs, node);
    1871             break;
    1872         }
    1873 
    1874         speculate(node, m_graph.varArgChild(node, 0));
     1873            return;
     1874        }
     1875
     1876        JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
     1877        JSValueRegs propertyRegs = property.jsValueRegs();
    18751878        speculate(node, m_graph.varArgChild(node, 1));
    18761879
    1877         JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
    1878         JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
    1879 
    1880         JSValueRegs baseRegs = base.jsValueRegs();
    1881         JSValueRegs propertyRegs = property.jsValueRegs();
    1882 
    1883         JSValueRegs resultRegs;
    1884         std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
    1885 
    1886         CodeOrigin codeOrigin = node->origin.semantic;
    1887         CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
    1888         RegisterSet usedRegisters = this->usedRegisters();
    1889 
    1890         JITCompiler::JumpList slowCases;
    1891         if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
    1892             slowCases.append(m_jit.branchIfNotCell(baseRegs.tagGPR()));
    1893 
    1894         JITGetByValGenerator gen(
    1895             m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
    1896             baseRegs, propertyRegs, resultRegs, InvalidGPRReg);
    1897 
    1898         if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString))
    1899             gen.stubInfo()->propertyIsString = true;
    1900         else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only))
    1901             gen.stubInfo()->propertyIsInt32 = true;
    1902         else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol))
    1903             gen.stubInfo()->propertyIsSymbol = true;
    1904 
    1905         gen.generateFastPath(m_jit);
    1906 
    1907         slowCases.append(gen.slowPathJump());
    1908 
    1909         std::unique_ptr<SlowPathGenerator> slowPath = slowPathCall(
    1910             slowCases, this, operationGetByValOptimize,
    1911             resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseRegs, propertyRegs);
    1912 
    1913         m_jit.addGetByVal(gen, slowPath.get());
    1914         addSlowPathGenerator(WTFMove(slowPath));
    1915 
    1916         jsValueResult(resultRegs, node);
     1880        auto generate = [&] (JSValueRegs baseRegs) {
     1881            JSValueRegs resultRegs;
     1882            std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
     1883
     1884            CodeOrigin codeOrigin = node->origin.semantic;
     1885            CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
     1886            RegisterSet usedRegisters = this->usedRegisters();
     1887
     1888            JITCompiler::JumpList slowCases;
     1889            if (!m_state.forNode(m_graph.varArgChild(node, 0)).isType(SpecCell))
     1890                slowCases.append(m_jit.branchIfNotCell(baseRegs));
     1891
     1892            JITGetByValGenerator gen(
     1893                m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::GetByVal, usedRegisters,
     1894                baseRegs, propertyRegs, resultRegs, InvalidGPRReg);
     1895
     1896            if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString))
     1897                gen.stubInfo()->propertyIsString = true;
     1898            else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only))
     1899                gen.stubInfo()->propertyIsInt32 = true;
     1900            else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol))
     1901                gen.stubInfo()->propertyIsSymbol = true;
     1902
     1903            gen.generateFastPath(m_jit);
     1904
     1905            slowCases.append(gen.slowPathJump());
     1906
     1907            std::unique_ptr<SlowPathGenerator> slowPath;
     1908            if (baseRegs.tagGPR() == InvalidGPRReg) {
     1909                slowPath = slowPathCall(
     1910                    slowCases, this, operationGetByValOptimize,
     1911                    resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, CCallHelpers::CellValue(baseRegs.payloadGPR()), propertyRegs);
     1912            } else {
     1913                slowPath = slowPathCall(
     1914                    slowCases, this, operationGetByValOptimize,
     1915                    resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), gen.stubInfo(), nullptr, baseRegs, propertyRegs);
     1916            }
     1917
     1918            m_jit.addGetByVal(gen, slowPath.get());
     1919            addSlowPathGenerator(WTFMove(slowPath));
     1920
     1921            jsValueResult(resultRegs, node);
     1922        };
     1923
     1924        if (isCell(m_graph.varArgChild(node, 0).useKind())) {
     1925            SpeculateCellOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
     1926            speculate(node, m_graph.varArgChild(node, 0));
     1927            generate(JSValueRegs::payloadOnly(base.gpr()));
     1928        } else {
     1929            JSValueOperand base(this, m_graph.varArgChild(node, 0), ManualOperandSpeculation);
     1930            speculate(node, m_graph.varArgChild(node, 0));
     1931            generate(base.jsValueRegs());
     1932        }
    19171933        break;
    19181934    }
     
    19331949            std::tie(resultRegs, format) = prefix(node->arrayMode().type() == Array::Int32 ? DataFormatInt32 : DataFormatJS);
    19341950
    1935             speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
     1951            speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
    19361952
    19371953            if (format == DataFormatInt32) {
     
    19952011
    19962012        m_jit.loadValue(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultRegs);
     2013
    19972014        slowCases.append(m_jit.branchIfEmpty(resultRegs.tagGPR()));
    1998 
    19992015        addSlowPathGenerator(
    20002016            slowPathCall(
     
    20172033
    20182034            FPRTemporary result(this);
     2035            FPRReg resultReg = result.fpr();
    20192036
    20202037            JSValueRegs resultRegs;
     
    20222039            std::tie(resultRegs, format) = prefix(DataFormatDouble);
    20232040
    2024             speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
    2025 
    2026             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
     2041            speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
     2042
     2043            m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
    20272044            if (!node->arrayMode().isInBoundsSaneChain())
    2028                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr()));
     2045                speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfNaN(resultReg));
    20292046            if (format == DataFormatJS) {
    2030                 boxDouble(result.fpr(), resultRegs);
     2047                boxDouble(resultReg, resultRegs);
    20312048                jsValueResult(resultRegs, node);
    20322049            } else {
    20332050                ASSERT(format == DataFormatDouble && !resultRegs);
    2034                 doubleResult(result.fpr(), node);
     2051                doubleResult(resultReg, node);
    20352052            }
    20362053            break;
     
    20842101            std::tie(resultRegs, std::ignore) = prefix(DataFormatJS);
    20852102
    2086             speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
     2103            speculationCheck(OutOfBounds, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
    20872104
    20882105            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR());
     
    20972114        SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
    20982115        StorageOperand storage(this, m_graph.varArgChild(node, 2));
     2116
     2117        GPRReg baseReg = base.gpr();
    20992118        GPRReg propertyReg = property.gpr();
    21002119        GPRReg storageReg = storage.gpr();
    2101         GPRReg baseReg = base.gpr();
    21022120
    21032121        if (!m_compileOkay)
     
    21212139            slowPathCall(
    21222140                slowCases, this, operationGetByValObjectInt,
    2123                 resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)),
    2124                 baseReg, propertyReg));
     2141                resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseReg, propertyReg));
    21252142
    21262143        jsValueResult(resultRegs, node);
     
    21362153        compileGetByValOnScopedArguments(node, prefix);
    21372154        break;
    2138     default: {
    2139         ASSERT(node->arrayMode().isSomeTypedArrayView());
     2155    case Array::Int8Array:
     2156    case Array::Int16Array:
     2157    case Array::Int32Array:
     2158    case Array::Uint8Array:
     2159    case Array::Uint8ClampedArray:
     2160    case Array::Uint16Array:
     2161    case Array::Uint32Array:
     2162    case Array::Float32Array:
     2163    case Array::Float64Array: {
    21402164        TypedArrayType type = node->arrayMode().typedArrayType();
    21412165        if (isInt(type))
     
    44994523}
    45004524
    4501 // FIXME: we are always taking the slow path here, we should be able to do the equivalent to the 64bit version if we add more available (callee-save registers) to ARMv7 and/or if we reduce the number of registers compileEnumeratorGetByVal uses. See bug #230189.
    4502 void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
    4503 {
    4504     Edge baseEdge = m_graph.varArgChild(node, 0);
    4505     auto generate = [&] (JSValueRegs baseRegs) {
    4506         JSValueOperand property(this, m_graph.varArgChild(node, 1), ManualOperandSpeculation);
    4507         SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
    4508         SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
    4509         SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
    4510         JSValueRegs propertyRegs = property.jsValueRegs();
    4511         GPRReg indexGPR = index.gpr();
    4512         GPRReg modeGPR = mode.gpr();
    4513         GPRReg enumeratorGPR = enumerator.gpr();
    4514 
    4515         flushRegisters();
    4516 
    4517         JSValueRegsFlushedCallResult result(this);
    4518         JSValueRegs resultRegs = result.regs();
    4519 
    4520         if (baseRegs.tagGPR() == InvalidGPRReg)
    4521             callOperation(operationEnumeratorGetByValGeneric, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), CCallHelpers::CellValue(baseRegs.payloadGPR()), propertyRegs, indexGPR, modeGPR, enumeratorGPR);
    4522         else
    4523             callOperation(operationEnumeratorGetByValGeneric, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseRegs, propertyRegs, indexGPR, modeGPR, enumeratorGPR);
    4524         m_jit.exceptionCheck();
    4525         jsValueResult(resultRegs, node);
    4526     };
    4527 
    4528     if (isCell(baseEdge.useKind())) {
    4529         // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
    4530         speculate(node, baseEdge);
    4531         SpeculateCellOperand base(this, baseEdge, ManualOperandSpeculation);
    4532         generate(JSValueRegs::payloadOnly(base.gpr()));
    4533     } else {
    4534         JSValueOperand base(this, baseEdge);
    4535         generate(base.regs());
    4536     }
    4537 }
    45384525#endif
    45394526
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r284369 r284700  
    64676467}
    64686468
    6469 void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
    6470 {
    6471     Edge baseEdge = m_graph.varArgChild(node, 0);
    6472     auto generate = [&] (GPRReg baseCellGPR) {
    6473         MacroAssembler::JumpList doneCases;
    6474         JSValueRegsTemporary result;
    6475         JSValueRegs resultRegs;
    6476         GPRReg indexGPR;
    6477         GPRReg enumeratorGPR;
    6478         MacroAssembler::Jump badStructureSlowPath;
    6479 
    6480         compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) {
    6481             Edge storageEdge = m_graph.varArgChild(node, 2);
    6482             StorageOperand storage;
    6483             if (storageEdge)
    6484                 storage.emplace(this, storageEdge);
    6485             SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
    6486             SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
    6487             SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
    6488 
    6489             GPRReg modeGPR = mode.gpr();
    6490             indexGPR = index.gpr();
    6491             enumeratorGPR = enumerator.gpr();
    6492 
    6493             result = JSValueRegsTemporary(this);
    6494             resultRegs = result.regs();
    6495             GPRReg scratchGPR = resultRegs.payloadGPR();
    6496 
    6497             bool haveStorage = !!storageEdge;
    6498             GPRTemporary storageTemporary;
    6499             GPRReg storageGPR;
    6500             if (!haveStorage) {
    6501                 storageTemporary = GPRTemporary(this, Reuse, enumerator);
    6502                 storageGPR = storageTemporary.gpr();
    6503             } else
    6504                 storageGPR = storage.gpr();
    6505 
    6506             MacroAssembler::JumpList notFastNamedCases;
    6507 
    6508             // FIXME: We shouldn't generate this code if we know base is not an object.
    6509             notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)));
    6510             {
    6511                 if (!m_state.forNode(baseEdge).isType(SpecCell))
    6512                     notFastNamedCases.append(m_jit.branchIfNotCell(baseCellGPR));
    6513 
    6514                 // Check the structure
    6515                 // FIXME: If we know there's only one structure for base we can just embed it here.
    6516                 m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), scratchGPR);
    6517 
    6518                 auto badStructure = m_jit.branch32(
    6519                     MacroAssembler::NotEqual,
    6520                     scratchGPR,
    6521                     MacroAssembler::Address(
    6522                         enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
    6523 
    6524                 // FIXME: Maybe we should have a better way to represent Indexed+Named?
    6525                 if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node())
    6526                     badStructureSlowPath = badStructure;
    6527                 else
    6528                     notFastNamedCases.append(badStructure);
    6529 
    6530                 // Compute the offset
    6531                 // If index is less than the enumerator's cached inline storage, then it's an inline access
    6532                 MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
    6533                     indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
    6534 
    6535                 m_jit.loadValue(MacroAssembler::BaseIndex(baseCellGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
    6536 
    6537                 doneCases.append(m_jit.jump());
    6538 
    6539                 // Otherwise it's out of line
    6540                 outOfLineAccess.link(&m_jit);
    6541                 m_jit.move(indexGPR, scratchGPR);
    6542                 m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
    6543                 m_jit.neg32(scratchGPR);
    6544                 m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
    6545                 if (!haveStorage)
    6546                     m_jit.loadPtr(MacroAssembler::Address(baseCellGPR, JSObject::butterflyOffset()), storageGPR);
    6547                 constexpr intptr_t offsetOfFirstProperty = offsetInButterfly(firstOutOfLineOffset) * static_cast<intptr_t>(sizeof(EncodedJSValue));
    6548                 m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
    6549                 doneCases.append(m_jit.jump());
    6550             }
    6551 
    6552             notFastNamedCases.link(&m_jit);
    6553             return std::make_pair(resultRegs, DataFormatJS);
    6554         }));
    6555 
    6556         // We rely on compileGetByVal to call jsValueResult for us.
    6557         // FIXME: This is kinda hacky...
    6558         ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
    6559 
    6560         if (badStructureSlowPath.isSet())
    6561             addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseCellGPR, indexGPR, enumeratorGPR));
    6562 
    6563         doneCases.link(&m_jit);
    6564     };
    6565 
    6566     if (isCell(baseEdge.useKind())) {
    6567         // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
    6568         speculate(node, baseEdge);
    6569         SpeculateCellOperand baseOperand(this, baseEdge, ManualOperandSpeculation);
    6570         generate(baseOperand.gpr());
    6571     } else {
    6572         JSValueOperand baseOperand(this, baseEdge);
    6573         generate(baseOperand.gpr());
    6574     }
    6575 }
    6576 
    65776469#endif
    65786470
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r282385 r284700  
    119119        if (arrayProfile && baseValue.isCell() && mode != JSPropertyNameEnumerator::OwnStructureMode)
    120120            arrayProfile->observeStructureID(baseValue.asCell()->structureID());
    121 #if USE(JSVALUE32_64)
    122         if (!propertyNameValue.isCell()) {
    123             // This branch is only needed because we use this method
    124             // both as a slow_path and as a DFG call op. We'll end up
    125             // here if propertyName is not a cell then we are in
    126             // index+named mode, so do what RecoverNameAndGetVal
    127             // does. This can probably be removed if we re-enable the
    128             // optimizations for enumeratorGetByVal in DFG, see bug
    129             // #230189.
    130             JSString* string = enumerator->propertyNameAtIndex(index);
    131             auto propertyName = string->toIdentifier(globalObject);
    132             RETURN_IF_EXCEPTION(scope, { });
    133             RELEASE_AND_RETURN(scope, baseValue.get(globalObject, propertyName));
    134         }
    135 #endif
    136121        JSString* string = asString(propertyNameValue);
    137122        auto propertyName = string->toIdentifier(globalObject);
Note: See TracChangeset for help on using the changeset viewer.