LCOV - code coverage report
Current view: top level - js/src/jit - Snapshots.h (source / functions) Hit Total Coverage
Test: output.info Lines: 107 164 65.2 %
Date: 2017-07-14 16:53:18 Functions: 45 66 68.2 %
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             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef jit_Snapshot_h
       8             : #define jit_Snapshot_h
       9             : 
      10             : #include "mozilla/Alignment.h"
      11             : #include "mozilla/Attributes.h"
      12             : 
      13             : #include "jsalloc.h"
      14             : #include "jsbytecode.h"
      15             : 
      16             : #include "jit/CompactBuffer.h"
      17             : #include "jit/IonTypes.h"
      18             : #include "jit/Registers.h"
      19             : 
      20             : #include "js/HashTable.h"
      21             : 
      22             : namespace js {
      23             : class GenericPrinter;
      24             : 
      25             : namespace jit {
      26             : 
      27             : class RValueAllocation;
      28             : 
      29             : // A Recover Value Allocation mirror what is known at compiled time as being the
      30             : // MIRType and the LAllocation.  This is read out of the snapshot to recover the
      31             : // value which would be there if this frame was an interpreter frame instead of
      32             : // an Ion frame.
      33             : //
      34             : // It is used with the SnapshotIterator to recover a Value from the stack,
      35             : // spilled registers or the list of constant of the compiled script.
      36             : //
      37             : // Unit tests are located in jsapi-tests/testJitRValueAlloc.cpp.
      38             : class RValueAllocation
      39             : {
      40             :   public:
      41             : 
      42             :     // See RValueAllocation encoding in Snapshots.cpp
      43             :     enum Mode
      44             :     {
      45             :         CONSTANT            = 0x00,
      46             :         CST_UNDEFINED       = 0x01,
      47             :         CST_NULL            = 0x02,
      48             :         DOUBLE_REG          = 0x03,
      49             :         ANY_FLOAT_REG       = 0x04,
      50             :         ANY_FLOAT_STACK     = 0x05,
      51             : #if defined(JS_NUNBOX32)
      52             :         UNTYPED_REG_REG     = 0x06,
      53             :         UNTYPED_REG_STACK   = 0x07,
      54             :         UNTYPED_STACK_REG   = 0x08,
      55             :         UNTYPED_STACK_STACK = 0x09,
      56             : #elif defined(JS_PUNBOX64)
      57             :         UNTYPED_REG         = 0x06,
      58             :         UNTYPED_STACK       = 0x07,
      59             : #endif
      60             : 
      61             :         // Recover instructions.
      62             :         RECOVER_INSTRUCTION = 0x0a,
      63             :         RI_WITH_DEFAULT_CST = 0x0b,
      64             : 
      65             :         // The JSValueType is packed in the Mode.
      66             :         TYPED_REG_MIN       = 0x10,
      67             :         TYPED_REG_MAX       = 0x1f,
      68             :         TYPED_REG = TYPED_REG_MIN,
      69             : 
      70             :         // The JSValueType is packed in the Mode.
      71             :         TYPED_STACK_MIN     = 0x20,
      72             :         TYPED_STACK_MAX     = 0x2f,
      73             :         TYPED_STACK = TYPED_STACK_MIN,
      74             : 
      75             :         // This mask can be used with any other valid mode. When this flag is
      76             :         // set on the mode, this inform the snapshot iterator that even if the
      77             :         // allocation is readable, the content of if might be incomplete unless
      78             :         // all side-effects are executed.
      79             :         RECOVER_SIDE_EFFECT_MASK = 0x80,
      80             : 
      81             :         // This mask represents the set of bits which can be used to encode a
      82             :         // value in a snapshot. The mode is used to determine how to interpret
      83             :         // the union of values and how to pack the value in memory.
      84             :         MODE_BITS_MASK           = 0x17f,
      85             : 
      86             :         INVALID = 0x100,
      87             :     };
      88             : 
      89             :     enum { PACKED_TAG_MASK = 0x0f };
      90             : 
      91             :     // See Payload encoding in Snapshots.cpp
      92             :     enum PayloadType {
      93             :         PAYLOAD_NONE,
      94             :         PAYLOAD_INDEX,
      95             :         PAYLOAD_STACK_OFFSET,
      96             :         PAYLOAD_GPR,
      97             :         PAYLOAD_FPU,
      98             :         PAYLOAD_PACKED_TAG
      99             :     };
     100             : 
     101             :     struct Layout {
     102             :         PayloadType type1;
     103             :         PayloadType type2;
     104             :         const char* name;
     105             :     };
     106             : 
     107             :   private:
     108             :     Mode mode_;
     109             : 
     110             :     // Additional information to recover the content of the allocation.
     111             :     struct FloatRegisterBits {
     112             :         uint32_t data;
     113           0 :         bool operator == (const FloatRegisterBits& other) const {
     114           0 :             return data == other.data;
     115             :         }
     116           2 :         uint32_t code() const {
     117           2 :             return data;
     118             :         }
     119           0 :         const char* name() const {
     120           0 :             FloatRegister tmp = FloatRegister::FromCode(data);
     121           0 :             return tmp.name();
     122             :         }
     123             :     };
     124             : 
     125       37092 :     union Payload {
     126             :         uint32_t index;
     127             :         int32_t stackOffset;
     128             :         Register gpr;
     129             :         FloatRegisterBits fpu;
     130             :         JSValueType type;
     131             :     };
     132             : 
     133             :     Payload arg1_;
     134             :     Payload arg2_;
     135             : 
     136        1074 :     static Payload payloadOfIndex(uint32_t index) {
     137        1074 :         Payload p;
     138        1074 :         p.index = index;
     139        1074 :         return p;
     140             :     }
     141        4368 :     static Payload payloadOfStackOffset(int32_t offset) {
     142        4368 :         Payload p;
     143        4368 :         p.stackOffset = offset;
     144        4368 :         return p;
     145             :     }
     146         774 :     static Payload payloadOfRegister(Register reg) {
     147         774 :         Payload p;
     148         774 :         p.gpr = reg;
     149         774 :         return p;
     150             :     }
     151           1 :     static Payload payloadOfFloatRegister(FloatRegister reg) {
     152           1 :         Payload p;
     153             :         FloatRegisterBits b;
     154           1 :         b.data = reg.code();
     155           1 :         p.fpu = b;
     156           1 :         return p;
     157             :     }
     158        2767 :     static Payload payloadOfValueType(JSValueType type) {
     159        2767 :         Payload p;
     160        2767 :         p.type = type;
     161        2767 :         return p;
     162             :     }
     163             : 
     164             :     static const Layout& layoutFromMode(Mode mode);
     165             : 
     166             :     static void readPayload(CompactBufferReader& reader, PayloadType t,
     167             :                             uint8_t* mode, Payload* p);
     168             :     static void writePayload(CompactBufferWriter& writer, PayloadType t,
     169             :                              Payload p);
     170             :     static void writePadding(CompactBufferWriter& writer);
     171             :     static void dumpPayload(GenericPrinter& out, PayloadType t, Payload p);
     172             :     static bool equalPayloads(PayloadType t, Payload lhs, Payload rhs);
     173             : 
     174        2767 :     RValueAllocation(Mode mode, Payload a1, Payload a2)
     175        2767 :       : mode_(mode),
     176             :         arg1_(a1),
     177        2767 :         arg2_(a2)
     178             :     {
     179        2767 :     }
     180             : 
     181        3450 :     RValueAllocation(Mode mode, Payload a1)
     182        3450 :       : mode_(mode),
     183        3450 :         arg1_(a1)
     184             :     {
     185        3450 :     }
     186             : 
     187        1043 :     explicit RValueAllocation(Mode mode)
     188        1043 :       : mode_(mode)
     189             :     {
     190        1043 :     }
     191             : 
     192             :   public:
     193       11286 :     RValueAllocation()
     194       11286 :       : mode_(INVALID)
     195       11286 :     { }
     196             : 
     197             :     // DOUBLE_REG
     198           1 :     static RValueAllocation Double(FloatRegister reg) {
     199           1 :         return RValueAllocation(DOUBLE_REG, payloadOfFloatRegister(reg));
     200             :     }
     201             : 
     202             :     // ANY_FLOAT_REG or ANY_FLOAT_STACK
     203           0 :     static RValueAllocation AnyFloat(FloatRegister reg) {
     204           0 :         return RValueAllocation(ANY_FLOAT_REG, payloadOfFloatRegister(reg));
     205             :     }
     206           0 :     static RValueAllocation AnyFloat(int32_t offset) {
     207           0 :         return RValueAllocation(ANY_FLOAT_STACK, payloadOfStackOffset(offset));
     208             :     }
     209             : 
     210             :     // TYPED_REG or TYPED_STACK
     211         131 :     static RValueAllocation Typed(JSValueType type, Register reg) {
     212         131 :         MOZ_ASSERT(type != JSVAL_TYPE_DOUBLE &&
     213             :                    type != JSVAL_TYPE_MAGIC &&
     214             :                    type != JSVAL_TYPE_NULL &&
     215             :                    type != JSVAL_TYPE_UNDEFINED);
     216         262 :         return RValueAllocation(TYPED_REG, payloadOfValueType(type),
     217         262 :                                 payloadOfRegister(reg));
     218             :     }
     219        2636 :     static RValueAllocation Typed(JSValueType type, int32_t offset) {
     220        2636 :         MOZ_ASSERT(type != JSVAL_TYPE_MAGIC &&
     221             :                    type != JSVAL_TYPE_NULL &&
     222             :                    type != JSVAL_TYPE_UNDEFINED);
     223        5272 :         return RValueAllocation(TYPED_STACK, payloadOfValueType(type),
     224        5272 :                                 payloadOfStackOffset(offset));
     225             :     }
     226             : 
     227             :     // UNTYPED
     228             : #if defined(JS_NUNBOX32)
     229             :     static RValueAllocation Untyped(Register type, Register payload) {
     230             :         return RValueAllocation(UNTYPED_REG_REG,
     231             :                                 payloadOfRegister(type),
     232             :                                 payloadOfRegister(payload));
     233             :     }
     234             : 
     235             :     static RValueAllocation Untyped(Register type, int32_t payloadStackOffset) {
     236             :         return RValueAllocation(UNTYPED_REG_STACK,
     237             :                                 payloadOfRegister(type),
     238             :                                 payloadOfStackOffset(payloadStackOffset));
     239             :     }
     240             : 
     241             :     static RValueAllocation Untyped(int32_t typeStackOffset, Register payload) {
     242             :         return RValueAllocation(UNTYPED_STACK_REG,
     243             :                                 payloadOfStackOffset(typeStackOffset),
     244             :                                 payloadOfRegister(payload));
     245             :     }
     246             : 
     247             :     static RValueAllocation Untyped(int32_t typeStackOffset, int32_t payloadStackOffset) {
     248             :         return RValueAllocation(UNTYPED_STACK_STACK,
     249             :                                 payloadOfStackOffset(typeStackOffset),
     250             :                                 payloadOfStackOffset(payloadStackOffset));
     251             :     }
     252             : 
     253             : #elif defined(JS_PUNBOX64)
     254         643 :     static RValueAllocation Untyped(Register reg) {
     255         643 :         return RValueAllocation(UNTYPED_REG, payloadOfRegister(reg));
     256             :     }
     257             : 
     258        1732 :     static RValueAllocation Untyped(int32_t stackOffset) {
     259        1732 :         return RValueAllocation(UNTYPED_STACK, payloadOfStackOffset(stackOffset));
     260             :     }
     261             : #endif
     262             : 
     263             :     // common constants.
     264        1043 :     static RValueAllocation Undefined() {
     265        1043 :         return RValueAllocation(CST_UNDEFINED);
     266             :     }
     267           0 :     static RValueAllocation Null() {
     268           0 :         return RValueAllocation(CST_NULL);
     269             :     }
     270             : 
     271             :     // CONSTANT's index
     272         766 :     static RValueAllocation ConstantPool(uint32_t index) {
     273         766 :         return RValueAllocation(CONSTANT, payloadOfIndex(index));
     274             :     }
     275             : 
     276             :     // Recover instruction's index
     277         308 :     static RValueAllocation RecoverInstruction(uint32_t index) {
     278         308 :         return RValueAllocation(RECOVER_INSTRUCTION, payloadOfIndex(index));
     279             :     }
     280           0 :     static RValueAllocation RecoverInstruction(uint32_t riIndex, uint32_t cstIndex) {
     281           0 :         return RValueAllocation(RI_WITH_DEFAULT_CST,
     282             :                                 payloadOfIndex(riIndex),
     283           0 :                                 payloadOfIndex(cstIndex));
     284             :     }
     285             : 
     286         308 :     void setNeedSideEffect() {
     287         308 :         MOZ_ASSERT(!needSideEffect() && mode_ != INVALID);
     288         308 :         mode_ = Mode(mode_ | RECOVER_SIDE_EFFECT_MASK);
     289         308 :     }
     290             : 
     291             :     void writeHeader(CompactBufferWriter& writer, JSValueType type, uint32_t regCode) const;
     292             :   public:
     293             :     static RValueAllocation read(CompactBufferReader& reader);
     294             :     void write(CompactBufferWriter& writer) const;
     295             : 
     296             :   public:
     297       14520 :     Mode mode() const {
     298       14520 :         return Mode(mode_ & MODE_BITS_MASK);
     299             :     }
     300         308 :     bool needSideEffect() const {
     301         308 :         return mode_ & RECOVER_SIDE_EFFECT_MASK;
     302             :     }
     303             : 
     304           0 :     uint32_t index() const {
     305           0 :         MOZ_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_INDEX);
     306           0 :         return arg1_.index;
     307             :     }
     308           0 :     int32_t stackOffset() const {
     309           0 :         MOZ_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_STACK_OFFSET);
     310           0 :         return arg1_.stackOffset;
     311             :     }
     312           0 :     Register reg() const {
     313           0 :         MOZ_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_GPR);
     314           0 :         return arg1_.gpr;
     315             :     }
     316           0 :     FloatRegister fpuReg() const {
     317           0 :         MOZ_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_FPU);
     318           0 :         FloatRegisterBits b = arg1_.fpu;
     319           0 :         return FloatRegister::FromCode(b.data);
     320             :     }
     321           0 :     JSValueType knownType() const {
     322           0 :         MOZ_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_PACKED_TAG);
     323           0 :         return arg1_.type;
     324             :     }
     325             : 
     326           0 :     uint32_t index2() const {
     327           0 :         MOZ_ASSERT(layoutFromMode(mode()).type2 == PAYLOAD_INDEX);
     328           0 :         return arg2_.index;
     329             :     }
     330           0 :     int32_t stackOffset2() const {
     331           0 :         MOZ_ASSERT(layoutFromMode(mode()).type2 == PAYLOAD_STACK_OFFSET);
     332           0 :         return arg2_.stackOffset;
     333             :     }
     334           0 :     Register reg2() const {
     335           0 :         MOZ_ASSERT(layoutFromMode(mode()).type2 == PAYLOAD_GPR);
     336           0 :         return arg2_.gpr;
     337             :     }
     338             : 
     339             :   public:
     340             :     void dump(GenericPrinter& out) const;
     341             : 
     342             :   public:
     343        7023 :     bool operator==(const RValueAllocation& rhs) const {
     344        7023 :         if (mode_ != rhs.mode_)
     345           0 :             return false;
     346             : 
     347        7023 :         const Layout& layout = layoutFromMode(mode());
     348       14046 :         return equalPayloads(layout.type1, arg1_, rhs.arg1_) &&
     349       14046 :             equalPayloads(layout.type2, arg2_, rhs.arg2_);
     350             :     }
     351             : 
     352             :     HashNumber hash() const;
     353             : 
     354             :     struct Hasher
     355             :     {
     356             :         typedef RValueAllocation Key;
     357             :         typedef Key Lookup;
     358        7260 :         static HashNumber hash(const Lookup& v) {
     359        7260 :             return v.hash();
     360             :         }
     361        7023 :         static bool match(const Key& k, const Lookup& l) {
     362        7023 :             return k == l;
     363             :         }
     364             :     };
     365             : };
     366             : 
     367             : class RecoverWriter;
     368             : 
     369             : // Collects snapshots in a contiguous buffer, which is copied into IonScript
     370             : // memory after code generation.
     371          16 : class SnapshotWriter
     372             : {
     373             :     CompactBufferWriter writer_;
     374             :     CompactBufferWriter allocWriter_;
     375             : 
     376             :     // Map RValueAllocations to an offset in the allocWriter_ buffer.  This is
     377             :     // useful as value allocations are repeated frequently.
     378             :     typedef RValueAllocation RVA;
     379             :     typedef HashMap<RVA, uint32_t, RVA::Hasher, SystemAllocPolicy> RValueAllocMap;
     380             :     RValueAllocMap allocMap_;
     381             : 
     382             :     // This is only used to assert sanity.
     383             :     uint32_t allocWritten_;
     384             : 
     385             :     // Used to report size of the snapshot in the spew messages.
     386             :     SnapshotOffset lastStart_;
     387             : 
     388             :   public:
     389             :     MOZ_MUST_USE bool init();
     390             : 
     391             :     SnapshotOffset startSnapshot(RecoverOffset recoverOffset, BailoutKind kind);
     392             : #ifdef TRACK_SNAPSHOTS
     393             :     void trackSnapshot(uint32_t pcOpcode, uint32_t mirOpcode, uint32_t mirId,
     394             :                        uint32_t lirOpcode, uint32_t lirId);
     395             : #endif
     396             :     MOZ_MUST_USE bool add(const RValueAllocation& slot);
     397             : 
     398       14520 :     uint32_t allocWritten() const {
     399       14520 :         return allocWritten_;
     400             :     }
     401             :     void endSnapshot();
     402             : 
     403        7583 :     bool oom() const {
     404       22749 :         return writer_.oom() || writer_.length() >= MAX_BUFFER_SIZE ||
     405       22749 :             allocWriter_.oom() || allocWriter_.length() >= MAX_BUFFER_SIZE;
     406             :     }
     407             : 
     408          20 :     size_t listSize() const {
     409          20 :         return writer_.length();
     410             :     }
     411           5 :     const uint8_t* listBuffer() const {
     412           5 :         return writer_.buffer();
     413             :     }
     414             : 
     415          10 :     size_t RVATableSize() const {
     416          10 :         return allocWriter_.length();
     417             :     }
     418           5 :     const uint8_t* RVATableBuffer() const {
     419           5 :         return allocWriter_.buffer();
     420             :     }
     421             : };
     422             : 
     423             : class MNode;
     424             : 
     425          16 : class RecoverWriter
     426             : {
     427             :     CompactBufferWriter writer_;
     428             : 
     429             :     uint32_t instructionCount_;
     430             :     uint32_t instructionsWritten_;
     431             : 
     432             :   public:
     433             :     SnapshotOffset startRecover(uint32_t instructionCount, bool resumeAfter);
     434             : 
     435             :     void writeInstruction(const MNode* rp);
     436             : 
     437             :     void endRecover();
     438             : 
     439          20 :     size_t size() const {
     440          20 :         return writer_.length();
     441             :     }
     442           5 :     const uint8_t* buffer() const {
     443           5 :         return writer_.buffer();
     444             :     }
     445             : 
     446         174 :     bool oom() const {
     447         174 :         return writer_.oom() || writer_.length() >= MAX_BUFFER_SIZE;
     448             :     }
     449             : };
     450             : 
     451             : class RecoverReader;
     452             : 
     453             : // A snapshot reader reads the entries out of the compressed snapshot buffer in
     454             : // a script. These entries describe the equivalent interpreter frames at a given
     455             : // position in JIT code. Each entry is an Ion's value allocations, used to
     456             : // recover the corresponding Value from an Ion frame.
     457             : class SnapshotReader
     458             : {
     459             :     CompactBufferReader reader_;
     460             :     CompactBufferReader allocReader_;
     461             :     const uint8_t* allocTable_;
     462             : 
     463             :     BailoutKind bailoutKind_;
     464             :     uint32_t allocRead_;          // Number of slots that have been read.
     465             :     RecoverOffset recoverOffset_; // Offset of the recover instructions.
     466             : 
     467             : #ifdef TRACK_SNAPSHOTS
     468             :   private:
     469             :     uint32_t pcOpcode_;
     470             :     uint32_t mirOpcode_;
     471             :     uint32_t mirId_;
     472             :     uint32_t lirOpcode_;
     473             :     uint32_t lirId_;
     474             : 
     475             :   public:
     476             :     void readTrackSnapshot();
     477             :     void spewBailingFrom() const;
     478             : #endif
     479             : 
     480             :   private:
     481             :     void readSnapshotHeader();
     482             :     uint32_t readAllocationIndex();
     483             : 
     484             :   public:
     485             :     SnapshotReader(const uint8_t* snapshots, uint32_t offset,
     486             :                    uint32_t RVATableSize, uint32_t listSize);
     487             : 
     488             :     RValueAllocation readAllocation();
     489           0 :     void skipAllocation() {
     490           0 :         readAllocationIndex();
     491           0 :     }
     492             : 
     493           0 :     BailoutKind bailoutKind() const {
     494           0 :         return bailoutKind_;
     495             :     }
     496         840 :     RecoverOffset recoverOffset() const {
     497         840 :         return recoverOffset_;
     498             :     }
     499             : 
     500         840 :     uint32_t numAllocationsRead() const {
     501         840 :         return allocRead_;
     502             :     }
     503           0 :     void resetNumAllocationsRead() {
     504           0 :         allocRead_ = 0;
     505           0 :     }
     506             : };
     507             : 
     508             : class MOZ_NON_PARAM RInstructionStorage
     509             : {
     510             :     static constexpr size_t Size = 4 * sizeof(uint32_t);
     511             : 
     512             :     // This presumes all RInstructionStorage are safely void*-alignable.
     513             :     // RInstruction::readRecoverData asserts that no RInstruction subclass
     514             :     // has stricter alignment requirements than RInstructionStorage.
     515             :     static constexpr size_t Alignment = alignof(void*);
     516             : 
     517             :     alignas(Alignment) unsigned char mem[Size];
     518             : 
     519             :   public:
     520        3360 :     const void* addr() const { return mem; }
     521        2520 :     void* addr() { return mem; }
     522             : 
     523        7212 :     RInstructionStorage() = default;
     524             : 
     525             :     // Making a copy of raw bytes holding a RInstruction instance would be a
     526             :     // strict aliasing violation: see bug 1269319 for an instance of bytewise
     527             :     // copying having caused crashes.
     528             :     RInstructionStorage(const RInstructionStorage&) = delete;
     529             :     RInstructionStorage& operator=(const RInstructionStorage& other) = delete;
     530             : };
     531             : 
     532             : class RInstruction;
     533             : 
     534             : class RecoverReader
     535             : {
     536             :     CompactBufferReader reader_;
     537             : 
     538             :     // Number of encoded instructions.
     539             :     uint32_t numInstructions_;
     540             : 
     541             :     // Number of instruction read.
     542             :     uint32_t numInstructionsRead_;
     543             : 
     544             :     // True if we need to resume after the Resume Point instruction of the
     545             :     // innermost frame.
     546             :     bool resumeAfter_;
     547             : 
     548             :     // Space is reserved as part of the RecoverReader to avoid allocations of
     549             :     // data which is needed to decode the current instruction.
     550             :     RInstructionStorage rawData_;
     551             : 
     552             :   private:
     553             :     void readRecoverHeader();
     554             :     void readInstruction();
     555             : 
     556             :   public:
     557             :     RecoverReader(SnapshotReader& snapshot, const uint8_t* recovers, uint32_t size);
     558             :     explicit RecoverReader(const RecoverReader& rr);
     559             :     RecoverReader& operator=(const RecoverReader& rr);
     560             : 
     561           0 :     uint32_t numInstructions() const {
     562           0 :         return numInstructions_;
     563             :     }
     564           0 :     uint32_t numInstructionsRead() const {
     565           0 :         return numInstructionsRead_;
     566             :     }
     567             : 
     568        2520 :     bool moreInstructions() const {
     569        2520 :         return numInstructionsRead_ < numInstructions_;
     570             :     }
     571           0 :     void nextInstruction() {
     572           0 :         readInstruction();
     573           0 :     }
     574             : 
     575        3360 :     const RInstruction* instruction() const {
     576        3360 :         return reinterpret_cast<const RInstruction*>(rawData_.addr());
     577             :     }
     578             : 
     579           0 :     bool resumeAfter() const {
     580           0 :         return resumeAfter_;
     581             :     }
     582             : };
     583             : 
     584             : } // namespace jit
     585             : } // namespace js
     586             : 
     587             : #endif /* jit_Snapshot_h */

Generated by: LCOV version 1.13