Commit c5bfc27d authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[asm.js] Maintain insertion order of exports.

This makes sure that the observable property order of the module export
maintains insertion order. Now that properties are configurable, we no
longer need to reverse the export processing.

R=clemensh@chromium.org
TEST=mjsunit/asm/asm-validation
BUG=chromium:715420

Change-Id: Ib2024254c07bdad7fee1cf2fa0bd3e847721f5b5
Reviewed-on: https://chromium-review.googlesource.com/488022Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44891}
parent e2accb42
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include <memory> #include <memory>
#include "src/assembler-inl.h" #include "src/assembler-inl.h"
#include "src/base/adapters.h"
#include "src/base/atomic-utils.h" #include "src/base/atomic-utils.h"
#include "src/code-stubs.h" #include "src/code-stubs.h"
#include "src/compiler/wasm-compiler.h" #include "src/compiler/wasm-compiler.h"
...@@ -1867,28 +1866,23 @@ class InstantiationHelper { ...@@ -1867,28 +1866,23 @@ class InstantiationHelper {
desc.set_enumerable(true); desc.set_enumerable(true);
desc.set_configurable(module_->is_asm_js()); desc.set_configurable(module_->is_asm_js());
// Count up export indexes.
int export_index = 0;
for (auto exp : module_->export_table) {
if (exp.kind == kExternalFunction) {
++export_index;
}
}
// Store weak references to all exported functions. // Store weak references to all exported functions.
Handle<FixedArray> weak_exported_functions; Handle<FixedArray> weak_exported_functions;
if (compiled_module->has_weak_exported_functions()) { if (compiled_module->has_weak_exported_functions()) {
weak_exported_functions = compiled_module->weak_exported_functions(); weak_exported_functions = compiled_module->weak_exported_functions();
} else { } else {
int export_count = 0;
for (WasmExport& exp : module_->export_table) {
if (exp.kind == kExternalFunction) ++export_count;
}
weak_exported_functions = weak_exported_functions =
isolate_->factory()->NewFixedArray(export_index); isolate_->factory()->NewFixedArray(export_count);
compiled_module->set_weak_exported_functions(weak_exported_functions); compiled_module->set_weak_exported_functions(weak_exported_functions);
} }
DCHECK_EQ(export_index, weak_exported_functions->length());
// Process each export in the export table (go in reverse so asm.js // Process each export in the export table.
// can skip duplicates). int export_index = 0; // Index into {weak_exported_functions}.
for (auto exp : base::Reversed(module_->export_table)) { for (WasmExport& exp : module_->export_table) {
Handle<String> name = Handle<String> name =
WasmCompiledModule::ExtractUtf8StringFromModuleBytes( WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
isolate_, compiled_module_, exp.name_offset, exp.name_length) isolate_, compiled_module_, exp.name_offset, exp.name_length)
...@@ -1907,7 +1901,7 @@ class InstantiationHelper { ...@@ -1907,7 +1901,7 @@ class InstantiationHelper {
// Wrap and export the code as a JSFunction. // Wrap and export the code as a JSFunction.
WasmFunction& function = module_->functions[exp.index]; WasmFunction& function = module_->functions[exp.index];
int func_index = int func_index =
static_cast<int>(module_->functions.size() + --export_index); static_cast<int>(module_->functions.size() + export_index);
Handle<JSFunction> js_function = js_wrappers_[exp.index]; Handle<JSFunction> js_function = js_wrappers_[exp.index];
if (js_function.is_null()) { if (js_function.is_null()) {
// Wrap the exported code as a JSFunction. // Wrap the exported code as a JSFunction.
...@@ -1931,6 +1925,7 @@ class InstantiationHelper { ...@@ -1931,6 +1925,7 @@ class InstantiationHelper {
isolate_->factory()->NewWeakCell(js_function); isolate_->factory()->NewWeakCell(js_function);
DCHECK_GT(weak_exported_functions->length(), export_index); DCHECK_GT(weak_exported_functions->length(), export_index);
weak_exported_functions->set(export_index, *weak_export); weak_exported_functions->set(export_index, *weak_export);
export_index++;
break; break;
} }
case kExternalTable: { case kExternalTable: {
...@@ -1998,13 +1993,6 @@ class InstantiationHelper { ...@@ -1998,13 +1993,6 @@ class InstantiationHelper {
break; break;
} }
// Skip duplicates for asm.js.
if (module_->is_asm_js()) {
v8::Maybe<bool> status = JSReceiver::HasOwnProperty(export_to, name);
if (status.FromMaybe(false)) {
continue;
}
}
v8::Maybe<bool> status = JSReceiver::DefineOwnProperty( v8::Maybe<bool> status = JSReceiver::DefineOwnProperty(
isolate_, export_to, name, &desc, Object::THROW_ON_ERROR); isolate_, export_to, name, &desc, Object::THROW_ON_ERROR);
if (!status.IsJust()) { if (!status.IsJust()) {
...@@ -2013,6 +2001,7 @@ class InstantiationHelper { ...@@ -2013,6 +2001,7 @@ class InstantiationHelper {
return; return;
} }
} }
DCHECK_EQ(export_index, weak_exported_functions->length());
if (module_->is_wasm()) { if (module_->is_wasm()) {
v8::Maybe<bool> success = JSReceiver::SetIntegrityLevel( v8::Maybe<bool> success = JSReceiver::SetIntegrityLevel(
......
...@@ -484,3 +484,15 @@ function assertValidAsm(func) { ...@@ -484,3 +484,15 @@ function assertValidAsm(func) {
assertTrue(o.__single_function__ === undefined); assertTrue(o.__single_function__ === undefined);
assertTrue(o.__foreign_init__ === undefined); assertTrue(o.__foreign_init__ === undefined);
})(); })();
(function TestAsmExportOrderPreserved() {
function Module() {
"use asm";
function f() {}
return { a:f, b:f, x:f, c:f, d:f };
}
var m = Module();
assertValidAsm(Module);
var props = Object.getOwnPropertyNames(m);
assertEquals(["a","b","x","c","d"], props);
})();
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