Commit d4266e30 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm][gc] Add code ref scopes for code GC

This CL adds all the necessary {WasmCodeRefScope}s in the code base, or
at least a good approximation. A follow-up CL will enable a check that
a {WasmCodeRefScope} exists whenever a pointer to a {WasmCode} object
is returned from the {NativeModule}. This should flush out any missing
scopes.

R=titzer@chromium.org

Bug: v8:8217
Change-Id: I54c7eb39aeb1acde38273c399396e6b1390a4cb2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1533860
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60566}
parent 837e8f5e
......@@ -93,6 +93,7 @@ const char* V8NameConverter::NameOfAddress(byte* pc) const {
return v8_buffer_.start();
}
wasm::WasmCodeRefScope wasm_code_ref_scope;
wasm::WasmCode* wasm_code =
isolate_ ? isolate_->wasm_engine()->code_manager()->LookupCode(
reinterpret_cast<Address>(pc))
......
......@@ -480,6 +480,7 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
Address pc = *(state->pc_address);
// If the {pc} does not point into WebAssembly code we can rely on the
// returned {wasm_code} to be null and fall back to {GetContainingCode}.
wasm::WasmCodeRefScope code_ref_scope;
wasm::WasmCode* wasm_code =
iterator->isolate()->wasm_engine()->code_manager()->LookupCode(pc);
if (wasm_code != nullptr) {
......@@ -1840,6 +1841,9 @@ int WasmCompiledFrame::position() const {
void WasmCompiledFrame::Summarize(std::vector<FrameSummary>* functions) const {
DCHECK(functions->empty());
// The {WasmCode*} escapes this scope via the {FrameSummary}, which is fine,
// since this code object is part of our stack.
wasm::WasmCodeRefScope code_ref_scope;
wasm::WasmCode* code = wasm_code();
int offset = static_cast<int>(pc() - code->instruction_start());
Handle<WasmInstanceObject> instance(wasm_instance(), isolate());
......
......@@ -405,6 +405,7 @@ void Isolate::Iterate(RootVisitor* v, ThreadLocalTop* thread) {
}
// Iterate over pointers on native execution stack.
wasm::WasmCodeRefScope wasm_code_ref_scope;
for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
it.frame()->Iterate(v);
}
......@@ -981,6 +982,7 @@ Handle<Object> CaptureStackTrace(Isolate* isolate, Handle<Object> caller,
CaptureStackTraceOptions options) {
DisallowJavascriptExecution no_js(isolate);
wasm::WasmCodeRefScope code_ref_scope;
FrameArrayBuilder builder(isolate, options.skip_mode, options.limit, caller,
options.filter_mode);
......@@ -1262,6 +1264,7 @@ static void PrintFrames(Isolate* isolate,
void Isolate::PrintStack(StringStream* accumulator, PrintStackMode mode) {
HandleScope scope(this);
wasm::WasmCodeRefScope wasm_code_ref_scope;
DCHECK(accumulator->IsMentionedObjectCacheClear(this));
// Avoid printing anything if there are no frames.
......@@ -1668,6 +1671,10 @@ Object Isolate::UnwindAndFindHandler() {
// For WebAssembly frames we perform a lookup in the handler table.
if (!catchable_by_js) break;
// This code ref scope is here to avoid a check failure when looking up
// the code. It's not actually necessary to keep the code alive as it's
// currently being executed.
wasm::WasmCodeRefScope code_ref_scope;
WasmCompiledFrame* wasm_frame = static_cast<WasmCompiledFrame*>(frame);
int stack_slots = 0; // Will contain stack slot count of frame.
int offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots);
......@@ -1725,6 +1732,7 @@ Object Isolate::UnwindAndFindHandler() {
// Some stubs are able to handle exceptions.
if (!catchable_by_js) break;
StubFrame* stub_frame = static_cast<StubFrame*>(frame);
wasm::WasmCodeRefScope code_ref_scope;
wasm::WasmCode* wasm_code =
wasm_engine()->code_manager()->LookupCode(frame->pc());
if (wasm_code != nullptr) {
......@@ -2046,6 +2054,7 @@ bool Isolate::ComputeLocation(MessageLocation* target) {
// baseline code. For optimized code this will use the deoptimization
// information to get canonical location information.
std::vector<FrameSummary> frames;
wasm::WasmCodeRefScope code_ref_scope;
frame->Summarize(&frames);
FrameSummary& summary = frames.back();
summary.EnsureSourcePositionsAvailable();
......
......@@ -1044,6 +1044,8 @@ MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate,
RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder),
Object);
wasm::WasmCodeRefScope wasm_code_ref_scope;
for (FrameArrayIterator it(isolate, elems); it.HasFrame(); it.Advance()) {
builder.AppendCString("\n at ");
......
......@@ -1183,6 +1183,7 @@ RUNTIME_FUNCTION(Runtime_WasmTraceMemory) {
reinterpret_cast<wasm::MemoryTracingInfo*>(info_addr.ptr());
// Find the caller wasm frame.
wasm::WasmCodeRefScope wasm_code_ref_scope;
StackTraceFrameIterator it(isolate);
DCHECK(!it.done());
DCHECK(it.is_wasm());
......
......@@ -231,6 +231,7 @@ void WasmCompilationUnit::CompileWasmFunction(Isolate* isolate,
&env, native_module->compilation_state()->GetWireBytesStorage(),
isolate->counters(), detected);
if (result.succeeded()) {
WasmCodeRefScope code_ref_scope;
native_module->AddCompiledCode(std::move(result));
} else {
native_module->compilation_state()->SetError();
......
......@@ -472,6 +472,7 @@ void CompileLazy(Isolate* isolate, NativeModule* native_module,
WasmCompilationResult result = baseline_unit.ExecuteCompilation(
&env, compilation_state->GetWireBytesStorage(), isolate->counters(),
compilation_state->detected_features());
WasmCodeRefScope code_ref_scope;
WasmCodeUpdate update = native_module->AddCompiledCode(std::move(result));
WasmCode* code = update.code;
......@@ -1769,6 +1770,7 @@ void CompilationStateImpl::FinishUnits(
auto module = native_module_->module();
auto enabled_features = native_module_->enabled_features();
WasmCodeRefScope code_ref_scope;
std::vector<WasmCodeUpdate> code_update_vector =
native_module_->AddCompiledCode(compilation_results);
......
......@@ -395,12 +395,14 @@ NativeModule::NativeModule(WasmEngine* engine, const WasmFeatures& enabled,
if (num_wasm_functions > 0) {
code_table_.reset(new WasmCode* [num_wasm_functions] {});
WasmCodeRefScope code_ref_scope;
jump_table_ = CreateEmptyJumpTable(
JumpTableAssembler::SizeForNumberOfSlots(num_wasm_functions));
}
}
void NativeModule::ReserveCodeTableForTesting(uint32_t max_functions) {
WasmCodeRefScope code_ref_scope;
DCHECK_LE(num_functions(), max_functions);
WasmCode** new_table = new WasmCode* [max_functions] {};
if (module_->num_declared_functions > 0) {
......@@ -459,6 +461,7 @@ void NativeModule::UseLazyStub(uint32_t func_index) {
void NativeModule::SetRuntimeStubs(Isolate* isolate) {
DCHECK_EQ(kNullAddress, runtime_stub_entries_[0]); // Only called once.
#ifdef V8_EMBEDDED_BUILTINS
WasmCodeRefScope code_ref_scope;
WasmCode* jump_table =
CreateEmptyJumpTable(JumpTableAssembler::SizeForNumberOfStubSlots(
WasmCode::kRuntimeStubCount));
......
......@@ -196,6 +196,7 @@ class InterpreterHandle {
uint32_t activation_id = StartActivation(frame_pointer);
WasmCodeRefScope code_ref_scope;
WasmInterpreter::Thread* thread = interpreter_.GetThread(0);
thread->InitFrame(&module()->functions[func_index], wasm_args.start());
bool finished = false;
......@@ -578,6 +579,7 @@ void WasmDebugInfo::RedirectToInterpreter(Handle<WasmDebugInfo> debug_info,
DCHECK_GT(module->functions.size(), func_index);
if (!interpreted_functions->get(func_index)->IsUndefined(isolate)) continue;
wasm::WasmCodeRefScope code_ref_scope;
wasm::WasmCompilationResult result = compiler::CompileWasmInterpreterEntry(
isolate->wasm_engine(), native_module->enabled_features(), func_index,
module->functions[func_index].sig);
......
......@@ -633,6 +633,7 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule(
native_module->set_lazy_compilation(FLAG_wasm_lazy_compilation);
NativeModuleDeserializer deserializer(native_module);
WasmCodeRefScope wasm_code_ref_scope;
Reader reader(data + kVersionSize);
if (!deserializer.Read(&reader)) return {};
......
......@@ -185,6 +185,7 @@ void TestReturnMultipleValues(MachineType type) {
std::shared_ptr<wasm::NativeModule> module = AllocateNativeModule(
handles.main_isolate(), code->raw_instruction_size());
wasm::WasmCodeRefScope wasm_code_ref_scope;
byte* code_start =
module->AddCodeForTesting(code)->instructions().start();
......@@ -274,6 +275,7 @@ void ReturnLastValue(MachineType type) {
std::shared_ptr<wasm::NativeModule> module = AllocateNativeModule(
handles.main_isolate(), code->raw_instruction_size());
wasm::WasmCodeRefScope wasm_code_ref_scope;
byte* code_start = module->AddCodeForTesting(code)->instructions().start();
// Generate caller.
......@@ -335,6 +337,7 @@ void ReturnSumOfReturns(MachineType type) {
std::shared_ptr<wasm::NativeModule> module = AllocateNativeModule(
handles.main_isolate(), code->raw_instruction_size());
wasm::WasmCodeRefScope wasm_code_ref_scope;
byte* code_start = module->AddCodeForTesting(code)->instructions().start();
// Generate caller.
......
......@@ -31,6 +31,7 @@ TEST(CacheHit) {
Isolate* isolate = CcTest::InitIsolateOnce();
auto module = NewModule(isolate);
TestSignatures sigs;
WasmCodeRefScope wasm_code_ref_scope;
auto kind = compiler::WasmImportCallKind::kJSFunctionArityMatch;
......@@ -51,6 +52,7 @@ TEST(CacheMissSig) {
Isolate* isolate = CcTest::InitIsolateOnce();
auto module = NewModule(isolate);
TestSignatures sigs;
WasmCodeRefScope wasm_code_ref_scope;
auto kind = compiler::WasmImportCallKind::kJSFunctionArityMatch;
......@@ -71,6 +73,7 @@ TEST(CacheMissKind) {
Isolate* isolate = CcTest::InitIsolateOnce();
auto module = NewModule(isolate);
TestSignatures sigs;
WasmCodeRefScope wasm_code_ref_scope;
auto kind1 = compiler::WasmImportCallKind::kJSFunctionArityMatch;
auto kind2 = compiler::WasmImportCallKind::kJSFunctionArityMismatch;
......@@ -92,6 +95,7 @@ TEST(CacheHitMissSig) {
Isolate* isolate = CcTest::InitIsolateOnce();
auto module = NewModule(isolate);
TestSignatures sigs;
WasmCodeRefScope wasm_code_ref_scope;
auto kind = compiler::WasmImportCallKind::kJSFunctionArityMatch;
......
......@@ -546,6 +546,9 @@ class WasmRunner : public WasmRunnerBase {
Handle<Code> GetWrapperCode() { return wrapper_.GetWrapperCode(); }
private:
wasm::WasmCodeRefScope code_ref_scope_;
std::vector<Handle<JSFunction>> jsfuncs_;
void SetThreadInWasmFlag() {
*reinterpret_cast<int*>(trap_handler::GetThreadInWasmThreadLocalAddress()) =
true;
......@@ -555,7 +558,6 @@ class WasmRunner : public WasmRunnerBase {
*reinterpret_cast<int*>(trap_handler::GetThreadInWasmThreadLocalAddress()) =
false;
}
std::vector<Handle<JSFunction>> jsfuncs_;
};
// A macro to define tests that run in different engine configurations.
......
......@@ -245,6 +245,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::shared_ptr<wasm::NativeModule> module =
AllocateNativeModule(i_isolate, code->raw_instruction_size());
wasm::WasmCodeRefScope wasm_code_ref_scope;
byte* code_start = module->AddCodeForTesting(code)->instructions().start();
// Generate wrapper.
int expect = 0;
......
......@@ -209,6 +209,7 @@ TEST_P(WasmCodeManagerTest, AllocateAndGoOverLimit) {
NativeModulePtr native_module = AllocModule(1 * page(), GetParam());
CHECK(native_module);
CHECK_EQ(0, manager()->remaining_uncommitted_code_space());
WasmCodeRefScope code_ref_scope;
uint32_t index = 0;
WasmCode* code = AddCode(native_module.get(), index++, 1 * kCodeAlignment);
CHECK_NOT_NULL(code);
......@@ -237,6 +238,7 @@ TEST_P(WasmCodeManagerTest, TotalLimitIrrespectiveOfModuleCount) {
NativeModulePtr nm2 = AllocModule(2 * page(), GetParam());
CHECK(nm1);
CHECK(nm2);
WasmCodeRefScope code_ref_scope;
WasmCode* code = AddCode(nm1.get(), 0, 2 * page() - kJumpTableSize);
CHECK_NOT_NULL(code);
ASSERT_DEATH_IF_SUPPORTED(AddCode(nm2.get(), 0, 2 * page() - kJumpTableSize),
......@@ -256,6 +258,7 @@ TEST_P(WasmCodeManagerTest, GrowingVsFixedModule) {
"OOM in NativeModule::AllocateForCode");
} else {
// The module grows by one page. One page remains uncommitted.
WasmCodeRefScope code_ref_scope;
CHECK_NOT_NULL(
AddCode(nm.get(), 0, remaining_space_in_module + kCodeAlignment));
CHECK_EQ(manager()->remaining_uncommitted_code_space(), 1 * page());
......@@ -265,6 +268,7 @@ TEST_P(WasmCodeManagerTest, GrowingVsFixedModule) {
TEST_P(WasmCodeManagerTest, CommitIncrements) {
SetMaxCommittedMemory(10 * page());
NativeModulePtr nm = AllocModule(3 * page(), GetParam());
WasmCodeRefScope code_ref_scope;
WasmCode* code = AddCode(nm.get(), 0, kCodeAlignment);
CHECK_NOT_NULL(code);
CHECK_EQ(manager()->remaining_uncommitted_code_space(), 9 * page());
......@@ -281,37 +285,42 @@ TEST_P(WasmCodeManagerTest, Lookup) {
NativeModulePtr nm1 = AllocModule(1 * page(), GetParam());
NativeModulePtr nm2 = AllocModule(1 * page(), GetParam());
WasmCode* code1_0 = AddCode(nm1.get(), 0, kCodeAlignment);
CHECK_EQ(nm1.get(), code1_0->native_module());
WasmCode* code1_1 = AddCode(nm1.get(), 1, kCodeAlignment);
WasmCode* code2_0 = AddCode(nm2.get(), 0, kCodeAlignment);
WasmCode* code2_1 = AddCode(nm2.get(), 1, kCodeAlignment);
CHECK_EQ(nm2.get(), code2_1->native_module());
CHECK_EQ(0, code1_0->index());
CHECK_EQ(1, code1_1->index());
CHECK_EQ(0, code2_0->index());
CHECK_EQ(1, code2_1->index());
// we know the manager object is allocated here, so we shouldn't
// find any WasmCode* associated with that ptr.
WasmCode* not_found =
manager()->LookupCode(reinterpret_cast<Address>(manager()));
CHECK_NULL(not_found);
WasmCode* found = manager()->LookupCode(code1_0->instruction_start());
CHECK_EQ(found, code1_0);
found = manager()->LookupCode(code2_1->instruction_start() +
(code2_1->instructions().size() / 2));
CHECK_EQ(found, code2_1);
found = manager()->LookupCode(code2_1->instruction_start() +
code2_1->instructions().size() - 1);
CHECK_EQ(found, code2_1);
found = manager()->LookupCode(code2_1->instruction_start() +
code2_1->instructions().size());
CHECK_NULL(found);
Address mid_code1_1 =
code1_1->instruction_start() + (code1_1->instructions().size() / 2);
CHECK_EQ(code1_1, manager()->LookupCode(mid_code1_1));
Address mid_code1_1;
{
// The {WasmCodeRefScope} needs to die before {nm1} dies.
WasmCodeRefScope code_ref_scope;
WasmCode* code1_0 = AddCode(nm1.get(), 0, kCodeAlignment);
CHECK_EQ(nm1.get(), code1_0->native_module());
WasmCode* code1_1 = AddCode(nm1.get(), 1, kCodeAlignment);
WasmCode* code2_0 = AddCode(nm2.get(), 0, kCodeAlignment);
WasmCode* code2_1 = AddCode(nm2.get(), 1, kCodeAlignment);
CHECK_EQ(nm2.get(), code2_1->native_module());
CHECK_EQ(0, code1_0->index());
CHECK_EQ(1, code1_1->index());
CHECK_EQ(0, code2_0->index());
CHECK_EQ(1, code2_1->index());
// we know the manager object is allocated here, so we shouldn't
// find any WasmCode* associated with that ptr.
WasmCode* not_found =
manager()->LookupCode(reinterpret_cast<Address>(manager()));
CHECK_NULL(not_found);
WasmCode* found = manager()->LookupCode(code1_0->instruction_start());
CHECK_EQ(found, code1_0);
found = manager()->LookupCode(code2_1->instruction_start() +
(code2_1->instructions().size() / 2));
CHECK_EQ(found, code2_1);
found = manager()->LookupCode(code2_1->instruction_start() +
code2_1->instructions().size() - 1);
CHECK_EQ(found, code2_1);
found = manager()->LookupCode(code2_1->instruction_start() +
code2_1->instructions().size());
CHECK_NULL(found);
mid_code1_1 =
code1_1->instruction_start() + (code1_1->instructions().size() / 2);
CHECK_EQ(code1_1, manager()->LookupCode(mid_code1_1));
}
nm1.reset();
CHECK_NULL(manager()->LookupCode(mid_code1_1));
}
......@@ -321,6 +330,7 @@ TEST_P(WasmCodeManagerTest, LookupWorksAfterRewrite) {
NativeModulePtr nm1 = AllocModule(1 * page(), GetParam());
WasmCodeRefScope code_ref_scope;
WasmCode* code0 = AddCode(nm1.get(), 0, kCodeAlignment);
WasmCode* code1 = AddCode(nm1.get(), 1, kCodeAlignment);
CHECK_EQ(0, code0->index());
......
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