[wasm] All strings are length-prefixed and inline

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/1781523002

Cr-Commit-Position: refs/heads/master@{#34637}
This commit is contained in:
binji 2016-03-09 10:55:27 -08:00 committed by Commit bot
parent ca5deb1ff8
commit ca0dbaece0
14 changed files with 244 additions and 248 deletions

View File

@ -2204,12 +2204,13 @@ void WasmGraphBuilder::Int64LoweringForTesting() {
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
CompilationInfo* info,
const char* message, uint32_t index,
const char* func_name) {
wasm::WasmName func_name) {
Isolate* isolate = info->isolate();
if (isolate->logger()->is_logging_code_events() ||
isolate->cpu_profiler()->is_profiling()) {
ScopedVector<char> buffer(128);
SNPrintF(buffer, "%s#%d:%s", message, index, func_name);
SNPrintF(buffer, "%s#%d:%.*s", message, index, func_name.length,
func_name.name);
Handle<String> name_str =
isolate->factory()->NewStringFromAsciiChecked(buffer.start());
Handle<String> script_str =
@ -2312,8 +2313,9 @@ Handle<JSFunction> CompileJSToWasmWrapper(
buffer.Dispose();
}
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "js-to-wasm", index,
module->module->GetName(func->name_offset));
RecordFunctionCompilation(
Logger::FUNCTION_TAG, &info, "js-to-wasm", index,
module->module->GetName(func->name_offset, func->name_length));
// Set the JSFunction's machine code.
function->set_code(*code);
}
@ -2323,8 +2325,8 @@ Handle<JSFunction> CompileJSToWasmWrapper(
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
Handle<JSFunction> function,
wasm::FunctionSig* sig,
const char* module_cstr,
const char* function_cstr) {
wasm::WasmName module_name,
wasm::WasmName function_name) {
//----------------------------------------------------------------------------
// Create the Graph
//----------------------------------------------------------------------------
@ -2392,7 +2394,7 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
}
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "wasm-to-js", 0,
module_cstr);
module_name);
}
return code;
}
@ -2431,9 +2433,10 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
}
// Add the function as another context for the exception
ScopedVector<char> buffer(128);
SNPrintF(buffer, "Compiling WASM function #%d:%s failed:",
function.func_index,
module_env->module->GetName(function.name_offset));
wasm::WasmName name =
module_env->module->GetName(function.name_offset, function.name_length);
SNPrintF(buffer, "Compiling WASM function #%d:%.*s failed:",
function.func_index, name.length, name.name);
thrower.Failed(buffer.start(), result);
return Handle<Code>::null();
}
@ -2456,8 +2459,10 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
Vector<char> buffer;
if (debugging) {
buffer = Vector<char>::New(128);
SNPrintF(buffer, "WASM_function_#%d:%s", function.func_index,
module_env->module->GetName(function.name_offset));
wasm::WasmName name =
module_env->module->GetName(function.name_offset, function.name_length);
SNPrintF(buffer, "WASM_function_#%d:%.*s", function.func_index, name.length,
name.name);
func_name = buffer.start();
}
CompilationInfo info(func_name, isolate, &zone, flags);
@ -2468,9 +2473,10 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
buffer.Dispose();
}
if (!code.is_null()) {
RecordFunctionCompilation(
Logger::FUNCTION_TAG, &info, "WASM_function", function.func_index,
module_env->module->GetName(function.name_offset));
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "WASM_function",
function.func_index,
module_env->module->GetName(
function.name_offset, function.name_length));
}
return code;

View File

@ -41,8 +41,8 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
Handle<JSFunction> function,
wasm::FunctionSig* sig,
const char* module_name,
const char* function_name);
wasm::WasmName module_name,
wasm::WasmName function_name);
// Wraps a given wasm code object, producing a JSFunction that can be called
// from JavaScript.

View File

@ -225,6 +225,8 @@ class Decoder {
*length = static_cast<int>(pc_ - pos);
if (pc_ == end && (b & 0x80)) {
error(pc_ - 1, "varint too large");
} else if (*length == 0) {
error(pc_, "varint of length 0");
} else {
TRACE("= %u\n", result);
}

View File

@ -187,7 +187,6 @@ void WasmFunctionBuilder::SetName(const unsigned char* name, int name_length) {
for (int i = 0; i < name_length; i++) {
name_.push_back(*(name + i));
}
name_.push_back('\0');
}
}
@ -294,7 +293,10 @@ WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalType return_type,
uint32_t WasmFunctionEncoder::HeaderSize() const {
uint32_t size = 3;
if (!external_) size += 2;
if (HasName()) size += 4;
if (HasName()) {
uint32_t name_size = NameSize();
size += static_cast<uint32_t>(SizeOfVarInt(name_size)) + name_size;
}
return size;
}
@ -327,10 +329,10 @@ void WasmFunctionEncoder::Serialize(byte* buffer, byte** header,
EmitUint16(header, signature_index_);
if (HasName()) {
uint32_t name_offset = static_cast<uint32_t>(*body - buffer);
EmitUint32(header, name_offset);
std::memcpy(*body, &name_[0], name_.size());
(*body) += name_.size();
EmitVarInt(header, NameSize());
for (size_t i = 0; i < name_.size(); ++i) {
EmitUint8(header, name_[i]);
}
}
@ -524,7 +526,8 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
sizes.AddSection(globals_.size());
if (globals_.size() > 0) {
sizes.Add(kDeclGlobalSize * globals_.size(), 0);
/* These globals never have names, so are always 3 bytes. */
sizes.Add(3 * globals_.size(), 0);
}
sizes.AddSection(functions_.size());
@ -571,7 +574,7 @@ WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
EmitVarInt(&header, globals_.size());
for (auto global : globals_) {
EmitUint32(&header, 0);
EmitVarInt(&header, 0); // Length of the global name.
EmitUint8(&header, WasmOpcodes::MemTypeCodeFor(global.first));
EmitUint8(&header, global.second);
}

View File

@ -161,7 +161,7 @@ class ModuleDecoder : public Decoder {
if (failed()) break;
TRACE("DecodeGlobal[%d] module+%d\n", i,
static_cast<int>(pc_ - start_));
module->globals.push_back({0, MachineType::Int32(), 0, false});
module->globals.push_back({0, 0, MachineType::Int32(), 0, false});
WasmGlobal* global = &module->globals.back();
DecodeGlobalInModule(global);
}
@ -252,12 +252,13 @@ class ModuleDecoder : public Decoder {
import->sig = module->signatures[import->sig_index];
}
const byte* pos = pc_;
import->module_name_offset = consume_string("import module name");
if (import->module_name_offset == 0) {
import->module_name_offset = consume_string(
&import->module_name_length, "import module name");
if (import->module_name_length == 0) {
error(pos, "import module name cannot be NULL");
}
import->function_name_offset =
consume_string("import function name");
import->function_name_offset = consume_string(
&import->function_name_length, "import function name");
}
break;
}
@ -285,7 +286,7 @@ class ModuleDecoder : public Decoder {
exp->func_index,
static_cast<int>(module->functions.size()));
}
exp->name_offset = consume_string("export name");
exp->name_offset = consume_string(&exp->name_length, "export name");
}
break;
}
@ -344,6 +345,7 @@ class ModuleDecoder : public Decoder {
pc_ = start_;
function->sig = consume_sig(); // read signature
function->name_offset = 0; // ---- name
function->name_length = 0; // ---- name length
function->code_start_offset = off(pc_); // ---- code start
function->code_end_offset = off(limit_); // ---- code end
function->exported = false; // ---- exported
@ -373,7 +375,7 @@ class ModuleDecoder : public Decoder {
// Decodes a single global entry inside a module starting at {pc_}.
void DecodeGlobalInModule(WasmGlobal* global) {
global->name_offset = consume_string("global name");
global->name_offset = consume_string(&global->name_length, "global name");
global->type = mem_type();
global->offset = 0;
global->exported = consume_u8("exported") != 0;
@ -402,7 +404,8 @@ class ModuleDecoder : public Decoder {
(decl_bits & kDeclFunctionImport) == 0 ? " body" : "");
if (decl_bits & kDeclFunctionName) {
function->name_offset = consume_string("function name");
function->name_offset =
consume_string(&function->name_length, "function name");
}
function->exported = decl_bits & kDeclFunctionExport;
@ -505,11 +508,14 @@ class ModuleDecoder : public Decoder {
return offset;
}
// Reads a single 32-bit unsigned integer interpreted as an offset into the
// data and validating the string there and advances.
uint32_t consume_string(const char* name = nullptr) {
// TODO(titzer): validate string
return consume_offset(name ? name : "string");
// Reads a length-prefixed string, checking that it is within bounds. Returns
// the offset of the string, and the length as an out parameter.
uint32_t consume_string(uint32_t* length, const char* name = nullptr) {
int varint_length;
*length = consume_u32v(&varint_length, "string length");
uint32_t offset = static_cast<uint32_t>(pc_ - start_);
consume_bytes(*length);
return offset;
}
// Reads a single 8-bit integer, interpreting it as a local type.

View File

@ -16,8 +16,11 @@
#define WASM_MODULE_HEADER U32_LE(kWasmMagic), U32_LE(kWasmVersion)
#define SIG_INDEX(v) U16_LE(v)
// TODO(binji): make SIG_INDEX match this.
#define IMPORT_SIG_INDEX(v) U32V_1(v)
#define FUNC_INDEX(v) U32V_1(v)
#define NAME_OFFSET(v) U32_LE(v)
#define NO_NAME U32V_1(0)
#define NAME_LENGTH(v) U32V_1(v)
#define ZERO_ALIGNMENT 0
#define ZERO_OFFSET 0

View File

@ -48,7 +48,9 @@ std::ostream& operator<<(std::ostream& os, const WasmFunctionName& pair) {
os << "#" << pair.function_->func_index << ":";
if (pair.function_->name_offset > 0) {
if (pair.module_) {
os << pair.module_->GetName(pair.function_->name_offset);
WasmName name = pair.module_->GetName(pair.function_->name_offset,
pair.function_->name_length);
os.write(name.name, name.length);
} else {
os << "+" << pair.function_->func_index;
}
@ -280,14 +282,15 @@ WasmModule::WasmModule()
static MaybeHandle<JSFunction> ReportFFIError(ErrorThrower& thrower,
const char* error, uint32_t index,
const char* module_cstr,
const char* function_cstr) {
if (function_cstr) {
thrower.Error("Import #%d module=\"%s\" function=\"%s\" error: %s", index,
module_cstr, function_cstr, error);
wasm::WasmName module_name,
wasm::WasmName function_name) {
if (function_name.name) {
thrower.Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s",
index, module_name.length, module_name.name,
function_name.length, function_name.name, error);
} else {
thrower.Error("Import #%d module=\"%s\" error: %s", index, module_cstr,
error);
thrower.Error("Import #%d module=\"%.*s\" error: %s", index,
module_name.length, module_name.name, error);
}
thrower.Error("Import ");
return MaybeHandle<JSFunction>();
@ -295,35 +298,37 @@ static MaybeHandle<JSFunction> ReportFFIError(ErrorThrower& thrower,
static MaybeHandle<JSFunction> LookupFunction(
ErrorThrower& thrower, Factory* factory, Handle<JSObject> ffi,
uint32_t index, const char* module_cstr, const char* function_cstr) {
uint32_t index, wasm::WasmName module_name, wasm::WasmName function_name) {
if (ffi.is_null()) {
return ReportFFIError(thrower, "FFI is not an object", index, module_cstr,
function_cstr);
return ReportFFIError(thrower, "FFI is not an object", index, module_name,
function_name);
}
// Look up the module first.
Handle<String> name = factory->InternalizeUtf8String(module_cstr);
Handle<String> name = factory->InternalizeUtf8String(
Vector<const char>(module_name.name, module_name.length));
MaybeHandle<Object> result = Object::GetProperty(ffi, name);
if (result.is_null()) {
return ReportFFIError(thrower, "module not found", index, module_cstr,
function_cstr);
return ReportFFIError(thrower, "module not found", index, module_name,
function_name);
}
Handle<Object> module = result.ToHandleChecked();
if (!module->IsJSReceiver()) {
return ReportFFIError(thrower, "module is not an object or function", index,
module_cstr, function_cstr);
module_name, function_name);
}
Handle<Object> function;
if (function_cstr) {
if (function_name.name) {
// Look up the function in the module.
Handle<String> name = factory->InternalizeUtf8String(function_cstr);
Handle<String> name = factory->InternalizeUtf8String(
Vector<const char>(function_name.name, function_name.length));
MaybeHandle<Object> result = Object::GetProperty(module, name);
if (result.is_null()) {
return ReportFFIError(thrower, "function not found", index, module_cstr,
function_cstr);
return ReportFFIError(thrower, "function not found", index, module_name,
function_name);
}
function = result.ToHandleChecked();
} else {
@ -332,8 +337,8 @@ static MaybeHandle<JSFunction> LookupFunction(
}
if (!function->IsJSFunction()) {
return ReportFFIError(thrower, "not a function", index, module_cstr,
function_cstr);
return ReportFFIError(thrower, "not a function", index, module_name,
function_name);
}
return Handle<JSFunction>::cast(function);
@ -404,14 +409,16 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
if (import_table.size() > 0) {
instance.import_code.reserve(import_table.size());
for (const WasmImport& import : import_table) {
const char* module_cstr = GetNameOrNull(import.module_name_offset);
const char* function_cstr = GetNameOrNull(import.function_name_offset);
WasmName module_name =
GetNameOrNull(import.module_name_offset, import.module_name_length);
WasmName function_name = GetNameOrNull(import.function_name_offset,
import.function_name_length);
MaybeHandle<JSFunction> function = LookupFunction(
thrower, factory, ffi, index, module_cstr, function_cstr);
thrower, factory, ffi, index, module_name, function_name);
if (function.is_null()) return MaybeHandle<JSObject>();
Handle<Code> code = compiler::CompileWasmToJSWrapper(
isolate, &module_env, function.ToHandleChecked(), import.sig,
module_cstr, function_cstr);
module_name, function_name);
instance.import_code.push_back(code);
index++;
}
@ -427,23 +434,26 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
if (thrower.error()) break;
DCHECK_EQ(index, func.func_index);
const char* cstr = GetName(func.name_offset);
Handle<String> name = factory->InternalizeUtf8String(cstr);
WasmName str = GetName(func.name_offset, func.name_length);
WasmName str_null = {nullptr, 0};
Handle<String> name = factory->InternalizeUtf8String(
Vector<const char>(str.name, str.length));
Handle<Code> code = Handle<Code>::null();
Handle<JSFunction> function = Handle<JSFunction>::null();
if (func.external) {
// Lookup external function in FFI object.
MaybeHandle<JSFunction> function =
LookupFunction(thrower, factory, ffi, index, cstr, nullptr);
LookupFunction(thrower, factory, ffi, index, str, str_null);
if (function.is_null()) return MaybeHandle<JSObject>();
code = compiler::CompileWasmToJSWrapper(isolate, &module_env,
function.ToHandleChecked(),
func.sig, cstr, nullptr);
func.sig, str, str_null);
} else {
// Compile the function.
code = compiler::CompileWasmFunction(thrower, isolate, &module_env, func);
if (code.is_null()) {
thrower.Error("Compilation of #%d:%s failed.", index, cstr);
thrower.Error("Compilation of #%d:%.*s failed.", index, str.length,
str.name);
return MaybeHandle<JSObject>();
}
if (func.exported) {
@ -485,8 +495,9 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
// Compile wrappers and add them to the exports object.
for (const WasmExport& exp : export_table) {
if (thrower.error()) break;
const char* cstr = GetName(exp.name_offset);
Handle<String> name = factory->InternalizeUtf8String(cstr);
WasmName str = GetName(exp.name_offset, exp.name_length);
Handle<String> name = factory->InternalizeUtf8String(
Vector<const char>(str.name, str.length));
Handle<Code> code = linker.GetFunctionCode(exp.func_index);
Handle<JSFunction> function = compiler::CompileJSToWasmWrapper(
isolate, &module_env, name, code, instance.js_object, exp.func_index);

View File

@ -57,7 +57,6 @@ enum WasmFunctionDeclBit {
// Constants for fixed-size elements within a module.
static const size_t kDeclMemorySize = 3;
static const size_t kDeclGlobalSize = 6;
static const size_t kDeclDataSegmentSize = 13;
// Static representation of a WASM function.
@ -66,6 +65,7 @@ struct WasmFunction {
uint32_t func_index; // index into the function table.
uint32_t sig_index; // index into the signature table.
uint32_t name_offset; // offset in the module bytes of the name, if any.
uint32_t name_length; // length in bytes of the name.
uint32_t code_start_offset; // offset in the module bytes of code start.
uint32_t code_end_offset; // offset in the module bytes of code end.
uint16_t local_i32_count; // number of i32 local variables.
@ -81,18 +81,22 @@ struct WasmImport {
FunctionSig* sig; // signature of the function.
uint32_t sig_index; // index into the signature table.
uint32_t module_name_offset; // offset in module bytes of the module name.
uint32_t module_name_length; // length in bytes of the module name.
uint32_t function_name_offset; // offset in module bytes of the import name.
uint32_t function_name_length; // length in bytes of the import name.
};
// Static representation of an exported WASM function.
struct WasmExport {
uint32_t func_index; // index into the function table.
uint32_t name_offset; // offset in module bytes of the name to export.
uint32_t name_length; // length in bytes of the exported name.
};
// Static representation of a wasm global variable.
struct WasmGlobal {
uint32_t name_offset; // offset in the module bytes of the name, if any.
uint32_t name_length; // length in bytes of the global name.
MachineType type; // type of the global.
uint32_t offset; // offset from beginning of globals area.
bool exported; // true if this global is exported.
@ -134,18 +138,18 @@ struct WasmModule {
WasmModule();
// Get a pointer to a string stored in the module bytes representing a name.
const char* GetName(uint32_t offset) const {
if (offset == 0) return "<?>"; // no name.
CHECK(BoundsCheck(offset, offset + 1));
return reinterpret_cast<const char*>(module_start + offset);
// Get a string stored in the module bytes representing a name.
WasmName GetName(uint32_t offset, uint32_t length) const {
if (length == 0) return {"<?>", 3}; // no name.
CHECK(BoundsCheck(offset, offset + length));
return {reinterpret_cast<const char*>(module_start + offset), length};
}
// Get a pointer to a string stored in the module bytes representing a name.
const char* GetNameOrNull(uint32_t offset) const {
if (offset == 0) return nullptr; // no name.
CHECK(BoundsCheck(offset, offset + 1));
return reinterpret_cast<const char*>(module_start + offset);
// Get a string stored in the module bytes representing a name.
WasmName GetNameOrNull(uint32_t offset, uint32_t length) const {
if (length == 0) return {NULL, 0}; // no name.
CHECK(BoundsCheck(offset, offset + length));
return {reinterpret_cast<const char*>(module_start + offset), length};
}
// Checks the given offset range is contained within the module bytes.

View File

@ -49,6 +49,11 @@ const LocalType kAstEnd = MachineRepresentation::kTagged;
typedef Signature<LocalType> FunctionSig;
std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
struct WasmName {
const char* name;
uint32_t length;
};
// TODO(titzer): Renumber all the opcodes to fill in holes.
// Control expressions and blocks.

View File

@ -56,8 +56,10 @@ uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig,
module->AddFunction(sig, Handle<Code>::null());
uint32_t index = static_cast<uint32_t>(module->module->functions.size() - 1);
Isolate* isolate = CcTest::InitIsolateOnce();
Handle<Code> code =
CompileWasmToJSWrapper(isolate, module, jsfunc, sig, "test", nullptr);
WasmName module_name = {"test", 4};
WasmName function_name = {nullptr, 0};
Handle<Code> code = CompileWasmToJSWrapper(isolate, module, jsfunc, sig,
module_name, function_name);
module->instance->function_code[index] = code;
return index;
}

View File

@ -167,7 +167,7 @@ class TestingModule : public ModuleEnv {
}
uint32_t index = static_cast<uint32_t>(module->functions.size());
module->functions.push_back(
{sig, index, 0, 0, 0, 0, 0, 0, 0, false, false});
{sig, index, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false});
instance->function_code.push_back(code);
DCHECK_LT(index, kMaxFunctions); // limited for testing.
return index;
@ -209,7 +209,7 @@ class TestingModule : public ModuleEnv {
WasmGlobal* AddGlobal(MachineType mem_type) {
byte size = WasmOpcodes::MemSize(mem_type);
global_offset = (global_offset + size - 1) & ~(size - 1); // align
module->globals.push_back({0, mem_type, global_offset, false});
module->globals.push_back({0, 0, mem_type, global_offset, false});
global_offset += size;
// limit number of globals.
CHECK_LT(global_offset, kMaxGlobalsSize);

View File

@ -2,11 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function StringRef(string) {
this.pos = -1;
this.string = string;
}
function DataRef(data) {
this.pos = -1;
this.data = data;
@ -117,10 +112,10 @@ function emit_u32(bytes, val) {
}
function emit_string(bytes, string) {
bytes.push(new StringRef(string));
bytes.push(0);
bytes.push(0);
bytes.push(0);
emit_varint(bytes, string.length);
for (var i = 0; i < string.length; i++) {
emit_u8(bytes, string.charCodeAt(i));
}
}
function emit_data_ref(bytes, string) {
@ -179,11 +174,7 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
for (imp of this.imports) {
emit_varint(bytes, imp.sig_index);
emit_string(bytes, imp.module);
if (imp.name == undefined) {
emit_u32(bytes, 0);
} else {
emit_string(bytes, imp.name);
}
emit_string(bytes, imp.name || '');
}
}
@ -297,21 +288,12 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
if (debug) print("emitting end @ " + bytes.length);
emit_u8(bytes, kDeclEnd);
// Collect references and canonicalize strings.
// Collect references.
var strings = new Object();
var data_segments = [];
var count = 0;
for (var i = 0; i < bytes.length; i++) {
var b = bytes[i];
if (b instanceof StringRef) {
count++;
var prev = strings[b.string];
if (prev) {
bytes[i] = prev;
} else {
strings[b.string] = b;
}
}
if (b instanceof DataRef) {
data_segments.push(b);
count++;
@ -319,18 +301,6 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
}
if (count > 0) {
// Emit strings.
if (debug) print("emitting strings @ " + bytes.length);
for (str in strings) {
var ref = strings[str];
if (!(ref instanceof StringRef)) continue;
if (debug) print(" \"" + str + "\" @ " + bytes.length);
ref.pos = bytes.length;
for (var i = 0; i < str.length; i++) {
emit_u8(bytes, str.charCodeAt(i));
}
emit_u8(bytes, 0); // null terminator.
}
// Emit data.
if (debug) print("emitting data @ " + bytes.length);
for (ref of data_segments) {
@ -342,7 +312,7 @@ WasmModuleBuilder.prototype.toArray = function(debug) {
// Update references to strings and data.
for (var i = 0; i < bytes.length; i++) {
var b = bytes[i];
if (b instanceof StringRef || b instanceof DataRef) {
if (b instanceof DataRef) {
bytes[i] = b.pos & 0xFF;
bytes[i + 1] = (b.pos >> 8) & 0xFF;
bytes[i + 2] = (b.pos >> 16) & 0xFF;

View File

@ -1013,7 +1013,7 @@ class TestModuleEnv : public ModuleEnv {
linker = nullptr;
}
byte AddGlobal(MachineType mem_type) {
mod.globals.push_back({0, mem_type, 0, false});
mod.globals.push_back({0, 0, mem_type, 0, false});
CHECK(mod.globals.size() <= 127);
return static_cast<byte>(mod.globals.size() - 1);
}

View File

@ -98,9 +98,9 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) {
static const byte data[] = {
kDeclGlobals,
1,
NAME_OFFSET(0),
kMemI32, // memory type
0, // exported
NAME_LENGTH(1), 'g', // name
kMemI32, // memory type
0, // exported
};
{
@ -113,7 +113,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) {
WasmGlobal* global = &result.val->globals.back();
EXPECT_EQ(0, global->name_offset);
EXPECT_EQ(1, global->name_length);
EXPECT_EQ(MachineType::Int32(), global->type);
EXPECT_EQ(0, global->offset);
EXPECT_FALSE(global->exported);
@ -152,9 +152,9 @@ static void AppendUint32v(std::vector<byte>& buffer, uint32_t val) {
TEST_F(WasmModuleVerifyTest, NGlobals) {
static const byte data[] = {
NAME_OFFSET(0), // name offset
kMemI32, // memory type
0, // exported
NO_NAME, // name length
kMemI32, // memory type
0, // exported
};
for (uint32_t i = 0; i < 1000000; i = i * 13 + 1) {
@ -172,26 +172,13 @@ TEST_F(WasmModuleVerifyTest, NGlobals) {
}
TEST_F(WasmModuleVerifyTest, GlobalWithInvalidNameOffset) {
static const byte data[] = {
kDeclGlobals,
1, // declare one global
NAME_OFFSET(300), // name offset
kMemI32, // memory type
0, // exported
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, GlobalWithInvalidMemoryType) {
static const byte data[] = {
kDeclGlobals,
1, // declare one global
NAME_OFFSET(0), // name offset
33, // memory type
0, // exported
1, // declare one global
NO_NAME, // name length
33, // memory type
0, // exported
};
EXPECT_FAILURE(data);
@ -202,12 +189,12 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) {
static const byte data[] = {
kDeclGlobals,
2,
NAME_OFFSET(0), // #0: name offset
kMemF32, // memory type
0, // exported
NAME_OFFSET(0), // #1: name offset
kMemF64, // memory type
1, // exported
NO_NAME, // #0: name length
kMemF32, // memory type
0, // exported
NO_NAME, // #1: name length
kMemF64, // memory type
1, // exported
};
{
@ -221,12 +208,12 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) {
WasmGlobal* g0 = &result.val->globals[0];
WasmGlobal* g1 = &result.val->globals[1];
EXPECT_EQ(0, g0->name_offset);
EXPECT_EQ(0, g0->name_length);
EXPECT_EQ(MachineType::Float32(), g0->type);
EXPECT_EQ(0, g0->offset);
EXPECT_FALSE(g0->exported);
EXPECT_EQ(0, g1->name_offset);
EXPECT_EQ(0, g1->name_length);
EXPECT_EQ(MachineType::Float64(), g1->type);
EXPECT_EQ(0, g1->offset);
EXPECT_TRUE(g1->exported);
@ -288,16 +275,16 @@ TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) {
static const byte data[] = {
kDeclFunctions, 1,
// func#0 ------------------------------------------------------
SIG_INDEX(0), // signature index
NAME_OFFSET(0), // name offset
U32_LE(0), // code start offset
U32_LE(0), // code end offset
U16_LE(899), // local int32 count
U16_LE(799), // local int64 count
U16_LE(699), // local float32 count
U16_LE(599), // local float64 count
0, // exported
1 // external
SIG_INDEX(0), // signature index
NO_NAME, // name length
U32_LE(0), // code start offset
U32_LE(0), // code end offset
U16_LE(899), // local int32 count
U16_LE(799), // local int64 count
U16_LE(699), // local float32 count
U16_LE(599), // local float64 count
0, // exported
1 // external
};
ModuleResult result = DecodeModule(data, data + arraysize(data));
@ -307,7 +294,7 @@ TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) {
TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
const int kCodeStartOffset = 31;
const int kCodeStartOffset = 30;
const int kCodeEndOffset = kCodeStartOffset + 1;
static const byte data[] = {
@ -317,13 +304,13 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
// func#0 ------------------------------------------------------
kDeclFunctions, 1,
kDeclFunctionLocals | kDeclFunctionExport | kDeclFunctionName,
SIG_INDEX(0), // signature index
NAME_OFFSET(9), // name offset
U16_LE(1466), // local int32 count
U16_LE(1355), // local int64 count
U16_LE(1244), // local float32 count
U16_LE(1133), // local float64 count
1, 0, // size
SIG_INDEX(0), // signature index
NAME_LENGTH(2), 'h', 'i', // name
U16_LE(1466), // local int32 count
U16_LE(1355), // local int64 count
U16_LE(1244), // local float32 count
U16_LE(1133), // local float64 count
1, 0, // size
kExprNop,
};
@ -339,7 +326,8 @@ TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(9, function->name_offset);
EXPECT_EQ(18, function->name_offset);
EXPECT_EQ(2, function->name_length);
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
@ -373,7 +361,7 @@ TEST_F(WasmModuleVerifyTest, OneFunctionImported) {
EXPECT_EQ(1, result.val->functions.size());
WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(0, function->name_offset);
EXPECT_EQ(0, function->name_length);
EXPECT_EQ(0, function->code_start_offset);
EXPECT_EQ(0, function->code_end_offset);
@ -409,7 +397,7 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) {
EXPECT_EQ(1, result.val->functions.size());
WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(0, function->name_offset);
EXPECT_EQ(0, function->name_length);
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
@ -449,7 +437,7 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) {
EXPECT_EQ(1, result.val->functions.size());
WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(0, function->name_offset);
EXPECT_EQ(0, function->name_length);
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
@ -466,31 +454,29 @@ TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) {
TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
static const byte kDeclMemorySize = 4;
static const byte kCodeStartOffset =
8 + 2 + kDeclMemorySize + kDeclGlobalSize + 4 + 2 + 17;
static const byte kCodeStartOffset = 8 + 4 + 5 + 4 + 18;
static const byte kCodeEndOffset = kCodeStartOffset + 3;
static const byte data[] = {
kDeclMemory, 28, 28, 1,
// global#0 --------------------------------------------------
kDeclGlobals, 1, 0, 0, 0, 0, // name offset
kMemU8, // memory type
0, // exported
kDeclGlobals, 1, 0, // name length
kMemU8, // memory type
0, // exported
// sig#0 -----------------------------------------------------
kDeclSignatures, 1, 0, 0, // void -> void
// func#0 ----------------------------------------------------
kDeclFunctions, 1, kDeclFunctionLocals | kDeclFunctionName, 0,
0, // signature index
9, 0, 0, 0, // name offset
1, 2, // local int32 count
3, 4, // local int64 count
5, 6, // local float32 count
7, 8, // local float64 count
3, 0, // body size
kExprNop, // func#0 body
kExprNop, // func#0 body
kExprNop, // func#0 body
0, // signature index
2, 'h', 'i', // name
1, 2, // local int32 count
3, 4, // local int64 count
5, 6, // local float32 count
7, 8, // local float64 count
3, 0, // body size
kExprNop, // func#0 body
kExprNop, // func#0 body
kExprNop, // func#0 body
// segment#0 -------------------------------------------------
kDeclDataSegments, 1, 0xae, 0xb3, 0x08, 0, // dest addr
15, 0, 0, 0, // source offset
@ -509,14 +495,15 @@ TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
WasmGlobal* global = &result.val->globals.back();
EXPECT_EQ(0, global->name_offset);
EXPECT_EQ(0, global->name_length);
EXPECT_EQ(MachineType::Uint8(), global->type);
EXPECT_EQ(0, global->offset);
EXPECT_FALSE(global->exported);
WasmFunction* function = &result.val->functions.back();
EXPECT_EQ(9, function->name_offset);
EXPECT_EQ(27, function->name_offset);
EXPECT_EQ(2, function->name_length);
EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
@ -1033,10 +1020,7 @@ TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) {
0, // one byte section
kDeclGlobals,
1,
0,
0,
0,
0, // name offset
0, // name length
kMemI32, // memory type
0, // exported
};
@ -1049,7 +1033,7 @@ TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) {
WasmGlobal* global = &result.val->globals.back();
EXPECT_EQ(0, global->name_offset);
EXPECT_EQ(0, global->name_length);
EXPECT_EQ(MachineType::Int32(), global->type);
EXPECT_EQ(0, global->offset);
EXPECT_FALSE(global->exported);
@ -1070,9 +1054,9 @@ TEST_F(WasmModuleVerifyTest, ImportTable_nosigs) {
TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) {
static const byte data[] = {
kDeclSignatures, 0, kDeclImportTable, 1,
SIG_INDEX(0), // sig index
NAME_OFFSET(1), // module name
NAME_OFFSET(1), // function name
IMPORT_SIG_INDEX(0), // sig index
NAME_LENGTH(1), 'm', // module name
NAME_LENGTH(1), 'f', // function name
};
EXPECT_FAILURE(data);
}
@ -1083,10 +1067,10 @@ TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
1,
VOID_VOID_SIG,
kDeclImportTable,
1, // --
U32V_1(0), // sig index
NAME_OFFSET(1), // module name
NAME_OFFSET(1) // function name
1, // --
IMPORT_SIG_INDEX(0), // sig index
NAME_LENGTH(1), 'm', // module name
NAME_LENGTH(1), 'f', // function name
};
EXPECT_VERIFIES(data);
}
@ -1097,10 +1081,10 @@ TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) {
1,
VOID_VOID_SIG,
kDeclImportTable,
1, // --
SIG_INDEX(0), // sig index
NAME_OFFSET(0), // module name
NAME_OFFSET(1) // function name
1, // --
IMPORT_SIG_INDEX(0), // sig index
NO_NAME, // module name
NAME_LENGTH(1), 'f' // function name
};
EXPECT_FAILURE(data);
}
@ -1108,9 +1092,9 @@ TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) {
TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
static const byte data[] = {
kDeclSignatures, 1, VOID_VOID_SIG, kDeclImportTable, 1,
SIG_INDEX(0), // sig index
NAME_OFFSET(1), // module name
NAME_OFFSET(1), // function name
IMPORT_SIG_INDEX(0), // sig index
NAME_LENGTH(1), 'm', // module name
NAME_LENGTH(1), 'f', // function name
};
EXPECT_OFF_END_FAILURE(data, 5, sizeof(data));
@ -1140,41 +1124,41 @@ TEST_F(WasmModuleVerifyTest, ExportTableOne) {
EMPTY_FUNCTION(0), // --
kDeclExportTable, 1, // exports
FUNC_INDEX(0), // --
NAME_OFFSET(0) // --
NO_NAME // --
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, ExportTableTwo) {
static const byte data[] = {
kDeclSignatures, 1, // sigs
VOID_VOID_SIG, // --
kDeclFunctions, 1, // functions
EMPTY_FUNCTION(0), // --
kDeclExportTable, 2, // exports
FUNC_INDEX(0), // --
NAME_OFFSET(1), // --
FUNC_INDEX(0), // --
NAME_OFFSET(2) // --
kDeclSignatures, 1, // sigs
VOID_VOID_SIG, // --
kDeclFunctions, 1, // functions
EMPTY_FUNCTION(0), // --
kDeclExportTable, 2, // exports
FUNC_INDEX(0), // --
NAME_LENGTH(4), 'n', 'a', 'm', 'e', // --
FUNC_INDEX(0), // --
NAME_LENGTH(3), 'n', 'o', 'm' // --
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, ExportTableThree) {
static const byte data[] = {
kDeclSignatures, 1, // sigs
VOID_VOID_SIG, // --
kDeclFunctions, 3, // functions
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
kDeclExportTable, 3, // exports
FUNC_INDEX(0), // --
NAME_OFFSET(1), // --
FUNC_INDEX(1), // --
NAME_OFFSET(2), // --
FUNC_INDEX(2), // --
NAME_OFFSET(2) // --
kDeclSignatures, 1, // sigs
VOID_VOID_SIG, // --
kDeclFunctions, 3, // functions
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
kDeclExportTable, 3, // exports
FUNC_INDEX(0), // --
NAME_LENGTH(1), 'a', // --
FUNC_INDEX(1), // --
NAME_LENGTH(1), 'b', // --
FUNC_INDEX(2), // --
NAME_LENGTH(1), 'c' // --
};
EXPECT_VERIFIES(data);
}
@ -1182,15 +1166,15 @@ TEST_F(WasmModuleVerifyTest, ExportTableThree) {
TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) {
for (int i = 0; i < 6; i++) {
const byte data[] = {
kDeclSignatures, 1, // sigs
VOID_VOID_SIG, // --
kDeclFunctions, 3, // functions
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
kDeclExportTable, 1, // exports
FUNC_INDEX(i), // --
NAME_OFFSET(1) // --
kDeclSignatures, 1, // sigs
VOID_VOID_SIG, // --
kDeclFunctions, 3, // functions
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
EMPTY_FUNCTION(0), // --
kDeclExportTable, 1, // exports
FUNC_INDEX(i), // --
NAME_LENGTH(2), 'e', 'x', // --
};
if (i < 3) {
@ -1209,7 +1193,7 @@ TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) {
EMPTY_FUNCTION(0), // --
kDeclExportTable, 1, // exports
FUNC_INDEX(0), // --
NAME_OFFSET(0) // --
NO_NAME // --
};
for (int length = 13; length < sizeof(data); length++) {