From ca0dbaece0083535e8ba3d03d49993d33365cf3a Mon Sep 17 00:00:00 2001 From: binji Date: Wed, 9 Mar 2016 10:55:27 -0800 Subject: [PATCH] [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} --- src/compiler/wasm-compiler.cc | 36 +-- src/compiler/wasm-compiler.h | 4 +- src/wasm/decoder.h | 2 + src/wasm/encoder.cc | 19 +- src/wasm/module-decoder.cc | 32 ++- src/wasm/wasm-macro-gen.h | 5 +- src/wasm/wasm-module.cc | 75 +++--- src/wasm/wasm-module.h | 26 +- src/wasm/wasm-opcodes.h | 5 + test/cctest/wasm/test-run-wasm-js.cc | 6 +- test/cctest/wasm/wasm-run-utils.h | 4 +- test/mjsunit/wasm/wasm-module-builder.js | 44 +--- test/unittests/wasm/ast-decoder-unittest.cc | 2 +- .../unittests/wasm/module-decoder-unittest.cc | 232 ++++++++---------- 14 files changed, 244 insertions(+), 248 deletions(-) diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index 80475ba006..6f756fdc8a 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -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 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 name_str = isolate->factory()->NewStringFromAsciiChecked(buffer.start()); Handle script_str = @@ -2312,8 +2313,9 @@ Handle 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 CompileJSToWasmWrapper( Handle CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module, Handle 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 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 CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, } // Add the function as another context for the exception ScopedVector 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::null(); } @@ -2456,8 +2459,10 @@ Handle CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, Vector buffer; if (debugging) { buffer = Vector::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 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; diff --git a/src/compiler/wasm-compiler.h b/src/compiler/wasm-compiler.h index 67e5e1688a..33c41d79a2 100644 --- a/src/compiler/wasm-compiler.h +++ b/src/compiler/wasm-compiler.h @@ -41,8 +41,8 @@ Handle CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, Handle CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module, Handle 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. diff --git a/src/wasm/decoder.h b/src/wasm/decoder.h index 0ca4e47f75..098c3306da 100644 --- a/src/wasm/decoder.h +++ b/src/wasm/decoder.h @@ -225,6 +225,8 @@ class Decoder { *length = static_cast(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); } diff --git a/src/wasm/encoder.cc b/src/wasm/encoder.cc index b65fc385df..6309f46553 100644 --- a/src/wasm/encoder.cc +++ b/src/wasm/encoder.cc @@ -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(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(*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); } diff --git a/src/wasm/module-decoder.cc b/src/wasm/module-decoder.cc index b245e1e079..8a81f44242 100644 --- a/src/wasm/module-decoder.cc +++ b/src/wasm/module-decoder.cc @@ -161,7 +161,7 @@ class ModuleDecoder : public Decoder { if (failed()) break; TRACE("DecodeGlobal[%d] module+%d\n", i, static_cast(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(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(pc_ - start_); + consume_bytes(*length); + return offset; } // Reads a single 8-bit integer, interpreting it as a local type. diff --git a/src/wasm/wasm-macro-gen.h b/src/wasm/wasm-macro-gen.h index 6245f341bf..b6818860f6 100644 --- a/src/wasm/wasm-macro-gen.h +++ b/src/wasm/wasm-macro-gen.h @@ -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 diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc index 74e60b70e8..19611c9272 100644 --- a/src/wasm/wasm-module.cc +++ b/src/wasm/wasm-module.cc @@ -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 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(); @@ -295,35 +298,37 @@ static MaybeHandle ReportFFIError(ErrorThrower& thrower, static MaybeHandle LookupFunction( ErrorThrower& thrower, Factory* factory, Handle 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 name = factory->InternalizeUtf8String(module_cstr); + Handle name = factory->InternalizeUtf8String( + Vector(module_name.name, module_name.length)); MaybeHandle 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 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 function; - if (function_cstr) { + if (function_name.name) { // Look up the function in the module. - Handle name = factory->InternalizeUtf8String(function_cstr); + Handle name = factory->InternalizeUtf8String( + Vector(function_name.name, function_name.length)); MaybeHandle 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 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::cast(function); @@ -404,14 +409,16 @@ MaybeHandle 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 function = LookupFunction( - thrower, factory, ffi, index, module_cstr, function_cstr); + thrower, factory, ffi, index, module_name, function_name); if (function.is_null()) return MaybeHandle(); Handle 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 WasmModule::Instantiate(Isolate* isolate, if (thrower.error()) break; DCHECK_EQ(index, func.func_index); - const char* cstr = GetName(func.name_offset); - Handle name = factory->InternalizeUtf8String(cstr); + WasmName str = GetName(func.name_offset, func.name_length); + WasmName str_null = {nullptr, 0}; + Handle name = factory->InternalizeUtf8String( + Vector(str.name, str.length)); Handle code = Handle::null(); Handle function = Handle::null(); if (func.external) { // Lookup external function in FFI object. MaybeHandle function = - LookupFunction(thrower, factory, ffi, index, cstr, nullptr); + LookupFunction(thrower, factory, ffi, index, str, str_null); if (function.is_null()) return MaybeHandle(); 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(); } if (func.exported) { @@ -485,8 +495,9 @@ MaybeHandle 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 name = factory->InternalizeUtf8String(cstr); + WasmName str = GetName(exp.name_offset, exp.name_length); + Handle name = factory->InternalizeUtf8String( + Vector(str.name, str.length)); Handle code = linker.GetFunctionCode(exp.func_index); Handle function = compiler::CompileJSToWasmWrapper( isolate, &module_env, name, code, instance.js_object, exp.func_index); diff --git a/src/wasm/wasm-module.h b/src/wasm/wasm-module.h index b13345e458..4a6eb92b5d 100644 --- a/src/wasm/wasm-module.h +++ b/src/wasm/wasm-module.h @@ -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(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(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(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(module_start + offset), length}; } // Checks the given offset range is contained within the module bytes. diff --git a/src/wasm/wasm-opcodes.h b/src/wasm/wasm-opcodes.h index f718465256..ab055fc8ee 100644 --- a/src/wasm/wasm-opcodes.h +++ b/src/wasm/wasm-opcodes.h @@ -49,6 +49,11 @@ const LocalType kAstEnd = MachineRepresentation::kTagged; typedef Signature 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. diff --git a/test/cctest/wasm/test-run-wasm-js.cc b/test/cctest/wasm/test-run-wasm-js.cc index 443a783287..1456850a02 100644 --- a/test/cctest/wasm/test-run-wasm-js.cc +++ b/test/cctest/wasm/test-run-wasm-js.cc @@ -56,8 +56,10 @@ uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig, module->AddFunction(sig, Handle::null()); uint32_t index = static_cast(module->module->functions.size() - 1); Isolate* isolate = CcTest::InitIsolateOnce(); - Handle code = - CompileWasmToJSWrapper(isolate, module, jsfunc, sig, "test", nullptr); + WasmName module_name = {"test", 4}; + WasmName function_name = {nullptr, 0}; + Handle code = CompileWasmToJSWrapper(isolate, module, jsfunc, sig, + module_name, function_name); module->instance->function_code[index] = code; return index; } diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h index 614f0fe10c..964ec7d688 100644 --- a/test/cctest/wasm/wasm-run-utils.h +++ b/test/cctest/wasm/wasm-run-utils.h @@ -167,7 +167,7 @@ class TestingModule : public ModuleEnv { } uint32_t index = static_cast(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); diff --git a/test/mjsunit/wasm/wasm-module-builder.js b/test/mjsunit/wasm/wasm-module-builder.js index 7ccd2a42c1..61e074b13d 100644 --- a/test/mjsunit/wasm/wasm-module-builder.js +++ b/test/mjsunit/wasm/wasm-module-builder.js @@ -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; diff --git a/test/unittests/wasm/ast-decoder-unittest.cc b/test/unittests/wasm/ast-decoder-unittest.cc index 36b43ef402..aa98929574 100644 --- a/test/unittests/wasm/ast-decoder-unittest.cc +++ b/test/unittests/wasm/ast-decoder-unittest.cc @@ -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(mod.globals.size() - 1); } diff --git a/test/unittests/wasm/module-decoder-unittest.cc b/test/unittests/wasm/module-decoder-unittest.cc index 0b363f68a3..c1368bbb4c 100644 --- a/test/unittests/wasm/module-decoder-unittest.cc +++ b/test/unittests/wasm/module-decoder-unittest.cc @@ -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& 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++) {