[wasm] Re-exported globals preserve their identity

V8 fails a recently added spec test that when an imported global get
re-exported, it should preserve its identity. This CL fixes the behavior
in V8.

Drive-by change: fix the object printer of globals: a global which
stores a reference type only has a tagged buffer, a global which stores
a value type only has an untagged buffer.

R=clemensb@chromium.org

Bug: v8:10556
Change-Id: I949d147fe4395610cfec6cf60082e1faecb23036
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2235702
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68513}
This commit is contained in:
Andreas Haas 2020-06-24 15:24:00 +02:00 committed by Commit Bot
parent 3f9119d586
commit f7a1932ef9
5 changed files with 3666 additions and 3644 deletions

View File

@ -1815,8 +1815,11 @@ void WasmTableObject::WasmTableObjectPrint(std::ostream& os) { // NOLINT
void WasmGlobalObject::WasmGlobalObjectPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "WasmGlobalObject");
os << "\n - untagged_buffer: " << Brief(untagged_buffer());
os << "\n - tagged_buffer: " << Brief(tagged_buffer());
if (type().is_reference_type()) {
os << "\n - tagged_buffer: " << Brief(tagged_buffer());
} else {
os << "\n - untagged_buffer: " << Brief(untagged_buffer());
}
os << "\n - offset: " << offset();
os << "\n - raw_type: " << raw_type();
os << "\n - is_mutable: " << is_mutable();

View File

@ -259,9 +259,6 @@ class InstanceBuilder {
// Process initialization of globals.
void InitGlobals(Handle<WasmInstanceObject> instance);
bool NeedsWrappers() const;
// Process the exports, creating wrappers for functions, tables, memories,
// and globals.
void ProcessExports(Handle<WasmInstanceObject> instance);
@ -1479,31 +1476,29 @@ bool InstanceBuilder::AllocateMemory() {
return true;
}
bool InstanceBuilder::NeedsWrappers() const {
if (module_->num_exported_functions > 0) return true;
for (auto& table : module_->tables) {
if (table.type.heap_type() == kHeapFunc) return true;
}
return false;
}
// Process the exports, creating wrappers for functions, tables, memories,
// globals, and exceptions.
void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
if (NeedsWrappers()) {
// If an imported WebAssembly function gets exported, the exported function
// has to be identical to to imported function. Therefore we cache all
// imported WebAssembly functions in the instance.
for (int index = 0, end = static_cast<int>(module_->import_table.size());
index < end; ++index) {
const WasmImport& import = module_->import_table[index];
if (import.kind == kExternalFunction) {
Handle<Object> value = sanitized_imports_[index].value;
if (WasmExternalFunction::IsWasmExternalFunction(*value)) {
WasmInstanceObject::SetWasmExternalFunction(
isolate_, instance, import.index,
Handle<WasmExternalFunction>::cast(value));
}
std::unordered_map<int, Handle<Object>> imported_globals;
// If an imported WebAssembly function or global gets exported, the export
// has to be identical to to import. Therefore we cache all imported
// WebAssembly functions in the instance, and all imported globals in a map
// here.
for (int index = 0, end = static_cast<int>(module_->import_table.size());
index < end; ++index) {
const WasmImport& import = module_->import_table[index];
if (import.kind == kExternalFunction) {
Handle<Object> value = sanitized_imports_[index].value;
if (WasmExternalFunction::IsWasmExternalFunction(*value)) {
WasmInstanceObject::SetWasmExternalFunction(
isolate_, instance, import.index,
Handle<WasmExternalFunction>::cast(value));
}
} else if (import.kind == kExternalGlobal) {
Handle<Object> value = sanitized_imports_[index].value;
if (value->IsWasmGlobalObject()) {
imported_globals[import.index] = value;
}
}
}
@ -1563,6 +1558,13 @@ void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
}
case kExternalGlobal: {
const WasmGlobal& global = module_->globals[exp.index];
if (global.imported) {
auto cached_global = imported_globals.find(exp.index);
if (cached_global != imported_globals.end()) {
desc.set_value(cached_global->second);
break;
}
}
Handle<JSArrayBuffer> untagged_buffer;
Handle<FixedArray> tagged_buffer;
uint32_t offset;

View File

@ -0,0 +1,31 @@
// Copyright 2020 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.
load('test/mjsunit/wasm/wasm-module-builder.js');
const global1 = new WebAssembly.Global({value: 'i32', mutable: true}, 14);
const global2 = new WebAssembly.Global({value: 'i32', mutable: true}, 15);
const global3 = new WebAssembly.Global({value: 'i32', mutable: true}, 32);
const builder = new WasmModuleBuilder();
// Two additional globals, so that global-index != export-index.
builder.addImportedGlobal('module', 'global1', kWasmI32, true);
builder.addImportedGlobal('module', 'global2', kWasmI32, true);
const globalIndex =
builder.addImportedGlobal('module', 'global3', kWasmI32, true);
builder.addExportOfKind('exportedGlobal', kExternalGlobal, globalIndex);
const buffer = builder.toBuffer();
const module = new WebAssembly.Module(buffer);
const instance = new WebAssembly.Instance(module, {
'module': {
'global1': global1,
'global2': global2,
'global3': global3,
}
});
assertEquals(global3, instance.exports.exportedGlobal);

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@
[ALWAYS, {
# TODO(v8:10556): Remove sub-typing in the reference-types implementation
'constructor/instantiate': [FAIL],
'instance/constructor-caching': [FAIL],
'instance/constructor': [FAIL],
'proposals/js-types/constructor/instantiate': [FAIL],
'proposals/js-types/global/constructor': [FAIL],