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

[asm.js] Maintain global order of exported functions.

This makes sure that the order of exports as they appear in asm.js
modules is maintained globally (not just per function) while being
translated to a WASM module.

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

Change-Id: I8b26d717ae2f88467d41670bced901f196c7b3fc
Reviewed-on: https://chromium-review.googlesource.com/503708
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45277}
parent 11d80c95
...@@ -629,7 +629,7 @@ void AsmJsParser::ValidateExport() { ...@@ -629,7 +629,7 @@ void AsmJsParser::ValidateExport() {
if (info->kind != VarKind::kFunction) { if (info->kind != VarKind::kFunction) {
FAIL("Expected function"); FAIL("Expected function");
} }
info->function_builder->ExportAs(name); module_builder_->AddExport(name, info->function_builder);
if (Check(',')) { if (Check(',')) {
if (!Peek('}')) { if (!Peek('}')) {
continue; continue;
...@@ -646,7 +646,8 @@ void AsmJsParser::ValidateExport() { ...@@ -646,7 +646,8 @@ void AsmJsParser::ValidateExport() {
if (info->kind != VarKind::kFunction) { if (info->kind != VarKind::kFunction) {
FAIL("Single function export must be a function"); FAIL("Single function export must be a function");
} }
info->function_builder->ExportAs(CStrVector(AsmJs::kSingleFunctionName)); module_builder_->AddExport(CStrVector(AsmJs::kSingleFunctionName),
info->function_builder);
} }
} }
......
...@@ -57,7 +57,6 @@ WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder) ...@@ -57,7 +57,6 @@ WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
signature_index_(0), signature_index_(0),
func_index_(static_cast<uint32_t>(builder->functions_.size())), func_index_(static_cast<uint32_t>(builder->functions_.size())),
body_(builder->zone()), body_(builder->zone()),
exported_names_(builder->zone()),
i32_temps_(builder->zone()), i32_temps_(builder->zone()),
i64_temps_(builder->zone()), i64_temps_(builder->zone()),
f32_temps_(builder->zone()), f32_temps_(builder->zone()),
...@@ -148,10 +147,6 @@ void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) { ...@@ -148,10 +147,6 @@ void WasmFunctionBuilder::EmitDirectCallIndex(uint32_t index) {
EmitCode(placeholder_bytes, arraysize(placeholder_bytes)); EmitCode(placeholder_bytes, arraysize(placeholder_bytes));
} }
void WasmFunctionBuilder::ExportAs(Vector<const char> name) {
exported_names_.push_back(name);
}
void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; } void WasmFunctionBuilder::SetName(Vector<const char> name) { name_ = name; }
void WasmFunctionBuilder::AddAsmWasmOffset(int call_position, void WasmFunctionBuilder::AddAsmWasmOffset(int call_position,
...@@ -190,15 +185,6 @@ void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const { ...@@ -190,15 +185,6 @@ void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
buffer.write_u32v(signature_index_); buffer.write_u32v(signature_index_);
} }
void WasmFunctionBuilder::WriteExports(ZoneBuffer& buffer) const {
for (auto name : exported_names_) {
buffer.write_size(name.length());
buffer.write(reinterpret_cast<const byte*>(name.start()), name.length());
buffer.write_u8(kExternalFunction);
buffer.write_size(func_index_ + builder_->function_imports_.size());
}
}
void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const { void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
size_t locals_size = locals_.Size(); size_t locals_size = locals_.Size();
buffer.write_size(locals_size + body_.size()); buffer.write_size(locals_size + body_.size());
...@@ -239,6 +225,7 @@ WasmModuleBuilder::WasmModuleBuilder(Zone* zone) ...@@ -239,6 +225,7 @@ WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
: zone_(zone), : zone_(zone),
signatures_(zone), signatures_(zone),
function_imports_(zone), function_imports_(zone),
function_exports_(zone),
global_imports_(zone), global_imports_(zone),
functions_(zone), functions_(zone),
data_segments_(zone), data_segments_(zone),
...@@ -305,14 +292,13 @@ void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect, ...@@ -305,14 +292,13 @@ void WasmModuleBuilder::SetIndirectFunction(uint32_t indirect,
uint32_t WasmModuleBuilder::AddImport(Vector<const char> name, uint32_t WasmModuleBuilder::AddImport(Vector<const char> name,
FunctionSig* sig) { FunctionSig* sig) {
function_imports_.push_back({AddSignature(sig), name.start(), name.length()}); function_imports_.push_back({name, AddSignature(sig)});
return static_cast<uint32_t>(function_imports_.size() - 1); return static_cast<uint32_t>(function_imports_.size() - 1);
} }
uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name, uint32_t WasmModuleBuilder::AddGlobalImport(Vector<const char> name,
ValueType type) { ValueType type) {
global_imports_.push_back( global_imports_.push_back({name, WasmOpcodes::ValueTypeCodeFor(type)});
{WasmOpcodes::ValueTypeCodeFor(type), name.start(), name.length()});
return static_cast<uint32_t>(global_imports_.size() - 1); return static_cast<uint32_t>(global_imports_.size() - 1);
} }
...@@ -320,6 +306,11 @@ void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) { ...@@ -320,6 +306,11 @@ void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) {
start_function_index_ = function->func_index(); start_function_index_ = function->func_index();
} }
void WasmModuleBuilder::AddExport(Vector<const char> name,
WasmFunctionBuilder* function) {
function_exports_.push_back({name, function->func_index()});
}
uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported, uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
bool mutability, bool mutability,
const WasmInitExpr& init) { const WasmInitExpr& init) {
...@@ -328,8 +319,6 @@ uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported, ...@@ -328,8 +319,6 @@ uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool exported,
} }
void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
uint32_t exports = 0;
// == Emit magic ============================================================= // == Emit magic =============================================================
TRACE("emit magic\n"); TRACE("emit magic\n");
buffer.write_u32(kWasmMagic); buffer.write_u32(kWasmMagic);
...@@ -359,19 +348,15 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { ...@@ -359,19 +348,15 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
size_t start = EmitSection(kImportSectionCode, buffer); size_t start = EmitSection(kImportSectionCode, buffer);
buffer.write_size(global_imports_.size() + function_imports_.size()); buffer.write_size(global_imports_.size() + function_imports_.size());
for (auto import : global_imports_) { for (auto import : global_imports_) {
buffer.write_u32v(0); // module name length buffer.write_u32v(0); // module name (length)
buffer.write_u32v(import.name_length); // field name length buffer.write_string(import.name); // field name
buffer.write(reinterpret_cast<const byte*>(import.name), // field name
import.name_length);
buffer.write_u8(kExternalGlobal); buffer.write_u8(kExternalGlobal);
buffer.write_u8(import.type_code); buffer.write_u8(import.type_code);
buffer.write_u8(0); // immutable buffer.write_u8(0); // immutable
} }
for (auto import : function_imports_) { for (auto import : function_imports_) {
buffer.write_u32v(0); // module name length buffer.write_u32v(0); // module name (length)
buffer.write_u32v(import.name_length); // field name length buffer.write_string(import.name); // field name
buffer.write(reinterpret_cast<const byte*>(import.name), // field name
import.name_length);
buffer.write_u8(kExternalFunction); buffer.write_u8(kExternalFunction);
buffer.write_u32v(import.sig_index); buffer.write_u32v(import.sig_index);
} }
...@@ -385,7 +370,6 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { ...@@ -385,7 +370,6 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
buffer.write_size(functions_.size()); buffer.write_size(functions_.size());
for (auto function : functions_) { for (auto function : functions_) {
function->WriteSignature(buffer); function->WriteSignature(buffer);
exports += static_cast<uint32_t>(function->exported_names_.size());
if (!function->name_.is_empty()) ++num_function_names; if (!function->name_.is_empty()) ++num_function_names;
} }
FixupSection(buffer, start); FixupSection(buffer, start);
...@@ -477,10 +461,15 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { ...@@ -477,10 +461,15 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
} }
// == emit exports =========================================================== // == emit exports ===========================================================
if (exports > 0) { if (!function_exports_.empty()) {
size_t start = EmitSection(kExportSectionCode, buffer); size_t start = EmitSection(kExportSectionCode, buffer);
buffer.write_u32v(exports); buffer.write_size(function_exports_.size());
for (auto function : functions_) function->WriteExports(buffer); for (auto function_export : function_exports_) {
buffer.write_string(function_export.name);
buffer.write_u8(kExternalFunction);
buffer.write_size(function_export.function_index +
function_imports_.size());
}
FixupSection(buffer, start); FixupSection(buffer, start);
} }
...@@ -554,11 +543,9 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { ...@@ -554,11 +543,9 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
uint32_t function_index = 0; uint32_t function_index = 0;
for (; function_index < num_imports; ++function_index) { for (; function_index < num_imports; ++function_index) {
const WasmFunctionImport* import = &function_imports_[function_index]; const WasmFunctionImport* import = &function_imports_[function_index];
DCHECK_NOT_NULL(import->name); DCHECK(!import->name.is_empty());
buffer.write_u32v(function_index); buffer.write_u32v(function_index);
uint32_t name_len = static_cast<uint32_t>(import->name_length); buffer.write_string(import->name);
buffer.write_u32v(name_len);
buffer.write(reinterpret_cast<const byte*>(import->name), name_len);
} }
if (num_function_names > 0) { if (num_function_names > 0) {
for (auto function : functions_) { for (auto function : functions_) {
...@@ -566,9 +553,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { ...@@ -566,9 +553,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
function->func_index() + function_imports_.size()); function->func_index() + function_imports_.size());
if (!function->name_.is_empty()) { if (!function->name_.is_empty()) {
buffer.write_u32v(function_index); buffer.write_u32v(function_index);
buffer.write_size(function->name_.length()); buffer.write_string(function->name_);
buffer.write(reinterpret_cast<const byte*>(function->name_.start()),
function->name_.length());
} }
++function_index; ++function_index;
} }
......
...@@ -86,6 +86,11 @@ class ZoneBuffer : public ZoneObject { ...@@ -86,6 +86,11 @@ class ZoneBuffer : public ZoneObject {
pos_ += size; pos_ += size;
} }
void write_string(Vector<const char> name) {
write_size(name.length());
write(reinterpret_cast<const byte*>(name.start()), name.length());
}
size_t reserve_u32v() { size_t reserve_u32v() {
size_t off = offset(); size_t off = offset();
EnsureSpace(kMaxVarInt32Size); EnsureSpace(kMaxVarInt32Size);
...@@ -167,7 +172,6 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject { ...@@ -167,7 +172,6 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject {
void EmitWithI32V(WasmOpcode opcode, int32_t immediate); void EmitWithI32V(WasmOpcode opcode, int32_t immediate);
void EmitWithU32V(WasmOpcode opcode, uint32_t immediate); void EmitWithU32V(WasmOpcode opcode, uint32_t immediate);
void EmitDirectCallIndex(uint32_t index); void EmitDirectCallIndex(uint32_t index);
void ExportAs(Vector<const char> name);
void SetName(Vector<const char> name); void SetName(Vector<const char> name);
void AddAsmWasmOffset(int call_position, int to_number_position); void AddAsmWasmOffset(int call_position, int to_number_position);
void SetAsmFunctionStartPosition(int position); void SetAsmFunctionStartPosition(int position);
...@@ -179,10 +183,10 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject { ...@@ -179,10 +183,10 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject {
void DeleteCodeAfter(size_t position); void DeleteCodeAfter(size_t position);
void WriteSignature(ZoneBuffer& buffer) const; void WriteSignature(ZoneBuffer& buffer) const;
void WriteExports(ZoneBuffer& buffer) const;
void WriteBody(ZoneBuffer& buffer) const; void WriteBody(ZoneBuffer& buffer) const;
void WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const; void WriteAsmWasmOffsetTable(ZoneBuffer& buffer) const;
WasmModuleBuilder* builder() const { return builder_; }
uint32_t func_index() { return func_index_; } uint32_t func_index() { return func_index_; }
FunctionSig* signature(); FunctionSig* signature();
...@@ -201,7 +205,6 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject { ...@@ -201,7 +205,6 @@ class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject {
uint32_t func_index_; uint32_t func_index_;
ZoneBuffer body_; ZoneBuffer body_;
Vector<const char> name_; Vector<const char> name_;
ZoneVector<Vector<const char>> exported_names_;
ZoneVector<uint32_t> i32_temps_; ZoneVector<uint32_t> i32_temps_;
ZoneVector<uint32_t> i64_temps_; ZoneVector<uint32_t> i64_temps_;
ZoneVector<uint32_t> f32_temps_; ZoneVector<uint32_t> f32_temps_;
...@@ -221,10 +224,6 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject { ...@@ -221,10 +224,6 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
// Building methods. // Building methods.
uint32_t AddImport(Vector<const char> name, FunctionSig* sig); uint32_t AddImport(Vector<const char> name, FunctionSig* sig);
void SetImportName(uint32_t index, Vector<const char> name) {
function_imports_[index].name = name.start();
function_imports_[index].name_length = name.length();
}
WasmFunctionBuilder* AddFunction(FunctionSig* sig = nullptr); WasmFunctionBuilder* AddFunction(FunctionSig* sig = nullptr);
uint32_t AddGlobal(ValueType type, bool exported, bool mutability = true, uint32_t AddGlobal(ValueType type, bool exported, bool mutability = true,
const WasmInitExpr& init = WasmInitExpr()); const WasmInitExpr& init = WasmInitExpr());
...@@ -234,6 +233,7 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject { ...@@ -234,6 +233,7 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
uint32_t AllocateIndirectFunctions(uint32_t count); uint32_t AllocateIndirectFunctions(uint32_t count);
void SetIndirectFunction(uint32_t indirect, uint32_t direct); void SetIndirectFunction(uint32_t indirect, uint32_t direct);
void MarkStartFunction(WasmFunctionBuilder* builder); void MarkStartFunction(WasmFunctionBuilder* builder);
void AddExport(Vector<const char> name, WasmFunctionBuilder* builder);
// Writing methods. // Writing methods.
void WriteTo(ZoneBuffer& buffer) const; void WriteTo(ZoneBuffer& buffer) const;
...@@ -252,15 +252,18 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject { ...@@ -252,15 +252,18 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
private: private:
struct WasmFunctionImport { struct WasmFunctionImport {
Vector<const char> name;
uint32_t sig_index; uint32_t sig_index;
const char* name; };
int name_length;
struct WasmFunctionExport {
Vector<const char> name;
uint32_t function_index;
}; };
struct WasmGlobalImport { struct WasmGlobalImport {
Vector<const char> name;
ValueTypeCode type_code; ValueTypeCode type_code;
const char* name;
int name_length;
}; };
struct WasmGlobal { struct WasmGlobal {
...@@ -279,6 +282,7 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject { ...@@ -279,6 +282,7 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
Zone* zone_; Zone* zone_;
ZoneVector<FunctionSig*> signatures_; ZoneVector<FunctionSig*> signatures_;
ZoneVector<WasmFunctionImport> function_imports_; ZoneVector<WasmFunctionImport> function_imports_;
ZoneVector<WasmFunctionExport> function_exports_;
ZoneVector<WasmGlobalImport> global_imports_; ZoneVector<WasmGlobalImport> global_imports_;
ZoneVector<WasmFunctionBuilder*> functions_; ZoneVector<WasmFunctionBuilder*> functions_;
ZoneVector<WasmDataSegment> data_segments_; ZoneVector<WasmDataSegment> data_segments_;
......
...@@ -62,7 +62,9 @@ void TestModuleException(Zone* zone, WasmModuleBuilder* builder) { ...@@ -62,7 +62,9 @@ void TestModuleException(Zone* zone, WasmModuleBuilder* builder) {
isolate->clear_pending_exception(); isolate->clear_pending_exception();
} }
void ExportAsMain(WasmFunctionBuilder* f) { f->ExportAs(CStrVector("main")); } void ExportAsMain(WasmFunctionBuilder* f) {
f->builder()->AddExport(CStrVector("main"), f);
}
#define EMIT_CODE_WITH_END(f, code) \ #define EMIT_CODE_WITH_END(f, code) \
do { \ do { \
...@@ -226,7 +228,7 @@ class WasmSerializationTest { ...@@ -226,7 +228,7 @@ class WasmSerializationTest {
WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i()); WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i());
byte code[] = {WASM_GET_LOCAL(0), kExprI32Const, 1, kExprI32Add}; byte code[] = {WASM_GET_LOCAL(0), kExprI32Const, 1, kExprI32Add};
EMIT_CODE_WITH_END(f, code); EMIT_CODE_WITH_END(f, code);
f->ExportAs(CStrVector(kFunctionName)); builder->AddExport(CStrVector(kFunctionName), f);
builder->WriteTo(*buffer); builder->WriteTo(*buffer);
} }
......
...@@ -109,7 +109,7 @@ class WasmCallFuzzer : public WasmExecutionFuzzer { ...@@ -109,7 +109,7 @@ class WasmCallFuzzer : public WasmExecutionFuzzer {
data += code_size; data += code_size;
size -= code_size; size -= code_size;
if (fun == 0) { if (fun == 0) {
f->ExportAs(v8::internal::CStrVector("main")); builder.AddExport(v8::internal::CStrVector("main"), f);
} }
} }
......
...@@ -29,7 +29,7 @@ class WasmCodeFuzzer : public WasmExecutionFuzzer { ...@@ -29,7 +29,7 @@ class WasmCodeFuzzer : public WasmExecutionFuzzer {
f->EmitCode(data, static_cast<uint32_t>(size)); f->EmitCode(data, static_cast<uint32_t>(size));
uint8_t end_opcode = kExprEnd; uint8_t end_opcode = kExprEnd;
f->EmitCode(&end_opcode, 1); f->EmitCode(&end_opcode, 1);
f->ExportAs(CStrVector("main")); builder.AddExport(CStrVector("main"), f);
builder.WriteTo(buffer); builder.WriteTo(buffer);
num_args = 3; num_args = 3;
......
...@@ -316,7 +316,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer { ...@@ -316,7 +316,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
uint8_t end_opcode = kExprEnd; uint8_t end_opcode = kExprEnd;
f->EmitCode(&end_opcode, 1); f->EmitCode(&end_opcode, 1);
f->ExportAs(v8::internal::CStrVector("main")); builder.AddExport(v8::internal::CStrVector("main"), f);
builder.WriteTo(buffer); builder.WriteTo(buffer);
......
...@@ -489,7 +489,8 @@ function assertValidAsm(func) { ...@@ -489,7 +489,8 @@ function assertValidAsm(func) {
function Module() { function Module() {
"use asm"; "use asm";
function f() {} function f() {}
return { a:f, b:f, x:f, c:f, d:f }; function g() {}
return { a:f, b:g, x:f, c:g, d:f };
} }
var m = Module(); var m = Module();
assertValidAsm(Module); assertValidAsm(Module);
......
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