diff options
Diffstat (limited to 'Source/JavaScriptCore/bytecode/CallLinkInfo.h')
-rw-r--r-- | Source/JavaScriptCore/bytecode/CallLinkInfo.h | 329 |
1 files changed, 288 insertions, 41 deletions
diff --git a/Source/JavaScriptCore/bytecode/CallLinkInfo.h b/Source/JavaScriptCore/bytecode/CallLinkInfo.h index 36eb84bee..beeeaa12c 100644 --- a/Source/JavaScriptCore/bytecode/CallLinkInfo.h +++ b/Source/JavaScriptCore/bytecode/CallLinkInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,89 +26,336 @@ #ifndef CallLinkInfo_h #define CallLinkInfo_h -#include "ClosureCallStubRoutine.h" +#include "CallMode.h" #include "CodeLocation.h" #include "CodeSpecializationKind.h" #include "JITWriteBarrier.h" #include "JSFunction.h" #include "Opcode.h" +#include "PolymorphicCallStubRoutine.h" #include "WriteBarrier.h" -#include <wtf/Platform.h> #include <wtf/SentinelLinkedList.h> namespace JSC { #if ENABLE(JIT) -class RepatchBuffer; +struct CallFrameShuffleData; -struct CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> { - enum CallType { None, Call, CallVarargs, Construct }; +class CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> { +public: + enum CallType { None, Call, CallVarargs, Construct, ConstructVarargs, TailCall, TailCallVarargs }; static CallType callTypeFor(OpcodeID opcodeID) { if (opcodeID == op_call || opcodeID == op_call_eval) return Call; + if (opcodeID == op_call_varargs) + return CallVarargs; if (opcodeID == op_construct) return Construct; - ASSERT(opcodeID == op_call_varargs); - return CallVarargs; + if (opcodeID == op_construct_varargs) + return ConstructVarargs; + if (opcodeID == op_tail_call) + return TailCall; + ASSERT(opcodeID == op_tail_call_varargs); + return TailCallVarargs; } - - CallLinkInfo() - : hasSeenShouldRepatch(false) - , isDFG(false) - , hasSeenClosure(false) - , callType(None) + + static bool isVarargsCallType(CallType callType) { + switch (callType) { + case CallVarargs: + case ConstructVarargs: + case TailCallVarargs: + return true; + + default: + return false; + } } + + CallLinkInfo(); - ~CallLinkInfo() + ~CallLinkInfo(); + + static CodeSpecializationKind specializationKindFor(CallType callType) { - if (isOnList()) - remove(); + return specializationFromIsConstruct(callType == Construct || callType == ConstructVarargs); } - CodeSpecializationKind specializationKind() const { - return specializationFromIsConstruct(callType == Construct); + return specializationKindFor(static_cast<CallType>(m_callType)); + } + + static CallMode callModeFor(CallType callType) + { + switch (callType) { + case Call: + case CallVarargs: + return CallMode::Regular; + case TailCall: + case TailCallVarargs: + return CallMode::Tail; + case Construct: + case ConstructVarargs: + return CallMode::Construct; + case None: + RELEASE_ASSERT_NOT_REACHED(); + } + + RELEASE_ASSERT_NOT_REACHED(); + } + + CallMode callMode() const + { + return callModeFor(static_cast<CallType>(m_callType)); + } + + bool isTailCall() const + { + return callMode() == CallMode::Tail; + } + + bool isVarargs() const + { + return isVarargsCallType(static_cast<CallType>(m_callType)); + } + + bool isLinked() { return m_stub || m_callee; } + void unlink(VM&); + + void setUpCall(CallType callType, CodeOrigin codeOrigin, unsigned calleeGPR) + { + m_callType = callType; + m_codeOrigin = codeOrigin; + m_calleeGPR = calleeGPR; + } + + void setCallLocations(CodeLocationNearCall callReturnLocation, CodeLocationDataLabelPtr hotPathBegin, + CodeLocationNearCall hotPathOther) + { + m_callReturnLocation = callReturnLocation; + m_hotPathBegin = hotPathBegin; + m_hotPathOther = hotPathOther; + } + + bool allowStubs() const { return m_allowStubs; } + + void disallowStubs() + { + m_allowStubs = false; + } + + void setUpCallFromFTL(CallType callType, CodeOrigin codeOrigin, + CodeLocationNearCall callReturnLocation, CodeLocationDataLabelPtr hotPathBegin, + CodeLocationNearCall hotPathOther, unsigned calleeGPR) + { + m_callType = callType; + m_codeOrigin = codeOrigin; + m_callReturnLocation = callReturnLocation; + m_hotPathBegin = hotPathBegin; + m_hotPathOther = hotPathOther; + m_calleeGPR = calleeGPR; + } + + CodeLocationNearCall callReturnLocation() + { + return m_callReturnLocation; + } + + CodeLocationDataLabelPtr hotPathBegin() + { + return m_hotPathBegin; + } + + CodeLocationNearCall hotPathOther() + { + return m_hotPathOther; + } + + void setCallee(VM& vm, CodeLocationDataLabelPtr location, JSCell* owner, JSFunction* callee) + { + m_callee.set(vm, location, owner, callee); + } + + void clearCallee() + { + m_callee.clear(); + } + + JSFunction* callee() + { + return m_callee.get(); + } + + void setLastSeenCallee(VM& vm, const JSCell* owner, JSFunction* callee) + { + m_lastSeenCallee.set(vm, owner, callee); + } + + void clearLastSeenCallee() + { + m_lastSeenCallee.clear(); + } + + JSFunction* lastSeenCallee() + { + return m_lastSeenCallee.get(); + } + + bool haveLastSeenCallee() + { + return !!m_lastSeenCallee; + } + + void setStub(PassRefPtr<PolymorphicCallStubRoutine> newStub) + { + clearStub(); + m_stub = newStub; } - CodeLocationNearCall callReturnLocation; - CodeLocationDataLabelPtr hotPathBegin; - CodeLocationNearCall hotPathOther; - JITWriteBarrier<JSFunction> callee; - WriteBarrier<JSFunction> lastSeenCallee; - RefPtr<ClosureCallStubRoutine> stub; - bool hasSeenShouldRepatch : 1; - bool isDFG : 1; - bool hasSeenClosure : 1; - CallType callType : 5; - unsigned calleeGPR : 8; - CodeOrigin codeOrigin; + void clearStub(); - bool isLinked() { return stub || callee; } - void unlink(VM&, RepatchBuffer&); + PolymorphicCallStubRoutine* stub() + { + return m_stub.get(); + } + + void setSlowStub(PassRefPtr<JITStubRoutine> newSlowStub) + { + m_slowStub = newSlowStub; + } + + void clearSlowStub() + { + m_slowStub = nullptr; + } + + JITStubRoutine* slowStub() + { + return m_slowStub.get(); + } bool seenOnce() { - return hasSeenShouldRepatch; + return m_hasSeenShouldRepatch; + } + + void clearSeen() + { + m_hasSeenShouldRepatch = false; } void setSeen() { - hasSeenShouldRepatch = true; + m_hasSeenShouldRepatch = true; + } + + bool hasSeenClosure() + { + return m_hasSeenClosure; + } + + void setHasSeenClosure() + { + m_hasSeenClosure = true; + } + + bool clearedByGC() + { + return m_clearedByGC; + } + + void setCallType(CallType callType) + { + m_callType = callType; + } + + CallType callType() + { + return static_cast<CallType>(m_callType); + } + + uint8_t* addressOfMaxNumArguments() + { + return &m_maxNumArguments; } + + uint8_t maxNumArguments() + { + return m_maxNumArguments; + } + + static ptrdiff_t offsetOfSlowPathCount() + { + return OBJECT_OFFSETOF(CallLinkInfo, m_slowPathCount); + } + + void setCalleeGPR(unsigned calleeGPR) + { + m_calleeGPR = calleeGPR; + } + + unsigned calleeGPR() + { + return m_calleeGPR; + } + + uint32_t slowPathCount() + { + return m_slowPathCount; + } + + void setCodeOrigin(CodeOrigin codeOrigin) + { + m_codeOrigin = codeOrigin; + } + + CodeOrigin codeOrigin() + { + return m_codeOrigin; + } + + void visitWeak(VM&); + + void setFrameShuffleData(const CallFrameShuffleData&); + + const CallFrameShuffleData* frameShuffleData() + { + return m_frameShuffleData.get(); + } + +private: + CodeLocationNearCall m_callReturnLocation; + CodeLocationDataLabelPtr m_hotPathBegin; + CodeLocationNearCall m_hotPathOther; + JITWriteBarrier<JSFunction> m_callee; + WriteBarrier<JSFunction> m_lastSeenCallee; + RefPtr<PolymorphicCallStubRoutine> m_stub; + RefPtr<JITStubRoutine> m_slowStub; + std::unique_ptr<CallFrameShuffleData> m_frameShuffleData; + bool m_hasSeenShouldRepatch : 1; + bool m_hasSeenClosure : 1; + bool m_clearedByGC : 1; + bool m_allowStubs : 1; + unsigned m_callType : 4; // CallType + unsigned m_calleeGPR : 8; + uint8_t m_maxNumArguments; // Only used for varargs calls. + uint32_t m_slowPathCount; + CodeOrigin m_codeOrigin; }; -inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo) +inline CodeOrigin getCallLinkInfoCodeOrigin(CallLinkInfo& callLinkInfo) { - return callLinkInfo->callReturnLocation.executableAddress(); + return callLinkInfo.codeOrigin(); } -inline unsigned getCallLinkInfoBytecodeIndex(CallLinkInfo* callLinkInfo) -{ - return callLinkInfo->codeOrigin.bytecodeIndex; -} +typedef HashMap<CodeOrigin, CallLinkInfo*, CodeOriginApproximateHash> CallLinkInfoMap; + +#else // ENABLE(JIT) + +typedef HashMap<int, void*> CallLinkInfoMap; + #endif // ENABLE(JIT) } // namespace JSC |