Skip to content

Commit

Permalink
[JSC] Use probe instead of debugCall for speculation failure dump
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=259810
rdar://113365827

Reviewed by Mark Lam.

debugCall is now leveraged even in FTL, but this does not work well for FTL since it does not restore all registers used by FTL.
In this patch, we remove debugCall, and instead we use JIT probe. This is cleaner, fixing FTL issue, and it is OK for debug purpose calls.

* Source/JavaScriptCore/dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::compileExit):
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* Source/JavaScriptCore/dfg/DFGOSRExit.h:
* Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):
* Source/JavaScriptCore/jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::debugCall): Deleted.
* Source/JavaScriptCore/jit/AssemblyHelpers.h:

Canonical link: https://commits.webkit.org/266567@main
  • Loading branch information
Constellation committed Aug 4, 2023
1 parent e4772fa commit 2d80018
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 66 deletions.
25 changes: 11 additions & 14 deletions Source/JavaScriptCore/dfg/DFGOSRExit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,7 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
debugInfo->codeBlock = jit.codeBlock();
debugInfo->kind = exit.m_kind;
debugInfo->bytecodeIndex = exit.m_codeOrigin.bytecodeIndex();

jit.debugCall(vm, operationDebugPrintSpeculationFailure, debugInfo);
jit.probe(tagCFunction<JITProbePtrTag>(operationDebugPrintSpeculationFailure), debugInfo, SavedFPWidth::DontSaveVectors);
}

// Perform speculation recovery. This only comes into play when an operation
Expand Down Expand Up @@ -882,15 +881,16 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
adjustAndJumpToTarget(vm, jit, exit);
}

JSC_DEFINE_JIT_OPERATION(operationDebugPrintSpeculationFailure, void, (CallFrame* callFrame, void* debugInfoRaw, void* scratch))
JSC_DEFINE_JIT_OPERATION(operationDebugPrintSpeculationFailure, void, (Probe::Context& context))
{
VM& vm = callFrame->deprecatedVM();
NativeCallFrameTracer tracer(vm, callFrame);
ActiveScratchBufferScope activeScratchBufferScope(ScratchBuffer::fromData(scratch), GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters);

SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
auto* debugInfo = context.arg<SpeculationFailureDebugInfo*>();
CodeBlock* codeBlock = debugInfo->codeBlock;
CodeBlock* alternative = codeBlock->alternative();
CallFrame* callFrame = bitwise_cast<CallFrame*>(context.fp());

VM& vm = codeBlock->vm();
NativeCallFrameTracer tracer(vm, callFrame);

dataLog("Speculation failure in ", *codeBlock);
dataLog(" @ exit #", vm.osrExitIndex, " (", debugInfo->bytecodeIndex, ", ", exitKindToString(debugInfo->kind), ") with ");
if (alternative) {
Expand All @@ -902,21 +902,18 @@ JSC_DEFINE_JIT_OPERATION(operationDebugPrintSpeculationFailure, void, (CallFrame
dataLog("no alternative code block (i.e. we've been jettisoned)");
dataLog(", osrExitCounter = ", codeBlock->osrExitCounter(), "\n");
dataLog(" GPRs at time of exit:");
char* scratchPointer = static_cast<char*>(scratch);
for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
GPRReg gpr = GPRInfo::toRegister(i);
dataLog(" ", GPRInfo::debugName(gpr), ":", RawPointer(*reinterpret_cast_ptr<void**>(scratchPointer)));
scratchPointer += sizeof(EncodedJSValue);
dataLog(" ", GPRInfo::debugName(gpr), ":", RawPointer(context.gpr<void*>(gpr)));
}
dataLog("\n");
dataLog(" FPRs at time of exit:");
for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
FPRReg fpr = FPRInfo::toRegister(i);
dataLog(" ", FPRInfo::debugName(fpr), ":");
uint64_t bits = *reinterpret_cast_ptr<uint64_t*>(scratchPointer);
double value = *reinterpret_cast_ptr<double*>(scratchPointer);
uint64_t bits = context.fpr<uint64_t>(fpr);
double value = bitwise_cast<double>(bits);
dataLogF("%llx:%lf", static_cast<long long>(bits), value);
scratchPointer += sizeof(EncodedJSValue);
}
dataLog("\n");
}
Expand Down
3 changes: 1 addition & 2 deletions Source/JavaScriptCore/dfg/DFGOSRExit.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class SpeculationRecovery {
};

JSC_DECLARE_JIT_OPERATION(operationCompileOSRExit, void, (CallFrame*, void*));
JSC_DECLARE_JIT_OPERATION(operationDebugPrintSpeculationFailure, void, (CallFrame*, void*, void*));
JSC_DECLARE_JIT_OPERATION(operationDebugPrintSpeculationFailure, void, (Probe::Context&));
JSC_DECLARE_JIT_OPERATION(operationMaterializeOSRExitSideState, void, (VM*, const OSRExitBase*, EncodedJSValue*));

// === OSRExit ===
Expand Down Expand Up @@ -133,7 +133,6 @@ struct OSRExit : public OSRExitBase {

private:
static void emitRestoreArguments(CCallHelpers&, VM&, const Operands<ValueRecovery>&);
friend void JIT_OPERATION_ATTRIBUTES operationDebugPrintSpeculationFailure(CallFrame*, void*, void*);
};

struct SpeculationFailureDebugInfo {
Expand Down
3 changes: 1 addition & 2 deletions Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,7 @@ static void compileStub(VM& vm, unsigned exitID, JITCode* jitCode, OSRExit& exit
debugInfo->codeBlock = jit.codeBlock();
debugInfo->kind = exit.m_kind;
debugInfo->bytecodeIndex = exit.m_codeOrigin.bytecodeIndex();

jit.debugCall(vm, operationDebugPrintSpeculationFailure, debugInfo);
jit.probe(tagCFunction<JITProbePtrTag>(operationDebugPrintSpeculationFailure), debugInfo, SavedFPWidth::DontSaveVectors);
}

// The first thing we need to do is restablish our frame in the case of an exception.
Expand Down
45 changes: 0 additions & 45 deletions Source/JavaScriptCore/jit/AssemblyHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1363,51 +1363,6 @@ void AssemblyHelpers::prepareWasmCallOperation(GPRReg instanceGPR)

#endif // ENABLE(WEBASSEMBLY)

void AssemblyHelpers::debugCall(VM& vm, V_DebugOperation_EPP function, void* argument)
{
JIT_COMMENT(*this, "debugCall");
size_t scratchSize = sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters);
ScratchBuffer* scratchBuffer = vm.scratchBufferForSize(scratchSize);
EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());

for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
#if USE(JSVALUE64)
store64(GPRInfo::toRegister(i), buffer + i);
#else
store32(GPRInfo::toRegister(i), buffer + i);
#endif
}

for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
storeDouble(FPRInfo::toRegister(i), Address(GPRInfo::regT0));
}

#if CPU(X86_64) || CPU(ARM_THUMB2) || CPU(ARM64) || CPU(MIPS) || CPU(RISCV64)
move(TrustedImmPtr(buffer), GPRInfo::argumentGPR2);
move(TrustedImmPtr(argument), GPRInfo::argumentGPR1);
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
GPRReg scratch = selectScratchGPR(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, GPRInfo::argumentGPR2);
#else
#error "JIT not supported on this platform."
#endif
prepareCallOperation(vm);
move(TrustedImmPtr(tagCFunctionPtr<OperationPtrTag>(function)), scratch);
call(scratch, OperationPtrTag);

for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
loadDouble(Address(GPRInfo::regT0), FPRInfo::toRegister(i));
}
for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
#if USE(JSVALUE64)
load64(buffer + i, GPRInfo::toRegister(i));
#else
load32(buffer + i, GPRInfo::toRegister(i));
#endif
}
}

void AssemblyHelpers::copyCalleeSavesToEntryFrameCalleeSavesBufferImpl(GPRReg calleeSavesBuffer)
{
JIT_COMMENT(*this, "copyCalleeSavesToEntryFrameCalleeSavesBufferImpl ", calleeSavesBuffer);
Expand Down
3 changes: 0 additions & 3 deletions Source/JavaScriptCore/jit/AssemblyHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1379,9 +1379,6 @@ class AssemblyHelpers : public MacroAssembler {
constructRegisterSet(set, args...);
}

// Add a debug call. This call has no effect on JIT code execution state.
void debugCall(VM&, V_DebugOperation_EPP function, void* argument);

// These methods JIT generate dynamic, debug-only checks - akin to ASSERTs.
#if ASSERT_ENABLED
void jitAssertIsInt32(GPRReg);
Expand Down

0 comments on commit 2d80018

Please sign in to comment.