[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:
parent
7de9631d57
commit
5f49bbdf84
1
BUILD.gn
1
BUILD.gn
@ -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",
|
||||
|
1
src/DEPS
1
src/DEPS
@ -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",
|
||||
|
38
src/baseline/baseline-osr-inl.h
Normal file
38
src/baseline/baseline-osr-inl.h
Normal 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_
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
51
test/mjsunit/baseline/test-osr.js
Normal file
51
test/mjsunit/baseline/test-osr.js
Normal 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();
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user