js/src/jit/Snapshots.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     7 #ifndef jit_Snapshot_h
     8 #define jit_Snapshot_h
    10 #include "mozilla/Alignment.h"
    12 #include "jsalloc.h"
    13 #include "jsbytecode.h"
    15 #include "jit/CompactBuffer.h"
    16 #include "jit/IonTypes.h"
    17 #include "jit/Registers.h"
    19 #include "js/HashTable.h"
    21 namespace js {
    22 namespace jit {
    24 class RValueAllocation;
    26 // A Recover Value Allocation mirror what is known at compiled time as being the
    27 // MIRType and the LAllocation.  This is read out of the snapshot to recover the
    28 // value which would be there if this frame was an interpreter frame instead of
    29 // an Ion frame.
    30 //
    31 // It is used with the SnapshotIterator to recover a Value from the stack,
    32 // spilled registers or the list of constant of the compiled script.
    33 //
    34 // Unit tests are located in jsapi-tests/testJitRValueAlloc.cpp.
    35 class RValueAllocation
    36 {
    37   public:
    39     // See RValueAllocation encoding in Snapshots.cpp
    40     enum Mode
    41     {
    42         CONSTANT            = 0x00,
    43         CST_UNDEFINED       = 0x01,
    44         CST_NULL            = 0x02,
    45         DOUBLE_REG          = 0x03,
    46         FLOAT32_REG         = 0x04,
    47         FLOAT32_STACK       = 0x05,
    48 #if defined(JS_NUNBOX32)
    49         UNTYPED_REG_REG     = 0x06,
    50         UNTYPED_REG_STACK   = 0x07,
    51         UNTYPED_STACK_REG   = 0x08,
    52         UNTYPED_STACK_STACK = 0x09,
    53 #elif defined(JS_PUNBOX64)
    54         UNTYPED_REG         = 0x06,
    55         UNTYPED_STACK       = 0x07,
    56 #endif
    57         // The JSValueType is packed in the Mode.
    58         TYPED_REG_MIN       = 0x10,
    59         TYPED_REG_MAX       = 0x17,
    60         TYPED_REG = TYPED_REG_MIN,
    62         // The JSValueType is packed in the Mode.
    63         TYPED_STACK_MIN     = 0x18,
    64         TYPED_STACK_MAX     = 0x1f,
    65         TYPED_STACK = TYPED_STACK_MIN,
    67         INVALID = 0x100,
    68     };
    70     // See Payload encoding in Snapshots.cpp
    71     enum PayloadType {
    72         PAYLOAD_NONE,
    73         PAYLOAD_INDEX,
    74         PAYLOAD_STACK_OFFSET,
    75         PAYLOAD_GPR,
    76         PAYLOAD_FPU,
    77         PAYLOAD_PACKED_TAG
    78     };
    80     struct Layout {
    81         PayloadType type1;
    82         PayloadType type2;
    83         const char *name;
    84     };
    86   private:
    87     Mode mode_;
    89     // Additional information to recover the content of the allocation.
    90     union Payload {
    91         uint32_t index;
    92         int32_t stackOffset;
    93         Register gpr;
    94         FloatRegister fpu;
    95         JSValueType type;
    96     };
    98     Payload arg1_;
    99     Payload arg2_;
   101     static Payload payloadOfIndex(uint32_t index) {
   102         Payload p;
   103         p.index = index;
   104         return p;
   105     }
   106     static Payload payloadOfStackOffset(int32_t offset) {
   107         Payload p;
   108         p.stackOffset = offset;
   109         return p;
   110     }
   111     static Payload payloadOfRegister(Register reg) {
   112         Payload p;
   113         p.gpr = reg;
   114         return p;
   115     }
   116     static Payload payloadOfFloatRegister(FloatRegister reg) {
   117         Payload p;
   118         p.fpu = reg;
   119         return p;
   120     }
   121     static Payload payloadOfValueType(JSValueType type) {
   122         Payload p;
   123         p.type = type;
   124         return p;
   125     }
   127     static const Layout &layoutFromMode(Mode mode);
   129     static void readPayload(CompactBufferReader &reader, PayloadType t,
   130                             uint8_t *mode, Payload *p);
   131     static void writePayload(CompactBufferWriter &writer, PayloadType t,
   132                              Payload p);
   133     static void writePadding(CompactBufferWriter &writer);
   134     static void dumpPayload(FILE *fp, PayloadType t, Payload p);
   135     static bool equalPayloads(PayloadType t, Payload lhs, Payload rhs);
   137     RValueAllocation(Mode mode, Payload a1, Payload a2)
   138       : mode_(mode),
   139         arg1_(a1),
   140         arg2_(a2)
   141     {
   142     }
   144     RValueAllocation(Mode mode, Payload a1)
   145       : mode_(mode),
   146         arg1_(a1)
   147     {
   148     }
   150     RValueAllocation(Mode mode)
   151       : mode_(mode)
   152     {
   153     }
   155   public:
   156     RValueAllocation()
   157       : mode_(INVALID)
   158     { }
   160     // DOUBLE_REG
   161     static RValueAllocation Double(const FloatRegister &reg) {
   162         return RValueAllocation(DOUBLE_REG, payloadOfFloatRegister(reg));
   163     }
   165     // FLOAT32_REG or FLOAT32_STACK
   166     static RValueAllocation Float32(const FloatRegister &reg) {
   167         return RValueAllocation(FLOAT32_REG, payloadOfFloatRegister(reg));
   168     }
   169     static RValueAllocation Float32(int32_t offset) {
   170         return RValueAllocation(FLOAT32_STACK, payloadOfStackOffset(offset));
   171     }
   173     // TYPED_REG or TYPED_STACK
   174     static RValueAllocation Typed(JSValueType type, const Register &reg) {
   175         JS_ASSERT(type != JSVAL_TYPE_DOUBLE &&
   176                   type != JSVAL_TYPE_MAGIC &&
   177                   type != JSVAL_TYPE_NULL &&
   178                   type != JSVAL_TYPE_UNDEFINED);
   179         return RValueAllocation(TYPED_REG, payloadOfValueType(type),
   180                                 payloadOfRegister(reg));
   181     }
   182     static RValueAllocation Typed(JSValueType type, int32_t offset) {
   183         JS_ASSERT(type != JSVAL_TYPE_MAGIC &&
   184                   type != JSVAL_TYPE_NULL &&
   185                   type != JSVAL_TYPE_UNDEFINED);
   186         return RValueAllocation(TYPED_STACK, payloadOfValueType(type),
   187                                 payloadOfStackOffset(offset));
   188     }
   190     // UNTYPED
   191 #if defined(JS_NUNBOX32)
   192     static RValueAllocation Untyped(const Register &type, const Register &payload) {
   193         return RValueAllocation(UNTYPED_REG_REG,
   194                                 payloadOfRegister(type),
   195                                 payloadOfRegister(payload));
   196     }
   198     static RValueAllocation Untyped(const Register &type, int32_t payloadStackOffset) {
   199         return RValueAllocation(UNTYPED_REG_STACK,
   200                                 payloadOfRegister(type),
   201                                 payloadOfStackOffset(payloadStackOffset));
   202     }
   204     static RValueAllocation Untyped(int32_t typeStackOffset, const Register &payload) {
   205         return RValueAllocation(UNTYPED_STACK_REG,
   206                                 payloadOfStackOffset(typeStackOffset),
   207                                 payloadOfRegister(payload));
   208     }
   210     static RValueAllocation Untyped(int32_t typeStackOffset, int32_t payloadStackOffset) {
   211         return RValueAllocation(UNTYPED_STACK_STACK,
   212                                 payloadOfStackOffset(typeStackOffset),
   213                                 payloadOfStackOffset(payloadStackOffset));
   214     }
   216 #elif defined(JS_PUNBOX64)
   217     static RValueAllocation Untyped(const Register &reg) {
   218         return RValueAllocation(UNTYPED_REG, payloadOfRegister(reg));
   219     }
   221     static RValueAllocation Untyped(int32_t stackOffset) {
   222         return RValueAllocation(UNTYPED_STACK, payloadOfStackOffset(stackOffset));
   223     }
   224 #endif
   226     // common constants.
   227     static RValueAllocation Undefined() {
   228         return RValueAllocation(CST_UNDEFINED);
   229     }
   230     static RValueAllocation Null() {
   231         return RValueAllocation(CST_NULL);
   232     }
   234     // CONSTANT's index
   235     static RValueAllocation ConstantPool(uint32_t index) {
   236         return RValueAllocation(CONSTANT, payloadOfIndex(index));
   237     }
   239     void writeHeader(CompactBufferWriter &writer, JSValueType type, uint32_t regCode) const;
   240   public:
   241     static RValueAllocation read(CompactBufferReader &reader);
   242     void write(CompactBufferWriter &writer) const;
   244   public:
   245     Mode mode() const {
   246         return mode_;
   247     }
   249     uint32_t index() const {
   250         JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_INDEX);
   251         return arg1_.index;
   252     }
   253     int32_t stackOffset() const {
   254         JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_STACK_OFFSET);
   255         return arg1_.stackOffset;
   256     }
   257     Register reg() const {
   258         JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_GPR);
   259         return arg1_.gpr;
   260     }
   261     FloatRegister fpuReg() const {
   262         JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_FPU);
   263         return arg1_.fpu;
   264     }
   265     JSValueType knownType() const {
   266         JS_ASSERT(layoutFromMode(mode()).type1 == PAYLOAD_PACKED_TAG);
   267         return arg1_.type;
   268     }
   270     int32_t stackOffset2() const {
   271         JS_ASSERT(layoutFromMode(mode()).type2 == PAYLOAD_STACK_OFFSET);
   272         return arg2_.stackOffset;
   273     }
   274     Register reg2() const {
   275         JS_ASSERT(layoutFromMode(mode()).type2 == PAYLOAD_GPR);
   276         return arg2_.gpr;
   277     }
   279   public:
   280     void dump(FILE *fp) const;
   282   public:
   283     bool operator==(const RValueAllocation &rhs) const {
   284         if (mode_ != rhs.mode_)
   285             return false;
   287         const Layout &layout = layoutFromMode(mode());
   288         return equalPayloads(layout.type1, arg1_, rhs.arg1_) &&
   289             equalPayloads(layout.type2, arg2_, rhs.arg2_);
   290     }
   292     HashNumber hash() const;
   294     struct Hasher
   295     {
   296         typedef RValueAllocation Key;
   297         typedef Key Lookup;
   298         static HashNumber hash(const Lookup &v) {
   299             return v.hash();
   300         }
   301         static bool match(const Key &k, const Lookup &l) {
   302             return k == l;
   303         }
   304     };
   305 };
   307 class RecoverWriter;
   309 // Collects snapshots in a contiguous buffer, which is copied into IonScript
   310 // memory after code generation.
   311 class SnapshotWriter
   312 {
   313     CompactBufferWriter writer_;
   314     CompactBufferWriter allocWriter_;
   316     // Map RValueAllocations to an offset in the allocWriter_ buffer.  This is
   317     // useful as value allocations are repeated frequently.
   318     typedef RValueAllocation RVA;
   319     typedef HashMap<RVA, uint32_t, RVA::Hasher, SystemAllocPolicy> RValueAllocMap;
   320     RValueAllocMap allocMap_;
   322     // This is only used to assert sanity.
   323     uint32_t allocWritten_;
   325     // Used to report size of the snapshot in the spew messages.
   326     SnapshotOffset lastStart_;
   328   public:
   329     bool init();
   331     SnapshotOffset startSnapshot(RecoverOffset recoverOffset, BailoutKind kind);
   332 #ifdef TRACK_SNAPSHOTS
   333     void trackSnapshot(uint32_t pcOpcode, uint32_t mirOpcode, uint32_t mirId,
   334                        uint32_t lirOpcode, uint32_t lirId);
   335 #endif
   336     bool add(const RValueAllocation &slot);
   338     uint32_t allocWritten() const {
   339         return allocWritten_;
   340     }
   341     void endSnapshot();
   343     bool oom() const {
   344         return writer_.oom() || writer_.length() >= MAX_BUFFER_SIZE ||
   345             allocWriter_.oom() || allocWriter_.length() >= MAX_BUFFER_SIZE;
   346     }
   348     size_t listSize() const {
   349         return writer_.length();
   350     }
   351     const uint8_t *listBuffer() const {
   352         return writer_.buffer();
   353     }
   355     size_t RVATableSize() const {
   356         return allocWriter_.length();
   357     }
   358     const uint8_t *RVATableBuffer() const {
   359         return allocWriter_.buffer();
   360     }
   361 };
   363 class MResumePoint;
   365 class RecoverWriter
   366 {
   367     CompactBufferWriter writer_;
   369     uint32_t nframes_;
   370     uint32_t framesWritten_;
   372   public:
   373     SnapshotOffset startRecover(uint32_t frameCount, bool resumeAfter);
   375     bool writeFrame(const MResumePoint *rp);
   377     void endRecover();
   379     size_t size() const {
   380         return writer_.length();
   381     }
   382     const uint8_t *buffer() const {
   383         return writer_.buffer();
   384     }
   386     bool oom() const {
   387         return writer_.oom() || writer_.length() >= MAX_BUFFER_SIZE;
   388     }
   389 };
   391 class RecoverReader;
   393 // A snapshot reader reads the entries out of the compressed snapshot buffer in
   394 // a script. These entries describe the equivalent interpreter frames at a given
   395 // position in JIT code. Each entry is an Ion's value allocations, used to
   396 // recover the corresponding Value from an Ion frame.
   397 class SnapshotReader
   398 {
   399     CompactBufferReader reader_;
   400     CompactBufferReader allocReader_;
   401     const uint8_t* allocTable_;
   403     BailoutKind bailoutKind_;
   404     uint32_t allocRead_;          // Number of slots that have been read.
   405     RecoverOffset recoverOffset_; // Offset of the recover instructions.
   407 #ifdef TRACK_SNAPSHOTS
   408   private:
   409     uint32_t pcOpcode_;
   410     uint32_t mirOpcode_;
   411     uint32_t mirId_;
   412     uint32_t lirOpcode_;
   413     uint32_t lirId_;
   415   public:
   416     void readTrackSnapshot();
   417     void spewBailingFrom() const;
   418 #endif
   420   private:
   421     void readSnapshotHeader();
   422     uint32_t readAllocationIndex();
   424   public:
   425     SnapshotReader(const uint8_t *snapshots, uint32_t offset,
   426                    uint32_t RVATableSize, uint32_t listSize);
   428     RValueAllocation readAllocation();
   429     void skipAllocation() {
   430         readAllocationIndex();
   431     }
   433     BailoutKind bailoutKind() const {
   434         return bailoutKind_;
   435     }
   436     RecoverOffset recoverOffset() const {
   437         return recoverOffset_;
   438     }
   440     uint32_t numAllocationsRead() const {
   441         return allocRead_;
   442     }
   443     void resetNumAllocationsRead() {
   444         allocRead_ = 0;
   445     }
   446 };
   448 typedef mozilla::AlignedStorage<4 * sizeof(uint32_t)> RInstructionStorage;
   449 class RInstruction;
   451 class RecoverReader
   452 {
   453     CompactBufferReader reader_;
   455     // Number of encoded instructions.
   456     uint32_t numInstructions_;
   458     // Number of instruction read.
   459     uint32_t numInstructionsRead_;
   461     // True if we need to resume after the Resume Point instruction of the
   462     // innermost frame.
   463     bool resumeAfter_;
   465     // Space is reserved as part of the RecoverReader to avoid allocations of
   466     // data which is needed to decode the current instruction.
   467     RInstructionStorage rawData_;
   469   private:
   470     void readRecoverHeader();
   471     void readInstruction();
   473   public:
   474     RecoverReader(SnapshotReader &snapshot, const uint8_t *recovers, uint32_t size);
   476     bool moreInstructions() const {
   477         return numInstructionsRead_ < numInstructions_;
   478     }
   479     void nextInstruction() {
   480         readInstruction();
   481     }
   483     const RInstruction *instruction() const {
   484         return reinterpret_cast<const RInstruction *>(rawData_.addr());
   485     }
   487     bool resumeAfter() const {
   488         return resumeAfter_;
   489     }
   490 };
   492 }
   493 }
   495 #endif /* jit_Snapshot_h */

mercurial