Commit 3e43010a authored by Jakob Linke's avatar Jakob Linke Committed by V8 LUCI CQ

[osr] Extend OSR tracing

New trace events:

- finished OSR compilation.
- entry into OSR code.

Since the latter now happens without a trip into runtime, tracing is a
bit more involved - we need to check FLAG_trace_osr in generated code,
and call a runtime function if it is set.

Drive-by: Slightly reorganize other OSR tracing.

Bug: v8:12161
Change-Id: I3096424ca7d47a19802281a0e0a39f7f3394c12b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3629331
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Auto-Submit: Jakob Linke <jgruber@chromium.org>
Commit-Queue: Jakob Linke <jgruber@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80420}
parent 71dbb03e
...@@ -1863,6 +1863,24 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source, ...@@ -1863,6 +1863,24 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source,
__ bind(&jump_to_optimized_code); __ bind(&jump_to_optimized_code);
DCHECK_EQ(maybe_target_code, r0); // Already in the right spot. DCHECK_EQ(maybe_target_code, r0); // Already in the right spot.
// OSR entry tracing.
{
Label next;
__ Move(r1, ExternalReference::address_of_FLAG_trace_osr());
__ ldr(r1, MemOperand(r1));
__ tst(r1, Operand(0xFF)); // Mask to the LSB.
__ b(eq, &next);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ Push(r0); // Preserve the code object.
__ CallRuntime(Runtime::kTraceOptimizedOSREntry, 0);
__ Pop(r0);
}
__ bind(&next);
}
if (source == OsrSourceTier::kInterpreter) { if (source == OsrSourceTier::kInterpreter) {
// Drop the handler frame that is be sitting on top of the actual // Drop the handler frame that is be sitting on top of the actual
// JavaScript frame. This is the case then OSR is triggered from bytecode. // JavaScript frame. This is the case then OSR is triggered from bytecode.
......
...@@ -2095,6 +2095,25 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source, ...@@ -2095,6 +2095,25 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source,
__ Ret(); __ Ret();
__ Bind(&jump_to_optimized_code); __ Bind(&jump_to_optimized_code);
DCHECK_EQ(maybe_target_code, x0); // Already in the right spot.
// OSR entry tracing.
{
Label next;
__ Mov(x1, ExternalReference::address_of_FLAG_trace_osr());
__ Ldr(x1, MemOperand(x1));
__ Tst(x1, 0xFF); // Mask to the LSB.
__ B(eq, &next);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(x0, padreg); // Preserve the code object.
__ CallRuntime(Runtime::kTraceOptimizedOSREntry, 0);
__ Pop(padreg, x0);
}
__ Bind(&next);
}
if (source == OsrSourceTier::kInterpreter) { if (source == OsrSourceTier::kInterpreter) {
// Drop the handler frame that is be sitting on top of the actual // Drop the handler frame that is be sitting on top of the actual
......
...@@ -2844,6 +2844,25 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source, ...@@ -2844,6 +2844,25 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source,
__ ret(0); __ ret(0);
__ bind(&jump_to_optimized_code); __ bind(&jump_to_optimized_code);
DCHECK_EQ(maybe_target_code, eax); // Already in the right spot.
// OSR entry tracing.
{
Label next;
__ cmpb(__ ExternalReferenceAsOperand(
ExternalReference::address_of_FLAG_trace_osr(), ecx),
Immediate(0));
__ j(equal, &next, Label::kNear);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(eax); // Preserve the code object.
__ CallRuntime(Runtime::kTraceOptimizedOSREntry, 0);
__ Pop(eax);
}
__ bind(&next);
}
if (source == OsrSourceTier::kInterpreter) { if (source == OsrSourceTier::kInterpreter) {
// Drop the handler frame that is be sitting on top of the actual // Drop the handler frame that is be sitting on top of the actual
......
...@@ -2748,6 +2748,25 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source, ...@@ -2748,6 +2748,25 @@ void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source,
__ bind(&jump_to_optimized_code); __ bind(&jump_to_optimized_code);
DCHECK_EQ(maybe_target_code, rax); // Already in the right spot. DCHECK_EQ(maybe_target_code, rax); // Already in the right spot.
// OSR entry tracing.
{
Label next;
__ cmpb(
__ ExternalReferenceAsOperand(
ExternalReference::address_of_FLAG_trace_osr(), kScratchRegister),
Immediate(0));
__ j(equal, &next, Label::kNear);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(rax); // Preserve the code object.
__ CallRuntime(Runtime::kTraceOptimizedOSREntry, 0);
__ Pop(rax);
}
__ bind(&next);
}
if (source == OsrSourceTier::kInterpreter) { if (source == OsrSourceTier::kInterpreter) {
// Drop the handler frame that is be sitting on top of the actual // Drop the handler frame that is be sitting on top of the actual
// JavaScript frame. This is the case then OSR is triggered from bytecode. // JavaScript frame. This is the case then OSR is triggered from bytecode.
......
...@@ -120,13 +120,37 @@ class CompilerTracer : public AllStatic { ...@@ -120,13 +120,37 @@ class CompilerTracer : public AllStatic {
PrintTraceSuffix(scope); PrintTraceSuffix(scope);
} }
static void TraceOptimizeOSR(Isolate* isolate, Handle<JSFunction> function, static void TraceOptimizeOSRStarted(Isolate* isolate,
BytecodeOffset osr_offset, Handle<JSFunction> function,
ConcurrencyMode mode) { BytecodeOffset osr_offset,
ConcurrencyMode mode) {
if (!FLAG_trace_osr) return;
CodeTracer::Scope scope(isolate->GetCodeTracer());
PrintF(
scope.file(),
"[OSR - compilation started. function: %s, osr offset: %d, mode: %s]\n",
function->DebugNameCStr().get(), osr_offset.ToInt(), ToString(mode));
}
static void TraceOptimizeOSRFinished(Isolate* isolate,
Handle<JSFunction> function,
BytecodeOffset osr_offset) {
if (!FLAG_trace_osr) return;
CodeTracer::Scope scope(isolate->GetCodeTracer());
PrintF(scope.file(),
"[OSR - compilation finished. function: %s, osr offset: %d]\n",
function->DebugNameCStr().get(), osr_offset.ToInt());
}
static void TraceOptimizeOSRAvailable(Isolate* isolate,
Handle<JSFunction> function,
BytecodeOffset osr_offset,
ConcurrencyMode mode) {
if (!FLAG_trace_osr) return; if (!FLAG_trace_osr) return;
CodeTracer::Scope scope(isolate->GetCodeTracer()); CodeTracer::Scope scope(isolate->GetCodeTracer());
PrintF(scope.file(), PrintF(scope.file(),
"[OSR - started. function: %s, osr offset: %d, mode: %s]\n", "[OSR - available (compilation completed or cache hit). function: "
"%s, osr offset: %d, mode: %s]\n",
function->DebugNameCStr().get(), osr_offset.ToInt(), ToString(mode)); function->DebugNameCStr().get(), osr_offset.ToInt(), ToString(mode));
} }
...@@ -3365,13 +3389,16 @@ MaybeHandle<CodeT> Compiler::CompileOptimizedOSR(Isolate* isolate, ...@@ -3365,13 +3389,16 @@ MaybeHandle<CodeT> Compiler::CompileOptimizedOSR(Isolate* isolate,
function->feedback_vector().reset_osr_urgency(); function->feedback_vector().reset_osr_urgency();
CompilerTracer::TraceOptimizeOSR(isolate, function, osr_offset, mode); CompilerTracer::TraceOptimizeOSRStarted(isolate, function, osr_offset, mode);
MaybeHandle<CodeT> result = GetOrCompileOptimized( MaybeHandle<CodeT> result = GetOrCompileOptimized(
isolate, function, mode, CodeKind::TURBOFAN, osr_offset, frame); isolate, function, mode, CodeKind::TURBOFAN, osr_offset, frame);
if (result.is_null()) { if (result.is_null()) {
CompilerTracer::TraceOptimizeOSRUnavailable(isolate, function, osr_offset, CompilerTracer::TraceOptimizeOSRUnavailable(isolate, function, osr_offset,
mode); mode);
} else {
CompilerTracer::TraceOptimizeOSRAvailable(isolate, function, osr_offset,
mode);
} }
return result; return result;
...@@ -3429,7 +3456,10 @@ bool Compiler::FinalizeTurbofanCompilationJob(TurbofanCompilationJob* job, ...@@ -3429,7 +3456,10 @@ bool Compiler::FinalizeTurbofanCompilationJob(TurbofanCompilationJob* job,
compilation_info->osr_offset(), ToCodeT(*compilation_info->code()), compilation_info->osr_offset(), ToCodeT(*compilation_info->code()),
compilation_info->function_context_specializing()); compilation_info->function_context_specializing());
CompilerTracer::TraceCompletedJob(isolate, compilation_info); CompilerTracer::TraceCompletedJob(isolate, compilation_info);
if (!IsOSR(osr_offset)) { if (IsOSR(osr_offset)) {
CompilerTracer::TraceOptimizeOSRFinished(isolate, function,
osr_offset);
} else {
function->set_code(*compilation_info->code(), kReleaseStore); function->set_code(*compilation_info->code(), kReleaseStore);
} }
} }
......
...@@ -550,6 +550,12 @@ ExternalReference::address_of_mock_arraybuffer_allocator_flag() { ...@@ -550,6 +550,12 @@ ExternalReference::address_of_mock_arraybuffer_allocator_flag() {
return ExternalReference(&FLAG_mock_arraybuffer_allocator); return ExternalReference(&FLAG_mock_arraybuffer_allocator);
} }
// TODO(jgruber): Update the other extrefs pointing at FLAG_ addresses to be
// called address_of_FLAG_foo (easier grep-ability).
ExternalReference ExternalReference::address_of_FLAG_trace_osr() {
return ExternalReference(&FLAG_trace_osr);
}
ExternalReference ExternalReference::address_of_builtin_subclassing_flag() { ExternalReference ExternalReference::address_of_builtin_subclassing_flag() {
return ExternalReference(&FLAG_builtin_subclassing); return ExternalReference(&FLAG_builtin_subclassing);
} }
......
...@@ -92,6 +92,7 @@ class StatsCounter; ...@@ -92,6 +92,7 @@ class StatsCounter;
#define EXTERNAL_REFERENCE_LIST(V) \ #define EXTERNAL_REFERENCE_LIST(V) \
V(abort_with_reason, "abort_with_reason") \ V(abort_with_reason, "abort_with_reason") \
V(address_of_FLAG_trace_osr, "FLAG_trace_osr") \
V(address_of_builtin_subclassing_flag, "FLAG_builtin_subclassing") \ V(address_of_builtin_subclassing_flag, "FLAG_builtin_subclassing") \
V(address_of_double_abs_constant, "double_absolute_constant") \ V(address_of_double_abs_constant, "double_absolute_constant") \
V(address_of_double_neg_constant, "double_negate_constant") \ V(address_of_double_neg_constant, "double_negate_constant") \
......
...@@ -337,18 +337,12 @@ RUNTIME_FUNCTION(Runtime_CompileOptimizedOSR) { ...@@ -337,18 +337,12 @@ RUNTIME_FUNCTION(Runtime_CompileOptimizedOSR) {
DCHECK(result->is_turbofanned()); // TODO(v8:7700): Support Maglev. DCHECK(result->is_turbofanned()); // TODO(v8:7700): Support Maglev.
DCHECK(CodeKindIsOptimizedJSFunction(result->kind())); DCHECK(CodeKindIsOptimizedJSFunction(result->kind()));
#ifdef DEBUG
DeoptimizationData data = DeoptimizationData data =
DeoptimizationData::cast(result->deoptimization_data()); DeoptimizationData::cast(result->deoptimization_data());
DCHECK_EQ(BytecodeOffset(data.OsrBytecodeOffset().value()), osr_offset); DCHECK_EQ(BytecodeOffset(data.OsrBytecodeOffset().value()), osr_offset);
DCHECK_GE(data.OsrPcOffset().value(), 0); DCHECK_GE(data.OsrPcOffset().value(), 0);
#endif // DEBUG
if (FLAG_trace_osr) {
CodeTracer::Scope scope(isolate->GetCodeTracer());
PrintF(scope.file(),
"[OSR - entry. function: %s, osr offset: %d, pc offset: %d]\n",
function->DebugNameCStr().get(), osr_offset.ToInt(),
data.OsrPcOffset().value());
}
if (function->feedback_vector().invocation_count() <= 1 && if (function->feedback_vector().invocation_count() <= 1 &&
!IsNone(function->tiering_state()) && !IsNone(function->tiering_state()) &&
...@@ -368,6 +362,27 @@ RUNTIME_FUNCTION(Runtime_CompileOptimizedOSR) { ...@@ -368,6 +362,27 @@ RUNTIME_FUNCTION(Runtime_CompileOptimizedOSR) {
return *result; return *result;
} }
RUNTIME_FUNCTION(Runtime_TraceOptimizedOSREntry) {
HandleScope handle_scope(isolate);
DCHECK_EQ(0, args.length());
CHECK(FLAG_trace_osr);
// Determine the frame that triggered the OSR request.
JavaScriptFrameIterator it(isolate);
UnoptimizedFrame* frame = UnoptimizedFrame::cast(it.frame());
// Determine the entry point for which this OSR request has been fired.
BytecodeOffset osr_offset = BytecodeOffset(frame->GetBytecodeOffset());
DCHECK(!osr_offset.IsNone());
Handle<JSFunction> function(frame->function(), isolate);
PrintF(CodeTracer::Scope{isolate->GetCodeTracer()}.file(),
"[OSR - entry. function: %s, osr offset: %d]\n",
function->DebugNameCStr().get(), osr_offset.ToInt());
return ReadOnlyRoots(isolate).undefined_value();
}
static Object CompileGlobalEval(Isolate* isolate, static Object CompileGlobalEval(Isolate* isolate,
Handle<i::Object> source_object, Handle<i::Object> source_object,
Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> outer_info,
......
...@@ -108,6 +108,7 @@ namespace internal { ...@@ -108,6 +108,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_COMPILER(F, I) \ #define FOR_EACH_INTRINSIC_COMPILER(F, I) \
F(CompileOptimizedOSR, 0, 1) \ F(CompileOptimizedOSR, 0, 1) \
F(TraceOptimizedOSREntry, 0, 1) \
F(CompileLazy, 1, 1) \ F(CompileLazy, 1, 1) \
F(CompileBaseline, 1, 1) \ F(CompileBaseline, 1, 1) \
F(CompileMaglev_Concurrent, 1, 1) \ F(CompileMaglev_Concurrent, 1, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment