[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:
parent
918aca7fcc
commit
da03262e4c
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
})();
|
||||
|
@ -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}});
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user