LCOV - code coverage report
Current view: top level - js/src/wasm - WasmCode.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 109 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 58 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  *
       4             :  * Copyright 2016 Mozilla Foundation
       5             :  *
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  */
      18             : 
      19             : #ifndef wasm_code_h
      20             : #define wasm_code_h
      21             : 
      22             : #include "js/HashTable.h"
      23             : #include "threading/ExclusiveData.h"
      24             : #include "wasm/WasmTypes.h"
      25             : 
      26             : namespace js {
      27             : 
      28             : struct AsmJSMetadata;
      29             : class WasmInstanceObject;
      30             : 
      31             : namespace wasm {
      32             : 
      33             : struct LinkData;
      34             : struct LinkDataTier;
      35             : struct Metadata;
      36             : struct MetadataTier;
      37             : class FrameIterator;
      38             : 
      39             : // ShareableBytes is a reference-counted Vector of bytes.
      40             : 
      41           0 : struct ShareableBytes : ShareableBase<ShareableBytes>
      42             : {
      43             :     // Vector is 'final', so instead make Vector a member and add boilerplate.
      44             :     Bytes bytes;
      45           0 :     size_t sizeOfExcludingThis(MallocSizeOf m) const { return bytes.sizeOfExcludingThis(m); }
      46           0 :     const uint8_t* begin() const { return bytes.begin(); }
      47           0 :     const uint8_t* end() const { return bytes.end(); }
      48           0 :     size_t length() const { return bytes.length(); }
      49           0 :     bool append(const uint8_t *p, uint32_t ct) { return bytes.append(p, ct); }
      50             : };
      51             : 
      52             : typedef RefPtr<ShareableBytes> MutableBytes;
      53             : typedef RefPtr<const ShareableBytes> SharedBytes;
      54             : 
      55             : // A wasm CodeSegment owns the allocated executable code for a wasm module.
      56             : 
      57             : class CodeSegment;
      58             : typedef UniquePtr<CodeSegment> UniqueCodeSegment;
      59             : typedef UniquePtr<const CodeSegment> UniqueConstCodeSegment;
      60             : 
      61           0 : class CodeSegment
      62             : {
      63             :     // Executable code must be deallocated specially.
      64             :     struct FreeCode {
      65             :         uint32_t codeLength;
      66           0 :         FreeCode() : codeLength(0) {}
      67           0 :         explicit FreeCode(uint32_t codeLength) : codeLength(codeLength) {}
      68             :         void operator()(uint8_t* codeBytes);
      69             :     };
      70             :     typedef UniquePtr<uint8_t, FreeCode> UniqueCodeBytes;
      71             :     static UniqueCodeBytes AllocateCodeBytes(uint32_t codeLength);
      72             : 
      73             :     // How this code was compiled.
      74             :     Tier tier_;
      75             : 
      76             :     // bytes_ points to a single allocation of executable machine code in
      77             :     // the range [0, length_).  The range [0, functionLength_) is
      78             :     // the subrange of [0, length_) which contains function code.
      79             :     UniqueCodeBytes bytes_;
      80             :     uint32_t        functionLength_;
      81             :     uint32_t        length_;
      82             : 
      83             :     // These are pointers into code for stubs used for asynchronous
      84             :     // signal-handler control-flow transfer.
      85             :     uint8_t* interruptCode_;
      86             :     uint8_t* outOfBoundsCode_;
      87             :     uint8_t* unalignedAccessCode_;
      88             : 
      89             :     bool initialize(Tier tier,
      90             :                     UniqueCodeBytes bytes,
      91             :                     uint32_t codeLength,
      92             :                     const ShareableBytes& bytecode,
      93             :                     const LinkDataTier& linkData,
      94             :                     const Metadata& metadata);
      95             : 
      96             :     static UniqueConstCodeSegment create(Tier tier,
      97             :                                          UniqueCodeBytes bytes,
      98             :                                          uint32_t codeLength,
      99             :                                          const ShareableBytes& bytecode,
     100             :                                          const LinkDataTier& linkData,
     101             :                                          const Metadata& metadata);
     102             :   public:
     103             :     CodeSegment(const CodeSegment&) = delete;
     104             :     void operator=(const CodeSegment&) = delete;
     105             : 
     106           0 :     CodeSegment()
     107           0 :       : tier_(Tier(-1)),
     108             :         functionLength_(0),
     109             :         length_(0),
     110             :         interruptCode_(nullptr),
     111             :         outOfBoundsCode_(nullptr),
     112           0 :         unalignedAccessCode_(nullptr)
     113           0 :     {}
     114             : 
     115             :     static UniqueConstCodeSegment create(Tier tier,
     116             :                                          jit::MacroAssembler& masm,
     117             :                                          const ShareableBytes& bytecode,
     118             :                                          const LinkDataTier& linkData,
     119             :                                          const Metadata& metadata);
     120             : 
     121             :     static UniqueConstCodeSegment create(Tier tier,
     122             :                                          const Bytes& unlinkedBytes,
     123             :                                          const ShareableBytes& bytecode,
     124             :                                          const LinkDataTier& linkData,
     125             :                                          const Metadata& metadata);
     126             : 
     127           0 :     Tier tier() const { return tier_; }
     128             : 
     129           0 :     uint8_t* base() const { return bytes_.get(); }
     130           0 :     uint32_t length() const { return length_; }
     131             : 
     132           0 :     uint8_t* interruptCode() const { return interruptCode_; }
     133           0 :     uint8_t* outOfBoundsCode() const { return outOfBoundsCode_; }
     134             :     uint8_t* unalignedAccessCode() const { return unalignedAccessCode_; }
     135             : 
     136             :     // The range [0, functionBytes) is a subrange of [0, codeBytes) that
     137             :     // contains only function body code, not the stub code. This distinction is
     138             :     // used by the async interrupt handler to only interrupt when the pc is in
     139             :     // function code which, in turn, simplifies reasoning about how stubs
     140             :     // enter/exit.
     141             : 
     142           0 :     bool containsFunctionPC(const void* pc) const {
     143           0 :         return pc >= base() && pc < (base() + functionLength_);
     144             :     }
     145           0 :     bool containsCodePC(const void* pc) const {
     146           0 :         return pc >= base() && pc < (base() + length_);
     147             :     }
     148             : 
     149             :     // Structured clone support:
     150             : 
     151             :     size_t serializedSize() const;
     152             :     uint8_t* serialize(uint8_t* cursor, const LinkDataTier& linkData) const;
     153             :     const uint8_t* deserialize(const uint8_t* cursor, const ShareableBytes& bytecode,
     154             :                                const LinkDataTier& linkData, const Metadata& metadata);
     155             : 
     156             :     void addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t* code, size_t* data) const;
     157             : };
     158             : 
     159             : // A FuncExport represents a single function definition inside a wasm Module
     160             : // that has been exported one or more times. A FuncExport represents an
     161             : // internal entry point that can be called via function definition index by
     162             : // Instance::callExport(). To allow O(log(n)) lookup of a FuncExport by
     163             : // function definition index, the FuncExportVector is stored sorted by
     164             : // function definition index.
     165             : 
     166           0 : class FuncExport
     167             : {
     168             :     Sig sig_;
     169             :     MOZ_INIT_OUTSIDE_CTOR struct CacheablePod {
     170             :         uint32_t funcIndex_;
     171             :         uint32_t codeRangeIndex_;
     172             :         uint32_t entryOffset_;      // Machine code offset
     173             :     } pod;
     174             : 
     175             :   public:
     176           0 :     FuncExport() = default;
     177           0 :     explicit FuncExport(Sig&& sig,
     178             :                         uint32_t funcIndex,
     179             :                         uint32_t codeRangeIndex)
     180           0 :       : sig_(Move(sig))
     181             :     {
     182           0 :         pod.funcIndex_ = funcIndex;
     183           0 :         pod.codeRangeIndex_ = codeRangeIndex;
     184           0 :         pod.entryOffset_ = UINT32_MAX;
     185           0 :     }
     186           0 :     void initEntryOffset(uint32_t entryOffset) {
     187           0 :         MOZ_ASSERT(pod.entryOffset_ == UINT32_MAX);
     188           0 :         pod.entryOffset_ = entryOffset;
     189           0 :     }
     190             : 
     191           0 :     const Sig& sig() const {
     192           0 :         return sig_;
     193             :     }
     194           0 :     uint32_t funcIndex() const {
     195           0 :         return pod.funcIndex_;
     196             :     }
     197           0 :     uint32_t codeRangeIndex() const {
     198           0 :         return pod.codeRangeIndex_;
     199             :     }
     200           0 :     uint32_t entryOffset() const {
     201           0 :         MOZ_ASSERT(pod.entryOffset_ != UINT32_MAX);
     202           0 :         return pod.entryOffset_;
     203             :     }
     204             : 
     205             :     WASM_DECLARE_SERIALIZABLE(FuncExport)
     206             : };
     207             : 
     208             : typedef Vector<FuncExport, 0, SystemAllocPolicy> FuncExportVector;
     209             : 
     210             : // An FuncImport contains the runtime metadata needed to implement a call to an
     211             : // imported function. Each function import has two call stubs: an optimized path
     212             : // into JIT code and a slow path into the generic C++ js::Invoke and these
     213             : // offsets of these stubs are stored so that function-import callsites can be
     214             : // dynamically patched at runtime.
     215             : 
     216           0 : class FuncImport
     217             : {
     218             :     Sig sig_;
     219             :     struct CacheablePod {
     220             :         uint32_t tlsDataOffset_;
     221             :         uint32_t interpExitCodeOffset_; // Machine code offset
     222             :         uint32_t jitExitCodeOffset_;    // Machine code offset
     223             :     } pod;
     224             : 
     225             :   public:
     226           0 :     FuncImport() {
     227           0 :         memset(&pod, 0, sizeof(CacheablePod));
     228           0 :     }
     229             : 
     230           0 :     FuncImport(Sig&& sig, uint32_t tlsDataOffset)
     231           0 :       : sig_(Move(sig))
     232             :     {
     233           0 :         pod.tlsDataOffset_ = tlsDataOffset;
     234           0 :         pod.interpExitCodeOffset_ = 0;
     235           0 :         pod.jitExitCodeOffset_ = 0;
     236           0 :     }
     237             : 
     238           0 :     void initInterpExitOffset(uint32_t off) {
     239           0 :         MOZ_ASSERT(!pod.interpExitCodeOffset_);
     240           0 :         pod.interpExitCodeOffset_ = off;
     241           0 :     }
     242           0 :     void initJitExitOffset(uint32_t off) {
     243           0 :         MOZ_ASSERT(!pod.jitExitCodeOffset_);
     244           0 :         pod.jitExitCodeOffset_ = off;
     245           0 :     }
     246             : 
     247           0 :     const Sig& sig() const {
     248           0 :         return sig_;
     249             :     }
     250           0 :     uint32_t tlsDataOffset() const {
     251           0 :         return pod.tlsDataOffset_;
     252             :     }
     253           0 :     uint32_t interpExitCodeOffset() const {
     254           0 :         return pod.interpExitCodeOffset_;
     255             :     }
     256           0 :     uint32_t jitExitCodeOffset() const {
     257           0 :         return pod.jitExitCodeOffset_;
     258             :     }
     259             : 
     260             :     WASM_DECLARE_SERIALIZABLE(FuncImport)
     261             : };
     262             : 
     263             : typedef Vector<FuncImport, 0, SystemAllocPolicy> FuncImportVector;
     264             : 
     265             : // A wasm module can either use no memory, a unshared memory (ArrayBuffer) or
     266             : // shared memory (SharedArrayBuffer).
     267             : 
     268             : enum class MemoryUsage
     269             : {
     270             :     None = false,
     271             :     Unshared = 1,
     272             :     Shared = 2
     273             : };
     274             : 
     275             : static inline bool
     276           0 : UsesMemory(MemoryUsage memoryUsage)
     277             : {
     278           0 :     return bool(memoryUsage);
     279             : }
     280             : 
     281             : // NameInBytecode represents a name that is embedded in the wasm bytecode.
     282             : // The presence of NameInBytecode implies that bytecode has been kept.
     283             : 
     284             : struct NameInBytecode
     285             : {
     286             :     uint32_t offset;
     287             :     uint32_t length;
     288             : 
     289           0 :     NameInBytecode()
     290           0 :       : offset(UINT32_MAX), length(0)
     291           0 :     {}
     292             :     NameInBytecode(uint32_t offset, uint32_t length)
     293             :       : offset(offset), length(length)
     294             :     {}
     295             : };
     296             : 
     297             : typedef Vector<NameInBytecode, 0, SystemAllocPolicy> NameInBytecodeVector;
     298             : 
     299             : // CustomSection represents a custom section in the bytecode which can be
     300             : // extracted via Module.customSections. The (offset, length) pair does not
     301             : // include the custom section name.
     302             : 
     303             : struct CustomSection
     304             : {
     305             :     NameInBytecode name;
     306             :     uint32_t offset;
     307             :     uint32_t length;
     308             : 
     309             :     CustomSection() = default;
     310           0 :     CustomSection(NameInBytecode name, uint32_t offset, uint32_t length)
     311           0 :       : name(name), offset(offset), length(length)
     312           0 :     {}
     313             : };
     314             : 
     315             : typedef Vector<CustomSection, 0, SystemAllocPolicy> CustomSectionVector;
     316             : typedef Vector<ValTypeVector, 0, SystemAllocPolicy> FuncArgTypesVector;
     317             : typedef Vector<ExprType, 0, SystemAllocPolicy> FuncReturnTypesVector;
     318             : 
     319             : // Metadata holds all the data that is needed to describe compiled wasm code
     320             : // at runtime (as opposed to data that is only used to statically link or
     321             : // instantiate a module).
     322             : //
     323             : // Metadata is built incrementally by ModuleGenerator and then shared immutably
     324             : // between modules.
     325             : //
     326             : // The Metadata structure is split into tier-invariant and tier-variant parts;
     327             : // the former points to instances of the latter.  Additionally, the asm.js
     328             : // subsystem subclasses the Metadata, adding more tier-invariant data, some of
     329             : // which is serialized.  See AsmJS.cpp.
     330             : 
     331           0 : struct MetadataCacheablePod
     332             : {
     333             :     ModuleKind            kind;
     334             :     MemoryUsage           memoryUsage;
     335             :     uint32_t              minMemoryLength;
     336             :     uint32_t              globalDataLength;
     337             :     Maybe<uint32_t>       maxMemoryLength;
     338             :     Maybe<uint32_t>       startFuncIndex;
     339             : 
     340           0 :     explicit MetadataCacheablePod(ModuleKind kind)
     341           0 :       : kind(kind),
     342             :         memoryUsage(MemoryUsage::None),
     343             :         minMemoryLength(0),
     344           0 :         globalDataLength(0)
     345           0 :     {}
     346             : };
     347             : 
     348             : typedef uint8_t ModuleHash[8];
     349             : 
     350           0 : struct MetadataTier
     351             : {
     352           0 :     explicit MetadataTier(Tier tier)
     353           0 :       : tier(tier)
     354             :     {
     355           0 :         MOZ_ASSERT(tier == Tier::Baseline || tier == Tier::Ion);
     356           0 :     }
     357             : 
     358             :     const Tier            tier;
     359             : 
     360             :     MemoryAccessVector    memoryAccesses;
     361             :     CodeRangeVector       codeRanges;
     362             :     CallSiteVector        callSites;
     363             :     FuncImportVector      funcImports;
     364             :     FuncExportVector      funcExports;
     365             : 
     366             :     // Debug information, not serialized.
     367             :     Uint32Vector          debugTrapFarJumpOffsets;
     368             :     Uint32Vector          debugFuncToCodeRange;
     369             : 
     370             :     const FuncExport& lookupFuncExport(uint32_t funcIndex) const;
     371             : 
     372             :     WASM_DECLARE_SERIALIZABLE(MetadataTier);
     373             : };
     374             : 
     375             : typedef UniquePtr<MetadataTier> UniqueMetadataTier;
     376             : 
     377             : struct Metadata : ShareableBase<Metadata>, MetadataCacheablePod
     378             : {
     379             :     // `tier_` will become more complicated when tiering is implemented.
     380             :     UniqueMetadataTier tier_;
     381             : 
     382             :     Tiers tiers() const;
     383             :     const MetadataTier& metadata(Tier t) const;
     384             :     MetadataTier& metadata(Tier t);
     385             : 
     386           0 :     explicit Metadata(UniqueMetadataTier tier, ModuleKind kind = ModuleKind::Wasm)
     387           0 :       : MetadataCacheablePod(kind),
     388           0 :         tier_(Move(tier))
     389           0 :     {}
     390           0 :     virtual ~Metadata() {}
     391             : 
     392           0 :     MetadataCacheablePod& pod() { return *this; }
     393           0 :     const MetadataCacheablePod& pod() const { return *this; }
     394             : 
     395             :     SigWithIdVector       sigIds;
     396             :     GlobalDescVector      globals;
     397             :     TableDescVector       tables;
     398             :     NameInBytecodeVector  funcNames;
     399             :     CustomSectionVector   customSections;
     400             :     CacheableChars        filename;
     401             :     ModuleHash            hash;
     402             : 
     403             :     // Debug-enabled code is not serialized.
     404             :     bool                  debugEnabled;
     405             :     FuncArgTypesVector    debugFuncArgTypes;
     406             :     FuncReturnTypesVector debugFuncReturnTypes;
     407             : 
     408           0 :     bool usesMemory() const { return UsesMemory(memoryUsage); }
     409             :     bool hasSharedMemory() const { return memoryUsage == MemoryUsage::Shared; }
     410             : 
     411             :     // AsmJSMetadata derives Metadata iff isAsmJS(). Mostly this distinction is
     412             :     // encapsulated within AsmJS.cpp, but the additional virtual functions allow
     413             :     // asm.js to override wasm behavior in the handful of cases that can't be
     414             :     // easily encapsulated by AsmJS.cpp.
     415             : 
     416           0 :     bool isAsmJS() const {
     417           0 :         return kind == ModuleKind::AsmJS;
     418             :     }
     419           0 :     const AsmJSMetadata& asAsmJS() const {
     420           0 :         MOZ_ASSERT(isAsmJS());
     421           0 :         return *(const AsmJSMetadata*)this;
     422             :     }
     423           0 :     virtual bool mutedErrors() const {
     424           0 :         return false;
     425             :     }
     426           0 :     virtual const char16_t* displayURL() const {
     427           0 :         return nullptr;
     428             :     }
     429           0 :     virtual ScriptSource* maybeScriptSource() const {
     430           0 :         return nullptr;
     431             :     }
     432             :     virtual bool getFuncName(const Bytes* maybeBytecode, uint32_t funcIndex, UTF8Bytes* name) const;
     433             : 
     434             :     WASM_DECLARE_SERIALIZABLE_VIRTUAL(Metadata);
     435             : };
     436             : 
     437             : typedef RefPtr<Metadata> MutableMetadata;
     438             : typedef RefPtr<const Metadata> SharedMetadata;
     439             : 
     440             : // Code objects own executable code and the metadata that describe it. A single
     441             : // Code object is normally shared between a module and all its instances.
     442             : //
     443             : // profilingLabels_ is lazily initialized, but behind a lock.
     444             : 
     445           0 : class Code : public ShareableBase<Code>
     446             : {
     447             :     // `tier_` will become more complicated when tiering is implemented.
     448             :     UniqueConstCodeSegment              tier_;
     449             :     SharedMetadata                      metadata_;
     450             :     ExclusiveData<CacheableCharsVector> profilingLabels_;
     451             : 
     452             :   public:
     453             :     Code();
     454             : 
     455             :     Code(UniqueConstCodeSegment tier, const Metadata& metadata);
     456             : 
     457             :     Tier anyTier() const;
     458             :     Tiers tiers() const;
     459             : 
     460             :     const CodeSegment& segment(Tier tier) const;
     461           0 :     const MetadataTier& metadata(Tier tier) const { return metadata_->metadata(tier); }
     462           0 :     const Metadata& metadata() const { return *metadata_; }
     463             : 
     464             :     // Frame iterator support:
     465             : 
     466             :     const CallSite* lookupCallSite(void* returnAddress, const CodeSegment** segment = nullptr) const;
     467             :     const CodeRange* lookupRange(void* pc, const CodeSegment** segment = nullptr) const;
     468             :     const MemoryAccess* lookupMemoryAccess(void* pc, const CodeSegment** segment = nullptr) const;
     469             : 
     470             :     // Signal handling support:
     471             : 
     472             :     bool containsFunctionPC(const void* pc, const CodeSegment** segmentp = nullptr) const;
     473             :     bool containsCodePC(const void* pc, const CodeSegment** segmentp = nullptr) const;
     474             : 
     475             :     // To save memory, profilingLabels_ are generated lazily when profiling mode
     476             :     // is enabled.
     477             : 
     478             :     void ensureProfilingLabels(const Bytes* maybeBytecode, bool profilingEnabled) const;
     479             :     const char* profilingLabel(uint32_t funcIndex) const;
     480             : 
     481             :     // about:memory reporting:
     482             : 
     483             :     void addSizeOfMiscIfNotSeen(MallocSizeOf mallocSizeOf,
     484             :                                 Metadata::SeenSet* seenMetadata,
     485             :                                 Code::SeenSet* seenCode,
     486             :                                 size_t* code,
     487             :                                 size_t* data) const;
     488             : 
     489             :     // A Code object is serialized as the length and bytes of the machine code
     490             :     // after statically unlinking it; the Code is then later recreated from the
     491             :     // machine code and other parts.
     492             : 
     493             :     size_t serializedSize() const;
     494             :     uint8_t* serialize(uint8_t* cursor, const LinkData& linkData) const;
     495             :     const uint8_t* deserialize(const uint8_t* cursor, const SharedBytes& bytecode,
     496             :                                const LinkData& linkData, Metadata* maybeMetadata);
     497             : };
     498             : 
     499             : typedef RefPtr<const Code> SharedCode;
     500             : typedef RefPtr<Code> MutableCode;
     501             : 
     502             : } // namespace wasm
     503             : } // namespace js
     504             : 
     505             : #endif // wasm_code_h

Generated by: LCOV version 1.13