Commit 633d8307 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Add test for multiple code spaces

This CL adds a flag to reduce the initial code space reservation size
(--wasm-max-initial-code-space-reservation), and adds a test which creates at
least four separate code spaces and calls between them.

R=mstarzinger@chromium.org

Bug: v8:9477
Change-Id: I1b4c430266962eb94dbe4b381f46b03c2ec07fc2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1782999
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63797}
parent 20bf2b7b
......@@ -765,6 +765,8 @@ DEFINE_BOOL(stress_wasm_code_gc, false,
DEFINE_BOOL(wasm_far_jump_table, false,
"use multiple separate code spaces that might require far jumps "
"between them")
DEFINE_INT(wasm_max_initial_code_space_reservation, 0,
"maximum size of the initial wasm code space reservation (in MB)")
// Profiler flags.
DEFINE_INT(frame_count, 1, "number of stack frames inspected by the profiler")
......
......@@ -32,6 +32,7 @@
#include "src/utils/ostreams.h"
#include "src/wasm/memory-tracing.h"
#include "src/wasm/module-compiler.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h"
......@@ -1231,6 +1232,22 @@ RUNTIME_FUNCTION(Runtime_WasmNumInterpretedCalls) {
return *isolate->factory()->NewNumberFromSize(static_cast<size_t>(num));
}
RUNTIME_FUNCTION(Runtime_WasmNumCodeSpaces) {
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSObject, argument, 0);
Handle<WasmModuleObject> module;
if (argument->IsWasmInstanceObject()) {
module = handle(Handle<WasmInstanceObject>::cast(argument)->module_object(),
isolate);
} else if (argument->IsWasmModuleObject()) {
module = Handle<WasmModuleObject>::cast(argument);
}
size_t num_spaces =
module->native_module()->GetNumberOfCodeSpacesForTesting();
return *isolate->factory()->NewNumberFromSize(num_spaces);
}
RUNTIME_FUNCTION(Runtime_RedirectToWasmInterpreter) {
DCHECK_EQ(2, args.length());
HandleScope scope(isolate);
......
......@@ -523,6 +523,7 @@ namespace internal {
F(UnblockConcurrentRecompilation, 0, 1) \
F(WasmGetNumberOfInstances, 1, 1) \
F(WasmNumInterpretedCalls, 1, 1) \
F(WasmNumCodeSpaces, 1, 1) \
F(WasmTierUpFunction, 2, 1) \
F(WasmTraceMemory, 1, 1) \
I(DeoptimizeNow, 0, 1)
......
......@@ -702,6 +702,11 @@ void WasmCodeAllocator::FreeCode(Vector<WasmCode* const> codes) {
}
}
size_t WasmCodeAllocator::GetNumCodeSpaces() const {
base::RecursiveMutexGuard lock(&mutex_);
return owned_code_space_.size();
}
base::AddressRegion WasmCodeAllocator::GetSingleCodeRegion() const {
base::RecursiveMutexGuard lock(&mutex_);
DCHECK_EQ(1, owned_code_space_.size());
......@@ -1575,6 +1580,15 @@ std::shared_ptr<NativeModule> WasmCodeManager::NewNativeModule(
kRequiresCodeRange ? kMaxWasmCodeMemory
: ReservationSize(code_size_estimate,
module->num_declared_functions, 0);
// The '--wasm-max-code-space-reservation' testing flag can be used to reduce
// the maximum size of the initial code space reservation (in MB).
if (FLAG_wasm_max_initial_code_space_reservation > 0) {
size_t flag_max_bytes =
static_cast<size_t>(FLAG_wasm_max_initial_code_space_reservation) * MB;
if (flag_max_bytes < code_vmem_size) code_vmem_size = flag_max_bytes;
}
// Try up to two times; getting rid of dead JSArrayBuffer allocations might
// require two GCs because the first GC maybe incremental and may have
// floating garbage.
......@@ -1714,6 +1728,10 @@ void NativeModule::FreeCode(Vector<WasmCode* const> codes) {
}
}
size_t NativeModule::GetNumberOfCodeSpacesForTesting() const {
return code_allocator_.GetNumCodeSpaces();
}
void WasmCodeManager::FreeNativeModule(Vector<VirtualMemory> owned_code_space,
size_t committed_size) {
base::MutexGuard lock(&native_modules_mutex_);
......
......@@ -310,6 +310,9 @@ class WasmCodeAllocator {
// Free memory pages of all given code objects. Used for wasm code GC.
void FreeCode(Vector<WasmCode* const>);
// Retrieve the number of separately reserved code spaces.
size_t GetNumCodeSpaces() const;
// Returns the region of the single code space managed by this code allocator.
// Will fail if more than one code space has been created.
base::AddressRegion GetSingleCodeRegion() const;
......@@ -503,6 +506,9 @@ class V8_EXPORT_PRIVATE NativeModule final {
// its accounting.
void FreeCode(Vector<WasmCode* const>);
// Retrieve the number of separately reserved code spaces for this module.
size_t GetNumberOfCodeSpacesForTesting() const;
private:
friend class WasmCode;
friend class WasmCodeAllocator;
......
// Copyright 2019 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
// Flags: --wasm-far-jump-table --wasm-max-initial-code-space-reservation=1
load('test/mjsunit/wasm/wasm-module-builder.js');
// Instantiate bigger modules, until at least four separate code spaces have
// been allocated.
// Each function calls through many of the previous functions to execute the
// jump table(s) sufficiently.
let num_functions = 50;
while (true) {
print(`Trying ${num_functions} functions...`);
if (num_functions > 1e6) {
throw new Error('We should have hit four code spaces by now');
}
const builder = new WasmModuleBuilder();
builder.addMemory(1, 1, false);
builder.addFunction('f0', kSig_i_i).addBody([kExprGetLocal, 0]);
// Generate some code per function to fill the code space.
// Each function contains a number of loads that will not be executed
// (inside an "if (i == 0)" block). They increase the code size a bit so we
// do not need too many functions.
// Each function f<n> with argument {i} then calls f<n/10> with argument
// {i + 1} and returns whatever that function returns.
const body_template = [
kExprGetLocal, 0, kExprI32Eqz, kExprIf, kWasmStmt, // if (i == 0)
kExprGetLocal, 0 // get i
];
for (let i = 0; i < 1000; ++i) body_template.push(kExprI32LoadMem, 0, 0);
body_template.push(
kExprDrop, kExprEnd, // end if
kExprGetLocal, 0, kExprI32Const, 1, kExprI32Add, // i + 1
kExprCallFunction // call f<?>
);
for (let i = 1; i < num_functions; ++i) {
const body = body_template.slice();
body.push(...wasmSignedLeb(Math.floor(i / 10)));
builder.addFunction('f' + i, kSig_i_i).addBody(body);
}
builder.addExport('f', num_functions - 1);
const instance = builder.instantiate();
let expected = 17;
for (let i = num_functions - 1; i > 0; i = Math.floor(i / 10)) ++expected;
assertEquals(expected, instance.exports.f(17));
const num_code_spaces = %WasmNumCodeSpaces(instance);
print(`--> ${num_code_spaces} code spaces.`);
if (num_code_spaces >= 4) break;
num_functions *= 2;
}
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