[test][sparkplug] Test Ignition -> Sparkplug OSR

- Add %BaselineOsr to manually trigger OSR to Baseline.
- Add flags to %GetOptimizationStatus to check if the topmost frame is
an Interpreter/Baseline frame.
- Add mjsunit test.

Bug: v8:11420
Change-Id: Id80421ad97ee719a67ef299cc700da9c44f23bae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2814567
Auto-Submit: Patrick Thier <pthier@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Patrick Thier <pthier@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73937}
This commit is contained in:
Patrick Thier 2021-04-13 12:52:09 +00:00 committed by Commit Bot
parent 7de9631d57
commit 5f49bbdf84
9 changed files with 233 additions and 108 deletions

View File

@ -2310,6 +2310,7 @@ v8_header_set("v8_internal_headers") {
"src/baseline/baseline-assembler-inl.h",
"src/baseline/baseline-assembler.h",
"src/baseline/baseline-compiler.h",
"src/baseline/baseline-osr-inl.h",
"src/baseline/baseline.h",
"src/baseline/bytecode-offset-iterator.h",
"src/builtins/accessors.h",

View File

@ -5,6 +5,7 @@ include_rules = [
"+src/asmjs/asm-js.h",
"-src/baseline",
"+src/baseline/baseline.h",
"+src/baseline/baseline-osr-inl.h",
"+src/baseline/bytecode-offset-iterator.h",
"-src/bigint",
"+src/bigint/bigint.h",

View File

@ -0,0 +1,38 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef V8_BASELINE_BASELINE_OSR_INL_H_
#define V8_BASELINE_BASELINE_OSR_INL_H_
#include "src/execution/frames.h"
#include "src/execution/isolate-inl.h"
namespace v8 {
namespace internal {
inline void OSRInterpreterFrameToBaseline(Isolate* isolate,
Handle<JSFunction> function,
UnoptimizedFrame* frame) {
IsCompiledScope is_compiled_scope(
function->shared().is_compiled_scope(isolate));
if (Compiler::CompileBaseline(isolate, function, Compiler::CLEAR_EXCEPTION,
&is_compiled_scope)) {
if (V8_LIKELY(FLAG_use_osr)) {
DCHECK_NOT_NULL(frame);
if (FLAG_trace_osr) {
CodeTracer::Scope scope(isolate->GetCodeTracer());
PrintF(scope.file(),
"[OSR - Entry at OSR bytecode offset %d into baseline code]\n",
frame->GetBytecodeOffset());
}
frame->GetBytecodeArray().set_osr_loop_nesting_level(
AbstractCode::kMaxLoopNestingMarker);
}
}
}
} // namespace internal
} // namespace v8
#endif // V8_BASELINE_BASELINE_OSR_INL_H_

View File

@ -7,6 +7,7 @@
#include "src/api/api.h"
#include "src/ast/ast-traversal-visitor.h"
#include "src/ast/prettyprinter.h"
#include "src/baseline/baseline-osr-inl.h"
#include "src/baseline/baseline.h"
#include "src/builtins/builtins.h"
#include "src/common/message-template.h"
@ -342,23 +343,13 @@ RUNTIME_FUNCTION(Runtime_BytecodeBudgetInterruptFromBytecode) {
// a non zero invocation count so we can inline functions.
function->feedback_vector().set_invocation_count(1);
if (FLAG_sparkplug) {
if (Compiler::CompileBaseline(isolate, function,
Compiler::CLEAR_EXCEPTION,
&is_compiled_scope)) {
if (FLAG_use_osr) {
JavaScriptFrameIterator it(isolate);
DCHECK(it.frame()->is_unoptimized());
UnoptimizedFrame* frame = UnoptimizedFrame::cast(it.frame());
if (FLAG_trace_osr) {
CodeTracer::Scope scope(isolate->GetCodeTracer());
PrintF(
scope.file(),
"[OSR - Entry at OSR bytecode offset %d into baseline code]\n",
frame->GetBytecodeOffset());
}
frame->GetBytecodeArray().set_osr_loop_nesting_level(
AbstractCode::kMaxLoopNestingMarker);
}
if (V8_LIKELY(FLAG_use_osr)) {
JavaScriptFrameIterator it(isolate);
DCHECK(it.frame()->is_unoptimized());
UnoptimizedFrame* frame = UnoptimizedFrame::cast(it.frame());
OSRInterpreterFrameToBaseline(isolate, function, frame);
} else {
OSRInterpreterFrameToBaseline(isolate, function, nullptr);
}
}
return ReadOnlyRoots(isolate).undefined_value();

View File

@ -4,6 +4,7 @@
#include "src/api/api-inl.h"
#include "src/base/platform/mutex.h"
#include "src/baseline/baseline-osr-inl.h"
#include "src/codegen/assembler-inl.h"
#include "src/codegen/compiler.h"
#include "src/codegen/pending-optimization-table.h"
@ -470,6 +471,37 @@ RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_BaselineOsr) {
HandleScope scope(isolate);
DCHECK(args.length() == 0 || args.length() == 1);
Handle<JSFunction> function;
// The optional parameter determines the frame being targeted.
int stack_depth = 0;
if (args.length() == 1) {
if (!args[0].IsSmi()) return CrashUnlessFuzzing(isolate);
stack_depth = args.smi_at(0);
}
// Find the JavaScript function on the top of the stack.
JavaScriptFrameIterator it(isolate);
while (!it.done() && stack_depth--) it.Advance();
if (!it.done()) function = handle(it.frame()->function(), isolate);
if (function.is_null()) return CrashUnlessFuzzing(isolate);
if (!FLAG_sparkplug || !FLAG_use_osr) {
return ReadOnlyRoots(isolate).undefined_value();
}
if (!it.frame()->is_unoptimized()) {
return ReadOnlyRoots(isolate).undefined_value();
}
UnoptimizedFrame* frame = UnoptimizedFrame::cast(it.frame());
OSRInterpreterFrameToBaseline(isolate, function, frame);
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
@ -576,6 +608,11 @@ RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
if (frame->is_optimized()) {
status |=
static_cast<int>(OptimizationStatus::kTopmostFrameIsTurboFanned);
} else if (frame->is_interpreted()) {
status |=
static_cast<int>(OptimizationStatus::kTopmostFrameIsInterpreted);
} else if (frame->is_baseline()) {
status |= static_cast<int>(OptimizationStatus::kTopmostFrameIsBaseline);
}
}

View File

@ -220,6 +220,7 @@ bool Runtime::IsAllowListedForFuzzing(FunctionId id) {
case Runtime::kIsBeingInterpreted:
return !FLAG_allow_natives_for_differential_fuzzing;
case Runtime::kCompileBaseline:
case Runtime::kBaselineOsr:
return FLAG_sparkplug;
default:
return false;

View File

@ -460,97 +460,98 @@ namespace internal {
F(SymbolDescriptiveString, 1, 1) \
F(SymbolIsPrivate, 1, 1)
#define FOR_EACH_INTRINSIC_TEST(F, I) \
F(Abort, 1, 1) \
F(AbortJS, 1, 1) \
F(AbortCSAAssert, 1, 1) \
F(ArraySpeciesProtector, 0, 1) \
F(ClearFunctionFeedback, 1, 1) \
F(ClearMegamorphicStubCache, 0, 1) \
F(CompleteInobjectSlackTracking, 1, 1) \
F(ConstructConsString, 2, 1) \
F(ConstructDouble, 2, 1) \
F(ConstructSlicedString, 2, 1) \
F(DebugPrint, 1, 1) \
F(DebugPrintPtr, 1, 1) \
F(DebugTrace, 0, 1) \
F(DebugTrackRetainingPath, -1, 1) \
F(DeoptimizeFunction, 1, 1) \
F(DisallowCodegenFromStrings, 1, 1) \
F(DisassembleFunction, 1, 1) \
F(DynamicCheckMapsEnabled, 0, 1) \
F(IsTopTierTurboprop, 0, 1) \
F(IsMidTierTurboprop, 0, 1) \
F(EnableCodeLoggingForTesting, 0, 1) \
F(EnsureFeedbackVectorForFunction, 1, 1) \
F(GetCallable, 0, 1) \
F(GetInitializerFunction, 1, 1) \
F(GetOptimizationStatus, -1, 1) \
F(GetUndetectable, 0, 1) \
F(GlobalPrint, 1, 1) \
F(HasDictionaryElements, 1, 1) \
F(HasDoubleElements, 1, 1) \
F(HasElementsInALargeObjectSpace, 1, 1) \
F(HasFastElements, 1, 1) \
F(HasFastProperties, 1, 1) \
F(HasOwnConstDataProperty, 2, 1) \
F(HasFixedBigInt64Elements, 1, 1) \
F(HasFixedBigUint64Elements, 1, 1) \
F(HasFixedFloat32Elements, 1, 1) \
F(HasFixedFloat64Elements, 1, 1) \
F(HasFixedInt16Elements, 1, 1) \
F(HasFixedInt32Elements, 1, 1) \
F(HasFixedInt8Elements, 1, 1) \
F(HasFixedUint16Elements, 1, 1) \
F(HasFixedUint32Elements, 1, 1) \
F(HasFixedUint8ClampedElements, 1, 1) \
F(HasFixedUint8Elements, 1, 1) \
F(HasHoleyElements, 1, 1) \
F(HasObjectElements, 1, 1) \
F(HasPackedElements, 1, 1) \
F(HasSloppyArgumentsElements, 1, 1) \
F(HasSmiElements, 1, 1) \
F(HasSmiOrObjectElements, 1, 1) \
F(HaveSameMap, 2, 1) \
F(HeapObjectVerify, 1, 1) \
F(ICsAreEnabled, 0, 1) \
F(InLargeObjectSpace, 1, 1) \
F(InYoungGeneration, 1, 1) \
F(IsBeingInterpreted, 0, 1) \
F(IsConcurrentRecompilationSupported, 0, 1) \
F(IsDictPropertyConstTrackingEnabled, 0, 1) \
F(RegexpHasBytecode, 2, 1) \
F(RegexpHasNativeCode, 2, 1) \
F(RegexpTypeTag, 1, 1) \
F(RegexpIsUnmodified, 1, 1) \
F(MapIteratorProtector, 0, 1) \
F(ArrayIteratorProtector, 0, 1) \
F(NeverOptimizeFunction, 1, 1) \
F(NotifyContextDisposed, 0, 1) \
F(OptimizeFunctionOnNextCall, -1, 1) \
F(TierupFunctionOnNextCall, -1, 1) \
F(OptimizeOsr, -1, 1) \
F(NewRegExpWithBacktrackLimit, 3, 1) \
F(PrepareFunctionForOptimization, -1, 1) \
F(PrintWithNameForAssert, 2, 1) \
F(RunningInSimulator, 0, 1) \
F(RuntimeEvaluateREPL, 1, 1) \
F(SerializeDeserializeNow, 0, 1) \
F(SetAllocationTimeout, -1 /* 2 || 3 */, 1) \
F(SetForceSlowPath, 1, 1) \
F(SetIteratorProtector, 0, 1) \
F(SimulateNewspaceFull, 0, 1) \
F(ScheduleGCInStackCheck, 0, 1) \
F(StringIteratorProtector, 0, 1) \
F(SystemBreak, 0, 1) \
F(TraceEnter, 0, 1) \
F(TraceExit, 1, 1) \
F(TurbofanStaticAssert, 1, 1) \
F(TypedArraySpeciesProtector, 0, 1) \
F(UnblockConcurrentRecompilation, 0, 1) \
I(DeoptimizeNow, 0, 1) \
F(PromiseSpeciesProtector, 0, 1) \
F(IsConcatSpreadableProtector, 0, 1) \
#define FOR_EACH_INTRINSIC_TEST(F, I) \
F(Abort, 1, 1) \
F(AbortJS, 1, 1) \
F(AbortCSAAssert, 1, 1) \
F(ArraySpeciesProtector, 0, 1) \
F(BaselineOsr, -1, 1) \
F(ClearFunctionFeedback, 1, 1) \
F(ClearMegamorphicStubCache, 0, 1) \
F(CompleteInobjectSlackTracking, 1, 1) \
F(ConstructConsString, 2, 1) \
F(ConstructDouble, 2, 1) \
F(ConstructSlicedString, 2, 1) \
F(DebugPrint, 1, 1) \
F(DebugPrintPtr, 1, 1) \
F(DebugTrace, 0, 1) \
F(DebugTrackRetainingPath, -1, 1) \
F(DeoptimizeFunction, 1, 1) \
F(DisallowCodegenFromStrings, 1, 1) \
F(DisassembleFunction, 1, 1) \
F(DynamicCheckMapsEnabled, 0, 1) \
F(IsTopTierTurboprop, 0, 1) \
F(IsMidTierTurboprop, 0, 1) \
F(EnableCodeLoggingForTesting, 0, 1) \
F(EnsureFeedbackVectorForFunction, 1, 1) \
F(GetCallable, 0, 1) \
F(GetInitializerFunction, 1, 1) \
F(GetOptimizationStatus, -1, 1) \
F(GetUndetectable, 0, 1) \
F(GlobalPrint, 1, 1) \
F(HasDictionaryElements, 1, 1) \
F(HasDoubleElements, 1, 1) \
F(HasElementsInALargeObjectSpace, 1, 1) \
F(HasFastElements, 1, 1) \
F(HasFastProperties, 1, 1) \
F(HasOwnConstDataProperty, 2, 1) \
F(HasFixedBigInt64Elements, 1, 1) \
F(HasFixedBigUint64Elements, 1, 1) \
F(HasFixedFloat32Elements, 1, 1) \
F(HasFixedFloat64Elements, 1, 1) \
F(HasFixedInt16Elements, 1, 1) \
F(HasFixedInt32Elements, 1, 1) \
F(HasFixedInt8Elements, 1, 1) \
F(HasFixedUint16Elements, 1, 1) \
F(HasFixedUint32Elements, 1, 1) \
F(HasFixedUint8ClampedElements, 1, 1) \
F(HasFixedUint8Elements, 1, 1) \
F(HasHoleyElements, 1, 1) \
F(HasObjectElements, 1, 1) \
F(HasPackedElements, 1, 1) \
F(HasSloppyArgumentsElements, 1, 1) \
F(HasSmiElements, 1, 1) \
F(HasSmiOrObjectElements, 1, 1) \
F(HaveSameMap, 2, 1) \
F(HeapObjectVerify, 1, 1) \
F(ICsAreEnabled, 0, 1) \
F(InLargeObjectSpace, 1, 1) \
F(InYoungGeneration, 1, 1) \
F(IsBeingInterpreted, 0, 1) \
F(IsConcurrentRecompilationSupported, 0, 1) \
F(IsDictPropertyConstTrackingEnabled, 0, 1) \
F(RegexpHasBytecode, 2, 1) \
F(RegexpHasNativeCode, 2, 1) \
F(RegexpTypeTag, 1, 1) \
F(RegexpIsUnmodified, 1, 1) \
F(MapIteratorProtector, 0, 1) \
F(ArrayIteratorProtector, 0, 1) \
F(NeverOptimizeFunction, 1, 1) \
F(NotifyContextDisposed, 0, 1) \
F(OptimizeFunctionOnNextCall, -1, 1) \
F(TierupFunctionOnNextCall, -1, 1) \
F(OptimizeOsr, -1, 1) \
F(NewRegExpWithBacktrackLimit, 3, 1) \
F(PrepareFunctionForOptimization, -1, 1) \
F(PrintWithNameForAssert, 2, 1) \
F(RunningInSimulator, 0, 1) \
F(RuntimeEvaluateREPL, 1, 1) \
F(SerializeDeserializeNow, 0, 1) \
F(SetAllocationTimeout, -1 /* 2 || 3 */, 1) \
F(SetForceSlowPath, 1, 1) \
F(SetIteratorProtector, 0, 1) \
F(SimulateNewspaceFull, 0, 1) \
F(ScheduleGCInStackCheck, 0, 1) \
F(StringIteratorProtector, 0, 1) \
F(SystemBreak, 0, 1) \
F(TraceEnter, 0, 1) \
F(TraceExit, 1, 1) \
F(TurbofanStaticAssert, 1, 1) \
F(TypedArraySpeciesProtector, 0, 1) \
F(UnblockConcurrentRecompilation, 0, 1) \
I(DeoptimizeNow, 0, 1) \
F(PromiseSpeciesProtector, 0, 1) \
F(IsConcatSpreadableProtector, 0, 1) \
F(RegExpSpeciesProtector, 0, 1)
#define FOR_EACH_INTRINSIC_TYPEDARRAY(F, I) \
@ -862,6 +863,8 @@ enum class OptimizationStatus {
kLiteMode = 1 << 12,
kMarkedForDeoptimization = 1 << 13,
kBaseline = 1 << 14,
kTopmostFrameIsInterpreted = 1 << 15,
kTopmostFrameIsBaseline = 1 << 16,
};
} // namespace internal

View File

@ -0,0 +1,51 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --sparkplug --no-always-sparkplug --use-osr
// Flags: --opt
function isExecutingBaseline(func) {
let opt_status = %GetOptimizationStatus(func);
return (opt_status & V8OptimizationStatus.kTopmostFrameIsBaseline) !== 0;
}
function f() {
for (var i = 0; i <= 20; i++) {
if (i == 5) {
%BaselineOsr();
}
if (i > 5) {
assertTrue(isBaseline(f));
assertTrue(isExecutingBaseline(f));
}
}
}
%NeverOptimizeFunction(f);
f();
var expectedStatus = V8OptimizationStatus.kTopmostFrameIsInterpreted;
function checkTopmostFrame(func) {
let opt_status = %GetOptimizationStatus(func);
assertTrue ((opt_status & expectedStatus) !== 0, "Expected flag " +
expectedStatus + " to be set in optimization status");
}
function g() {
for (var i = 0; i <= 20; i++) {
checkTopmostFrame(g)
if (i == 2) {
%BaselineOsr();
expectedStatus = V8OptimizationStatus.kTopmostFrameIsBaseline;
}
if (i == 5) {
%OptimizeOsr();
expectedStatus = V8OptimizationStatus.kTopmostFrameIsTurboFanned;
}
}
}
%PrepareFunctionForOptimization(g);
g();

View File

@ -176,6 +176,8 @@ var V8OptimizationStatus = {
kLiteMode: 1 << 12,
kMarkedForDeoptimization: 1 << 13,
kBaseline: 1 << 14,
kTopmostFrameIsInterpreted: 1 << 15,
kTopmostFrameIsBaseline: 1 << 16,
};
// Returns true if --lite-mode is on and we can't ever turn on optimization.