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