| /* |
| * Copyright (C) 2013-2018 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #if ENABLE(JIT) |
| |
| #include "AssemblyHelpers.h" |
| #include "CCallHelpers.h" |
| #include "CodeOrigin.h" |
| #include "JITOperationValidation.h" |
| #include "JITOperations.h" |
| #include "JSCJSValue.h" |
| #include "PutKind.h" |
| #include "RegisterSet.h" |
| |
| namespace JSC { |
| namespace DFG { |
| class JITCompiler; |
| struct UnlinkedStructureStubInfo; |
| } |
| |
| class CacheableIdentifier; |
| class CallSiteIndex; |
| class CodeBlock; |
| class JIT; |
| class StructureStubInfo; |
| struct UnlinkedStructureStubInfo; |
| struct BaselineUnlinkedStructureStubInfo; |
| |
| enum class AccessType : int8_t; |
| enum class JITType : uint8_t; |
| |
| using CompileTimeStructureStubInfo = std::variant<StructureStubInfo*, BaselineUnlinkedStructureStubInfo*, DFG::UnlinkedStructureStubInfo*>; |
| |
| class JITInlineCacheGenerator { |
| protected: |
| JITInlineCacheGenerator() { } |
| JITInlineCacheGenerator(CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, AccessType); |
| |
| public: |
| StructureStubInfo* stubInfo() const { return m_stubInfo; } |
| |
| void reportSlowPathCall(CCallHelpers::Label slowPathBegin, CCallHelpers::Call call) |
| { |
| m_slowPathBegin = slowPathBegin; |
| m_slowPathCall = call; |
| } |
| |
| CCallHelpers::Label slowPathBegin() const { return m_slowPathBegin; } |
| |
| void finalize( |
| LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer, |
| CodeLocationLabel<JITStubRoutinePtrTag> start); |
| |
| void generateBaselineDataICFastPath(JIT&, unsigned stubInfoConstant, GPRReg stubInfoGPR); |
| #if ENABLE(DFG_JIT) |
| void generateDFGDataICFastPath(DFG::JITCompiler&, unsigned stubInfoConstant, GPRReg stubInfoGPR); |
| #endif |
| |
| UnlinkedStructureStubInfo* m_unlinkedStubInfo { nullptr }; |
| unsigned m_unlinkedStubInfoConstantIndex { std::numeric_limits<unsigned>::max() }; |
| |
| template<typename StubInfo> |
| static void setUpStubInfoImpl(StubInfo& stubInfo, AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters) |
| { |
| stubInfo.accessType = accessType; |
| if constexpr (std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.bytecodeIndex = codeOrigin.bytecodeIndex(); |
| UNUSED_PARAM(callSiteIndex); |
| UNUSED_PARAM(usedRegisters); |
| } else { |
| stubInfo.codeOrigin = codeOrigin; |
| stubInfo.callSiteIndex = callSiteIndex; |
| stubInfo.usedRegisters = usedRegisters; |
| stubInfo.hasConstantIdentifier = true; |
| } |
| } |
| |
| protected: |
| StructureStubInfo* m_stubInfo { nullptr }; |
| |
| public: |
| CCallHelpers::Label m_start; |
| CCallHelpers::Label m_done; |
| CCallHelpers::Label m_slowPathBegin; |
| CCallHelpers::Call m_slowPathCall; |
| }; |
| |
| class JITByIdGenerator : public JITInlineCacheGenerator { |
| protected: |
| JITByIdGenerator() { } |
| |
| JITByIdGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, AccessType, |
| JSValueRegs base, JSValueRegs value); |
| |
| public: |
| CCallHelpers::Jump slowPathJump() const |
| { |
| ASSERT(m_slowPathJump.isSet()); |
| return m_slowPathJump; |
| } |
| |
| void finalize( |
| LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer); |
| |
| template<typename StubInfo> |
| static void setUpStubInfoImpl(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs valueRegs, GPRReg stubInfoGPR) |
| { |
| JITInlineCacheGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.m_baseGPR = baseRegs.payloadGPR(); |
| stubInfo.m_valueGPR = valueRegs.payloadGPR(); |
| stubInfo.m_extraGPR = InvalidGPRReg; |
| stubInfo.m_stubInfoGPR = stubInfoGPR; |
| #if USE(JSVALUE32_64) |
| stubInfo.m_baseTagGPR = baseRegs.tagGPR(); |
| stubInfo.m_valueTagGPR = valueRegs.tagGPR(); |
| stubInfo.m_extraTagGPR = InvalidGPRReg; |
| #endif |
| } else { |
| UNUSED_PARAM(baseRegs); |
| UNUSED_PARAM(valueRegs); |
| UNUSED_PARAM(stubInfoGPR); |
| } |
| } |
| |
| |
| protected: |
| |
| void generateFastCommon(CCallHelpers&, size_t size); |
| |
| JSValueRegs m_base; |
| JSValueRegs m_value; |
| |
| public: |
| CCallHelpers::Jump m_slowPathJump; |
| }; |
| |
| class JITGetByIdGenerator final : public JITByIdGenerator { |
| public: |
| JITGetByIdGenerator() { } |
| |
| JITGetByIdGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, CacheableIdentifier, |
| JSValueRegs base, JSValueRegs value, GPRReg stubInfoGPR, AccessType); |
| |
| void generateFastPath(CCallHelpers&, GPRReg scratchGPR); |
| void generateBaselineDataICFastPath(JIT&, unsigned stubInfoConstant, GPRReg stubInfoGPR); |
| #if ENABLE(DFG_JIT) |
| void generateDFGDataICFastPath(DFG::JITCompiler&, unsigned stubInfoConstant, JSValueRegs baseJSR, JSValueRegs resultJSR, GPRReg stubInfoGPR, GPRReg scratchGPR); |
| #endif |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs valueRegs, GPRReg stubInfoGPR) |
| { |
| JITByIdGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters, baseRegs, valueRegs, stubInfoGPR); |
| } |
| |
| private: |
| bool m_isLengthAccess; |
| }; |
| |
| class JITGetByIdWithThisGenerator final : public JITByIdGenerator { |
| public: |
| JITGetByIdWithThisGenerator() { } |
| |
| JITGetByIdWithThisGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, CacheableIdentifier, |
| JSValueRegs value, JSValueRegs base, JSValueRegs thisRegs, GPRReg stubInfoGPR); |
| |
| void generateFastPath(CCallHelpers&, GPRReg scratchGPR); |
| void generateBaselineDataICFastPath(JIT&, unsigned stubInfoConstant, GPRReg stubInfoGPR); |
| #if ENABLE(DFG_JIT) |
| void generateDFGDataICFastPath(DFG::JITCompiler&, unsigned stubInfoConstant, JSValueRegs baseJSR, JSValueRegs resultJSR, GPRReg stubInfoGPR, GPRReg scratchGPR); |
| #endif |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs valueRegs, JSValueRegs baseRegs, JSValueRegs thisRegs, GPRReg stubInfoGPR) |
| { |
| JITByIdGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters, baseRegs, valueRegs, stubInfoGPR); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.m_extraGPR = thisRegs.payloadGPR(); |
| #if USE(JSVALUE32_64) |
| stubInfo.m_extraTagGPR = thisRegs.tagGPR(); |
| #endif |
| } else |
| UNUSED_PARAM(thisRegs); |
| } |
| }; |
| |
| class JITPutByIdGenerator final : public JITByIdGenerator { |
| public: |
| JITPutByIdGenerator() = default; |
| |
| JITPutByIdGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, CacheableIdentifier, |
| JSValueRegs base, JSValueRegs value, GPRReg stubInfoGPR, GPRReg scratch, ECMAMode, PutKind); |
| |
| void generateFastPath(CCallHelpers&, GPRReg scratchGPR, GPRReg scratch2GPR); |
| void generateBaselineDataICFastPath(JIT&, unsigned stubInfoConstant, GPRReg stubInfoGPR); |
| #if ENABLE(DFG_JIT) |
| void generateDFGDataICFastPath(DFG::JITCompiler&, unsigned stubInfoConstant, JSValueRegs baseJSR, JSValueRegs valueJSR, GPRReg stubInfoGPR, GPRReg scratchGPR, GPRReg scratch2GPR); |
| #endif |
| |
| V_JITOperation_GSsiJJC slowPathFunction(); |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs valueRegs, GPRReg stubInfoGPR, GPRReg scratchGPR, ECMAMode ecmaMode, PutKind putKind) |
| { |
| JITByIdGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters, baseRegs, valueRegs, stubInfoGPR); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) |
| stubInfo.usedRegisters.clear(scratchGPR); |
| else |
| UNUSED_PARAM(scratchGPR); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, StructureStubInfo>) { |
| stubInfo.ecmaMode = ecmaMode; |
| stubInfo.putKind = putKind; |
| } else { |
| UNUSED_PARAM(ecmaMode); |
| UNUSED_PARAM(putKind); |
| } |
| } |
| |
| private: |
| ECMAMode m_ecmaMode { ECMAMode::strict() }; |
| PutKind m_putKind; |
| }; |
| |
| class JITPutByValGenerator final : public JITInlineCacheGenerator { |
| using Base = JITInlineCacheGenerator; |
| public: |
| JITPutByValGenerator() = default; |
| |
| JITPutByValGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, AccessType, const RegisterSet& usedRegisters, |
| JSValueRegs base, JSValueRegs property, JSValueRegs result, GPRReg arrayProfileGPR, GPRReg stubInfoGPR, PutKind, ECMAMode, PrivateFieldPutKind); |
| |
| CCallHelpers::Jump slowPathJump() const |
| { |
| ASSERT(m_slowPathJump.m_jump.isSet()); |
| return m_slowPathJump.m_jump; |
| } |
| |
| void finalize(LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer); |
| |
| void generateFastPath(CCallHelpers&); |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs propertyRegs, JSValueRegs valueRegs, GPRReg arrayProfileGPR, GPRReg stubInfoGPR, PutKind putKind, ECMAMode ecmaMode, PrivateFieldPutKind privateFieldPutKind) |
| { |
| JITInlineCacheGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.m_baseGPR = baseRegs.payloadGPR(); |
| stubInfo.m_extraGPR = propertyRegs.payloadGPR(); |
| stubInfo.m_valueGPR = valueRegs.payloadGPR(); |
| stubInfo.m_stubInfoGPR = stubInfoGPR; |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, DFG::UnlinkedStructureStubInfo>) |
| stubInfo.m_arrayProfileGPR = arrayProfileGPR; |
| else |
| UNUSED_PARAM(arrayProfileGPR); |
| #if USE(JSVALUE32_64) |
| stubInfo.m_baseTagGPR = baseRegs.tagGPR(); |
| stubInfo.m_valueTagGPR = valueRegs.tagGPR(); |
| stubInfo.m_extraTagGPR = propertyRegs.tagGPR(); |
| #endif |
| stubInfo.hasConstantIdentifier = false; |
| } else { |
| UNUSED_PARAM(baseRegs); |
| UNUSED_PARAM(propertyRegs); |
| UNUSED_PARAM(valueRegs); |
| UNUSED_PARAM(stubInfoGPR); |
| UNUSED_PARAM(arrayProfileGPR); |
| } |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, StructureStubInfo>) { |
| stubInfo.putKind = putKind; |
| stubInfo.ecmaMode = ecmaMode; |
| stubInfo.privateFieldPutKind = privateFieldPutKind; |
| } else { |
| UNUSED_PARAM(putKind); |
| UNUSED_PARAM(ecmaMode); |
| UNUSED_PARAM(privateFieldPutKind); |
| } |
| } |
| |
| JSValueRegs m_base; |
| JSValueRegs m_value; |
| |
| CCallHelpers::PatchableJump m_slowPathJump; |
| }; |
| |
| class JITDelByValGenerator final : public JITInlineCacheGenerator { |
| using Base = JITInlineCacheGenerator; |
| public: |
| JITDelByValGenerator() { } |
| |
| JITDelByValGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs base, JSValueRegs property, JSValueRegs result, GPRReg stubInfoGPR); |
| |
| CCallHelpers::Jump slowPathJump() const |
| { |
| ASSERT(m_slowPathJump.m_jump.isSet()); |
| return m_slowPathJump.m_jump; |
| } |
| |
| void finalize( |
| LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer); |
| |
| void generateFastPath(CCallHelpers&); |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs propertyRegs, JSValueRegs resultRegs, GPRReg stubInfoGPR) |
| { |
| JITInlineCacheGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.m_baseGPR = baseRegs.payloadGPR(); |
| stubInfo.m_extraGPR = propertyRegs.payloadGPR(); |
| stubInfo.m_valueGPR = resultRegs.payloadGPR(); |
| stubInfo.m_stubInfoGPR = stubInfoGPR; |
| #if USE(JSVALUE32_64) |
| stubInfo.m_baseTagGPR = baseRegs.tagGPR(); |
| stubInfo.m_valueTagGPR = resultRegs.tagGPR(); |
| stubInfo.m_extraTagGPR = propertyRegs.tagGPR(); |
| #endif |
| stubInfo.hasConstantIdentifier = false; |
| } else { |
| UNUSED_PARAM(baseRegs); |
| UNUSED_PARAM(propertyRegs); |
| UNUSED_PARAM(resultRegs); |
| UNUSED_PARAM(stubInfoGPR); |
| } |
| } |
| |
| CCallHelpers::PatchableJump m_slowPathJump; |
| }; |
| |
| class JITDelByIdGenerator final : public JITInlineCacheGenerator { |
| using Base = JITInlineCacheGenerator; |
| public: |
| JITDelByIdGenerator() { } |
| |
| JITDelByIdGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, CacheableIdentifier, |
| JSValueRegs base, JSValueRegs result, GPRReg stubInfoGPR); |
| |
| CCallHelpers::Jump slowPathJump() const |
| { |
| ASSERT(m_slowPathJump.m_jump.isSet()); |
| return m_slowPathJump.m_jump; |
| } |
| |
| void finalize( |
| LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer); |
| |
| void generateFastPath(CCallHelpers&); |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs resultRegs, GPRReg stubInfoGPR) |
| { |
| JITInlineCacheGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.m_baseGPR = baseRegs.payloadGPR(); |
| stubInfo.m_extraGPR = InvalidGPRReg; |
| stubInfo.m_valueGPR = resultRegs.payloadGPR(); |
| stubInfo.m_stubInfoGPR = stubInfoGPR; |
| #if USE(JSVALUE32_64) |
| stubInfo.m_baseTagGPR = baseRegs.tagGPR(); |
| stubInfo.m_valueTagGPR = resultRegs.tagGPR(); |
| stubInfo.m_extraTagGPR = InvalidGPRReg; |
| #endif |
| stubInfo.hasConstantIdentifier = true; |
| } else { |
| UNUSED_PARAM(baseRegs); |
| UNUSED_PARAM(resultRegs); |
| UNUSED_PARAM(stubInfoGPR); |
| } |
| } |
| |
| CCallHelpers::PatchableJump m_slowPathJump; |
| }; |
| |
| class JITInByValGenerator : public JITInlineCacheGenerator { |
| using Base = JITInlineCacheGenerator; |
| public: |
| JITInByValGenerator() { } |
| |
| JITInByValGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, AccessType, const RegisterSet& usedRegisters, |
| JSValueRegs base, JSValueRegs property, JSValueRegs result, GPRReg stubInfoGPR); |
| |
| CCallHelpers::Jump slowPathJump() const |
| { |
| ASSERT(m_slowPathJump.m_jump.isSet()); |
| return m_slowPathJump.m_jump; |
| } |
| |
| void finalize( |
| LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer); |
| |
| void generateFastPath(CCallHelpers&); |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs propertyRegs, JSValueRegs resultRegs, GPRReg stubInfoGPR) |
| { |
| JITInlineCacheGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.m_baseGPR = baseRegs.payloadGPR(); |
| stubInfo.m_extraGPR = propertyRegs.payloadGPR(); |
| stubInfo.m_valueGPR = resultRegs.payloadGPR(); |
| stubInfo.m_stubInfoGPR = stubInfoGPR; |
| #if USE(JSVALUE32_64) |
| stubInfo.m_baseTagGPR = baseRegs.tagGPR(); |
| stubInfo.m_valueTagGPR = resultRegs.tagGPR(); |
| stubInfo.m_extraTagGPR = propertyRegs.tagGPR(); |
| #endif |
| stubInfo.hasConstantIdentifier = false; |
| } else { |
| UNUSED_PARAM(baseRegs); |
| UNUSED_PARAM(propertyRegs); |
| UNUSED_PARAM(resultRegs); |
| UNUSED_PARAM(stubInfoGPR); |
| } |
| } |
| |
| CCallHelpers::PatchableJump m_slowPathJump; |
| }; |
| |
| class JITInByIdGenerator final : public JITByIdGenerator { |
| public: |
| JITInByIdGenerator() { } |
| |
| JITInByIdGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, CacheableIdentifier, |
| JSValueRegs base, JSValueRegs value, GPRReg stubInfoGPR); |
| |
| void generateFastPath(CCallHelpers&, GPRReg scratchGPR); |
| void generateBaselineDataICFastPath(JIT&, unsigned stubInfoConstant, GPRReg stubInfoGPR); |
| #if ENABLE(DFG_JIT) |
| void generateDFGDataICFastPath(DFG::JITCompiler&, unsigned stubInfoConstant, JSValueRegs baseJSR, JSValueRegs resultJSR, GPRReg stubInfoGPR, GPRReg scratchGPR); |
| #endif |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs valueRegs, GPRReg stubInfoGPR) |
| { |
| JITByIdGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters, baseRegs, valueRegs, stubInfoGPR); |
| } |
| }; |
| |
| class JITInstanceOfGenerator final : public JITInlineCacheGenerator { |
| public: |
| using Base = JITInlineCacheGenerator; |
| JITInstanceOfGenerator() { } |
| |
| JITInstanceOfGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, GPRReg result, |
| GPRReg value, GPRReg prototype, GPRReg stubInfoGPR, |
| bool prototypeIsKnownObject = false); |
| |
| void generateFastPath(CCallHelpers&); |
| |
| CCallHelpers::Jump slowPathJump() const |
| { |
| ASSERT(m_slowPathJump.m_jump.isSet()); |
| return m_slowPathJump.m_jump; |
| } |
| |
| void finalize(LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer); |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| GPRReg resultGPR, GPRReg valueGPR, GPRReg prototypeGPR, GPRReg stubInfoGPR, bool prototypeIsKnownObject) |
| { |
| JITInlineCacheGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters); |
| stubInfo.prototypeIsKnownObject = prototypeIsKnownObject; |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.m_baseGPR = valueGPR; |
| stubInfo.m_valueGPR = resultGPR; |
| stubInfo.m_extraGPR = prototypeGPR; |
| stubInfo.m_stubInfoGPR = stubInfoGPR; |
| #if USE(JSVALUE32_64) |
| stubInfo.m_baseTagGPR = InvalidGPRReg; |
| stubInfo.m_valueTagGPR = InvalidGPRReg; |
| stubInfo.m_extraTagGPR = InvalidGPRReg; |
| #endif |
| stubInfo.usedRegisters.clear(resultGPR); |
| stubInfo.hasConstantIdentifier = false; |
| } else { |
| UNUSED_PARAM(valueGPR); |
| UNUSED_PARAM(resultGPR); |
| UNUSED_PARAM(prototypeGPR); |
| UNUSED_PARAM(stubInfoGPR); |
| } |
| } |
| |
| CCallHelpers::PatchableJump m_slowPathJump; |
| }; |
| |
| class JITGetByValGenerator final : public JITInlineCacheGenerator { |
| using Base = JITInlineCacheGenerator; |
| public: |
| JITGetByValGenerator() { } |
| |
| JITGetByValGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, AccessType, const RegisterSet& usedRegisters, |
| JSValueRegs base, JSValueRegs property, JSValueRegs result, GPRReg stubInfoGPR); |
| |
| CCallHelpers::Jump slowPathJump() const |
| { |
| ASSERT(m_slowPathJump.m_jump.isSet()); |
| return m_slowPathJump.m_jump; |
| } |
| |
| void finalize( |
| LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer); |
| |
| void generateFastPath(CCallHelpers&); |
| |
| void generateEmptyPath(CCallHelpers&); |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs propertyRegs, JSValueRegs resultRegs, GPRReg stubInfoGPR) |
| { |
| JITInlineCacheGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.m_baseGPR = baseRegs.payloadGPR(); |
| stubInfo.m_extraGPR = propertyRegs.payloadGPR(); |
| stubInfo.m_valueGPR = resultRegs.payloadGPR(); |
| stubInfo.m_stubInfoGPR = stubInfoGPR; |
| #if USE(JSVALUE32_64) |
| stubInfo.m_baseTagGPR = baseRegs.tagGPR(); |
| stubInfo.m_valueTagGPR = resultRegs.tagGPR(); |
| stubInfo.m_extraTagGPR = propertyRegs.tagGPR(); |
| #endif |
| stubInfo.hasConstantIdentifier = false; |
| } else { |
| UNUSED_PARAM(baseRegs); |
| UNUSED_PARAM(propertyRegs); |
| UNUSED_PARAM(resultRegs); |
| UNUSED_PARAM(stubInfoGPR); |
| } |
| } |
| |
| JSValueRegs m_base; |
| JSValueRegs m_result; |
| |
| CCallHelpers::PatchableJump m_slowPathJump; |
| }; |
| |
| class JITPrivateBrandAccessGenerator final : public JITInlineCacheGenerator { |
| using Base = JITInlineCacheGenerator; |
| public: |
| JITPrivateBrandAccessGenerator() { } |
| |
| JITPrivateBrandAccessGenerator( |
| CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, AccessType, const RegisterSet& usedRegisters, |
| JSValueRegs base, JSValueRegs brand, GPRReg stubInfoGPR); |
| |
| CCallHelpers::Jump slowPathJump() const |
| { |
| ASSERT(m_slowPathJump.m_jump.isSet()); |
| return m_slowPathJump.m_jump; |
| } |
| |
| void finalize( |
| LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer); |
| |
| void generateFastPath(CCallHelpers&); |
| |
| template<typename StubInfo> |
| static void setUpStubInfo(StubInfo& stubInfo, |
| AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSet& usedRegisters, |
| JSValueRegs baseRegs, JSValueRegs brandRegs, GPRReg stubInfoGPR) |
| { |
| JITInlineCacheGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters); |
| if constexpr (!std::is_same_v<std::decay_t<StubInfo>, BaselineUnlinkedStructureStubInfo>) { |
| stubInfo.m_baseGPR = baseRegs.payloadGPR(); |
| stubInfo.m_extraGPR = brandRegs.payloadGPR(); |
| stubInfo.m_valueGPR = InvalidGPRReg; |
| stubInfo.m_stubInfoGPR = stubInfoGPR; |
| #if USE(JSVALUE32_64) |
| stubInfo.m_baseTagGPR = baseRegs.tagGPR(); |
| stubInfo.m_extraTagGPR = brandRegs.tagGPR(); |
| stubInfo.m_valueTagGPR = InvalidGPRReg; |
| #endif |
| stubInfo.hasConstantIdentifier = false; |
| } else { |
| UNUSED_PARAM(baseRegs); |
| UNUSED_PARAM(brandRegs); |
| UNUSED_PARAM(stubInfoGPR); |
| } |
| } |
| |
| CCallHelpers::PatchableJump m_slowPathJump; |
| }; |
| |
| template<typename VectorType> |
| void finalizeInlineCaches(VectorType& vector, LinkBuffer& fastPath, LinkBuffer& slowPath) |
| { |
| for (auto& entry : vector) |
| entry.finalize(fastPath, slowPath); |
| } |
| |
| template<typename VectorType> |
| void finalizeInlineCaches(VectorType& vector, LinkBuffer& linkBuffer) |
| { |
| finalizeInlineCaches(vector, linkBuffer, linkBuffer); |
| } |
| |
| } // namespace JSC |
| |
| #endif // ENABLE(JIT) |