[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) {
|
||||
if (V8_LIKELY(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);
|
||||
}
|
||||
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;
|
||||
|
@ -465,6 +465,7 @@ namespace internal {
|
||||
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) \
|
||||
@ -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