Commit aa93e6ca authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Call a runtime function for a MemorySize instruction.

The implementation of MemorySize with RelocatableInt32Constants is
problematic if MemorySize is placed close to a GrowMemory instruction in
the code. The use of a runtime function guarantees that the order in
which MemorySize and GrowMemory is executed is correct.

R=titzer@chromium.org
BUG=chromium:651961
TEST=mjsunit/regress/wasm/regression-651961

Committed: https://crrev.com/2c12a9a42d454a36fcd2931fa458d72832eeb689
Review-Url: https://codereview.chromium.org/2386183004
Cr-Original-Commit-Position: refs/heads/master@{#39972}
Cr-Commit-Position: refs/heads/master@{#39980}
parent 9c3d08f9
......@@ -2759,8 +2759,27 @@ Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
}
Node* WasmGraphBuilder::CurrentMemoryPages() {
return graph()->NewNode(jsgraph()->machine()->Word32Shr(), MemSize(0),
jsgraph()->Int32Constant(16));
Runtime::FunctionId function_id = Runtime::kWasmMemorySize;
const Runtime::Function* function = Runtime::FunctionForId(function_id);
CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
jsgraph()->zone(), function_id, function->nargs, Operator::kNoThrow,
CallDescriptor::kNoFlags);
wasm::ModuleEnv* module = module_;
Node* inputs[] = {
jsgraph()->CEntryStubConstant(function->result_size), // C entry
jsgraph()->ExternalConstant(
ExternalReference(function_id, jsgraph()->isolate())), // ref
jsgraph()->Int32Constant(function->nargs), // arity
jsgraph()->HeapConstant(module->instance->context), // context
*effect_,
*control_};
Node* call = graph()->NewNode(jsgraph()->common()->Call(desc),
static_cast<int>(arraysize(inputs)), inputs);
Node* result = BuildChangeSmiToInt32(call);
*effect_ = call;
return result;
}
Node* WasmGraphBuilder::MemSize(uint32_t offset) {
......
......@@ -18,6 +18,27 @@
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_WasmMemorySize) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
Handle<JSObject> module_instance;
{
// Get the module JSObject
DisallowHeapAllocation no_allocation;
const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
Address pc =
Memory::Address_at(entry + StandardFrameConstants::kCallerPCOffset);
Code* code =
isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code;
Object* owning_instance = wasm::GetOwningWasmInstance(code);
CHECK_NOT_NULL(owning_instance);
module_instance = handle(JSObject::cast(owning_instance), isolate);
}
return *isolate->factory()->NewNumberFromInt(
wasm::GetInstanceMemorySize(isolate, module_instance));
}
RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -917,6 +917,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_WASM(F) \
F(WasmGrowMemory, 1, 1) \
F(WasmMemorySize, 0, 1) \
F(WasmThrowTypeError, 0, 1) \
F(WasmThrow, 2, 1) \
F(WasmGetCaughtExceptionValue, 1, 1)
......
......@@ -1809,6 +1809,17 @@ void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) {
module->set_ptr_to_heap(buffer);
}
int32_t GetInstanceMemorySize(Isolate* isolate, Handle<JSObject> instance) {
MaybeHandle<JSArrayBuffer> maybe_mem_buffer =
GetInstanceMemory(isolate, instance);
Handle<JSArrayBuffer> buffer;
if (!maybe_mem_buffer.ToHandle(&buffer)) {
return 0;
} else {
return buffer->byte_length()->Number() / WasmModule::kPageSize;
}
}
int32_t GrowInstanceMemory(Isolate* isolate, Handle<JSObject> instance,
uint32_t pages) {
Address old_mem_start = nullptr;
......
......@@ -534,6 +534,8 @@ uint32_t GetNumImportedFunctions(Handle<JSObject> wasm_object);
// Returns nullptr on failing to get owning instance.
Object* GetOwningWasmInstance(Code* code);
int32_t GetInstanceMemorySize(Isolate* isolate, Handle<JSObject> instance);
int32_t GrowInstanceMemory(Isolate* isolate, Handle<JSObject> instance,
uint32_t pages);
......
......@@ -253,6 +253,21 @@ TEST(Run_WasmModule_Serialization) {
}
}
TEST(MemorySize) {
// Initial memory size is 16, see wasm-module-builder.cc
static const int kExpectedValue = 16;
TestSignatures sigs;
v8::internal::AccountingAllocator allocator;
Zone zone(&allocator);
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
ExportAsMain(f);
byte code[] = {WASM_MEMORY_SIZE};
f->EmitCode(code, sizeof(code));
TestModule(&zone, builder, kExpectedValue);
}
TEST(Run_WasmModule_MemSize_GrowMem) {
// Initial memory size = 16 + GrowMemory(10)
static const int kExpectedValue = 26;
......
......@@ -79,22 +79,6 @@ WASM_EXEC_TEST(Int32Const_many) {
}
}
WASM_EXEC_TEST(MemorySize1) {
TestingModule module(execution_mode);
WasmRunner<int32_t> r(&module);
module.AddMemory(WasmModule::kPageSize * 1);
BUILD(r, kExprMemorySize);
CHECK_EQ(1, r.Call());
}
WASM_EXEC_TEST(MemorySize2) {
TestingModule module(execution_mode);
WasmRunner<int32_t> r(&module);
module.AddMemory(WasmModule::kPageSize * 3);
BUILD(r, kExprMemorySize);
CHECK_EQ(3, r.Call());
}
WASM_EXEC_TEST(Int32Param0) {
WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
// return(local[0])
......
// Copyright 2016 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: --expose-wasm
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
(function() {
var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, false);
builder.addFunction("foo", kSig_i_v)
.addBody([
kExprMemorySize,
kExprI32Const, 0x10,
kExprGrowMemory,
kExprI32Mul,
])
.exportFunc();
var module = builder.instantiate();
var result = module.exports.foo();
assertEquals(1, result);
})();
// Copyright 2016 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: --expose-wasm
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
(function testMemorySizeZero() {
print("testMemorySizeZero()");
var builder = new WasmModuleBuilder();
builder.addFunction("memory_size", kSig_i_v)
.addBody([kExprMemorySize])
.exportFunc();
var module = builder.instantiate();
assertEquals(0, module.exports.memory_size());
})();
(function testMemorySizeNonZero() {
print("testMemorySizeNonZero()");
var builder = new WasmModuleBuilder();
var size = 11;
builder.addMemory(size, size, false);
builder.addFunction("memory_size", kSig_i_v)
.addBody([kExprMemorySize])
.exportFunc();
var module = builder.instantiate();
assertEquals(size, module.exports.memory_size());
})();
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