Commit 9f902b74 authored by Fanchen Kong's avatar Fanchen Kong Committed by V8 LUCI CQ

[turbofan] Making OSR concurrent

... to reduce compilation overhead on the main thread for OSR

Bug: v8:12161
Change-Id: I54ca5fa6201405daf92dac9cf51d5de4b46577b3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3369361Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Fanchen Kong <fanchen.kong@intel.com>
Cr-Commit-Position: refs/heads/main@{#79188}
parent 6573bce1
......@@ -163,11 +163,21 @@ class CompilerTracer : public AllStatic {
PrintF(scope.file(), "]\n");
}
static void TraceStartConcurrentOSRJob(Isolate* isolate,
Handle<JSFunction> function,
OptimizedCompilationInfo* info) {
if (!FLAG_trace_osr) return;
CodeTracer::Scope scope(isolate->GetCodeTracer());
PrintTracePrefix(scope, "OSR - Concurrent compiling: ", info);
PrintTraceSuffix(scope);
}
private:
static void PrintTracePrefix(const CodeTracer::Scope& scope,
const char* header,
OptimizedCompilationInfo* info) {
PrintTracePrefix(scope, header, info->closure(), info->code_kind());
PrintF(scope.file(), " osr target offset %d", info->osr_offset().ToInt());
}
static void PrintTracePrefix(const CodeTracer::Scope& scope,
......@@ -990,7 +1000,12 @@ bool GetOptimizedCodeLater(std::unique_ptr<OptimizedCompilationJob> job,
}
if (CodeKindIsStoredInOptimizedCodeCache(code_kind)) {
function->SetOptimizationMarker(OptimizationMarker::kInOptimizationQueue);
if (compilation_info->is_osr()) {
DCHECK(function->has_feedback_vector());
function->shared().set_osr_is_in_optimization_queue(true);
} else {
function->SetOptimizationMarker(OptimizationMarker::kInOptimizationQueue);
}
}
// Note: Usually the active tier is expected to be Ignition at this point (in
......@@ -1026,14 +1041,18 @@ MaybeHandle<CodeT> GetOptimizedCode(
CodeKind code_kind, BytecodeOffset osr_offset = BytecodeOffset::None(),
JavaScriptFrame* osr_frame = nullptr,
GetOptimizedCodeResultHandling result_handling =
GetOptimizedCodeResultHandling::kDefault) {
GetOptimizedCodeResultHandling::kDefault,
int osr_depth = AbstractCode::kNoLoopNestingLevelValue) {
DCHECK(CodeKindIsOptimizedJSFunction(code_kind));
Handle<SharedFunctionInfo> shared(function->shared(), isolate);
// Make sure we clear the optimization marker on the function so that we
// don't try to re-optimize.
if (function->HasOptimizationMarker()) function->ClearOptimizationMarker();
if (function->HasOptimizationMarker() &&
osr_offset == BytecodeOffset::None()) {
function->ClearOptimizationMarker();
}
if (shared->optimization_disabled() &&
shared->disabled_optimization_reason() == BailoutReason::kNeverOptimize) {
......@@ -1057,7 +1076,9 @@ MaybeHandle<CodeT> GetOptimizedCode(
}
// Check the optimized code cache (stored on the SharedFunctionInfo).
if (CodeKindIsStoredInOptimizedCodeCache(code_kind)) {
// For OSR, this is handled at GetOptimizedCodeForOSR.
if (CodeKindIsStoredInOptimizedCodeCache(code_kind) &&
osr_offset == BytecodeOffset::None()) {
Handle<CodeT> cached_code;
if (GetCodeFromOptimizedCodeCache(function, osr_offset, code_kind)
.ToHandle(&cached_code)) {
......@@ -1069,7 +1090,9 @@ MaybeHandle<CodeT> GetOptimizedCode(
// Reset profiler ticks, function is no longer considered hot.
DCHECK(shared->is_compiled());
function->feedback_vector().set_profiler_ticks(0);
if (osr_offset == BytecodeOffset::None()) {
function->feedback_vector().set_profiler_ticks(0);
}
VMState<COMPILER> state(isolate);
TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
......@@ -1095,6 +1118,16 @@ MaybeHandle<CodeT> GetOptimizedCode(
if (mode == ConcurrencyMode::kConcurrent) {
if (GetOptimizedCodeLater(std::move(job), isolate, compilation_info,
code_kind, function)) {
if (osr_offset != BytecodeOffset::None()) {
DCHECK(isolate->concurrent_osr_enabled());
compilation_info->set_osr_depth(osr_depth);
DCHECK(shared->osr_is_in_optimization_queue());
CompilerTracer::TraceStartConcurrentOSRJob(isolate, function,
compilation_info);
// Return empty handle when execution continues and concurrent
// optimization job for OSR has been started (but not finished).
return Handle<CodeT>();
}
return ContinuationForConcurrentOptimization(isolate, function);
}
} else {
......@@ -3204,13 +3237,40 @@ template Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
FunctionLiteral* literal, Handle<Script> script, LocalIsolate* isolate);
// static
MaybeHandle<CodeT> Compiler::GetOptimizedCodeForOSR(
Isolate* isolate, Handle<JSFunction> function, BytecodeOffset osr_offset,
JavaScriptFrame* osr_frame) {
MaybeHandle<CodeT> Compiler::GetOptimizedCodeForOSR(Isolate* isolate,
Handle<JSFunction> function,
BytecodeOffset osr_offset,
JavaScriptFrame* osr_frame,
int osr_depth) {
DCHECK(!osr_offset.IsNone());
DCHECK_NOT_NULL(osr_frame);
return GetOptimizedCode(isolate, function, ConcurrencyMode::kNotConcurrent,
CodeKindForOSR(), osr_offset, osr_frame);
DCHECK(0 <= osr_depth && osr_depth <= AbstractCode::kMaxLoopNestingMarker);
CodeKind code_kind = CodeKindForOSR();
// Check the optimized code cache.
if (CodeKindIsStoredInOptimizedCodeCache(code_kind)) {
Handle<CodeT> cached_code;
if (GetCodeFromOptimizedCodeCache(function, osr_offset, code_kind)
.ToHandle(&cached_code)) {
CompilerTracer::TraceOptimizedCodeCacheHit(isolate, function, osr_offset,
code_kind);
return cached_code;
}
}
if (isolate->concurrent_osr_enabled() &&
function->shared().osr_is_in_optimization_queue()) {
return {};
}
return GetOptimizedCode(
isolate, function,
isolate->concurrent_osr_enabled() && !isolate->bootstrapper()->IsActive()
? ConcurrencyMode::kConcurrent
: ConcurrencyMode::kNotConcurrent,
code_kind, osr_offset, osr_frame,
GetOptimizedCodeResultHandling::kDefault, osr_depth);
}
// static
......@@ -3229,7 +3289,7 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
const bool use_result = !compilation_info->discard_result_for_testing();
if (V8_LIKELY(use_result)) {
if (V8_LIKELY(use_result) && !compilation_info->is_osr()) {
// Reset profiler ticks, function is no longer considered hot.
compilation_info->closure()->feedback_vector().set_profiler_ticks(0);
}
......@@ -3252,9 +3312,21 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
if (V8_LIKELY(use_result)) {
InsertCodeIntoOptimizedCodeCache(compilation_info);
CompilerTracer::TraceCompletedJob(isolate, compilation_info);
compilation_info->closure()->set_code(*compilation_info->code(),
kReleaseStore);
if (!compilation_info->is_osr()) {
compilation_info->closure()->set_code(*compilation_info->code(),
kReleaseStore);
} else {
DCHECK(shared->osr_is_in_optimization_queue());
shared->set_osr_is_in_optimization_queue(false);
// Store new loop nesting level to trigger OSR and use the optimized
// code from OSROptimizedCodeCache during the later execution if
// bytecode offsets match.
int osr_depth = compilation_info->osr_depth();
shared->GetBytecodeArray(isolate).set_osr_loop_nesting_level(
std::min({osr_depth + 1, AbstractCode::kMaxLoopNestingMarker}));
}
}
return CompilationJob::SUCCEEDED;
}
}
......@@ -3268,6 +3340,9 @@ bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
compilation_info->closure()->ClearOptimizationMarker();
}
}
if (compilation_info->is_osr() && shared->osr_is_in_optimization_queue()) {
shared->set_osr_is_in_optimization_queue(false);
}
return CompilationJob::FAILED;
}
......
......@@ -236,7 +236,7 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
// Generate and return optimized code for OSR, or empty handle on failure.
V8_WARN_UNUSED_RESULT static MaybeHandle<CodeT> GetOptimizedCodeForOSR(
Isolate* isolate, Handle<JSFunction> function, BytecodeOffset osr_offset,
JavaScriptFrame* osr_frame);
JavaScriptFrame* osr_frame, int osr_depth);
};
// A base class for compilation jobs intended to run concurrent to the main
......
......@@ -241,6 +241,10 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
return std::move(canonical_handles_);
}
void set_osr_depth(int n) { osr_depth_ = n; }
int osr_depth() const { return osr_depth_; }
private:
void ConfigureFlags();
......@@ -312,6 +316,8 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
// handles above. The only difference is that is created in the
// CanonicalHandleScope(i.e step 1) is different).
std::unique_ptr<CanonicalHandlesMap> canonical_handles_;
int osr_depth_ = AbstractCode::kNoLoopNestingLevelValue;
};
} // namespace internal
......
......@@ -32,6 +32,9 @@ void DisposeCompilationJob(OptimizedCompilationJob* job,
if (function->IsInOptimizationQueue()) {
function->ClearOptimizationMarker();
}
if (job->compilation_info()->is_osr()) {
function->shared().set_osr_is_in_optimization_queue(false);
}
}
delete job;
}
......@@ -205,7 +208,7 @@ void OptimizingCompileDispatcher::InstallOptimizedFunctions() {
}
OptimizedCompilationInfo* info = job->compilation_info();
Handle<JSFunction> function(*info->closure(), isolate_);
if (function->HasAvailableCodeKind(info->code_kind())) {
if (function->HasAvailableCodeKind(info->code_kind()) && !info->is_osr()) {
if (FLAG_trace_concurrent_recompilation) {
PrintF(" ** Aborting compilation for ");
function->ShortPrint();
......
......@@ -453,6 +453,11 @@ void Deoptimizer::DeoptimizeFunction(JSFunction function, Code code) {
// this call from here.
OSROptimizedCodeCache::Compact(
Handle<NativeContext>(function.context().native_context(), isolate));
// Background compilation for OSR arm back edges at compilation finalization
// stage regardless of the active execution state (unoptimized/optimized).
// Reset osr_loop_nesting_level to avoid unwanted OSR from unoptimized frame
// after deoptimization.
function.shared().GetBytecodeArray(isolate).set_osr_loop_nesting_level(0);
}
}
......
......@@ -1468,13 +1468,17 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
return baseline_batch_compiler_;
}
bool concurrent_recompilation_enabled() {
bool concurrent_recompilation_enabled() const {
// Thread is only available with flag enabled.
DCHECK(optimizing_compile_dispatcher_ == nullptr ||
FLAG_concurrent_recompilation);
return optimizing_compile_dispatcher_ != nullptr;
}
bool concurrent_osr_enabled() const {
return concurrent_recompilation_enabled() && FLAG_concurrent_osr;
}
OptimizingCompileDispatcher* optimizing_compile_dispatcher() {
DCHECK_NOT_NULL(optimizing_compile_dispatcher_);
return optimizing_compile_dispatcher_;
......
......@@ -123,7 +123,6 @@ void TieringManager::MaybeOptimizeFrame(JSFunction function,
CodeKind code_kind) {
if (function.IsInOptimizationQueue()) {
TraceInOptimizationQueue(function);
return;
}
if (FLAG_testing_d8_test_runner &&
......@@ -155,6 +154,7 @@ void TieringManager::MaybeOptimizeFrame(JSFunction function,
}
bool TieringManager::MaybeOSR(JSFunction function, UnoptimizedFrame* frame) {
if (function.shared().osr_is_in_optimization_queue()) return false;
int ticks = function.feedback_vector().profiler_ticks();
if (function.IsMarkedForOptimization() ||
function.IsMarkedForConcurrentOptimization() ||
......@@ -181,9 +181,6 @@ bool ShouldOptimizeAsSmallFunction(int bytecode_size, bool any_ic_changed) {
OptimizationReason TieringManager::ShouldOptimize(JSFunction function,
BytecodeArray bytecode,
JavaScriptFrame* frame) {
if (function.ActiveTierIsTurbofan()) {
return OptimizationReason::kDoNotOptimize;
}
// If function's SFI has OSR cache, once enter loop range of OSR cache, set
// OSR loop nesting level for matching condition of OSR (loop_depth <
// osr_level), soon later OSR will be triggered when executing bytecode
......@@ -205,10 +202,18 @@ OptimizationReason TieringManager::ShouldOptimize(JSFunction function,
current_offset >= jump_target_offset) {
bytecode.set_osr_loop_nesting_level(iterator.GetImmediateOperand(1) +
1);
return OptimizationReason::kHotAndStable;
return function.ActiveTierIsTurbofan() ||
function.IsInOptimizationQueue()
? OptimizationReason::kDoNotOptimize
: OptimizationReason::kHotAndStable;
}
}
}
if (function.ActiveTierIsTurbofan() || function.HasOptimizationMarker()) {
return OptimizationReason::kDoNotOptimize;
}
const int ticks = function.feedback_vector().profiler_ticks();
const int ticks_for_optimization =
FLAG_ticks_before_optimization +
......
......@@ -553,6 +553,7 @@ DEFINE_BOOL(assert_types, false,
"generate runtime type assertions to test the typer")
// TODO(tebbi): Support allocating types from background thread.
DEFINE_NEG_IMPLICATION(assert_types, concurrent_recompilation)
DEFINE_NEG_IMPLICATION(assert_types, concurrent_osr)
DEFINE_BOOL(trace_compilation_dependencies, false, "trace code dependencies")
// Depend on --trace-deopt-verbose for reporting dependency invalidations.
......@@ -1544,6 +1545,8 @@ DEFINE_BOOL(always_opt, false, "always try to optimize functions")
DEFINE_IMPLICATION(always_opt, opt)
DEFINE_BOOL(always_osr, false, "always try to OSR functions")
DEFINE_BOOL(prepare_always_opt, false, "prepare for turning on always opt")
DEFINE_BOOL(concurrent_osr, true,
"compile turbofan optimized code for osr on background thread")
DEFINE_BOOL(trace_serializer, false, "print code serializer trace")
#ifdef DEBUG
......
......@@ -814,6 +814,8 @@ class AbstractCode : public HeapObject {
// nesting that is deeper than 5 levels into account.
static const int kMaxLoopNestingMarker = 6;
static const int kNoLoopNestingLevelValue = -1;
OBJECT_CONSTRUCTORS(AbstractCode, HeapObject);
private:
......
......@@ -261,6 +261,9 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2,
has_static_private_methods_or_accessors,
SharedFunctionInfo::HasStaticPrivateMethodsOrAccessorsBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, osr_is_in_optimization_queue,
SharedFunctionInfo::OsrIsInOptimizationQueueBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags, syntax_kind,
SharedFunctionInfo::FunctionSyntaxKindBits)
......
......@@ -492,6 +492,8 @@ class SharedFunctionInfo
// closest outer class scope.
DECL_BOOLEAN_ACCESSORS(private_name_lookup_skips_outer_class)
DECL_BOOLEAN_ACCESSORS(osr_is_in_optimization_queue)
inline FunctionKind kind() const;
// Defines the index in a native context of closure's map instantiated using
......
......@@ -44,6 +44,7 @@ bitfield struct SharedFunctionInfoFlags extends uint32 {
bitfield struct SharedFunctionInfoFlags2 extends uint8 {
class_scope_has_private_brand: bool: 1 bit;
has_static_private_methods_or_accessors: bool: 1 bit;
osr_is_in_optimization_queue: bool: 1 bit;
}
@generateBodyDescriptor
......
......@@ -19,6 +19,9 @@
#include "src/execution/v8threads.h"
#include "src/execution/vm-state-inl.h"
#include "src/heap/parked-scope.h"
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/interpreter.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/shared-function-info.h"
......@@ -236,7 +239,7 @@ static bool IsSuitableForOnStackReplacement(Isolate* isolate,
namespace {
BytecodeOffset DetermineEntryAndDisarmOSRForUnoptimized(
std::tuple<BytecodeOffset, int> DetermineEntryAndDisarmOSRForUnoptimized(
JavaScriptFrame* js_frame) {
UnoptimizedFrame* frame = reinterpret_cast<UnoptimizedFrame*>(js_frame);
......@@ -257,9 +260,15 @@ BytecodeOffset DetermineEntryAndDisarmOSRForUnoptimized(
// Reset the OSR loop nesting depth to disarm back edges.
bytecode->set_osr_loop_nesting_level(0);
// Read depth of loop from bytecode array
interpreter::BytecodeArrayIterator bytecode_iterator(
bytecode, frame->GetBytecodeOffset());
int osr_depth = bytecode_iterator.GetImmediateOperand(1);
// Return a BytecodeOffset representing the bytecode offset of the back
// branch.
return BytecodeOffset(frame->GetBytecodeOffset());
// branch and an int which is the loop depth of the corresponding bytecode
// offset.
return {BytecodeOffset(frame->GetBytecodeOffset()), osr_depth};
}
} // namespace
......@@ -278,7 +287,10 @@ RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
// Determine the entry point for which this OSR request has been fired and
// also disarm all back edges in the calling code to stop new requests.
BytecodeOffset osr_offset = DetermineEntryAndDisarmOSRForUnoptimized(frame);
BytecodeOffset osr_offset = BytecodeOffset::None();
int osr_depth = AbstractCode::kNoLoopNestingLevelValue;
std::tie(osr_offset, osr_depth) =
DetermineEntryAndDisarmOSRForUnoptimized(frame);
DCHECK(!osr_offset.IsNone());
MaybeHandle<CodeT> maybe_result;
......@@ -290,8 +302,11 @@ RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
function->PrintName(scope.file());
PrintF(scope.file(), " at OSR bytecode offset %d]\n", osr_offset.ToInt());
}
maybe_result =
Compiler::GetOptimizedCodeForOSR(isolate, function, osr_offset, frame);
// With concurrent osr enabled, GetOptimizedCodeForOSR only returns valid
// code at OSROptimizeCodeCache hit.
maybe_result = Compiler::GetOptimizedCodeForOSR(
isolate, function, osr_offset, frame, osr_depth);
}
// Check whether we ended up with usable optimized code.
......@@ -323,15 +338,18 @@ RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
// feedback. We cannot do this currently since we OSR only after we mark
// a function for optimization. We should instead change it to be based
// based on number of ticks.
DCHECK(!function->IsInOptimizationQueue());
function->ClearOptimizationMarker();
if (function->IsMarkedForOptimization() ||
function->IsMarkedForConcurrentOptimization()) {
function->ClearOptimizationMarker();
}
}
// TODO(mythria): Once we have OSR code cache we may not need to mark
// the function for non-concurrent compilation. We could arm the loops
// early so the second execution uses the already compiled OSR code and
// the optimization occurs concurrently off main thread.
if (!function->HasAvailableOptimizedCode() &&
function->feedback_vector().invocation_count() > 1) {
function->feedback_vector().invocation_count() > 1 &&
!function->IsInOptimizationQueue()) {
// If we're not already optimized, set to optimize non-concurrently on
// the next call, otherwise we'd run unoptimized once more and
// potentially compile for OSR again.
......@@ -344,6 +362,7 @@ RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
function->SetOptimizationMarker(
OptimizationMarker::kCompileTurbofan_NotConcurrent);
}
function->feedback_vector().set_profiler_ticks(0);
return *result;
}
}
......
......@@ -264,6 +264,17 @@ bool CanOptimizeFunction(Handle<JSFunction> function, Isolate* isolate,
return true;
}
ConcurrencyMode ConcurrencyModeFromString(Handle<Object> mode,
Isolate* isolate) {
if (mode->IsString() &&
Handle<String>::cast(mode)->IsOneByteEqualTo(
base::StaticCharVector("concurrent")) &&
isolate->concurrent_recompilation_enabled()) {
return ConcurrencyMode::kConcurrent;
}
return ConcurrencyMode::kNotConcurrent;
}
Object OptimizeFunctionOnNextCall(RuntimeArguments& args, Isolate* isolate,
TierupKind tierup_kind) {
if (args.length() != 1 && args.length() != 2) {
......@@ -285,11 +296,7 @@ Object OptimizeFunctionOnNextCall(RuntimeArguments& args, Isolate* isolate,
if (args.length() == 2) {
CONVERT_ARG_HANDLE_CHECKED(Object, type, 1);
if (!type->IsString()) return CrashUnlessFuzzing(isolate);
if (Handle<String>::cast(type)->IsOneByteEqualTo(
base::StaticCharVector("concurrent")) &&
isolate->concurrent_recompilation_enabled()) {
concurrency_mode = ConcurrencyMode::kConcurrent;
}
concurrency_mode = ConcurrencyModeFromString(type, isolate);
}
if (FLAG_trace_opt) {
PrintF("[manually marking ");
......@@ -343,6 +350,14 @@ bool EnsureFeedbackVector(Isolate* isolate, Handle<JSFunction> function) {
return true;
}
void FinalizeOptimization(Isolate* isolate) {
if (isolate->concurrent_recompilation_enabled()) {
isolate->optimizing_compile_dispatcher()->AwaitCompileTasks();
isolate->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
isolate->optimizing_compile_dispatcher()->set_finalize(true);
}
}
} // namespace
RUNTIME_FUNCTION(Runtime_CompileBaseline) {
......@@ -459,13 +474,13 @@ RUNTIME_FUNCTION(Runtime_OptimizeFunctionForTopTier) {
RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
HandleScope handle_scope(isolate);
DCHECK(args.length() == 0 || args.length() == 1);
DCHECK(args.length() == 0 || args.length() == 1 || args.length() == 2);
Handle<JSFunction> function;
// The optional parameter determines the frame being targeted.
// The first optional parameter determines the frame being targeted.
int stack_depth = 0;
if (args.length() == 1) {
if (args.length() >= 1) {
if (!args[0].IsSmi()) return CrashUnlessFuzzing(isolate);
stack_depth = args.smi_at(0);
}
......@@ -476,6 +491,21 @@ RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
if (!it.done()) function = handle(it.frame()->function(), isolate);
if (function.is_null()) return CrashUnlessFuzzing(isolate);
if (it.frame()->is_optimized()) {
return ReadOnlyRoots(isolate).undefined_value();
}
if (function->shared().osr_is_in_optimization_queue()) {
FinalizeOptimization(isolate);
return ReadOnlyRoots(isolate).undefined_value();
} else if (function->shared().osr_code_cache_state() !=
OSRCodeCacheStateOfSFI::kNotCached) {
isolate->tiering_manager()->AttemptOnStackReplacement(
UnoptimizedFrame::cast(it.frame()),
AbstractCode::kMaxLoopNestingMarker);
return ReadOnlyRoots(isolate).undefined_value();
}
if (!FLAG_opt) return ReadOnlyRoots(isolate).undefined_value();
if (!function->shared().allows_lazy_compilation()) {
......@@ -503,18 +533,33 @@ RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
return ReadOnlyRoots(isolate).undefined_value();
}
// Ensure that the function is marked for non-concurrent optimization, so that
// subsequent runs don't also optimize.
// The second parameter determines the concurrency mode.
ConcurrencyMode concurrency_mode = ConcurrencyMode::kNotConcurrent;
if (args.length() == 2) {
CONVERT_ARG_HANDLE_CHECKED(Object, type, 1);
if (!type->IsString()) return CrashUnlessFuzzing(isolate);
concurrency_mode = ConcurrencyModeFromString(type, isolate);
}
if (concurrency_mode == ConcurrencyMode::kNotConcurrent) {
CHECK(!isolate->concurrent_osr_enabled());
} else {
CHECK(isolate->concurrent_osr_enabled());
}
if (FLAG_trace_osr) {
CodeTracer::Scope scope(isolate->GetCodeTracer());
PrintF(scope.file(), "[OSR - OptimizeOsr marking ");
function->ShortPrint(scope.file());
PrintF(scope.file(), " for non-concurrent optimization]\n");
PrintF(scope.file(), " for %s optimization]\n",
concurrency_mode == ConcurrencyMode::kConcurrent ? "concurrent"
: "non-concurrent");
}
IsCompiledScope is_compiled_scope(
function->shared().is_compiled_scope(isolate));
JSFunction::EnsureFeedbackVector(function, &is_compiled_scope);
function->MarkForOptimization(ConcurrencyMode::kNotConcurrent);
function->MarkForOptimization(concurrency_mode);
// Make the profiler arm all back edges in unoptimized code.
if (it.frame()->is_unoptimized()) {
......@@ -672,11 +717,7 @@ RUNTIME_FUNCTION(Runtime_WaitForBackgroundOptimization) {
RUNTIME_FUNCTION(Runtime_FinalizeOptimization) {
DCHECK_EQ(0, args.length());
if (isolate->concurrent_recompilation_enabled()) {
isolate->optimizing_compile_dispatcher()->AwaitCompileTasks();
isolate->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
isolate->optimizing_compile_dispatcher()->set_finalize(true);
}
FinalizeOptimization(isolate);
return ReadOnlyRoots(isolate).undefined_value();
}
......
......@@ -28615,7 +28615,7 @@ TEST(FastApiStackSlot) {
" let foo = 128;"
" for (let i = 0; i < 100; ++i) {"
" let bar = true;"
" if (i == 10) %OptimizeOsr();"
" if (i == 10 || i == 11) %OptimizeOsr(0, \"concurrent\");"
" try { receiver.api_func(arg) } catch(_) {};"
" try { receiver.api_func(arg) } catch(_) {};"
" };"
......@@ -2376,7 +2376,7 @@ static const char* pre_profiling_osr_script = R"(
for (let pass = 0; pass <= optDuration + deoptDuration; pass++) {
const startTime = Date.now();
// Let a few passes go by to ensure we have enough feeback info
if (pass == 3) %OptimizeOsr();
if (pass == 3 || pass == 4) %OptimizeOsr(0, "concurrent");
// Force deoptimization. %DeoptimizeNow and %DeoptimizeFunction don't
// doptimize OSRs.
if (pass == optDuration) whenPass = () => {};
......
......@@ -271,6 +271,9 @@ class FastJSWasmCallTester {
i::FLAG_allow_natives_syntax = true;
i::FLAG_turbo_inline_js_wasm_calls = true;
i::FLAG_stress_background_compile = false;
// Disable concurrent osr to avoid background compilation after test has
// been finished.
i::FLAG_concurrent_osr = false;
}
void DeclareCallback(const char* name, FunctionSig* signature,
......
......@@ -31,7 +31,7 @@ function ChangeSmiConstantAndOsr() {
var j = 1;
for (var i = 0; i < 4; i++) {
if (i == 2) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
g();
}
}
......@@ -49,7 +49,7 @@ function ChangeFloatConstantAndOsr() {
var j = 0.1;
for (var i = 0; i < 4; i++) {
if (i == 2) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
g();
}
}
......@@ -68,7 +68,7 @@ function ChangeFloatVarAndOsr() {
for (var i = 0; i < 4; i++) {
j = j + 0.1;
if (i == 2) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
g();
}
}
......@@ -102,7 +102,7 @@ function ChangeIntVarAndOsr() {
for (var i = 0; i < 4; i++) {
j = j + 1|0;
if (i == 2) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
g();
}
}
......
......@@ -11,7 +11,7 @@ function f() {
const myObj = {};
for (let i = 0; i < 10; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%ScheduleBreak();
%PrepareFunctionForOptimization(f);
}
......
......@@ -8,7 +8,7 @@ Debug.setListener(function() {});
function f() {
for (var i = 0; i < 100; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f);
}
}
......
......@@ -17,7 +17,7 @@ function wrapper1() {
for (var i = 0; i < 4; i++) {
// Get this function optimized before calling to increment.
// Check that that call performs the necessary side-effect checks.
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(wrapper1);
}
f1();
......
// 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 --no-always-opt --deopt-every-n-times=0
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++) {
if (i == 6) {
let opt_status = %GetOptimizationStatus(g);
if ((V8OptimizationStatus.kTopmostFrameIsTurboFanned & opt_status) !== 0) {
console.log("quit for concurrent osr not enabled.");
testRunner.quit(0);
}
}
checkTopmostFrame(g)
if (i == 2) {
%BaselineOsr();
expectedStatus = V8OptimizationStatus.kTopmostFrameIsBaseline;
}
if (i == 5) {
%OptimizeOsr(0, "concurrent");
}
if (i == 6) {
%FinalizeOptimization();
expectedStatus = V8OptimizationStatus.kTopmostFrameIsTurboFanned;
}
}
}
%PrepareFunctionForOptimization(g);
g();
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Flags: --allow-natives-syntax --sparkplug --no-always-sparkplug --use-osr
// Flags: --opt --no-always-opt --deopt-every-n-times=0
// Flags: --opt --no-always-opt --deopt-every-n-times=0 --no-concurrent-osr
function isExecutingBaseline(func) {
let opt_status = %GetOptimizationStatus(func);
......
......@@ -53,7 +53,7 @@ function createSource(name, fillCnt) {
}
src +=
` if (i == 5) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PretenureAllocationSite(local_arr);
}
}
......
......@@ -262,7 +262,8 @@ function osr_inner(t, limit) {
if (t.hasOwnProperty(x)) {
for (var i = 0; i < t[x].length; i++) {
r += t[x][i];
if (i === limit) %OptimizeOsr();
if (i === limit) %OptimizeOsr(0, "concurrent");
%FinalizeOptimization();
}
r += x;
}
......@@ -278,7 +279,8 @@ function osr_outer(t, osr_after) {
for (var i = 0; i < t[x].length; i++) {
r += t[x][i];
}
if (x === osr_after) %OptimizeOsr();
if (x === osr_after) %OptimizeOsr(0, "concurrent");
%FinalizeOptimization();
r += x;
}
return r;
......@@ -289,7 +291,8 @@ function osr_outer_and_deopt(t, osr_after) {
var r = 1;
for (var x in t) {
r += x;
if (x == osr_after) %OptimizeOsr();
if (x == osr_after) %OptimizeOsr(0, "concurrent");
%FinalizeOptimization();
}
return r;
}
......
......@@ -34,7 +34,7 @@ function f1() {
var y = x + 5;
var z = y + 3;
sum += z;
if (i == 18) %OptimizeOsr();
if (i >= 18) %OptimizeOsr(0, "concurrent");
}
return sum;
}
......@@ -46,7 +46,7 @@ function f2() {
var y = x + 5;
var z = y + 3;
sum += z;
if (i == 19) %OptimizeOsr();
if (i >= 19) %OptimizeOsr(0, "concurrent");
}
return sum;
}
......@@ -58,7 +58,7 @@ function f3() {
var y = x + 5;
var z = y + 3;
sum += z;
if (i == 20) %OptimizeOsr();
if (i >= 20) %OptimizeOsr(0, "concurrent");
}
return sum;
}
......
......@@ -8,7 +8,7 @@ function f1() {
var sum = 0;
for (var i = 0; i < 1000; i++) {
sum += arguments[0] + arguments[1] + arguments[2] + arguments[3];
if (i == 18) %OptimizeOsr();
if (i == 18 || i == 19) %OptimizeOsr(0, "concurrent");
}
return sum;
}
......
......@@ -9,7 +9,7 @@ function fastaRandom(n, table) {
var line = new Array(5);
while (n > 0) {
if (n < line.length) line = new Array(n);
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
line[0] = n;
n--;
%PrepareFunctionForOptimization(fastaRandom);
......
......@@ -34,8 +34,8 @@ function f(x, b, c) {
a = a + 5;
assertEquals(b + 1, c);
outer--;
if (outer === 5) {
%OptimizeOsr();
if (outer === 5 || outer === 4) {
%OptimizeOsr(0, "concurrent");
}
}
return a + 4;
......
......@@ -15,7 +15,7 @@ function foo(a) {
if (i == 5) { i = 6; continue; }
if (i == 6) { i = 7; continue; }
if (i == 7) { i = 8; continue; }
for (var j = 0; j < 10; j++) { if (i == 5) %OptimizeOsr(); }
for (var j = 0; j < 10; j++) { if (i == 5) %OptimizeOsr(0, "concurrent"); }
break;
}
return j;
......
......@@ -11,7 +11,7 @@ function foo() {
{
let sum = 0;
for (var i = 0; i < 100; i++) {
if (i == 50) %OptimizeOsr();
if (i == 50 || i == 51) %OptimizeOsr(0, "concurrent");
sum += i;
}
result = ret;
......
......@@ -14,7 +14,7 @@ function foo() {
for (var i = 0; i < 10; i++) {
{
let x = i;
if (i == 5) %OptimizeOsr();
if (i == 5 || i == 6) %OptimizeOsr(0, "concurrent");
sum += i;
result.push(function() { return x; });
}
......
......@@ -51,7 +51,7 @@ function foo() {
{
let sum = 0;
for (var i = 0; i < 10; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
sum += i;
%PrepareFunctionForOptimization(foo);
}
......@@ -66,7 +66,7 @@ test(45, foo);
function bar() {
let sum = 0;
for (var i = 0; i < 10; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
sum += i;
%PrepareFunctionForOptimization(bar);
}
......@@ -80,7 +80,7 @@ function bon() {
{
let sum = 0;
for (var i = 0; i < 10; i++) {
if (i == 5) %OptimizeOsr();
if (i == 5) %OptimizeOsr(0, "concurrent");
sum += i;
}
return sum;
......@@ -96,7 +96,7 @@ function row() {
let sum = 0;
while (true) {
if (i == 8) return sum;
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
sum = i;
i = i + 1 | 0;
%PrepareFunctionForOptimization(row);
......@@ -111,7 +111,7 @@ test(7, row);
function nub() {
let i = 0;
while (i < 2) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
i++;
%PrepareFunctionForOptimization(nub);
}
......@@ -126,7 +126,7 @@ function kub() {
let i = 0;
while (i < 2) {
let x = i;
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
i++;
result = x;
%PrepareFunctionForOptimization(kub);
......
......@@ -21,7 +21,7 @@ function bar() {
let sum = 0;
for (let i = 0; i < 90; i++) {
sum += i;
if (i == 45) %OptimizeOsr();
if (i == 45 || i == 46) %OptimizeOsr(0, "concurrent");
}
result = sum;
}
......@@ -33,10 +33,10 @@ test(4005, bar);
function baz() {
let sum = 0;
for (let i = 0; i < 2; i++) {
for (let i = 0; i < 3; i++) {
%PrepareFunctionForOptimization(baz);
sum = 2;
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
}
return sum;
}
......@@ -45,30 +45,30 @@ test(2, baz);
function qux() {
var result = 0;
for (let i = 0; i < 2; i++) {
for (let i = 0; i < 3; i++) {
%PrepareFunctionForOptimization(qux);
result = i;
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
}
return result;
}
test(1, qux);
test(2, qux);
function nux() {
var result = 0;
for (let i = 0; i < 2; i++) {
for (let i = 0; i < 3; i++) {
{
%PrepareFunctionForOptimization(nux);
let sum = i;
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
result = sum;
}
}
return result;
}
test(1, nux);
test(2, nux);
function blo() {
var result;
......@@ -76,7 +76,7 @@ function blo() {
let sum = 0;
for (let i = 0; i < 90; i++) {
sum += i;
if (i == 45) %OptimizeOsr();
if (i == 45 || i == 46) %OptimizeOsr(0, "concurrent");
}
result = ret;
function ret() {
......
......@@ -12,8 +12,8 @@ function test(e, f, v) {
function foo(t) {
for (var x in t) {
for (var i = 0; i < 2; i++) {
%OptimizeOsr();
for (var i = 0; i < 3; i++) {
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(foo);
}
}
......@@ -26,8 +26,8 @@ test(5, foo, {x:20});
function bar(t) {
var sum = 0;
for (var x in t) {
for (var i = 0; i < 2; i++) {
%OptimizeOsr();
for (var i = 0; i < 3; i++) {
%OptimizeOsr(0, "concurrent");
sum += t[x];
%PrepareFunctionForOptimization(bar);
}
......@@ -36,4 +36,4 @@ function bar(t) {
}
%PrepareFunctionForOptimization(bar);
test(62, bar, {x:20,y:11});
test(93, bar, {x:20,y:11});
......@@ -8,7 +8,7 @@ var global_counter = 0;
function thrower() {
var x = global_counter++;
if (x == 5) %OptimizeOsr(1);
if (x == 5 || x == 6) %OptimizeOsr(1, "concurrent");
if (x == 10) throw "terminate";
}
......
......@@ -10,7 +10,7 @@ function foo() {
B: for (var j = 0; j < 5; j++) {
%PrepareFunctionForOptimization(foo);
C: for (var k = 0; k < 10; k++) {
if (k === 5) %OptimizeOsr();
if (k === 4 || k === 5) %OptimizeOsr(0, "concurrent");
if (k === 6) break B;
sum++;
}
......@@ -30,7 +30,7 @@ function bar(a) {
%PrepareFunctionForOptimization(bar);
C: for (var k = 0; k < 10; k++) {
sum++;
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
if (a === 1) break A;
if (a === 2) break B;
if (a === 3) break C;
......
......@@ -7,7 +7,7 @@
function mod() {
function f0() {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f0);
}
return {blah: i};
......@@ -16,7 +16,7 @@ function mod() {
function f1(a) {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f1);
}
return {blah: i};
......@@ -25,7 +25,7 @@ function mod() {
function f2(a,b) {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f2);
}
return {blah: i};
......@@ -34,7 +34,7 @@ function mod() {
function f3(a,b,c) {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f3);
}
return {blah: i};
......@@ -43,7 +43,7 @@ function mod() {
function f4(a,b,c,d) {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f4);
}
return {blah: i};
......
......@@ -6,8 +6,8 @@
function mod() {
function f0() {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
for (var i = 0; i < 4; i = i + 1 | 0) {
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f0);
}
return {blah: i};
......@@ -15,8 +15,8 @@ function mod() {
%PrepareFunctionForOptimization(f0);
function f1(a) {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
for (var i = 0; i < 4; i = i + 1 | 0) {
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f1);
}
return {blah: i};
......@@ -24,8 +24,8 @@ function mod() {
%PrepareFunctionForOptimization(f1);
function f2(a,b) {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
for (var i = 0; i < 4; i = i + 1 | 0) {
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f2);
}
return {blah: i};
......@@ -33,8 +33,8 @@ function mod() {
%PrepareFunctionForOptimization(f2);
function f3(a,b,c) {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
for (var i = 0; i < 4; i = i + 1 | 0) {
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f3);
}
return {blah: i};
......@@ -42,8 +42,8 @@ function mod() {
%PrepareFunctionForOptimization(f3);
function f4(a,b,c,d) {
for (var i = 0; i < 3; i = i + 1 | 0) {
%OptimizeOsr();
for (var i = 0; i < 4; i = i + 1 | 0) {
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f4);
}
return {blah: i};
......@@ -51,11 +51,11 @@ function mod() {
%PrepareFunctionForOptimization(f4);
function bar() {
assertEquals(3, f0().blah);
assertEquals(3, f1(1).blah);
assertEquals(3, f2(1,2).blah);
assertEquals(3, f3(1,2,3).blah);
assertEquals(3, f4(1,2,3,4).blah);
assertEquals(4, f0().blah);
assertEquals(4, f1(1).blah);
assertEquals(4, f2(1,2).blah);
assertEquals(4, f3(1,2,3).blah);
assertEquals(4, f4(1,2,3,4).blah);
}
bar();
}
......
......@@ -9,7 +9,7 @@ var counter = 111;
function gen(w) { // defeat compiler cache.
var num = counter++;
var Z = [ "", "", "", ];
Z[w] = "%OptimizeOsr(); %PrepareFunctionForOptimization(f" + num + ")";
Z[w] = "%OptimizeOsr(0, \"concurrent\"); %PrepareFunctionForOptimization(f" + num + ")";
var src =
"function f" + num + "(a,b,c) {" +
" var x = 0;" +
......
......@@ -9,7 +9,7 @@ var counter = 188;
function gen(w) { // defeat compiler cache.
var num = counter++;
var Z = [ "", "", "", ];
Z[w] = "%OptimizeOsr(); %PrepareFunctionForOptimization(f" + num + ")";
Z[w] = "%OptimizeOsr(0, \"concurrent\"); %PrepareFunctionForOptimization(f" + num + ")";
var src =
"function f" + num + "(a,b,c) {" +
" var x = 0;" +
......
......@@ -10,43 +10,43 @@ function bar(goal) {
var i = 35;
%PrepareFunctionForOptimization(bar);
while (i-- > 33) {
if (count++ == goal) %OptimizeOsr();
if (count++ == goal || count == goal + 1) %OptimizeOsr(0, "concurrent");
sum = sum + i;
}
%PrepareFunctionForOptimization(bar);
while (i-- > 31) {
if (count++ == goal) %OptimizeOsr();
if (count++ == goal || count == goal + 1) %OptimizeOsr(0, "concurrent");
j = 9;
%PrepareFunctionForOptimization(bar);
while (j-- > 7) {
if (count++ == goal) %OptimizeOsr();
if (count++ == goal || count == goal + 1) %OptimizeOsr(0, "concurrent");
sum = sum + j * 3;
}
%PrepareFunctionForOptimization(bar);
while (j-- > 5) {
if (count++ == goal) %OptimizeOsr();
if (count++ == goal || count == goal + 1) %OptimizeOsr(0, "concurrent");
sum = sum + j * 5;
}
}
while (i-- > 29) {
%PrepareFunctionForOptimization(bar);
if (count++ == goal) %OptimizeOsr();
if (count++ == goal || count == goal + 1) %OptimizeOsr(0, "concurrent");
while (j-- > 3) {
var k = 10;
%PrepareFunctionForOptimization(bar);
if (count++ == goal) %OptimizeOsr();
if (count++ == goal || count == goal + 1) %OptimizeOsr(0, "concurrent");
while (k-- > 8) {
%PrepareFunctionForOptimization(bar);
if (count++ == goal) %OptimizeOsr();
if (count++ == goal || count == goal + 1) %OptimizeOsr(0, "concurrent");
sum = sum + k * 11;
}
}
while (j-- > 1) {
%PrepareFunctionForOptimization(bar);
if (count++ == goal) %OptimizeOsr();
if (count++ == goal || count == goal + 1) %OptimizeOsr(0, "concurrent");
while (k-- > 6) {
%PrepareFunctionForOptimization(bar);
if (count++ == goal) %OptimizeOsr();
if (count++ == goal || count == goal + 1) %OptimizeOsr(0, "concurrent");
sum = sum + j * 13;
}
}
......
......@@ -51,7 +51,7 @@ function gen(i) {
body = body.replace(new RegExp("bar"), "bar" + i);
for (var j = 1; j < 10; j++) {
var r = new RegExp("LOOP" + j + "\\(\\);");
if (i == j) body = body.replace(r, "%OptimizeOsr(); %PrepareFunctionForOptimization(bar" + i +");");
if (i == j || i == j + 1) body = body.replace(r, "%OptimizeOsr(0, \"concurrent\"); %PrepareFunctionForOptimization(bar" + i +");");
else body = body.replace(r, "");
}
return eval("(" + body + ")");
......
......@@ -36,7 +36,7 @@ function f() {
var y = x + 5;
var z = y + 3;
sum += z;
if (j == 5) %OptimizeOsr();
if (j == 5 || j == 6) %OptimizeOsr(0, "concurrent");
}
}
return sum;
......
......@@ -12,7 +12,7 @@ function f() {
var y = x + 5;
var z = y + 3;
sum += z;
if (i == 21) %OptimizeOsr();
if (i == 21) %OptimizeOsr(0, "concurrent");
}
}
return sum;
......
......@@ -12,7 +12,7 @@ function f() {
var y = x + 5;
var z = y + 3;
sum += z;
if (i == 25) %OptimizeOsr();
if (i == 25) %OptimizeOsr(0, "concurrent");
}
if (true) break;
}
......
......@@ -13,7 +13,7 @@ function f() {
var y = x + 5;
var z = y + 3;
sum += z;
if (i == 19) %OptimizeOsr();
if (i == 19) %OptimizeOsr(0, "concurrent");
}
}
}
......
......@@ -13,7 +13,7 @@ function f() {
var y = x + 5;
var z = y + 3;
sum += z;
if (i == 25) %OptimizeOsr();
if (i == 25) %OptimizeOsr(0, "concurrent");
}
if (true) break;
}
......
......@@ -10,8 +10,8 @@ function f(x) {
while (count > 0) {
sum += x;
count--;
if (count == 5) {
%OptimizeOsr();
if (count == 5 || count == 4) {
%OptimizeOsr(0, "concurrent");
}
}
return sum;
......
......@@ -9,7 +9,7 @@ function id(f) { return f; }
function foo(a) {
var r = /\0/;
for (var i = 0; i < 10; i++) {
if (a) %OptimizeOsr();
if (a) %OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(foo);
}
return r;
......@@ -18,7 +18,7 @@ function foo(a) {
function bar(a) {
for (var i = 0; i < 10; i++) {
if (a) %OptimizeOsr();
if (a) %OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(bar);
var r = /\0/;
}
......@@ -28,7 +28,7 @@ function bar(a) {
function baz(a) {
for (var i = 0; i < 10; i++) {
if (a) %OptimizeOsr();
if (a) %OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(baz);
}
return /\0/;
......@@ -38,7 +38,7 @@ function baz(a) {
function qux(a) {
for (var i = 0; i < 10; i++) {
if (i > 5 && a) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(qux);
} else {
var r = /\0/;
......
......@@ -11,7 +11,7 @@ function f() {
var y = x + 5;
var z = y + 3;
sum += z;
if (i == 11) %OptimizeOsr();
if (i == 11 || i == 12) %OptimizeOsr(0, "concurrent");
}
return sum;
}
......
......@@ -7,7 +7,7 @@
function f() {
var sum = 0;
for (var i = 0; i < 10000; i++) {
if (i == 100) %OptimizeOsr();
if (i == 100 || i == 101) %OptimizeOsr(0, "concurrent");
var x = i + 2;
var y = x + 5;
var z = y + 3;
......
......@@ -8,7 +8,7 @@ function f() {
for (var j = 0; j < 3; j++) {
var sum = 0;
for (var i = 0; i < 1000; i++) {
if (i == 100) %OptimizeOsr();
if (i == 100 || i == 101) %OptimizeOsr(0, "concurrent");
var x = i + 2;
var y = x + 5;
var z = y + 3;
......
......@@ -9,7 +9,7 @@ function f() {
for (var j = 0; j < 3; j++) {
var sum = 0;
for (var i = 0; i < 1000; i++) {
if (i == 100) %OptimizeOsr();
if (i == 100 || i == 101) %OptimizeOsr(0, "concurrent");
var x = i + 2;
var y = x + 5;
var z = y + 3;
......
......@@ -14,8 +14,8 @@ function SingleLoop() {
for (var a = 0; a < 2; a++) {
try { throw 'The exception should have been caught.'; }
catch(e) {}
for (var b = 0; b < 1; b++) {
%OptimizeOsr();
for (var b = 0; b < 2; b++) {
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(SingleLoop);
}
}
......@@ -33,10 +33,10 @@ function EmptyBody() {
try {; } catch(e) {; }
var a = 0;
while (1) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
print("foo");
if (a == 1) break;
if (a == 2) break;
a++;
%PrepareFunctionForOptimization(EmptyBody);
}
......@@ -46,12 +46,12 @@ function EmptyBody() {
function NestedLoops() {
for (var a = 0; a < 2; a++) {
try {; } catch(e) {; }
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
var b = 0;
while (1) {
print("bar");
if (b == 1) break;
if (b == 2) break;
b++;
}
%PrepareFunctionForOptimization(NestedLoops);
......
......@@ -12,8 +12,8 @@ function f(x) {
while (inner > 0) {
sum += x;
inner--;
if (inner == 5) {
%OptimizeOsr();
if (inner == 5 || inner == 4) {
%OptimizeOsr(0, "concurrent");
}
}
outer--;
......
......@@ -25,7 +25,7 @@ function foo() {
var flag = 1;
for (; flag == 1; (flag = 0, temp_x = x)) {
if (x < 2) {
result = x; %OptimizeOsr();
result = x; %OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(foo);
} else {
break outer;
......@@ -48,7 +48,7 @@ function smo() {
outer: while (true) {
let y = x;
for (var i = 0; i < 5; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(smo);
if (i) break outer;
else result = y;
......
......@@ -11,7 +11,7 @@
for (var x in a) {
try {
for (var i = 0; i < 10; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(g);
}
return;
......@@ -32,7 +32,7 @@
for (var x in a) {
if (x) {
for (var i = 0; i < 10; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(g);
}
}
......
......@@ -9,7 +9,7 @@ function f() {
while (1) {
for (var j = 0; j < 200; j -= j) {
sum = sum + 1;
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
if (sum == 2) return;
%PrepareFunctionForOptimization(f);
}
......
......@@ -8,7 +8,7 @@ function f() {
var x = 0;
for (var i = 0; i < 10; i++) {
x = (2 % x) | 0;
if (i === 5) %OptimizeOsr();
if (i === 5 || i === 6) %OptimizeOsr(0, "concurrent");
}
return x;
}
......
......@@ -8,8 +8,8 @@
"use asm";
var f = function() {
for (var i = 0; i < 10; i++) {
if (i == 5) {
%OptimizeOsr();
if (i == 5 || i == 6) {
%OptimizeOsr(0, "concurrent");
}
}
with (Object());
......
......@@ -8,7 +8,7 @@ function f() {
var accumulator = false;
for (var i = 0; i < 4; i++) {
accumulator = accumulator.hasOwnProperty(3);
if (i === 1) %OptimizeOsr();
if (i === 1 || i === 2) %OptimizeOsr(0, "concurrent");
}
}
......
......@@ -5,8 +5,8 @@
// Flags: --allow-natives-syntax
function foo() {
for (var a = 0; a < 2; a++) {
if (a === 1) %OptimizeOsr();
for (var a = 0; a < 3; a++) {
if (a === 1 || a === 2) %OptimizeOsr(0, "concurrent");
while (0 && 1) {
for (var j = 1; j < 2; j++) { }
}
......
......@@ -7,7 +7,7 @@
function f(get, ...a) {
for (let i = 0; i < 1000; i++) {
if (i === 999) %OptimizeOsr();
if (i === 998 || i === 999) %OptimizeOsr(0, "concurrent");
a.map(f);
}
return get();
......
......@@ -6,7 +6,7 @@
function OSRInsideTry(x) {
try {
for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); }
for (var i = 0; i < 10; i++) { if (i > 5) %OptimizeOsr(0, "concurrent"); }
throw x;
} catch (e) {
return e + 1;
......@@ -21,7 +21,7 @@ function OSRInsideCatch(x) {
try {
throw x;
} catch (e) {
for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); }
for (var i = 0; i < 10; i++) { if (i > 5) %OptimizeOsr(0, "concurrent"); }
return e + 1;
}
return x + 2;
......@@ -34,7 +34,7 @@ function OSRInsideFinally_Return(x) {
try {
throw x;
} finally {
for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); }
for (var i = 0; i < 10; i++) { if (i > 5) %OptimizeOsr(0, "concurrent"); }
return x + 1;
}
return x + 2;
......@@ -47,7 +47,7 @@ function OSRInsideFinally_ReThrow(x) {
try {
throw x;
} finally {
for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); }
for (var i = 0; i < 10; i++) { if (i > 5) %OptimizeOsr(0, "concurrent"); }
}
return x + 2;
}
......
......@@ -6,7 +6,7 @@
function f() {
for (var i = 0; i < 10; i++) {
if (i == 5) %OptimizeOsr();
if (i == 5 || i == 6) %OptimizeOsr(0, "concurrent");
}
}
%PrepareFunctionForOptimization(f);
......
......@@ -7,7 +7,7 @@
(function TestGeneratorOSRSimple() {
function* gen1() {
for (var i = 0; i < 3; ++i) {
if (i == 1) %OptimizeOsr();
if (i >= 1) %OptimizeOsr(0, "concurrent");
}
return 23;
}
......@@ -19,7 +19,10 @@
(function TestGeneratorOSRYieldAfterArming() {
function* gen2() {
for (var i = 0; i < 3; ++i) {
if (i == 1) %OptimizeOsr();
if (i == 1 || i == 2) {
%PrepareFunctionForOptimization(gen2);
%OptimizeOsr(0, "concurrent");
}
yield i;
}
return 23;
......@@ -36,7 +39,7 @@
function* gen3() {
for (var i = 0; i < 3; ++i) {
yield i;
if (i == 1) %OptimizeOsr();
if (i >= 1) %OptimizeOsr(0, "concurrent");
}
return 23;
}
......@@ -53,7 +56,7 @@
for (var i = 0; i < 3; ++i) {
for (var j = 0; j < 3; ++j) {
for (var k = 0; k < 10; ++k) {
if (k == 5) %OptimizeOsr();
if (k == 5 || k == 6) %OptimizeOsr(0, "concurrent");
}
%PrepareFunctionForOptimization(gen4);
}
......
......@@ -92,7 +92,7 @@ function test_osr_elements_kind() {
%NeverOptimizeFunction(construct_smis);
%NeverOptimizeFunction(construct_doubles);
%NeverOptimizeFunction(convert_mixed);
for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); }
for (var i = 0; i < 10; i++) { if (i == 5 || i == 6) %OptimizeOsr(0, "concurrent"); }
// This code exists to eliminate the learning influence of AllocationSites
// on the following tests.
......
......@@ -33,7 +33,7 @@
var dummy = deopt + 0;
for (var i = 0; osr && i < 2; i++) {
%PrepareFunctionForOptimization(f);
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
}
return result;
}
......
......@@ -33,7 +33,7 @@ function f(deopt, osr) {
var dummy = deopt + 0;
for (var i = 0; osr && i < 2; i++) {
%PrepareFunctionForOptimization(f);
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
}
return result;
}
......
......@@ -15,7 +15,7 @@ function v0() {
function v1() {
while (!v0()) {
// Trigger OSR early to get a crashing case asap.
if (ticks == 5) %OptimizeOsr();
if (ticks >= 5 && ticks < 10) %OptimizeOsr(0, "concurrent");
// With the bug fixed, there's no easy way to trigger termination. Instead,
// run until we reach a certain number of ticks. The crash triggers locally
// at tick 7562, thus running until 20k ticks to be somewhat safe.
......
......@@ -47,7 +47,7 @@ function g() { try { return o.f(); } finally { }}
// This function should be optimized via OSR.
function h() {
for (var i = 0; i < 10; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(h);
}
g();
......
......@@ -18,8 +18,8 @@ function foo () {
l = 0;
break;
case 0:
if (cnt++ == 5) {
%OptimizeOsr();
if (cnt++ == 5 || cnt == 6) {
%OptimizeOsr(0, "concurrent");
l = 1;
}
break;
......
......@@ -39,7 +39,7 @@ function f() {
do {
do {
for (var i = 0; i < 10; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f);
}
// Note: this check can't be wrapped in a function, because
......@@ -74,7 +74,7 @@ function g() {
do {
do {
for (var i = 0; i < 10; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(g);
}
var opt_status = %GetOptimizationStatus(g);
......
......@@ -11,7 +11,7 @@ function Cb(a, trigger) {
// This will fail after OSR if Runtime_StringCharCodeAt is modified
// to iterates optimized frames and visit safepoint pointers.
if (g == "C".charCodeAt(0)) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(Cb);
}
}
......@@ -24,7 +24,7 @@ var s2 = "long string to make cons string 2";
Cb(s1 + s2);
%PrepareFunctionForOptimization(Cb);
Cb(s1);
var s3 = "string for triggering osr in Cb";
var s3 = "string for triggering osr in CCb";
%PrepareFunctionForOptimization(Cb);
Cb(s3 + s3);
%PrepareFunctionForOptimization(Cb);
......
......@@ -28,7 +28,7 @@
// Flags: --allow-natives-syntax
function f() {
for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); }
for (var i = 0; i < 10; i++) { if (i == 5 || i == 6) %OptimizeOsr(0, "concurrent"); }
var xl = 4096;
var z = i % xl;
}
......
......@@ -7,7 +7,7 @@
function foo(obj) {
var counter = 1;
for (var i = 0; i < obj.length; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(foo);
}
counter += obj;
......
......@@ -7,7 +7,7 @@
(function TestNonLoopyLoop() {
function f() {
do {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
return 23;
} while(false)
}
......@@ -20,7 +20,7 @@
(function TestNonLoopyGenerator() {
function* g() {
do {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
yield 23;
yield 42;
} while(false)
......
......@@ -10,7 +10,7 @@ function boom(o) { o.g = h }
function f(osr_and_recurse) {
if (osr_and_recurse) {
for (var i = 0; i < 3; ++i) {
if (i == 1) %OptimizeOsr();
if (i >= 1) %OptimizeOsr(0, "concurrent");
}
%PrepareFunctionForOptimization(f);
%OptimizeFunctionOnNextCall(f);
......
......@@ -10,7 +10,7 @@ var f = (function() {
"use asm";
return function g(c1, c2) {
for (var x = 0 ; x < 10; ++x) {
if (x == 5) %OptimizeOsr();
if (x == 5 || x == 6) %OptimizeOsr(0, "concurrent");
c1();
}
}
......
......@@ -6,8 +6,8 @@
function f() {
var C = class {};
for (var i = 0; i < 4; ++i) {
if (i == 2) %OptimizeOsr();
for (var i = 0; i < 5; ++i) {
if (i >= 2) %OptimizeOsr(0, "concurrent");
C.prototype.foo = 42;
}
}
......
......@@ -8,7 +8,10 @@ function f() {
C = class {};
for (var i = 0; i < 5; ++i) {
gc();
if (i == 2) %OptimizeOsr();
if (i == 2 || i == 3) {
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(f);
}
C.prototype.foo = i + 9000000000000000;
}
}
......
......@@ -4,4 +4,4 @@
//
// Flags: --allow-natives-syntax --fuzzing --no-testing-d8-test-runner
[1,2,3].reduceRight(() => { %OptimizeOsr(1); });
[1,2,3].reduceRight(() => { %OptimizeOsr(1, "concurrent"); });
......@@ -47,7 +47,7 @@
function outer() {
inner(1,2,3);
for (var i = 0; i < 3; i++) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(outer);
}
}
......
......@@ -12,7 +12,7 @@ function f() {
function g() {
for (var i = 0; i < 300; i++) {
f();
if (i == 150) %OptimizeOsr();
if (i == 150 || i == 151) %OptimizeOsr(0, "concurrent");
}
}
%PrepareFunctionForOptimization(g);
......@@ -10,8 +10,8 @@ function foo() {
for (var a = 1; a > 0; a--) {
c += 1;
}
for (var b = 1; b > 0; b--) {
%OptimizeOsr();
for (var b = 2; b > 0; b--) {
%OptimizeOsr(0, "concurrent");
}
}
return c;
......
......@@ -10,10 +10,10 @@
function makeFun() {
function fun(osr_fuse) {
for (var i = 0; i < 3; ++i) {
if (i == osr_fuse) %OptimizeOsr();
if (i >= osr_fuse) %OptimizeOsr(0, "concurrent");
}
for (var i = 3; i < 6; ++i) {
if (i == osr_fuse) %OptimizeOsr();
if (i >= osr_fuse) %OptimizeOsr(0, "concurrent");
}
}
%PrepareFunctionForOptimization(fun);
......
......@@ -8,7 +8,7 @@ var body =
"function bar1( ) {" +
" var i = 35; " +
" while (i-- > 31) {" +
" %OptimizeOsr(); " +
" %OptimizeOsr(0, \"concurrent\"); " +
" j = 9; " +
" %PrepareFunctionForOptimization(bar1); " +
" while (j-- > 7);" +
......
......@@ -5,7 +5,7 @@
// Flags: --allow-natives-syntax --expose-gc --no-lazy
function f() {
for (var i = 0; i < 10; i++) if (i == 5) %OptimizeOsr();
for (var i = 0; i < 10; i++) if (i == 5 || i == 6) %OptimizeOsr(0, "concurrent");
function g() {}
%PrepareFunctionForOptimization(g);
%OptimizeFunctionOnNextCall(g);
......
......@@ -10,7 +10,7 @@ function A() {
}
%EnsureFeedbackVectorForFunction(A);
function foo() {
for (var i = 0; i < 1; i = 2) %OptimizeOsr();
for (var i = 0; i < 2; i++) %OptimizeOsr(0, "concurrent");
return new A();
}
%PrepareFunctionForOptimization(foo);
......
......@@ -7,7 +7,10 @@
function f() {
for (var i = 0; i < 3; ++i) {
if (i == 1) {
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
}
if (i == 2) {
%OptimizeOsr(0, "concurrent");
break; // Trigger next loop.
}
}
......
......@@ -12,7 +12,7 @@ function f() {
function g() {
try { f(); } catch(e) { }
%PrepareFunctionForOptimization(g);
for (var i = 0; i < 3; ++i) if (i === 1) %OptimizeOsr();
for (var i = 0; i < 3; ++i) %OptimizeOsr(0, "concurrent");
%_DeoptimizeNow();
}
%PrepareFunctionForOptimization(g);
......
......@@ -9,7 +9,7 @@ function f() {
for (var i = 0; i < 4; ++i) {
var x = a[0];
(function() { return x });
if (i == 1) %OptimizeOsr();
if (i == 1 || i == 2) %OptimizeOsr(0, "concurrent");
gc();
}
}
......
......@@ -10,8 +10,8 @@ function g() {
function f() {
var result = "R:";
for (var i = 0; i < 3; ++i) {
if (i == 1) %OptimizeOsr();
for (var i = 0; i < 4; ++i) {
if (i == 1 || i == 2) %OptimizeOsr(0, "concurrent");
result += g([1])[0];
result += g([2])[0];
}
......@@ -19,4 +19,4 @@ function f() {
}
%PrepareFunctionForOptimization(f);
assertEquals("R:121212", f());
assertEquals("R:12121212", f());
......@@ -15,7 +15,7 @@
// elided.
with(f&&g&&(s()=N)({...g})){}
} catch {}
%OptimizeOsr();
%OptimizeOsr(0, "concurrent");
}
}
%EnsureFeedbackVectorForFunction(f);
......
......@@ -12,7 +12,7 @@
for (let i = 0; i < 5; ++i) {
a--; // Make sure {a} is non-immutable, hence context allocated.
function g() { return i } // Make sure block has a context.
if (i == 2) %OptimizeOsr();
if (i == 2 || i == 3) %OptimizeOsr(0, "concurrent");
}
return a;
}
......
......@@ -12,8 +12,11 @@ function get_closure() {
return function add_field(obj, osr) {
obj.c = 3;
var x = 0;
if (osr) %OptimizeOsr();
for (var i = 0; i < 10; i++) {
if (osr && %IsBeingInterpreted()) {
%OptimizeOsr(0, "concurrent");
%PrepareFunctionForOptimization(add_field);
}
x = i + 1;
}
return x;
......
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