Changeset 284700 in webkit
- Timestamp:
- Oct 22, 2021, 11:31:50 AM (5 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 8 edited
-
ChangeLog (modified) (1 diff)
-
dfg/DFGFixupPhase.cpp (modified) (1 diff)
-
dfg/DFGOperations.cpp (modified) (4 diffs)
-
dfg/DFGOperations.h (modified) (2 diffs)
-
dfg/DFGSpeculativeJIT.cpp (modified) (1 diff)
-
dfg/DFGSpeculativeJIT32_64.cpp (modified) (12 diffs)
-
dfg/DFGSpeculativeJIT64.cpp (modified) (1 diff)
-
runtime/CommonSlowPaths.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r284699 r284700 1 2021-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 1 31 2021-10-22 Saam Barati <sbarati@apple.com> 2 32 -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r284646 r284700 1125 1125 } 1126 1126 } 1127 #if USE(JSVALUE32_64)1128 fixEdge<CellUse>(m_graph.varArgChild(node, 0)); // Speculating cell due to register pressure on 32-bit.1129 #endif1130 1127 break; 1131 1128 case Array::ForceExit: -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r284330 r284700 750 750 } 751 751 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 781 752 ALWAYS_INLINE EncodedJSValue getByValCellInt(JSGlobalObject* globalObject, VM& vm, JSCell* base, int32_t index) 782 753 { … … 2508 2479 } 2509 2480 2510 JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* base, uint32_t index, JSPropertyNameEnumerator* enumerator))2481 JSC_DEFINE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, uint32_t index, JSPropertyNameEnumerator* enumerator)) 2511 2482 { 2512 2483 VM& vm = globalObject->vm(); … … 2519 2490 // This should only really return for TerminationException since we know string is backed by a UUID. 2520 2491 RETURN_IF_EXCEPTION(scope, { }); 2521 JSObject* object = base->toObject(globalObject); 2492 JSValue base = JSValue::decode(baseValue); 2493 JSObject* object = base.toObject(globalObject); 2522 2494 RETURN_IF_EXCEPTION(scope, { }); 2523 2495 … … 2538 2510 JSString* propertyName = jsSecureCast<JSString*>(vm, JSValue::decode(propertyNameValue)); 2539 2511 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)));2553 2512 } 2554 2513 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r284330 r284700 91 91 JSC_DECLARE_JIT_OPERATION(operationArithCeil, EncodedJSValue, (JSGlobalObject*, EncodedJSValue)); 92 92 JSC_DECLARE_JIT_OPERATION(operationArithTrunc, EncodedJSValue, (JSGlobalObject*, EncodedJSValue)); 93 JSC_DECLARE_JIT_OPERATION(operationGetByValCell, EncodedJSValue, (JSGlobalObject*, JSCell*, EncodedJSValue encodedProperty));94 93 JSC_DECLARE_JIT_OPERATION(operationGetByValObjectInt, EncodedJSValue, (JSGlobalObject*, JSObject*, int32_t)); 95 94 JSC_DECLARE_JIT_OPERATION(operationGetByValStringInt, EncodedJSValue, (JSGlobalObject*, JSString*, int32_t)); … … 112 111 JSC_DECLARE_JIT_OPERATION(operationEnumeratorInByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t)); 113 112 JSC_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*)); 113 JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, uint32_t, JSPropertyNameEnumerator*)); 116 114 117 115 JSC_DECLARE_JIT_OPERATION(operationNewRegexpWithLastIndex, JSCell*, (JSGlobalObject*, JSCell*, EncodedJSValue)); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r284590 r284700 15855 15855 } 15856 15856 15857 void 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 15857 15969 } } // namespace JSC::DFG 15858 15970 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r284330 r284700 1819 1819 { 1820 1820 switch (node->arrayMode().type()) { 1821 case Array::AnyTypedArray: 1822 case Array::ForceExit: 1823 case Array::SelectUsingArguments: 1821 1824 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"); 1827 1829 break; 1828 1830 case Array::Undecided: { … … 1847 1849 if (m_graph.varArgChild(node, 1).useKind() == StringUse) { 1848 1850 compileGetByValForObjectWithString(node, prefix); 1849 break;1851 return; 1850 1852 } 1851 1853 1852 1854 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) { 1853 1855 compileGetByValForObjectWithSymbol(node, prefix); 1854 break;1856 return; 1855 1857 } 1856 1858 } 1857 1859 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)); 1859 1861 JSValueOperand property(this, m_graph.varArgChild(node, 1)); 1860 GPRReg baseGPR = base.gpr();1862 JSValueRegs baseGPR = base.jsValueRegs(); 1861 1863 JSValueRegs propertyRegs = property.jsValueRegs(); 1862 1864 … … 1865 1867 1866 1868 flushRegisters(); 1867 callOperation(operationGetByVal Cell, 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); 1868 1870 m_jit.exceptionCheck(); 1869 1871 1870 1872 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(); 1875 1878 speculate(node, m_graph.varArgChild(node, 1)); 1876 1879 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 } 1917 1933 break; 1918 1934 } … … 1933 1949 std::tie(resultRegs, format) = prefix(node->arrayMode().type() == Array::Int32 ? DataFormatInt32 : DataFormatJS); 1934 1950 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()))); 1936 1952 1937 1953 if (format == DataFormatInt32) { … … 1995 2011 1996 2012 m_jit.loadValue(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultRegs); 2013 1997 2014 slowCases.append(m_jit.branchIfEmpty(resultRegs.tagGPR())); 1998 1999 2015 addSlowPathGenerator( 2000 2016 slowPathCall( … … 2017 2033 2018 2034 FPRTemporary result(this); 2035 FPRReg resultReg = result.fpr(); 2019 2036 2020 2037 JSValueRegs resultRegs; … … 2022 2039 std::tie(resultRegs, format) = prefix(DataFormatDouble); 2023 2040 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); 2027 2044 if (!node->arrayMode().isInBoundsSaneChain()) 2028 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr()));2045 speculationCheck(LoadFromHole, JSValueRegs(), nullptr, m_jit.branchIfNaN(resultReg)); 2029 2046 if (format == DataFormatJS) { 2030 boxDouble(result .fpr(), resultRegs);2047 boxDouble(resultReg, resultRegs); 2031 2048 jsValueResult(resultRegs, node); 2032 2049 } else { 2033 2050 ASSERT(format == DataFormatDouble && !resultRegs); 2034 doubleResult(result .fpr(), node);2051 doubleResult(resultReg, node); 2035 2052 } 2036 2053 break; … … 2084 2101 std::tie(resultRegs, std::ignore) = prefix(DataFormatJS); 2085 2102 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()))); 2087 2104 2088 2105 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultRegs.tagGPR()); … … 2097 2114 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 2098 2115 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 2116 2117 GPRReg baseReg = base.gpr(); 2099 2118 GPRReg propertyReg = property.gpr(); 2100 2119 GPRReg storageReg = storage.gpr(); 2101 GPRReg baseReg = base.gpr();2102 2120 2103 2121 if (!m_compileOkay) … … 2121 2139 slowPathCall( 2122 2140 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)); 2125 2142 2126 2143 jsValueResult(resultRegs, node); … … 2136 2153 compileGetByValOnScopedArguments(node, prefix); 2137 2154 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: { 2140 2164 TypedArrayType type = node->arrayMode().typedArrayType(); 2141 2165 if (isInt(type)) … … 4499 4523 } 4500 4524 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 else4523 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 }4538 4525 #endif 4539 4526 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r284369 r284700 6467 6467 } 6468 6468 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 } else6504 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 structure6515 // 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 else6528 notFastNamedCases.append(badStructure);6529 6530 // Compute the offset6531 // If index is less than the enumerator's cached inline storage, then it's an inline access6532 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 line6540 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 6577 6469 #endif 6578 6470 -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h
r282385 r284700 119 119 if (arrayProfile && baseValue.isCell() && mode != JSPropertyNameEnumerator::OwnStructureMode) 120 120 arrayProfile->observeStructureID(baseValue.asCell()->structureID()); 121 #if USE(JSVALUE32_64)122 if (!propertyNameValue.isCell()) {123 // This branch is only needed because we use this method124 // both as a slow_path and as a DFG call op. We'll end up125 // here if propertyName is not a cell then we are in126 // index+named mode, so do what RecoverNameAndGetVal127 // does. This can probably be removed if we re-enable the128 // optimizations for enumeratorGetByVal in DFG, see bug129 // #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 #endif136 121 JSString* string = asString(propertyNameValue); 137 122 auto propertyName = string->toIdentifier(globalObject);
Note:
See TracChangeset
for help on using the changeset viewer.