2017-08-12 16:48:01 +00:00
|
|
|
/*
|
2020-08-29 13:27:11 +00:00
|
|
|
* Copyright (C) 2011-2018 Apple Inc. All rights reserved.
|
2017-08-12 16:48:01 +00:00
|
|
|
*
|
|
|
|
* 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(DFG_JIT)
|
|
|
|
|
|
|
|
#include "DFGOSRExitBase.h"
|
2020-08-29 13:27:11 +00:00
|
|
|
#include "DFGVariableEventStream.h"
|
2017-08-12 16:48:01 +00:00
|
|
|
#include "GPRInfo.h"
|
|
|
|
#include "MacroAssembler.h"
|
|
|
|
#include "MethodOfGettingAValueProfile.h"
|
2020-08-29 13:27:11 +00:00
|
|
|
#include "Operands.h"
|
|
|
|
#include "ValueRecovery.h"
|
|
|
|
#include <wtf/RefPtr.h>
|
2017-08-12 16:48:01 +00:00
|
|
|
|
2020-08-29 13:27:11 +00:00
|
|
|
namespace JSC {
|
|
|
|
|
|
|
|
class ArrayProfile;
|
|
|
|
class CCallHelpers;
|
|
|
|
|
|
|
|
namespace Probe {
|
|
|
|
class Context;
|
|
|
|
} // namespace Probe
|
|
|
|
|
|
|
|
namespace Profiler {
|
|
|
|
class OSRExit;
|
|
|
|
} // namespace Profiler
|
|
|
|
|
|
|
|
namespace DFG {
|
2017-08-12 16:48:01 +00:00
|
|
|
|
|
|
|
class SpeculativeJIT;
|
|
|
|
struct BasicBlock;
|
|
|
|
struct Node;
|
|
|
|
|
|
|
|
// This enum describes the types of additional recovery that
|
|
|
|
// may need be performed should a speculation check fail.
|
|
|
|
enum SpeculationRecoveryType : uint8_t {
|
|
|
|
SpeculativeAdd,
|
2020-08-29 13:27:11 +00:00
|
|
|
SpeculativeAddSelf,
|
2017-08-12 16:48:01 +00:00
|
|
|
SpeculativeAddImmediate,
|
|
|
|
BooleanSpeculationCheck
|
|
|
|
};
|
|
|
|
|
|
|
|
// === SpeculationRecovery ===
|
|
|
|
//
|
|
|
|
// This class provides additional information that may be associated with a
|
|
|
|
// speculation check - for example
|
|
|
|
class SpeculationRecovery {
|
|
|
|
public:
|
|
|
|
SpeculationRecovery(SpeculationRecoveryType type, GPRReg dest, GPRReg src)
|
|
|
|
: m_src(src)
|
|
|
|
, m_dest(dest)
|
|
|
|
, m_type(type)
|
|
|
|
{
|
2020-08-29 13:27:11 +00:00
|
|
|
ASSERT(m_type == SpeculativeAdd || m_type == SpeculativeAddSelf || m_type == BooleanSpeculationCheck);
|
2017-08-12 16:48:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SpeculationRecovery(SpeculationRecoveryType type, GPRReg dest, int32_t immediate)
|
|
|
|
: m_immediate(immediate)
|
|
|
|
, m_dest(dest)
|
|
|
|
, m_type(type)
|
|
|
|
{
|
|
|
|
ASSERT(m_type == SpeculativeAddImmediate);
|
|
|
|
}
|
|
|
|
|
|
|
|
SpeculationRecoveryType type() { return m_type; }
|
|
|
|
GPRReg dest() { return m_dest; }
|
|
|
|
GPRReg src() { return m_src; }
|
|
|
|
int32_t immediate() { return m_immediate; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
// different recovery types may required different additional information here.
|
|
|
|
union {
|
|
|
|
GPRReg m_src;
|
|
|
|
int32_t m_immediate;
|
|
|
|
};
|
|
|
|
GPRReg m_dest;
|
|
|
|
|
|
|
|
// Indicates the type of additional recovery to be performed.
|
|
|
|
SpeculationRecoveryType m_type;
|
|
|
|
};
|
|
|
|
|
2020-08-29 13:27:11 +00:00
|
|
|
enum class ExtraInitializationLevel;
|
|
|
|
|
|
|
|
struct OSRExitState : RefCounted<OSRExitState> {
|
2022-10-23 02:55:20 +00:00
|
|
|
OSRExitState(OSRExitBase& exit, CodeBlock* codeBlock, CodeBlock* baselineCodeBlock, Operands<ValueRecovery>& operands, Vector<UndefinedOperandSpan>&& undefinedOperandSpans, SpeculationRecovery* recovery, ptrdiff_t stackPointerOffset, int32_t activeThreshold, double memoryUsageAdjustedThreshold, void* jumpTarget, ArrayProfile* arrayProfile, bool isJumpToLLInt)
|
2020-08-29 13:27:11 +00:00
|
|
|
: exit(exit)
|
|
|
|
, codeBlock(codeBlock)
|
|
|
|
, baselineCodeBlock(baselineCodeBlock)
|
|
|
|
, operands(operands)
|
|
|
|
, undefinedOperandSpans(undefinedOperandSpans)
|
|
|
|
, recovery(recovery)
|
|
|
|
, stackPointerOffset(stackPointerOffset)
|
|
|
|
, activeThreshold(activeThreshold)
|
|
|
|
, memoryUsageAdjustedThreshold(memoryUsageAdjustedThreshold)
|
|
|
|
, jumpTarget(jumpTarget)
|
|
|
|
, arrayProfile(arrayProfile)
|
2022-10-23 02:55:20 +00:00
|
|
|
, isJumpToLLInt(isJumpToLLInt)
|
2020-08-29 13:27:11 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
OSRExitBase& exit;
|
|
|
|
CodeBlock* codeBlock;
|
|
|
|
CodeBlock* baselineCodeBlock;
|
|
|
|
Operands<ValueRecovery> operands;
|
|
|
|
Vector<UndefinedOperandSpan> undefinedOperandSpans;
|
|
|
|
SpeculationRecovery* recovery;
|
|
|
|
ptrdiff_t stackPointerOffset;
|
|
|
|
uint32_t activeThreshold;
|
|
|
|
double memoryUsageAdjustedThreshold;
|
|
|
|
void* jumpTarget;
|
|
|
|
ArrayProfile* arrayProfile;
|
2022-10-23 02:55:20 +00:00
|
|
|
bool isJumpToLLInt;
|
2020-08-29 13:27:11 +00:00
|
|
|
|
|
|
|
ExtraInitializationLevel extraInitializationLevel;
|
|
|
|
Profiler::OSRExit* profilerExit { nullptr };
|
|
|
|
};
|
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
JSC_DECLARE_JIT_OPERATION(operationCompileOSRExit, void, (CallFrame*));
|
|
|
|
JSC_DECLARE_JIT_OPERATION(operationDebugPrintSpeculationFailure, void, (CallFrame*, void*, void*));
|
|
|
|
|
2017-08-12 16:48:01 +00:00
|
|
|
// === OSRExit ===
|
|
|
|
//
|
|
|
|
// This structure describes how to exit the speculative path by
|
|
|
|
// going into baseline code.
|
|
|
|
struct OSRExit : public OSRExitBase {
|
|
|
|
OSRExit(ExitKind, JSValueSource, MethodOfGettingAValueProfile, SpeculativeJIT*, unsigned streamIndex, unsigned recoveryIndex = UINT_MAX);
|
|
|
|
|
2022-10-23 02:55:20 +00:00
|
|
|
friend void JIT_OPERATION_ATTRIBUTES operationCompileOSRExit(CallFrame*);
|
2020-08-29 13:27:11 +00:00
|
|
|
|
|
|
|
CodeLocationLabel<JSInternalPtrTag> m_patchableJumpLocation;
|
|
|
|
MacroAssemblerCodeRef<OSRExitPtrTag> m_code;
|
|
|
|
|
|
|
|
RefPtr<OSRExitState> exitState;
|
2017-08-12 16:48:01 +00:00
|
|
|
|
|
|
|
JSValueSource m_jsValueSource;
|
|
|
|
MethodOfGettingAValueProfile m_valueProfile;
|
|
|
|
|
|
|
|
unsigned m_recoveryIndex;
|
|
|
|
|
2020-08-29 13:27:11 +00:00
|
|
|
CodeLocationJump<JSInternalPtrTag> codeLocationForRepatch() const;
|
2017-08-12 16:48:01 +00:00
|
|
|
|
|
|
|
unsigned m_streamIndex;
|
|
|
|
void considerAddingAsFrequentExitSite(CodeBlock* profiledCodeBlock)
|
|
|
|
{
|
|
|
|
OSRExitBase::considerAddingAsFrequentExitSite(profiledCodeBlock, ExitFromDFG);
|
|
|
|
}
|
2020-08-29 13:27:11 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
static void compileExit(CCallHelpers&, VM&, const OSRExit&, const Operands<ValueRecovery>&, SpeculationRecovery*);
|
2022-10-23 02:55:20 +00:00
|
|
|
static void emitRestoreArguments(CCallHelpers&, VM&, const Operands<ValueRecovery>&);
|
|
|
|
friend void JIT_OPERATION_ATTRIBUTES operationDebugPrintSpeculationFailure(CallFrame*, void*, void*);
|
2017-08-12 16:48:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct SpeculationFailureDebugInfo {
|
2022-10-23 02:55:20 +00:00
|
|
|
WTF_MAKE_STRUCT_FAST_ALLOCATED;
|
2017-08-12 16:48:01 +00:00
|
|
|
CodeBlock* codeBlock;
|
|
|
|
ExitKind kind;
|
2022-10-23 02:55:20 +00:00
|
|
|
BytecodeIndex bytecodeIndex;
|
2017-08-12 16:48:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} } // namespace JSC::DFG
|
|
|
|
|
|
|
|
#endif // ENABLE(DFG_JIT)
|