LCOV - code coverage report
Current view: top level - src/wasm - wasm-module.h (source / functions) Hit Total Coverage
Test: app.info Lines: 28 28 100.0 %
Date: 2019-04-17 Functions: 2 2 100.0 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_WASM_WASM_MODULE_H_
       6             : #define V8_WASM_WASM_MODULE_H_
       7             : 
       8             : #include <memory>
       9             : 
      10             : #include "src/globals.h"
      11             : #include "src/handles.h"
      12             : #include "src/vector.h"
      13             : #include "src/wasm/signature-map.h"
      14             : #include "src/wasm/wasm-constants.h"
      15             : #include "src/wasm/wasm-opcodes.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20             : class WasmDebugInfo;
      21             : class WasmModuleObject;
      22             : 
      23             : namespace wasm {
      24             : 
      25             : using WasmName = Vector<const char>;
      26             : 
      27             : class ErrorThrower;
      28             : 
      29             : // Reference to a string in the wire bytes.
      30             : class WireBytesRef {
      31             :  public:
      32             :   WireBytesRef() : WireBytesRef(0, 0) {}
      33             :   WireBytesRef(uint32_t offset, uint32_t length)
      34     4788363 :       : offset_(offset), length_(length) {
      35             :     DCHECK_IMPLIES(offset_ == 0, length_ == 0);
      36             :     DCHECK_LE(offset_, offset_ + length_);  // no uint32_t overflow.
      37             :   }
      38             : 
      39             :   uint32_t offset() const { return offset_; }
      40             :   uint32_t length() const { return length_; }
      41     1222938 :   uint32_t end_offset() const { return offset_ + length_; }
      42             :   bool is_empty() const { return length_ == 0; }
      43             :   bool is_set() const { return offset_ != 0; }
      44             : 
      45             :  private:
      46             :   uint32_t offset_;
      47             :   uint32_t length_;
      48             : };
      49             : 
      50             : // Static representation of a wasm function.
      51             : struct WasmFunction {
      52             :   FunctionSig* sig;      // signature of the function.
      53             :   uint32_t func_index;   // index into the function table.
      54             :   uint32_t sig_index;    // index into the signature table.
      55             :   WireBytesRef code;     // code of this function.
      56             :   bool imported;
      57             :   bool exported;
      58             : };
      59             : 
      60             : // Static representation of a wasm global variable.
      61             : struct WasmGlobal {
      62             :   ValueType type;     // type of the global.
      63             :   bool mutability;    // {true} if mutable.
      64             :   WasmInitExpr init;  // the initialization expression of the global.
      65             :   union {
      66             :     uint32_t index;   // index of imported mutable global.
      67             :     uint32_t offset;  // offset into global memory (if not imported & mutable).
      68             :   };
      69             :   bool imported;  // true if imported.
      70             :   bool exported;  // true if exported.
      71             : };
      72             : 
      73             : // Note: An exception signature only uses the params portion of a
      74             : // function signature.
      75             : using WasmExceptionSig = FunctionSig;
      76             : 
      77             : // Static representation of a wasm exception type.
      78             : struct WasmException {
      79         835 :   explicit WasmException(const WasmExceptionSig* sig) : sig(sig) {}
      80         933 :   FunctionSig* ToFunctionSig() const { return const_cast<FunctionSig*>(sig); }
      81             : 
      82             :   const WasmExceptionSig* sig;  // type signature of the exception.
      83             : };
      84             : 
      85             : // Static representation of a wasm data segment.
      86             : struct WasmDataSegment {
      87             :   // Construct an active segment.
      88             :   explicit WasmDataSegment(WasmInitExpr dest_addr)
      89        3126 :       : dest_addr(dest_addr), active(true) {}
      90             : 
      91             :   // Construct a passive segment, which has no dest_addr.
      92         109 :   WasmDataSegment() : active(false) {}
      93             : 
      94             :   WasmInitExpr dest_addr;  // destination memory address of the data.
      95             :   WireBytesRef source;     // start offset in the module bytes.
      96             :   bool active = true;      // true if copied automatically during instantiation.
      97             : };
      98             : 
      99             : // Static representation of a wasm indirect call table.
     100             : struct WasmTable {
     101             :   MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(WasmTable);
     102             :   ValueType type = kWasmStmt;     // table type.
     103             :   uint32_t initial_size = 0;      // initial table size.
     104             :   uint32_t maximum_size = 0;      // maximum table size.
     105             :   bool has_maximum_size = false;  // true if there is a maximum size.
     106             :   bool imported = false;        // true if imported.
     107             :   bool exported = false;        // true if exported.
     108             : };
     109             : 
     110             : // Static representation of wasm element segment (table initializer).
     111        3525 : struct WasmElemSegment {
     112        1604 :   MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmElemSegment);
     113             : 
     114             :   // Construct an active segment.
     115             :   WasmElemSegment(uint32_t table_index, WasmInitExpr offset)
     116        5300 :       : table_index(table_index), offset(offset), active(true) {}
     117             : 
     118             :   // Construct a passive segment, which has no table index or offset.
     119         146 :   WasmElemSegment() : table_index(0), active(false) {}
     120             : 
     121             :   // Used in the {entries} vector to represent a `ref.null` entry in a passive
     122             :   // segment.
     123             :   V8_EXPORT_PRIVATE static const uint32_t kNullIndex = ~0u;
     124             : 
     125             :   uint32_t table_index;
     126             :   WasmInitExpr offset;
     127             :   std::vector<uint32_t> entries;
     128             :   bool active;  // true if copied automatically during instantiation.
     129             : };
     130             : 
     131             : // Static representation of a wasm import.
     132             : struct WasmImport {
     133             :   WireBytesRef module_name;   // module name.
     134             :   WireBytesRef field_name;    // import name.
     135             :   ImportExportKindCode kind;  // kind of the import.
     136             :   uint32_t index;             // index into the respective space.
     137             : };
     138             : 
     139             : // Static representation of a wasm export.
     140             : struct WasmExport {
     141             :   WireBytesRef name;          // exported name.
     142             :   ImportExportKindCode kind;  // kind of the export.
     143             :   uint32_t index;             // index into the respective space.
     144             : };
     145             : 
     146             : enum class WasmCompilationHintStrategy : uint8_t {
     147             :   kDefault = 0,
     148             :   kLazy = 1,
     149             :   kEager = 2,
     150             : };
     151             : 
     152             : enum class WasmCompilationHintTier : uint8_t {
     153             :   kDefault = 0,
     154             :   kInterpreter = 1,
     155             :   kBaseline = 2,
     156             :   kOptimized = 3,
     157             : };
     158             : 
     159             : // Static representation of a wasm compilation hint
     160             : struct WasmCompilationHint {
     161             :   WasmCompilationHintStrategy strategy;
     162             :   WasmCompilationHintTier baseline_tier;
     163             :   WasmCompilationHintTier top_tier;
     164             : };
     165             : 
     166             : enum ModuleOrigin : uint8_t { kWasmOrigin, kAsmJsOrigin };
     167             : 
     168             : #define SELECT_WASM_COUNTER(counters, origin, prefix, suffix)     \
     169             :   ((origin) == kWasmOrigin ? (counters)->prefix##_wasm_##suffix() \
     170             :                            : (counters)->prefix##_asm_##suffix())
     171             : 
     172             : struct ModuleWireBytes;
     173             : 
     174             : // Static representation of a module.
     175     5524540 : struct V8_EXPORT_PRIVATE WasmModule {
     176             :   MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmModule);
     177             : 
     178             :   std::unique_ptr<Zone> signature_zone;
     179             :   uint32_t initial_pages = 0;      // initial size of the memory in 64k pages
     180             :   uint32_t maximum_pages = 0;      // maximum size of the memory in 64k pages
     181             :   bool has_shared_memory = false;  // true if memory is a SharedArrayBuffer
     182             :   bool has_maximum_pages = false;  // true if there is a maximum memory size
     183             :   bool has_memory = false;         // true if the memory was defined or imported
     184             :   bool mem_export = false;         // true if the memory is exported
     185             :   int start_function_index = -1;   // start function, >= 0 if any
     186             : 
     187             :   std::vector<WasmGlobal> globals;
     188             :   // Size of the buffer required for all globals that are not imported and
     189             :   // mutable.
     190             :   uint32_t untagged_globals_buffer_size = 0;
     191             :   uint32_t tagged_globals_buffer_size = 0;
     192             :   uint32_t num_imported_mutable_globals = 0;
     193             :   uint32_t num_imported_functions = 0;
     194             :   uint32_t num_imported_tables = 0;
     195             :   uint32_t num_declared_functions = 0;  // excluding imported
     196             :   uint32_t num_exported_functions = 0;
     197             :   uint32_t num_declared_data_segments = 0;  // From the DataCount section.
     198             :   uint32_t num_lazy_compilation_hints = 0;  // From compilation hints section.
     199             :   WireBytesRef name = {0, 0};
     200             :   std::vector<FunctionSig*> signatures;  // by signature index
     201             :   std::vector<uint32_t> signature_ids;   // by signature index
     202             :   std::vector<WasmFunction> functions;
     203             :   std::vector<WasmDataSegment> data_segments;
     204             :   std::vector<WasmTable> tables;
     205             :   std::vector<WasmImport> import_table;
     206             :   std::vector<WasmExport> export_table;
     207             :   std::vector<WasmException> exceptions;
     208             :   std::vector<WasmElemSegment> elem_segments;
     209             :   std::vector<WasmCompilationHint> compilation_hints;
     210             :   SignatureMap signature_map;  // canonicalizing map for signature indexes.
     211             : 
     212             :   ModuleOrigin origin = kWasmOrigin;  // origin of the module
     213             :   mutable std::unique_ptr<std::unordered_map<uint32_t, WireBytesRef>>
     214             :       function_names;
     215             :   std::string source_map_url;
     216             : 
     217             :   explicit WasmModule(std::unique_ptr<Zone> signature_zone = nullptr);
     218             : 
     219             :   WireBytesRef LookupFunctionName(const ModuleWireBytes& wire_bytes,
     220             :                                   uint32_t function_index) const;
     221             :   void AddFunctionNameForTesting(int function_index, WireBytesRef name);
     222             : };
     223             : 
     224             : size_t EstimateStoredSize(const WasmModule* module);
     225             : 
     226             : // Interface to the storage (wire bytes) of a wasm module.
     227             : // It is illegal for anyone receiving a ModuleWireBytes to store pointers based
     228             : // on module_bytes, as this storage is only guaranteed to be alive as long as
     229             : // this struct is alive.
     230             : struct V8_EXPORT_PRIVATE ModuleWireBytes {
     231             :   explicit ModuleWireBytes(Vector<const byte> module_bytes)
     232       20975 :       : module_bytes_(module_bytes) {}
     233             :   ModuleWireBytes(const byte* start, const byte* end)
     234      423934 :       : module_bytes_(start, static_cast<int>(end - start)) {
     235             :     DCHECK_GE(kMaxInt, end - start);
     236             :   }
     237             : 
     238             :   // Get a string stored in the module bytes representing a name.
     239             :   WasmName GetNameOrNull(WireBytesRef ref) const;
     240             : 
     241             :   // Get a string stored in the module bytes representing a function name.
     242             :   WasmName GetNameOrNull(const WasmFunction* function,
     243             :                          const WasmModule* module) const;
     244             : 
     245             :   // Checks the given offset range is contained within the module bytes.
     246             :   bool BoundsCheck(uint32_t offset, uint32_t length) const {
     247         799 :     uint32_t size = static_cast<uint32_t>(module_bytes_.length());
     248         799 :     return offset <= size && length <= size - offset;
     249             :   }
     250             : 
     251             :   Vector<const byte> GetFunctionBytes(const WasmFunction* function) const {
     252             :     return module_bytes_.SubVector(function->code.offset(),
     253        9081 :                                    function->code.end_offset());
     254             :   }
     255             : 
     256      145546 :   Vector<const byte> module_bytes() const { return module_bytes_; }
     257             :   const byte* start() const { return module_bytes_.start(); }
     258             :   const byte* end() const { return module_bytes_.end(); }
     259      136927 :   size_t length() const { return module_bytes_.length(); }
     260             : 
     261             :  private:
     262             :   Vector<const byte> module_bytes_;
     263             : };
     264             : 
     265             : // A helper for printing out the names of functions.
     266             : struct WasmFunctionName {
     267             :   WasmFunctionName(const WasmFunction* function, WasmName name)
     268      136551 :       : function_(function), name_(name) {}
     269             : 
     270             :   const WasmFunction* function_;
     271             :   const WasmName name_;
     272             : };
     273             : 
     274             : std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name);
     275             : 
     276             : // Get the debug info associated with the given wasm object.
     277             : // If no debug info exists yet, it is created automatically.
     278             : Handle<WasmDebugInfo> GetDebugInfo(Handle<JSObject> wasm);
     279             : 
     280             : V8_EXPORT_PRIVATE MaybeHandle<WasmModuleObject> CreateModuleObjectFromBytes(
     281             :     Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower,
     282             :     ModuleOrigin origin, Handle<Script> asm_js_script,
     283             :     Vector<const byte> asm_offset_table);
     284             : 
     285             : V8_EXPORT_PRIVATE bool IsWasmCodegenAllowed(Isolate* isolate,
     286             :                                             Handle<Context> context);
     287             : 
     288             : V8_EXPORT_PRIVATE Handle<JSArray> GetImports(Isolate* isolate,
     289             :                                              Handle<WasmModuleObject> module);
     290             : V8_EXPORT_PRIVATE Handle<JSArray> GetExports(Isolate* isolate,
     291             :                                              Handle<WasmModuleObject> module);
     292             : V8_EXPORT_PRIVATE Handle<JSArray> GetCustomSections(
     293             :     Isolate* isolate, Handle<WasmModuleObject> module, Handle<String> name,
     294             :     ErrorThrower* thrower);
     295             : 
     296             : // Decode local variable names from the names section. Return FixedArray of
     297             : // FixedArray of <undefined|String>. The outer fixed array is indexed by the
     298             : // function index, the inner one by the local index.
     299             : Handle<FixedArray> DecodeLocalNames(Isolate*, Handle<WasmModuleObject>);
     300             : 
     301             : // TruncatedUserString makes it easy to output names up to a certain length, and
     302             : // output a truncation followed by '...' if they exceed a limit.
     303             : // Use like this:
     304             : //   TruncatedUserString<> name (pc, len);
     305             : //   printf("... %.*s ...", name.length(), name.start())
     306             : template <int kMaxLen = 50>
     307             : class TruncatedUserString {
     308             :   static_assert(kMaxLen >= 4, "minimum length is 4 (length of '...' plus one)");
     309             : 
     310             :  public:
     311             :   template <typename T>
     312             :   explicit TruncatedUserString(Vector<T> name)
     313         344 :       : TruncatedUserString(name.start(), name.length()) {}
     314             : 
     315             :   TruncatedUserString(const byte* start, size_t len)
     316         328 :       : TruncatedUserString(reinterpret_cast<const char*>(start), len) {}
     317             : 
     318         672 :   TruncatedUserString(const char* start, size_t len)
     319        1344 :       : start_(start), length_(std::min(kMaxLen, static_cast<int>(len))) {
     320         672 :     if (len > static_cast<size_t>(kMaxLen)) {
     321           8 :       memcpy(buffer_, start, kMaxLen - 3);
     322           8 :       memset(buffer_ + kMaxLen - 3, '.', 3);
     323           8 :       start_ = buffer_;
     324             :     }
     325         672 :   }
     326             : 
     327             :   const char* start() const { return start_; }
     328             : 
     329             :   int length() const { return length_; }
     330             : 
     331             :  private:
     332             :   const char* start_;
     333             :   const int length_;
     334             :   char buffer_[kMaxLen];
     335             : };
     336             : 
     337             : }  // namespace wasm
     338             : }  // namespace internal
     339             : }  // namespace v8
     340             : 
     341             : #endif  // V8_WASM_WASM_MODULE_H_

Generated by: LCOV version 1.10