Commit 61cf4396 authored by Nico Hartmann's avatar Nico Hartmann Committed by Commit Bot

[TurboFan] Transition SharedFunctionInfo to kNeverSerialized (3)

This is the 3rd step in a series of CLs to move the SharedFunctionInfo
class to kNeverSerialized and make it concurrently accessible from
the background thread. This CL:
* Adds synchronization to PrepareFunctionForDebugExecution
* Adds tests that mess with SharedFunctionInfo while it is accessed
  by another thread.

Bug: v8:7790
Change-Id: I2200fc7b6e977cda4e1003cb83d6ff49b1f1e337
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2523318Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71495}
parent 8a1e9457
......@@ -1744,7 +1744,7 @@ bool Compiler::CollectSourcePositions(Isolate* isolate,
shared_info->GetDebugInfo().HasInstrumentedBytecodeArray()) {
ByteArray source_position_table =
job->compilation_info()->bytecode_array()->SourcePositionTable();
shared_info->GetDebugBytecodeArray().set_source_position_table(
shared_info->GetActiveBytecodeArray().set_source_position_table(
source_position_table, kReleaseStore);
}
......
......@@ -330,15 +330,15 @@ class OptimizedCompilationJob : public CompilationJob {
compiler_name_(compiler_name) {}
// Prepare the compile job. Must be called on the main thread.
V8_WARN_UNUSED_RESULT Status PrepareJob(Isolate* isolate);
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Status PrepareJob(Isolate* isolate);
// Executes the compile job. Can be called on a background thread if
// can_execute_on_background_thread() returns true.
V8_WARN_UNUSED_RESULT Status
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Status
ExecuteJob(RuntimeCallStats* stats, LocalIsolate* local_isolate = nullptr);
// Finalizes the compile job. Must be called on the main thread.
V8_WARN_UNUSED_RESULT Status FinalizeJob(Isolate* isolate);
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Status FinalizeJob(Isolate* isolate);
// Report a transient failure, try again next time. Should only be called on
// optimization compilation jobs.
......@@ -443,7 +443,7 @@ class V8_NODISCARD CompilationHandleScope final {
explicit CompilationHandleScope(Isolate* isolate,
OptimizedCompilationInfo* info)
: persistent_(isolate), info_(info) {}
~CompilationHandleScope();
V8_EXPORT_PRIVATE ~CompilationHandleScope();
private:
PersistentHandlesScope persistent_;
......
......@@ -3603,7 +3603,7 @@ BIMODAL_ACCESSOR_C(ScopeInfo, bool, HasOuterScopeInfo)
BIMODAL_ACCESSOR(ScopeInfo, ScopeInfo, OuterScopeInfo)
BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id)
BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray)
BIMODAL_ACCESSOR_WITH_FLAG(SharedFunctionInfo, BytecodeArray, GetBytecodeArray)
#define DEF_SFI_ACCESSOR(type, name) \
BIMODAL_ACCESSOR_WITH_FLAG_C(SharedFunctionInfo, type, name)
BROKER_SFI_FIELDS(DEF_SFI_ACCESSOR)
......
......@@ -45,10 +45,11 @@ class SourcePositionTable;
class Pipeline : public AllStatic {
public:
// Returns a new compilation job for the given JavaScript function.
static std::unique_ptr<OptimizedCompilationJob> NewCompilationJob(
Isolate* isolate, Handle<JSFunction> function, CodeKind code_kind,
bool has_script, BailoutId osr_offset = BailoutId::None(),
JavaScriptFrame* osr_frame = nullptr);
static V8_EXPORT_PRIVATE std::unique_ptr<OptimizedCompilationJob>
NewCompilationJob(Isolate* isolate, Handle<JSFunction> function,
CodeKind code_kind, bool has_script,
BailoutId osr_offset = BailoutId::None(),
JavaScriptFrame* osr_frame = nullptr);
// Run the pipeline for the WebAssembly compilation info.
static void GenerateCodeForWasmFunction(
......
......@@ -1266,19 +1266,9 @@ void Debug::PrepareFunctionForDebugExecution(
Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
if (debug_info->flags() & DebugInfo::kPreparedForDebugExecution) return;
// Make a copy of the bytecode array if available.
Handle<HeapObject> maybe_original_bytecode_array =
isolate_->factory()->undefined_value();
if (shared->HasBytecodeArray()) {
Handle<BytecodeArray> original_bytecode_array =
handle(shared->GetBytecodeArray(), isolate_);
Handle<BytecodeArray> debug_bytecode_array =
isolate_->factory()->CopyBytecodeArray(original_bytecode_array);
debug_info->set_debug_bytecode_array(*debug_bytecode_array);
shared->SetDebugBytecodeArray(*debug_bytecode_array);
maybe_original_bytecode_array = original_bytecode_array;
}
debug_info->set_original_bytecode_array(*maybe_original_bytecode_array);
SharedFunctionInfo::InstallDebugBytecode(shared, isolate_);
}
if (debug_info->CanBreakAtEntry()) {
// Deopt everything in case the function is inlined anywhere.
......
......@@ -639,6 +639,11 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
return &transition_array_access_;
}
// Shared mutex for allowing concurrent read/writes to SharedFunctionInfos.
base::SharedMutex* shared_function_info_access() {
return &shared_function_info_access_;
}
// The isolate's string table.
StringTable* string_table() { return string_table_.get(); }
......@@ -1772,6 +1777,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
base::SharedMutex feedback_vector_access_;
base::SharedMutex string_access_;
base::SharedMutex transition_array_access_;
base::SharedMutex shared_function_info_access_;
Logger* logger_ = nullptr;
StubCache* load_stub_cache_ = nullptr;
StubCache* store_stub_cache_ = nullptr;
......
......@@ -2911,9 +2911,10 @@ Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
debug_info->set_debugger_hints(0);
DCHECK_EQ(DebugInfo::kNoDebuggingId, debug_info->debugging_id());
debug_info->set_script(shared->script_or_debug_info(kAcquireLoad));
debug_info->set_original_bytecode_array(
ReadOnlyRoots(heap).undefined_value());
debug_info->set_debug_bytecode_array(ReadOnlyRoots(heap).undefined_value());
debug_info->set_original_bytecode_array(ReadOnlyRoots(heap).undefined_value(),
kReleaseStore);
debug_info->set_debug_bytecode_array(ReadOnlyRoots(heap).undefined_value(),
kReleaseStore);
debug_info->set_break_points(ReadOnlyRoots(heap).empty_fixed_array());
// Link debug info to function.
......
......@@ -36,21 +36,26 @@ BIT_FIELD_ACCESSORS(DebugInfo, debugger_hints, computed_debug_is_blackboxed,
BIT_FIELD_ACCESSORS(DebugInfo, debugger_hints, debugging_id,
DebugInfo::DebuggingIdBits)
// TODO(nicohartmann@, v8:11122): Remove once Torque can generate them.
RELEASE_ACQUIRE_ACCESSORS(DebugInfo, debug_bytecode_array, HeapObject,
kDebugBytecodeArrayOffset)
RELEASE_ACQUIRE_ACCESSORS(DebugInfo, original_bytecode_array, HeapObject,
kOriginalBytecodeArrayOffset)
bool DebugInfo::HasInstrumentedBytecodeArray() {
DCHECK_EQ(debug_bytecode_array().IsBytecodeArray(),
original_bytecode_array().IsBytecodeArray());
return debug_bytecode_array().IsBytecodeArray();
return debug_bytecode_array(kAcquireLoad).IsBytecodeArray();
}
BytecodeArray DebugInfo::OriginalBytecodeArray() {
DCHECK(HasInstrumentedBytecodeArray());
return BytecodeArray::cast(original_bytecode_array());
return BytecodeArray::cast(original_bytecode_array(kAcquireLoad));
}
BytecodeArray DebugInfo::DebugBytecodeArray() {
DCHECK(HasInstrumentedBytecodeArray());
DCHECK_EQ(shared().GetDebugBytecodeArray(), debug_bytecode_array());
return BytecodeArray::cast(debug_bytecode_array());
DCHECK_EQ(shared().GetActiveBytecodeArray(),
debug_bytecode_array(kAcquireLoad));
return BytecodeArray::cast(debug_bytecode_array(kAcquireLoad));
}
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmValue)
......
......@@ -4,6 +4,7 @@
#include "src/objects/debug-objects.h"
#include "src/base/platform/mutex.h"
#include "src/debug/debug-evaluate.h"
#include "src/handles/handles-inl.h"
#include "src/objects/debug-objects-inl.h"
......@@ -29,10 +30,6 @@ void DebugInfo::SetDebugExecutionMode(ExecutionMode value) {
void DebugInfo::ClearBreakInfo(Isolate* isolate) {
if (HasInstrumentedBytecodeArray()) {
// Reset function's bytecode array field to point to the original bytecode
// array.
shared().SetDebugBytecodeArray(OriginalBytecodeArray());
// If the function is currently running on the stack, we need to update the
// bytecode pointers on the stack so they point to the original
// BytecodeArray before releasing that BytecodeArray from this DebugInfo.
......@@ -44,8 +41,7 @@ void DebugInfo::ClearBreakInfo(Isolate* isolate) {
isolate->thread_manager()->IterateArchivedThreads(&redirect_visitor);
}
set_original_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
set_debug_bytecode_array(ReadOnlyRoots(isolate).undefined_value());
SharedFunctionInfo::UninstallDebugBytecode(shared(), isolate);
}
set_break_points(ReadOnlyRoots(isolate).empty_fixed_array());
......
......@@ -45,6 +45,9 @@ class DebugInfo : public TorqueGeneratedDebugInfo<DebugInfo, Struct> {
ExecutionMode DebugExecutionMode() const;
void SetDebugExecutionMode(ExecutionMode value);
DECL_RELEASE_ACQUIRE_ACCESSORS(debug_bytecode_array, HeapObject)
DECL_RELEASE_ACQUIRE_ACCESSORS(original_bytecode_array, HeapObject)
// Specifies whether the associated function has an instrumented bytecode
// array. If so, OriginalBytecodeArray returns the non-instrumented bytecode,
// and DebugBytecodeArray returns the instrumented bytecode.
......@@ -59,7 +62,7 @@ class DebugInfo : public TorqueGeneratedDebugInfo<DebugInfo, Struct> {
bool HasBreakInfo() const;
// Clears all fields related to break points.
void ClearBreakInfo(Isolate* isolate);
V8_EXPORT_PRIVATE void ClearBreakInfo(Isolate* isolate);
// Accessors to flag whether to break before entering the function.
// This is used to break for functions with no source, e.g. builtins.
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_
#include "src/base/macros.h"
#include "src/base/platform/mutex.h"
#include "src/handles/handles-inl.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/local-heap-inl.h"
......@@ -455,6 +456,8 @@ bool SharedFunctionInfo::HasBytecodeArray() const {
}
BytecodeArray SharedFunctionInfo::GetBytecodeArray() const {
base::SharedMutexGuard<base::kShared> mutex_guard(
GetIsolate()->shared_function_info_access());
DCHECK(HasBytecodeArray());
if (HasDebugInfo() && GetDebugInfo().HasInstrumentedBytecodeArray()) {
return GetDebugInfo().OriginalBytecodeArray();
......@@ -469,9 +472,7 @@ BytecodeArray SharedFunctionInfo::GetBytecodeArray() const {
}
}
BytecodeArray SharedFunctionInfo::GetDebugBytecodeArray() const {
DCHECK(HasDebugInfo() && GetDebugInfo().HasInstrumentedBytecodeArray());
BytecodeArray SharedFunctionInfo::GetActiveBytecodeArray() const {
Object data = function_data(kAcquireLoad);
if (data.IsBytecodeArray()) {
return BytecodeArray::cast(data);
......@@ -481,7 +482,7 @@ BytecodeArray SharedFunctionInfo::GetDebugBytecodeArray() const {
}
}
void SharedFunctionInfo::SetDebugBytecodeArray(BytecodeArray bytecode) {
void SharedFunctionInfo::SetActiveBytecodeArray(BytecodeArray bytecode) {
Object data = function_data(kAcquireLoad);
if (data.IsBytecodeArray()) {
set_function_data(bytecode, kReleaseStore);
......
......@@ -705,5 +705,41 @@ void SharedFunctionInfo::EnsureSourcePositionsAvailable(
}
}
// static
void SharedFunctionInfo::InstallDebugBytecode(Handle<SharedFunctionInfo> shared,
Isolate* isolate) {
DCHECK(shared->HasBytecodeArray());
Handle<BytecodeArray> original_bytecode_array(shared->GetBytecodeArray(),
isolate);
Handle<BytecodeArray> debug_bytecode_array =
isolate->factory()->CopyBytecodeArray(original_bytecode_array);
{
DisallowGarbageCollection no_gc;
base::SharedMutexGuard<base::kExclusive> mutex_guard(
isolate->shared_function_info_access());
DebugInfo debug_info = shared->GetDebugInfo();
debug_info.set_original_bytecode_array(*original_bytecode_array,
kReleaseStore);
debug_info.set_debug_bytecode_array(*debug_bytecode_array, kReleaseStore);
shared->SetActiveBytecodeArray(*debug_bytecode_array);
}
}
// static
void SharedFunctionInfo::UninstallDebugBytecode(SharedFunctionInfo shared,
Isolate* isolate) {
DisallowGarbageCollection no_gc;
base::SharedMutexGuard<base::kExclusive> mutex_guard(
isolate->shared_function_info_access());
DebugInfo debug_info = shared.GetDebugInfo();
BytecodeArray original_bytecode_array = debug_info.OriginalBytecodeArray();
shared.SetActiveBytecodeArray(original_bytecode_array);
debug_info.set_original_bytecode_array(
ReadOnlyRoots(isolate).undefined_value(), kReleaseStore);
debug_info.set_debug_bytecode_array(ReadOnlyRoots(isolate).undefined_value(),
kReleaseStore);
}
} // namespace internal
} // namespace v8
......@@ -291,8 +291,8 @@ class SharedFunctionInfo
inline bool HasInterpreterData() const;
inline InterpreterData interpreter_data() const;
inline void set_interpreter_data(InterpreterData interpreter_data);
inline BytecodeArray GetDebugBytecodeArray() const;
inline void SetDebugBytecodeArray(BytecodeArray bytecode);
inline BytecodeArray GetActiveBytecodeArray() const;
inline void SetActiveBytecodeArray(BytecodeArray bytecode);
inline bool HasAsmWasmData() const;
inline AsmWasmData asm_wasm_data() const;
inline void set_asm_wasm_data(AsmWasmData data);
......@@ -627,6 +627,16 @@ class SharedFunctionInfo
// This is needed to set up the [[HomeObject]] on the function instance.
inline bool needs_home_object() const;
// Sets the bytecode in {shared}'s DebugInfo as the bytecode to
// be returned by following calls to GetActiveBytecodeArray. Stores a
// reference to the original bytecode in the DebugInfo.
static void InstallDebugBytecode(Handle<SharedFunctionInfo> shared,
Isolate* isolate);
// Removes the debug bytecode and restores the original bytecode to be
// returned by following calls to GetActiveBytecodeArray.
static void UninstallDebugBytecode(SharedFunctionInfo shared,
Isolate* isolate);
private:
#ifdef VERIFY_HEAP
void SharedFunctionInfoVerify(ReadOnlyRoots roots);
......
......@@ -169,7 +169,7 @@ void CodeSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
debug_info = sfi->GetDebugInfo();
if (debug_info.HasInstrumentedBytecodeArray()) {
debug_bytecode_array = debug_info.DebugBytecodeArray();
sfi->SetDebugBytecodeArray(debug_info.OriginalBytecodeArray());
sfi->SetActiveBytecodeArray(debug_info.OriginalBytecodeArray());
}
sfi->set_script_or_debug_info(debug_info.script(), kReleaseStore);
}
......@@ -181,7 +181,7 @@ void CodeSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
if (!debug_info.is_null()) {
sfi->set_script_or_debug_info(debug_info, kReleaseStore);
if (!debug_bytecode_array.is_null()) {
sfi->SetDebugBytecodeArray(debug_bytecode_array);
sfi->SetActiveBytecodeArray(debug_bytecode_array);
}
}
return;
......
......@@ -95,6 +95,7 @@ v8_source_set("cctest_sources") {
"compiler/test-branch-combine.cc",
"compiler/test-code-assembler.cc",
"compiler/test-code-generator.cc",
"compiler/test-concurrent-shared-function-info.cc",
"compiler/test-gap-resolver.cc",
"compiler/test-graph-visualizer.cc",
"compiler/test-instruction-scheduler.cc",
......
// Copyright 2020 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.
#include <limits>
#include "src/api/api-inl.h"
#include "src/codegen/compiler.h"
#include "src/codegen/optimized-compilation-info.h"
#include "src/compiler/pipeline.h"
#include "src/handles/handles.h"
#include "src/logging/counters.h"
#include "src/objects/js-function.h"
#include "src/objects/shared-function-info.h"
#include "src/utils/utils-inl.h"
#include "src/zone/zone.h"
#include "test/cctest/cctest.h"
#include "test/common/flag-utils.h"
namespace v8 {
namespace internal {
namespace compiler {
enum class SfiState {
Compiled,
DebugInfo,
PreparedForDebugExecution,
};
void ExpectSharedFunctionInfoState(SharedFunctionInfo sfi,
SfiState expectedState) {
Object function_data = sfi.function_data(kAcquireLoad);
HeapObject script_or_debug_info = sfi.script_or_debug_info(kAcquireLoad);
switch (expectedState) {
case SfiState::Compiled:
CHECK(function_data.IsBytecodeArray());
CHECK(script_or_debug_info.IsScript());
break;
case SfiState::DebugInfo:
CHECK(function_data.IsBytecodeArray());
CHECK(script_or_debug_info.IsDebugInfo());
{
DebugInfo debug_info = DebugInfo::cast(script_or_debug_info);
CHECK(!debug_info.HasInstrumentedBytecodeArray());
}
break;
case SfiState::PreparedForDebugExecution:
CHECK(function_data.IsBytecodeArray());
CHECK(script_or_debug_info.IsDebugInfo());
{
DebugInfo debug_info = DebugInfo::cast(script_or_debug_info);
CHECK(debug_info.HasInstrumentedBytecodeArray());
}
break;
}
}
class BackgroundCompilationThread final : public v8::base::Thread {
public:
BackgroundCompilationThread(Isolate* isolate,
base::Semaphore* sema_execute_start,
base::Semaphore* sema_execute_complete,
OptimizedCompilationJob* job)
: base::Thread(base::Thread::Options("BackgroundCompilationThread")),
isolate_(isolate),
sema_execute_start_(sema_execute_start),
sema_execute_complete_(sema_execute_complete),
job_(job) {}
void Run() override {
RuntimeCallStats stats(RuntimeCallStats::kWorkerThread);
LocalIsolate local_isolate(isolate_, ThreadKind::kBackground);
sema_execute_start_->Wait();
const CompilationJob::Status status =
job_->ExecuteJob(&stats, &local_isolate);
CHECK_EQ(status, CompilationJob::SUCCEEDED);
sema_execute_complete_->Signal();
}
private:
Isolate* isolate_;
base::Semaphore* sema_execute_start_;
base::Semaphore* sema_execute_complete_;
OptimizedCompilationJob* job_;
};
TEST(TestConcurrentSharedFunctionInfo) {
FlagScope<bool> allow_natives_syntax(&i::FLAG_allow_natives_syntax, true);
FlagScope<bool> concurrent_inlining(&i::FLAG_concurrent_inlining, true);
FlagScope<bool> turbo_direct_heap_access(&i::FLAG_turbo_direct_heap_access,
true);
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone zone(isolate->allocator(), ZONE_NAME);
HandleScope handle_scope(isolate);
const char* source_code =
"function f(x, y) { return x + y; }\n"
"function test(x) { return f(f(1, x), f(x, 1)); }\n"
"%PrepareFunctionForOptimization(f);\n"
"%PrepareFunctionForOptimization(test);\n"
"test(3);\n"
"test(-9);\n";
CompileRun(source_code);
// Get function "test"
Local<Function> function_test = Local<Function>::Cast(
CcTest::global()
->Get(CcTest::isolate()->GetCurrentContext(), v8_str("test"))
.ToLocalChecked());
Handle<JSFunction> test =
Handle<JSFunction>::cast(v8::Utils::OpenHandle(*function_test));
Handle<SharedFunctionInfo> test_sfi(test->shared(), isolate);
DCHECK(test_sfi->HasBytecodeArray());
IsCompiledScope compiled_scope_test(*test_sfi, isolate);
JSFunction::EnsureFeedbackVector(test, &compiled_scope_test);
// Get function "f"
Local<Function> function_f = Local<Function>::Cast(
CcTest::global()
->Get(CcTest::isolate()->GetCurrentContext(), v8_str("f"))
.ToLocalChecked());
Handle<JSFunction> f =
Handle<JSFunction>::cast(v8::Utils::OpenHandle(*function_f));
Handle<SharedFunctionInfo> f_sfi(f->shared(), isolate);
DCHECK(f_sfi->HasBytecodeArray());
OptimizedCompilationInfo f_info(&zone, isolate, f_sfi, f, CodeKind::TURBOFAN);
Handle<Code> f_code =
Pipeline::GenerateCodeForTesting(&f_info, isolate).ToHandleChecked();
f->set_code(*f_code);
IsCompiledScope compiled_scope_f(*f_sfi, isolate);
JSFunction::EnsureFeedbackVector(f, &compiled_scope_f);
ExpectSharedFunctionInfoState(*test_sfi, SfiState::Compiled);
auto job =
Pipeline::NewCompilationJob(isolate, test, CodeKind::TURBOFAN, true);
// Prepare job.
{
CompilationHandleScope compilation(isolate, job->compilation_info());
CanonicalHandleScope canonical(isolate, job->compilation_info());
job->compilation_info()->ReopenHandlesInNewHandleScope(isolate);
const CompilationJob::Status status = job->PrepareJob(isolate);
CHECK_EQ(status, CompilationJob::SUCCEEDED);
}
// Start a background thread to execute the compilation job.
base::Semaphore sema_execute_start(0);
base::Semaphore sema_execute_complete(0);
BackgroundCompilationThread thread(isolate, &sema_execute_start,
&sema_execute_complete, job.get());
CHECK(thread.Start());
sema_execute_start.Signal();
// Background thread is running, now mess with test's SFI.
ExpectSharedFunctionInfoState(*test_sfi, SfiState::Compiled);
// Compiled ==> DebugInfo
{
isolate->debug()->GetOrCreateDebugInfo(test_sfi);
ExpectSharedFunctionInfoState(*test_sfi, SfiState::DebugInfo);
}
for (int i = 0; i < 100; ++i) {
// DebugInfo ==> PreparedForDebugExecution
{
int breakpoint_id;
CHECK(isolate->debug()->SetBreakpointForFunction(
test_sfi, isolate->factory()->empty_string(), &breakpoint_id));
ExpectSharedFunctionInfoState(*test_sfi,
SfiState::PreparedForDebugExecution);
}
// PreparedForDebugExecution ==> DebugInfo
{
DebugInfo debug_info = test_sfi->GetDebugInfo();
debug_info.ClearBreakInfo(isolate);
ExpectSharedFunctionInfoState(*test_sfi, SfiState::DebugInfo);
}
}
sema_execute_complete.Wait();
thread.Join();
// Finalize job.
{
const CompilationJob::Status status = job->FinalizeJob(isolate);
CHECK_EQ(status, CompilationJob::SUCCEEDED);
CHECK(job->compilation_info()->has_bytecode_array());
}
}
} // namespace compiler
} // namespace internal
} // namespace v8
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