[wasm] Fix for exporting imported mutable globals

Mutable globals are stored in the instance differently, so they must be
exported differently as well.

Also fix a counting bug that occurred when a module contained a global
and an imported mutable global (CalculateGlobalOffsets is called
twice).

Bug: v8:7625
Change-Id: I1cd7ef5d6ff7cb7e09239035f89d7b36d0436063
Reviewed-on: https://chromium-review.googlesource.com/1096673
Commit-Queue: Ben Smith <binji@chromium.org>
Reviewed-by: Ben Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53681}
This commit is contained in:
Ben Smith 2018-06-12 10:04:17 -07:00 committed by Commit Bot
parent 918aca7fcc
commit da03262e4c
4 changed files with 57 additions and 8 deletions

View File

@ -2633,13 +2633,35 @@ void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
case kExternalGlobal: {
WasmGlobal& global = module_->globals[exp.index];
if (FLAG_experimental_wasm_mut_global) {
Handle<JSArrayBuffer> globals_buffer(instance->globals_buffer(),
isolate_);
Handle<JSArrayBuffer> buffer;
uint32_t offset;
if (global.mutability && global.imported) {
Handle<FixedArray> buffers_array(
instance->imported_mutable_globals_buffers(), isolate_);
buffer = buffers_array->GetValueChecked<JSArrayBuffer>(
isolate_, global.index);
Address global_addr =
instance->imported_mutable_globals()[global.index];
uint32_t buffer_size = 0;
CHECK(buffer->byte_length()->ToUint32(&buffer_size));
Address backing_store =
reinterpret_cast<Address>(buffer->backing_store());
CHECK(global_addr >= backing_store &&
global_addr < backing_store + buffer_size);
offset = static_cast<uint32_t>(global_addr - backing_store);
} else {
buffer = handle(instance->globals_buffer(), isolate_);
offset = global.offset;
}
// Since the global's array buffer is always provided, allocation
// should never fail.
Handle<WasmGlobalObject> global_obj =
WasmGlobalObject::New(isolate_, globals_buffer, global.type,
global.offset, global.mutability)
WasmGlobalObject::New(isolate_, buffer, global.type, offset,
global.mutability)
.ToHandleChecked();
desc.set_value(global_obj);
} else {

View File

@ -503,8 +503,12 @@ class ModuleDecoderImpl : public Decoder {
WasmGlobal* global = &module_->globals.back();
global->type = consume_value_type();
global->mutability = consume_mutability();
if (!FLAG_experimental_wasm_mut_global && global->mutability) {
error("mutable globals cannot be imported");
if (global->mutability) {
if (FLAG_experimental_wasm_mut_global) {
module_->num_imported_mutable_globals++;
} else {
error("mutable globals cannot be imported");
}
}
break;
}
@ -984,16 +988,16 @@ class ModuleDecoderImpl : public Decoder {
// Calculate individual global offsets and total size of globals table.
void CalculateGlobalOffsets(WasmModule* module) {
uint32_t offset = 0;
uint32_t num_imported_mutable_globals = 0;
if (module->globals.size() == 0) {
module->globals_buffer_size = 0;
module->num_imported_mutable_globals = 0;
return;
}
for (WasmGlobal& global : module->globals) {
byte size = ValueTypes::MemSize(ValueTypes::MachineTypeFor(global.type));
if (global.mutability && global.imported) {
DCHECK(FLAG_experimental_wasm_mut_global);
global.index = module->num_imported_mutable_globals++;
global.index = num_imported_mutable_globals++;
} else {
offset = (offset + size - 1) & ~(size - 1); // align
global.offset = offset;

View File

@ -84,3 +84,18 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
assertEquals(112358, obj.value, name);
}
})();
(function exportImportedMutableGlobal() {
let builder = new WasmModuleBuilder();
builder.addGlobal(kWasmI32, true).exportAs('g1');
let g1 = builder.instantiate().exports.g1;
builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", "g1", kWasmI32, true);
builder.addExportOfKind('g2', kExternalGlobal, 0);
let g2 = builder.instantiate({mod: {g1: g1}}).exports.g2;
g1.value = 123;
assertEquals(g1.value, g2.value);
})();

View File

@ -191,3 +191,11 @@ function addGlobalGetterAndSetter(builder, index, name, type) {
inst2.exports.seti32(0x789abcde);
assertEquals(0x789abcde, inst2.exports.geti32());
})();
(function TestImportedAndNonImportedMutableGlobal() {
let global = new WebAssembly.Global({value: 'i32', mutable: true}, 1);
let builder = new WasmModuleBuilder();
builder.addGlobal(kWasmI32, true).exportAs('i32');
builder.addImportedGlobal("mod", "g", kWasmI32, true);
builder.instantiate({mod: {g: global}});
})();