Index: src/wasm/wasm-module.h |
diff --git a/src/wasm/wasm-module.h b/src/wasm/wasm-module.h |
index 2ef75ec14ffcd563e121ac160f1e15b40f30033c..0b9bc9762edec2834637c738356d4c160f5f6e71 100644 |
--- a/src/wasm/wasm-module.h |
+++ b/src/wasm/wasm-module.h |
@@ -27,73 +27,84 @@ |
const size_t kMaxFunctionSize = 128 * 1024; |
const size_t kMaxStringSize = 256; |
const uint32_t kWasmMagic = 0x6d736100; |
-const uint32_t kWasmVersion = 0x0c; |
+const uint32_t kWasmVersion = 0x0b; |
const uint8_t kWasmFunctionTypeForm = 0x40; |
-const uint8_t kWasmAnyFunctionTypeForm = 0x20; |
- |
-enum WasmSectionCode { |
- kUnknownSectionCode = 0, // code for unknown sections |
- kTypeSectionCode = 1, // Function signature declarations |
- kImportSectionCode = 2, // Import declarations |
- kFunctionSectionCode = 3, // Function declarations |
- kTableSectionCode = 4, // Indirect function table and other tables |
- kMemorySectionCode = 5, // Memory attributes |
- kGlobalSectionCode = 6, // Global declarations |
- kExportSectionCode = 7, // Exports |
- kStartSectionCode = 8, // Start function declaration |
- kElementSectionCode = 9, // Elements section |
- kCodeSectionCode = 10, // Function code |
- kDataSectionCode = 11, // Data segments |
- kNameSectionCode = 12, // Name section (encoded as a string) |
-}; |
- |
-inline bool IsValidSectionCode(uint8_t byte) { |
- return kTypeSectionCode <= byte && byte <= kDataSectionCode; |
-} |
- |
-const char* SectionName(WasmSectionCode code); |
- |
-static const char* kNameString = "name"; |
-static const size_t kNameStringLength = 4; |
+ |
+// WebAssembly sections are named as strings in the binary format, but |
+// internally V8 uses an enum to handle them. |
+// |
+// Entries have the form F(enumerator, string). |
+#define FOR_EACH_WASM_SECTION_TYPE(F) \ |
+ F(Signatures, 1, "type") \ |
+ F(ImportTable, 2, "import") \ |
+ F(FunctionSignatures, 3, "function") \ |
+ F(FunctionTable, 4, "table") \ |
+ F(Memory, 5, "memory") \ |
+ F(ExportTable, 6, "export") \ |
+ F(StartFunction, 7, "start") \ |
+ F(FunctionBodies, 8, "code") \ |
+ F(DataSegments, 9, "data") \ |
+ F(Names, 10, "name") \ |
+ F(Globals, 0, "global") \ |
+ F(End, 0, "end") |
+ |
+// Contants for the above section types: {LEB128 length, characters...}. |
+#define WASM_SECTION_MEMORY 6, 'm', 'e', 'm', 'o', 'r', 'y' |
+#define WASM_SECTION_SIGNATURES 4, 't', 'y', 'p', 'e' |
+#define WASM_SECTION_GLOBALS 6, 'g', 'l', 'o', 'b', 'a', 'l' |
+#define WASM_SECTION_DATA_SEGMENTS 4, 'd', 'a', 't', 'a' |
+#define WASM_SECTION_FUNCTION_TABLE 5, 't', 'a', 'b', 'l', 'e' |
+#define WASM_SECTION_END 3, 'e', 'n', 'd' |
+#define WASM_SECTION_START_FUNCTION 5, 's', 't', 'a', 'r', 't' |
+#define WASM_SECTION_IMPORT_TABLE 6, 'i', 'm', 'p', 'o', 'r', 't' |
+#define WASM_SECTION_EXPORT_TABLE 6, 'e', 'x', 'p', 'o', 'r', 't' |
+#define WASM_SECTION_FUNCTION_SIGNATURES \ |
+ 8, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n' |
+#define WASM_SECTION_FUNCTION_BODIES 4, 'c', 'o', 'd', 'e' |
+#define WASM_SECTION_NAMES 4, 'n', 'a', 'm', 'e' |
+ |
+// Constants for the above section headers' size (LEB128 + characters). |
+#define WASM_SECTION_MEMORY_SIZE ((size_t)7) |
+#define WASM_SECTION_SIGNATURES_SIZE ((size_t)5) |
+#define WASM_SECTION_GLOBALS_SIZE ((size_t)7) |
+#define WASM_SECTION_DATA_SEGMENTS_SIZE ((size_t)5) |
+#define WASM_SECTION_FUNCTION_TABLE_SIZE ((size_t)6) |
+#define WASM_SECTION_END_SIZE ((size_t)4) |
+#define WASM_SECTION_START_FUNCTION_SIZE ((size_t)6) |
+#define WASM_SECTION_IMPORT_TABLE_SIZE ((size_t)7) |
+#define WASM_SECTION_EXPORT_TABLE_SIZE ((size_t)7) |
+#define WASM_SECTION_FUNCTION_SIGNATURES_SIZE ((size_t)9) |
+#define WASM_SECTION_FUNCTION_BODIES_SIZE ((size_t)5) |
+#define WASM_SECTION_NAMES_SIZE ((size_t)5) |
class WasmDebugInfo; |
+struct WasmSection { |
+ enum class Code : uint32_t { |
+#define F(enumerator, order, string) enumerator, |
+ FOR_EACH_WASM_SECTION_TYPE(F) |
+#undef F |
+ Max |
+ }; |
+ static WasmSection::Code begin(); |
+ static WasmSection::Code end(); |
+ static WasmSection::Code next(WasmSection::Code code); |
+ static const char* getName(Code code); |
+ static int getOrder(Code code); |
+ static size_t getNameLength(Code code); |
+ static WasmSection::Code lookup(const byte* string, uint32_t length); |
+}; |
+ |
+enum WasmFunctionDeclBit { |
+ kDeclFunctionName = 0x01, |
+ kDeclFunctionExport = 0x08 |
+}; |
+ |
// Constants for fixed-size elements within a module. |
+static const size_t kDeclMemorySize = 3; |
+static const size_t kDeclDataSegmentSize = 13; |
+ |
static const uint32_t kMaxReturnCount = 1; |
-static const uint8_t kResizableMaximumFlag = 1; |
-static const int32_t kInvalidFunctionIndex = -1; |
- |
-enum WasmExternalKind { |
- kExternalFunction = 0, |
- kExternalTable = 1, |
- kExternalMemory = 2, |
- kExternalGlobal = 3 |
-}; |
- |
-// Representation of an initializer expression. |
-struct WasmInitExpr { |
- enum WasmInitKind { |
- kNone, |
- kGlobalIndex, |
- kI32Const, |
- kI64Const, |
- kF32Const, |
- kF64Const |
- } kind; |
- |
- union { |
- int32_t i32_const; |
- int64_t i64_const; |
- float f32_const; |
- double f64_const; |
- uint32_t global_index; |
- } val; |
-}; |
- |
-#define NO_INIT \ |
- { \ |
- WasmInitExpr::kNone, { 0u } \ |
- } |
// Static representation of a WASM function. |
struct WasmFunction { |
@@ -104,59 +115,47 @@ |
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. |
- bool imported; |
- bool exported; |
+}; |
+ |
+// Static representation of an imported WASM function. |
+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. |
LocalType type; // type of the global. |
- bool mutability; // {true} if mutable. |
- WasmInitExpr init; // the initialization expression of the global. |
- uint32_t offset; // offset into global memory. |
- bool imported; // true if imported. |
- bool exported; // true if exported. |
+ uint32_t offset; // offset from beginning of globals area. |
+ bool exported; // true if this global is exported. |
}; |
// Static representation of a wasm data segment. |
struct WasmDataSegment { |
- WasmInitExpr dest_addr; // destination memory address of the data. |
+ uint32_t dest_addr; // destination memory address of the data. |
uint32_t source_offset; // start offset in the module bytes. |
uint32_t source_size; // end offset in the module bytes. |
+ bool init; // true if loaded upon instantiation. |
}; |
// Static representation of a wasm indirect call table. |
struct WasmIndirectFunctionTable { |
- uint32_t size; // initial table size. |
- uint32_t max_size; // maximum table size. |
- std::vector<int32_t> values; // function table, -1 indicating invalid. |
- bool imported; // true if imported. |
- bool exported; // true if exported. |
-}; |
- |
-// Static representation of how to initialize a table. |
-struct WasmTableInit { |
- uint32_t table_index; |
- WasmInitExpr offset; |
- std::vector<uint32_t> entries; |
-}; |
- |
-// Static representation of a WASM import. |
-struct WasmImport { |
- uint32_t module_name_length; // length in bytes of the module name. |
- uint32_t module_name_offset; // offset in module bytes of the module name. |
- uint32_t field_name_length; // length in bytes of the import name. |
- uint32_t field_name_offset; // offset in module bytes of the import name. |
- WasmExternalKind kind; // kind of the import. |
- uint32_t index; // index into the respective space. |
-}; |
- |
-// Static representation of a WASM export. |
-struct WasmExport { |
- uint32_t name_length; // length in bytes of the exported name. |
- uint32_t name_offset; // offset in module bytes of the name to export. |
- WasmExternalKind kind; // kind of the export. |
- uint32_t index; // index into the respective space. |
+ uint32_t size; // initial table size. |
+ uint32_t max_size; // maximum table size. |
+ std::vector<uint16_t> values; // function table. |
}; |
enum ModuleOrigin { kWasmOrigin, kAsmJsOrigin }; |
@@ -164,7 +163,6 @@ |
// Static representation of a module. |
struct WasmModule { |
static const uint32_t kPageSize = 0x10000; // Page size, 64kb. |
- static const uint32_t kMaxLegalPages = 65536; // Maximum legal pages |
static const uint32_t kMinMemPages = 1; // Minimum memory size = 64kb |
static const uint32_t kMaxMemPages = 16384; // Maximum memory size = 1gb |
@@ -173,6 +171,7 @@ |
uint32_t min_mem_pages; // minimum size of the memory in 64k pages. |
uint32_t max_mem_pages; // maximum size of the memory in 64k pages. |
bool mem_export; // true if the memory is exported. |
+ bool mem_external; // true if the memory is external. |
// TODO(wasm): reconcile start function index being an int with |
// the fact that we index on uint32_t, so we may technically not be |
// able to represent some start_function_index -es. |
@@ -181,16 +180,12 @@ |
std::vector<WasmGlobal> globals; // globals in this module. |
uint32_t globals_size; // size of globals table. |
- uint32_t num_imported_functions; // number of imported functions. |
- uint32_t num_declared_functions; // number of declared functions. |
- uint32_t num_exported_functions; // number of exported functions. |
std::vector<FunctionSig*> signatures; // signatures in this module. |
std::vector<WasmFunction> functions; // functions in this module. |
std::vector<WasmDataSegment> data_segments; // data segments in this module. |
std::vector<WasmIndirectFunctionTable> function_tables; // function tables. |
std::vector<WasmImport> import_table; // import table. |
std::vector<WasmExport> export_table; // export table. |
- std::vector<WasmTableInit> table_inits; // initializations of tables |
// We store the semaphore here to extend its lifetime. In <libc-2.21, which we |
// use on the try bots, semaphore::Wait() can return while some compilation |
// tasks are still executing semaphore::Signal(). If the semaphore is cleaned |
@@ -239,7 +234,6 @@ |
// Creates a new instantiation of the module in the given isolate. |
static MaybeHandle<JSObject> Instantiate(Isolate* isolate, |
- ErrorThrower* thrower, |
Handle<JSObject> module_object, |
Handle<JSReceiver> ffi, |
Handle<JSArrayBuffer> memory); |
@@ -261,6 +255,7 @@ |
Handle<JSArrayBuffer> globals_buffer; // Handle to array buffer of globals. |
std::vector<Handle<FixedArray>> function_tables; // indirect function tables. |
std::vector<Handle<Code>> function_code; // code objects for each function. |
+ std::vector<Handle<Code>> import_code; // code objects for each import. |
// -- raw memory ------------------------------------------------------------ |
byte* mem_start; // start of linear memory. |
uint32_t mem_size; // size of the linear memory. |
@@ -271,6 +266,7 @@ |
: module(m), |
function_tables(m->function_tables.size()), |
function_code(m->functions.size()), |
+ import_code(m->import_table.size()), |
mem_start(nullptr), |
mem_size(0), |
globals_start(nullptr) {} |
@@ -282,6 +278,9 @@ |
const WasmModule* module; |
WasmModuleInstance* instance; |
ModuleOrigin origin; |
+ // TODO(mtrofin): remove this once we introduce WASM_DIRECT_CALL |
+ // reloc infos. |
+ std::vector<Handle<Code>> placeholders; |
bool IsValidGlobal(uint32_t index) const { |
return module && index < module->globals.size(); |
@@ -291,6 +290,9 @@ |
} |
bool IsValidSignature(uint32_t index) const { |
return module && index < module->signatures.size(); |
+ } |
+ bool IsValidImport(uint32_t index) const { |
+ return module && index < module->import_table.size(); |
} |
bool IsValidTable(uint32_t index) const { |
return module && index < module->function_tables.size(); |
@@ -303,6 +305,10 @@ |
DCHECK(IsValidFunction(index)); |
return module->functions[index].sig; |
} |
+ FunctionSig* GetImportSignature(uint32_t index) { |
+ DCHECK(IsValidImport(index)); |
+ return module->import_table[index].sig; |
+ } |
FunctionSig* GetSignature(uint32_t index) { |
DCHECK(IsValidSignature(index)); |
return module->signatures[index]; |
@@ -314,10 +320,8 @@ |
bool asm_js() { return origin == kAsmJsOrigin; } |
- Handle<Code> GetFunctionCode(uint32_t index) { |
- DCHECK_NOT_NULL(instance); |
- return instance->function_code[index]; |
- } |
+ Handle<Code> GetCodeOrPlaceholder(uint32_t index) const; |
+ Handle<Code> GetImportCode(uint32_t index); |
static compiler::CallDescriptor* GetWasmCallDescriptor(Zone* zone, |
FunctionSig* sig); |
@@ -404,9 +408,6 @@ |
ErrorThrower* thrower, |
ModuleOrigin origin); |
-// Get the number of imported functions for a WASM instance. |
-uint32_t GetNumImportedFunctions(Handle<JSObject> wasm_object); |
- |
// Assumed to be called with a code object associated to a wasm module instance. |
// Intended to be called from runtime functions. |
// Returns undefined if the runtime support was not setup, nullptr if the |