Commit 7f121b4f authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[local-isolate] Move worker RCS scope into LocalIsolate

Rather than requiring the user of a LocalIsolate to pass in a
RuntimeCallStats from a WorkerThreadRuntimeCallStatsScope, create the
scope in the LocalIsolate directly and use its RuntimeCallStats in the
LocalIsolate constructor.

We can't do this for the main thread LocalIsolate, since
WorkerThreadRuntimeCallStatsScope doesn't work on the main thread, so
there we use the main-thread RuntimeCallStats instead.

This flushes out some issues of background-thread LocalIsolates being
used on the main thread, so fix those too, as well as RCS scopes using
background counters for operations that could happen on the main thread.

Change-Id: I21a53be0771f47a03ccdb27d24c2b9d25d8b2d1c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3318664Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78334}
parent 96c6986c
......@@ -120,17 +120,8 @@ class BaselineBatchCompilerJob {
// Executed in the background thread.
void Compile() {
#ifdef V8_RUNTIME_CALL_STATS
WorkerThreadRuntimeCallStatsScope runtime_call_stats_scope(
isolate_for_local_isolate_->counters()
->worker_thread_runtime_call_stats());
LocalIsolate local_isolate(isolate_for_local_isolate_,
ThreadKind::kBackground,
runtime_call_stats_scope.Get());
#else
LocalIsolate local_isolate(isolate_for_local_isolate_,
ThreadKind::kBackground);
#endif
local_isolate.heap()->AttachPersistentHandles(std::move(handles_));
UnparkedScope unparked_scope(&local_isolate);
LocalHandleScope handle_scope(&local_isolate);
......
......@@ -1340,15 +1340,14 @@ MaybeHandle<SharedFunctionInfo> CompileToplevel(
}
#ifdef V8_RUNTIME_CALL_STATS
RuntimeCallCounterId RuntimeCallCounterIdForCompileBackground(
ParseInfo* parse_info) {
RuntimeCallCounterId RuntimeCallCounterIdForCompile(ParseInfo* parse_info) {
if (parse_info->flags().is_toplevel()) {
if (parse_info->flags().is_eval()) {
return RuntimeCallCounterId::kCompileBackgroundEval;
return RuntimeCallCounterId::kCompileEval;
}
return RuntimeCallCounterId::kCompileBackgroundScript;
return RuntimeCallCounterId::kCompileScript;
}
return RuntimeCallCounterId::kCompileBackgroundFunction;
return RuntimeCallCounterId::kCompileFunction;
}
#endif // V8_RUNTIME_CALL_STATS
......@@ -1460,11 +1459,8 @@ void SetScriptFieldsFromDetails(Isolate* isolate, Script script,
} // namespace
void BackgroundCompileTask::Run() {
WorkerThreadRuntimeCallStatsScope worker_thread_scope(
worker_thread_runtime_call_stats_);
LocalIsolate isolate(isolate_for_local_isolate_, ThreadKind::kBackground,
worker_thread_scope.Get());
DCHECK_NE(ThreadId::Current(), isolate_for_local_isolate_->thread_id());
LocalIsolate isolate(isolate_for_local_isolate_, ThreadKind::kBackground);
UnparkedScope unparked_scope(&isolate);
LocalHandleScope handle_scope(&isolate);
......@@ -1473,13 +1469,20 @@ void BackgroundCompileTask::Run() {
Run(&isolate, &reusable_state);
}
void BackgroundCompileTask::RunOnMainThread(Isolate* isolate) {
LocalHandleScope handle_scope(isolate->main_thread_local_isolate());
ReusableUnoptimizedCompileState reusable_state(isolate);
Run(isolate->main_thread_local_isolate(), &reusable_state);
}
void BackgroundCompileTask::Run(
LocalIsolate* isolate, ReusableUnoptimizedCompileState* reusable_state) {
TimedHistogramScope timer(timer_);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"BackgroundCompileTask::Run");
RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileBackgroundCompileTask);
RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileCompileTask,
RuntimeCallStats::CounterMode::kThreadSpecific);
bool toplevel_script_compilation = flags_.is_toplevel();
......@@ -1554,8 +1557,8 @@ void BackgroundCompileTask::Run(
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileCodeBackground");
RCS_SCOPE(info.runtime_call_stats(),
RuntimeCallCounterIdForCompileBackground(&info));
RCS_SCOPE(isolate, RuntimeCallCounterIdForCompile(&info),
RuntimeCallStats::CounterMode::kThreadSpecific);
MaybeHandle<SharedFunctionInfo> maybe_result;
if (info.literal() != nullptr) {
......
......@@ -517,6 +517,7 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
TimedHistogram* timer, int max_stack_size);
void Run();
void RunOnMainThread(Isolate* isolate);
void Run(LocalIsolate* isolate,
ReusableUnoptimizedCompileState* reusable_state);
......
......@@ -12,6 +12,7 @@
#include "src/base/platform/time.h"
#include "src/codegen/compiler.h"
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/flags/flags.h"
#include "src/handles/global-handles-inl.h"
#include "src/heap/parked-scope.h"
......@@ -266,7 +267,7 @@ bool LazyCompileDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
}
if (job->state == Job::State::kPendingToRunOnForeground) {
job->task->Run();
job->task->RunOnMainThread(isolate_);
job->state = Job::State::kFinalizingNow;
}
......@@ -400,11 +401,7 @@ void LazyCompileDispatcher::DoBackgroundWork(JobDelegate* delegate) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.LazyCompileDispatcherDoBackgroundWork");
WorkerThreadRuntimeCallStatsScope worker_thread_scope(
worker_thread_runtime_call_stats_);
LocalIsolate isolate(isolate_, ThreadKind::kBackground,
worker_thread_scope.Get());
LocalIsolate isolate(isolate_, ThreadKind::kBackground);
UnparkedScope unparked_scope(&isolate);
LocalHandleScope handle_scope(&isolate);
......
......@@ -58,18 +58,11 @@ class OptimizingCompileDispatcher::CompileTask : public CancelableTask {
private:
// v8::Task overrides.
void RunInternal() override {
#ifdef V8_RUNTIME_CALL_STATS
WorkerThreadRuntimeCallStatsScope runtime_call_stats_scope(
worker_thread_runtime_call_stats_);
LocalIsolate local_isolate(isolate_, ThreadKind::kBackground,
runtime_call_stats_scope.Get());
#else // V8_RUNTIME_CALL_STATS
LocalIsolate local_isolate(isolate_, ThreadKind::kBackground);
#endif // V8_RUNTIME_CALL_STATS
DCHECK(local_isolate.heap()->IsParked());
{
RCS_SCOPE(runtime_call_stats_scope.Get(),
RCS_SCOPE(&local_isolate,
RuntimeCallCounterId::kOptimizeBackgroundDispatcherJob);
TimerEventScope<TimerEventRecompileConcurrent> timer(isolate_);
......
......@@ -14,8 +14,7 @@
namespace v8 {
namespace internal {
LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind,
RuntimeCallStats* runtime_call_stats)
LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind)
: HiddenLocalFactory(isolate),
heap_(isolate->heap(), kind),
isolate_(isolate),
......@@ -23,16 +22,20 @@ LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind,
thread_id_(ThreadId::Current()),
stack_limit_(kind == ThreadKind::kMain
? isolate->stack_guard()->real_climit()
: GetCurrentStackPosition() - FLAG_stack_size * KB),
runtime_call_stats_(kind == ThreadKind::kMain &&
runtime_call_stats == nullptr
? isolate->counters()->runtime_call_stats()
: runtime_call_stats)
: GetCurrentStackPosition() - FLAG_stack_size * KB)
#ifdef V8_INTL_SUPPORT
,
default_locale_(isolate->DefaultLocale())
#endif
{
#ifdef V8_RUNTIME_CALL_STATS
if (kind == ThreadKind::kMain) {
runtime_call_stats_ = isolate->counters()->runtime_call_stats();
} else {
rcs_scope_.emplace(isolate->counters()->worker_thread_runtime_call_stats());
runtime_call_stats_ = rcs_scope_->Get();
}
#endif
}
LocalIsolate::~LocalIsolate() {
......
......@@ -13,6 +13,7 @@
#include "src/handles/maybe-handles.h"
#include "src/heap/local-factory.h"
#include "src/heap/local-heap.h"
#include "src/logging/runtime-call-stats.h"
namespace v8 {
......@@ -43,8 +44,7 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
public:
using HandleScopeType = LocalHandleScope;
explicit LocalIsolate(Isolate* isolate, ThreadKind kind,
RuntimeCallStats* runtime_call_stats = nullptr);
explicit LocalIsolate(Isolate* isolate, ThreadKind kind);
~LocalIsolate();
// Kinda sketchy.
......@@ -110,7 +110,11 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
LocalLogger* logger() const { return logger_.get(); }
ThreadId thread_id() const { return thread_id_; }
Address stack_limit() const { return stack_limit_; }
#ifdef V8_RUNTIME_CALL_STATS
RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; }
#else
RuntimeCallStats* runtime_call_stats() const { return nullptr; }
#endif
bigint::Processor* bigint_processor() {
if (!bigint_processor_) InitializeBigIntProcessor();
return bigint_processor_;
......@@ -155,8 +159,12 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
ThreadId const thread_id_;
Address const stack_limit_;
RuntimeCallStats* runtime_call_stats_;
bigint::Processor* bigint_processor_{nullptr};
#ifdef V8_RUNTIME_CALL_STATS
base::Optional<WorkerThreadRuntimeCallStatsScope> rcs_scope_;
RuntimeCallStats* runtime_call_stats_;
#endif
#ifdef V8_INTL_SUPPORT
std::string default_locale_;
#endif
......
......@@ -58,10 +58,16 @@ LocalHandleScope::~LocalHandleScope() {
template <typename T>
Handle<T> LocalHandleScope::CloseAndEscape(Handle<T> handle_value) {
HandleScopeData* current = &local_heap_->handles()->scope_;
HandleScopeData* current;
T value = *handle_value;
// Throw away all handles in the current scope.
CloseScope(local_heap_, prev_next_, prev_limit_);
if (local_heap_->is_main_thread()) {
current = local_heap_->heap()->isolate()->handle_scope_data();
CloseMainThreadScope(local_heap_, prev_next_, prev_limit_);
} else {
current = &local_heap_->handles()->scope_;
CloseScope(local_heap_, prev_next_, prev_limit_);
}
// Allocate one handle in the parent scope.
DCHECK(current->level > current->sealed_level);
Handle<T> result(value, local_heap_);
......
......@@ -257,8 +257,8 @@ InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl(
Handle<SharedFunctionInfo> shared_info, LocalIsolate* isolate) {
RCS_SCOPE(parse_info()->runtime_call_stats(),
RuntimeCallCounterId::kCompileBackgroundIgnitionFinalization);
RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileIgnitionFinalization,
RuntimeCallStats::kThreadSpecific);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileIgnitionFinalization");
return DoFinalizeJobImpl(shared_info, isolate);
......
......@@ -30,11 +30,17 @@ RuntimeCallTimerScope::RuntimeCallTimerScope(Isolate* isolate,
stats_->Enter(&timer_, counter_id);
}
RuntimeCallTimerScope::RuntimeCallTimerScope(LocalIsolate* isolate,
RuntimeCallCounterId counter_id) {
RuntimeCallTimerScope::RuntimeCallTimerScope(
LocalIsolate* isolate, RuntimeCallCounterId counter_id,
RuntimeCallStats::CounterMode mode) {
if (V8_LIKELY(!TracingFlags::is_runtime_stats_enabled())) return;
DCHECK_NOT_NULL(isolate->runtime_call_stats());
stats_ = isolate->runtime_call_stats();
if (mode == RuntimeCallStats::CounterMode::kThreadSpecific) {
counter_id = stats_->CounterIdForThread(counter_id);
}
DCHECK(stats_->IsCounterAppropriateForThread(counter_id));
stats_->Enter(&timer_, counter_id);
}
......
......@@ -323,8 +323,7 @@ void WorkerThreadRuntimeCallStats::AddToMainTable(
}
WorkerThreadRuntimeCallStatsScope::WorkerThreadRuntimeCallStatsScope(
WorkerThreadRuntimeCallStats* worker_stats)
: table_(nullptr) {
WorkerThreadRuntimeCallStats* worker_stats) {
if (V8_LIKELY(!TracingFlags::is_runtime_stats_enabled())) return;
table_ = reinterpret_cast<RuntimeCallStats*>(
......
......@@ -314,6 +314,7 @@ class RuntimeCallTimer final {
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, RewriteReturnResult) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, ScopeAnalysis) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Script) \
ADD_THREAD_SPECIFIC_COUNTER(V, Compile, CompileTask) \
\
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AllocateFPRegisters) \
ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AllocateGeneralRegisters) \
......@@ -390,7 +391,6 @@ class RuntimeCallTimer final {
V(CodeGenerationFromStringsCallbacks) \
V(CompileBackgroundBaselinePreVisit) \
V(CompileBackgroundBaselineVisit) \
V(CompileBackgroundCompileTask) \
V(CompileBaseline) \
V(CompileBaselineFinalization) \
V(CompileBaselinePreVisit) \
......@@ -683,14 +683,20 @@ class WorkerThreadRuntimeCallStats final {
// when it is destroyed.
class V8_NODISCARD WorkerThreadRuntimeCallStatsScope final {
public:
WorkerThreadRuntimeCallStatsScope() = default;
explicit WorkerThreadRuntimeCallStatsScope(
WorkerThreadRuntimeCallStats* off_thread_stats);
~WorkerThreadRuntimeCallStatsScope();
WorkerThreadRuntimeCallStatsScope(WorkerThreadRuntimeCallStatsScope&&) =
delete;
WorkerThreadRuntimeCallStatsScope(const WorkerThreadRuntimeCallStatsScope&) =
delete;
RuntimeCallStats* Get() const { return table_; }
private:
RuntimeCallStats* table_;
RuntimeCallStats* table_ = nullptr;
};
#define CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats, counter_id) \
......@@ -713,7 +719,9 @@ class V8_NODISCARD RuntimeCallTimerScope {
inline RuntimeCallTimerScope(Isolate* isolate,
RuntimeCallCounterId counter_id);
inline RuntimeCallTimerScope(LocalIsolate* isolate,
RuntimeCallCounterId counter_id);
RuntimeCallCounterId counter_id,
RuntimeCallStats::CounterMode mode =
RuntimeCallStats::CounterMode::kExact);
inline RuntimeCallTimerScope(RuntimeCallStats* stats,
RuntimeCallCounterId counter_id,
RuntimeCallStats::CounterMode mode =
......
......@@ -3292,7 +3292,8 @@ void Parser::UpdateStatistics(
void Parser::ParseOnBackground(LocalIsolate* isolate, ParseInfo* info,
int start_position, int end_position,
int function_literal_id) {
RCS_SCOPE(runtime_call_stats_, RuntimeCallCounterId::kParseBackgroundProgram);
RCS_SCOPE(isolate, RuntimeCallCounterId::kParseProgram,
RuntimeCallStats::CounterMode::kThreadSpecific);
parsing_on_main_thread_ = false;
DCHECK_NULL(info->literal());
......
......@@ -8,6 +8,7 @@
#include "src/ast/scopes.h"
#include "src/ast/variables.h"
#include "src/base/logging.h"
#include "src/base/platform/wrappers.h"
#include "src/handles/handles.h"
#include "src/objects/objects-inl.h"
......@@ -529,7 +530,8 @@ class OnHeapProducedPreparseData final : public ProducedPreparseData {
Handle<PreparseData> Serialize(LocalIsolate* isolate) final {
DCHECK(!data_->is_null());
DCHECK(isolate->heap()->ContainsLocalHandle(data_.location()));
DCHECK_IMPLIES(!isolate->is_main_thread(),
isolate->heap()->ContainsLocalHandle(data_.location()));
return data_;
}
......
......@@ -528,6 +528,25 @@ static inline v8::Local<v8::Value> CompileRunWithOrigin(
return CompileRunWithOrigin(v8_str(source), origin_url);
}
// Run a ScriptStreamingTask in a separate thread.
class StreamerThread : public v8::base::Thread {
public:
static void StartThreadForTaskAndJoin(
v8::ScriptCompiler::ScriptStreamingTask* task) {
StreamerThread thread(task);
CHECK(thread.Start());
thread.Join();
}
explicit StreamerThread(v8::ScriptCompiler::ScriptStreamingTask* task)
: Thread(Thread::Options()), task_(task) {}
void Run() override { task_->Run(); }
private:
v8::ScriptCompiler::ScriptStreamingTask* task_;
};
// Takes a JSFunction and runs it through the test version of the optimizing
// pipeline, allocating the temporary compilation artifacts in a given Zone.
// For possible {flags} values, look at OptimizedCompilationInfo::Flag. If
......
......@@ -23800,9 +23800,9 @@ void RunStreamingTest(const char** chunks, v8::ScriptType type,
v8::ScriptCompiler::ScriptStreamingTask* task =
v8::ScriptCompiler::StartStreaming(isolate, &source, type);
// TestSourceStream::GetMoreData won't block, so it's OK to just run the
// task here in the main thread.
task->Run();
// TestSourceStream::GetMoreData won't block, so it's OK to just join the
// background task.
StreamerThread::StartThreadForTaskAndJoin(task);
delete task;
// Possible errors are only produced while compiling.
......@@ -24125,7 +24125,9 @@ TEST(StreamingWithDebuggingEnabledLate) {
v8::ScriptCompiler::ScriptStreamingTask* task =
v8::ScriptCompiler::StartStreaming(isolate, &source);
task->Run();
// TestSourceStream::GetMoreData won't block, so it's OK to just join the
// background task.
StreamerThread::StartThreadForTaskAndJoin(task);
delete task;
CHECK(!try_catch.HasCaught());
......@@ -24235,7 +24237,10 @@ TEST(StreamingWithHarmonyScopes) {
v8::ScriptCompiler::StreamedSource::ONE_BYTE);
v8::ScriptCompiler::ScriptStreamingTask* task =
v8::ScriptCompiler::StartStreaming(isolate, &source);
task->Run();
// TestSourceStream::GetMoreData won't block, so it's OK to just join the
// background task.
StreamerThread::StartThreadForTaskAndJoin(task);
delete task;
// Parsing should succeed (the script will be parsed and compiled in a context
......@@ -976,8 +976,9 @@ TEST(ProfilerEnabledDuringBackgroundCompile) {
std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task(
v8::ScriptCompiler::StartStreaming(isolate, &streamed_source));
// Run the background compilation task on the main thread.
task->Run();
// Run the background compilation task. DummySourceStream::GetMoreData won't
// block, so it's OK to just join the background task.
StreamerThread::StartThreadForTaskAndJoin(task.get());
// Enable the CPU profiler.
auto* cpu_profiler = v8::CpuProfiler::New(isolate, v8::kStandardNaming);
......
......@@ -79,7 +79,7 @@ TEST_F(BackgroundCompileTaskTest, SyntaxError) {
std::unique_ptr<BackgroundCompileTask> task(
NewBackgroundCompileTask(isolate(), shared));
task->Run();
task->RunOnMainThread(isolate());
ASSERT_FALSE(Compiler::FinalizeBackgroundCompileTask(
task.get(), isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(isolate()->has_pending_exception());
......@@ -105,7 +105,7 @@ TEST_F(BackgroundCompileTaskTest, CompileAndRun) {
std::unique_ptr<BackgroundCompileTask> task(
NewBackgroundCompileTask(isolate(), shared));
task->Run();
task->RunOnMainThread(isolate());
ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
task.get(), isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(shared->is_compiled());
......@@ -131,7 +131,7 @@ TEST_F(BackgroundCompileTaskTest, CompileFailure) {
std::unique_ptr<BackgroundCompileTask> task(
NewBackgroundCompileTask(isolate(), shared, 100));
task->Run();
task->RunOnMainThread(isolate());
ASSERT_FALSE(Compiler::FinalizeBackgroundCompileTask(
task.get(), isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(isolate()->has_pending_exception());
......@@ -201,7 +201,7 @@ TEST_F(BackgroundCompileTaskTest, EagerInnerFunctions) {
std::unique_ptr<BackgroundCompileTask> task(
NewBackgroundCompileTask(isolate(), shared));
task->Run();
task->RunOnMainThread(isolate());
ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
task.get(), isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(shared->is_compiled());
......@@ -231,7 +231,7 @@ TEST_F(BackgroundCompileTaskTest, LazyInnerFunctions) {
// There's already a task for this SFI.
task->Run();
task->RunOnMainThread(isolate());
ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
task.get(), isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(shared->is_compiled());
......
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