Index: src/wasm/wasm-module.h |
diff --git a/src/wasm/wasm-module.h b/src/wasm/wasm-module.h |
index 4f15b62457a329f0e970a1b58d07f23d407f6163..1db3304fb270bc5206fe4c29973e3df48e2baf44 100644 |
--- a/src/wasm/wasm-module.h |
+++ b/src/wasm/wasm-module.h |
@@ -27,84 +27,71 @@ const size_t kMaxModuleSize = 1024 * 1024 * 1024; |
const size_t kMaxFunctionSize = 128 * 1024; |
const size_t kMaxStringSize = 256; |
const uint32_t kWasmMagic = 0x6d736100; |
-const uint32_t kWasmVersion = 0x0b; |
+const uint32_t kWasmVersion = 0x0c; |
+ |
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; |
+} |
-// 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) |
+const char* SectionName(WasmSectionCode code); |
class WasmDebugInfo; |
-struct V8_EXPORT_PRIVATE 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); |
+// Constants for fixed-size elements within a module. |
+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 |
}; |
-enum WasmFunctionDeclBit { |
- kDeclFunctionName = 0x01, |
- kDeclFunctionExport = 0x08 |
+// 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; |
}; |
-// 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; |
+#define NO_INIT \ |
+ { \ |
+ WasmInitExpr::kNone, { 0u } \ |
+ } |
// Static representation of a WASM function. |
struct WasmFunction { |
@@ -115,47 +102,59 @@ struct WasmFunction { |
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. |
-}; |
- |
-// 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. |
+ bool imported; |
+ bool exported; |
}; |
// 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. |
- uint32_t offset; // offset from beginning of globals area. |
- bool exported; // true if this global is exported. |
+ 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. |
}; |
// Static representation of a wasm data segment. |
struct WasmDataSegment { |
- uint32_t dest_addr; // destination memory address of the data. |
+ WasmInitExpr 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<uint16_t> values; // function table. |
+ 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. |
}; |
enum ModuleOrigin { kWasmOrigin, kAsmJsOrigin }; |
@@ -163,6 +162,7 @@ enum ModuleOrigin { kWasmOrigin, kAsmJsOrigin }; |
// 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 |
@@ -171,7 +171,6 @@ struct WasmModule { |
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. |
@@ -180,12 +179,16 @@ struct WasmModule { |
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 |
@@ -234,8 +237,8 @@ struct WasmModule { |
// Creates a new instantiation of the module in the given isolate. |
V8_EXPORT_PRIVATE static MaybeHandle<JSObject> Instantiate( |
- Isolate* isolate, Handle<JSObject> module_object, Handle<JSReceiver> ffi, |
- Handle<JSArrayBuffer> memory); |
+ Isolate* isolate, ErrorThrower* thrower, Handle<JSObject> module_object, |
+ Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory); |
MaybeHandle<FixedArray> CompileFunctions(Isolate* isolate, |
ErrorThrower* thrower) const; |
@@ -254,7 +257,6 @@ struct WasmModuleInstance { |
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. |
@@ -265,7 +267,6 @@ struct WasmModuleInstance { |
: 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) {} |
@@ -277,9 +278,6 @@ struct ModuleEnv { |
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(); |
@@ -290,9 +288,6 @@ struct ModuleEnv { |
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(); |
} |
@@ -304,10 +299,6 @@ struct ModuleEnv { |
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]; |
@@ -319,8 +310,10 @@ struct ModuleEnv { |
bool asm_js() { return origin == kAsmJsOrigin; } |
- Handle<Code> GetCodeOrPlaceholder(uint32_t index) const; |
- Handle<Code> GetImportCode(uint32_t index); |
+ Handle<Code> GetFunctionCode(uint32_t index) { |
+ DCHECK_NOT_NULL(instance); |
+ return instance->function_code[index]; |
+ } |
static compiler::CallDescriptor* GetWasmCallDescriptor(Zone* zone, |
FunctionSig* sig); |
@@ -405,6 +398,9 @@ V8_EXPORT_PRIVATE MaybeHandle<JSObject> CreateModuleObjectFromBytes( |
Isolate* isolate, const byte* start, const byte* end, 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 |