LCOV - code coverage report
Current view: top level - js/src/jit - IonCode.h (source / functions) Hit Total Coverage
Test: output.info Lines: 143 287 49.8 %
Date: 2017-07-14 16:53:18 Functions: 59 107 55.1 %
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_IonCode_h
       8             : #define jit_IonCode_h
       9             : 
      10             : #include "mozilla/Atomics.h"
      11             : #include "mozilla/MemoryReporting.h"
      12             : #include "mozilla/PodOperations.h"
      13             : 
      14             : #include "jstypes.h"
      15             : 
      16             : #include "gc/Heap.h"
      17             : #include "jit/ExecutableAllocator.h"
      18             : #include "jit/ICStubSpace.h"
      19             : #include "jit/IonOptimizationLevels.h"
      20             : #include "jit/IonTypes.h"
      21             : #include "js/UbiNode.h"
      22             : #include "vm/TraceLogging.h"
      23             : #include "vm/TypeInference.h"
      24             : 
      25             : namespace js {
      26             : namespace jit {
      27             : 
      28             : class MacroAssembler;
      29             : class PatchableBackedge;
      30             : class IonBuilder;
      31             : class IonICEntry;
      32             : 
      33             : typedef Vector<JSObject*, 4, JitAllocPolicy> ObjectVector;
      34             : typedef Vector<TraceLoggerEvent, 0, SystemAllocPolicy> TraceLoggerEventVector;
      35             : 
      36             : class JitCode : public gc::TenuredCell
      37             : {
      38             :   protected:
      39             :     uint8_t* code_;
      40             :     ExecutablePool* pool_;
      41             :     uint32_t bufferSize_;             // Total buffer size. Does not include headerSize_.
      42             :     uint32_t insnSize_;               // Instruction stream size.
      43             :     uint32_t dataSize_;               // Size of the read-only data area.
      44             :     uint32_t jumpRelocTableBytes_;    // Size of the jump relocation table.
      45             :     uint32_t dataRelocTableBytes_;    // Size of the data relocation table.
      46             :     uint8_t headerSize_ : 5;          // Number of bytes allocated before codeStart.
      47             :     uint8_t kind_ : 3;                // jit::CodeKind, for the memory reporters.
      48             :     bool invalidated_ : 1;            // Whether the code object has been invalidated.
      49             :                                       // This is necessary to prevent GC tracing.
      50             :     bool hasBytecodeMap_ : 1;         // Whether the code object has been registered with
      51             :                                       // native=>bytecode mapping tables.
      52             : 
      53             :     JitCode()
      54             :       : code_(nullptr),
      55             :         pool_(nullptr)
      56             :     { }
      57        4499 :     JitCode(uint8_t* code, uint32_t bufferSize, uint32_t headerSize, ExecutablePool* pool,
      58             :             CodeKind kind)
      59        4499 :       : code_(code),
      60             :         pool_(pool),
      61             :         bufferSize_(bufferSize),
      62             :         insnSize_(0),
      63             :         dataSize_(0),
      64             :         jumpRelocTableBytes_(0),
      65             :         dataRelocTableBytes_(0),
      66             :         headerSize_(headerSize),
      67             :         kind_(kind),
      68             :         invalidated_(false),
      69        4499 :         hasBytecodeMap_(false)
      70             :     {
      71        4499 :         MOZ_ASSERT(CodeKind(kind_) == kind);
      72        4499 :         MOZ_ASSERT(headerSize_ == headerSize);
      73        4499 :     }
      74             : 
      75        9035 :     uint32_t dataOffset() const {
      76        9035 :         return insnSize_;
      77             :     }
      78        9035 :     uint32_t jumpRelocTableOffset() const {
      79        9035 :         return dataOffset() + dataSize_;
      80             :     }
      81        4501 :     uint32_t dataRelocTableOffset() const {
      82        4501 :         return jumpRelocTableOffset() + jumpRelocTableBytes_;
      83             :     }
      84             : 
      85             :   public:
      86      161702 :     uint8_t* raw() const {
      87      161702 :         return code_;
      88             :     }
      89         632 :     uint8_t* rawEnd() const {
      90         632 :         return code_ + insnSize_;
      91             :     }
      92           0 :     bool containsNativePC(const void* addr) const {
      93           0 :         const uint8_t* addr_u8 = (const uint8_t*) addr;
      94           0 :         return raw() <= addr_u8 && addr_u8 < rawEnd();
      95             :     }
      96       47748 :     size_t instructionsSize() const {
      97       47748 :         return insnSize_;
      98             :     }
      99           0 :     size_t bufferSize() const {
     100           0 :         return bufferSize_;
     101             :     }
     102           0 :     size_t headerSize() const {
     103           0 :         return headerSize_;
     104             :     }
     105             : 
     106             :     void traceChildren(JSTracer* trc);
     107             :     void finalize(FreeOp* fop);
     108           0 :     void setInvalidated() {
     109           0 :         invalidated_ = true;
     110           0 :     }
     111             : 
     112         632 :     void setHasBytecodeMap() {
     113         632 :         hasBytecodeMap_ = true;
     114         632 :     }
     115             : 
     116             :     void togglePreBarriers(bool enabled, ReprotectCode reprotect);
     117             : 
     118             :     // If this JitCode object has been, effectively, corrupted due to
     119             :     // invalidation patching, then we have to remember this so we don't try and
     120             :     // trace relocation entries that may now be corrupt.
     121          22 :     bool invalidated() const {
     122          22 :         return !!invalidated_;
     123             :     }
     124             : 
     125        7673 :     template <typename T> T as() const {
     126        7673 :         return JS_DATA_TO_FUNC_PTR(T, raw());
     127             :     }
     128             : 
     129             :     void copyFrom(MacroAssembler& masm);
     130             : 
     131         370 :     static JitCode* FromExecutable(uint8_t* buffer) {
     132         370 :         JitCode* code = *(JitCode**)(buffer - sizeof(JitCode*));
     133         370 :         MOZ_ASSERT(code->raw() == buffer);
     134         370 :         return code;
     135             :     }
     136             : 
     137          73 :     static size_t offsetOfCode() {
     138          73 :         return offsetof(JitCode, code_);
     139             :     }
     140             : 
     141          21 :     uint8_t* jumpRelocTable() {
     142          21 :         return code_ + jumpRelocTableOffset();
     143             :     }
     144             : 
     145             :     // Allocates a new JitCode object which will be managed by the GC. If no
     146             :     // object can be allocated, nullptr is returned. On failure, |pool| is
     147             :     // automatically released, so the code may be freed.
     148             :     template <AllowGC allowGC>
     149             :     static JitCode* New(JSContext* cx, uint8_t* code, uint32_t bufferSize, uint32_t headerSize,
     150             :                         ExecutablePool* pool, CodeKind kind);
     151             : 
     152             :   public:
     153             :     static const JS::TraceKind TraceKind = JS::TraceKind::JitCode;
     154             : };
     155             : 
     156             : class SnapshotWriter;
     157             : class RecoverWriter;
     158             : class SafepointWriter;
     159             : class SafepointIndex;
     160             : class OsiIndex;
     161             : class IonIC;
     162             : struct PatchableBackedgeInfo;
     163             : 
     164             : // An IonScript attaches Ion-generated information to a JSScript.
     165             : struct IonScript
     166             : {
     167             :   private:
     168             :     // Code pointer containing the actual method.
     169             :     PreBarrieredJitCode method_;
     170             : 
     171             :     // Deoptimization table used by this method.
     172             :     PreBarrieredJitCode deoptTable_;
     173             : 
     174             :     // Entrypoint for OSR, or nullptr.
     175             :     jsbytecode* osrPc_;
     176             : 
     177             :     // Offset to OSR entrypoint from method_->raw(), or 0.
     178             :     uint32_t osrEntryOffset_;
     179             : 
     180             :     // Offset to entrypoint skipping type arg check from method_->raw().
     181             :     uint32_t skipArgCheckEntryOffset_;
     182             : 
     183             :     // Offset of the invalidation epilogue (which pushes this IonScript
     184             :     // and calls the invalidation thunk).
     185             :     uint32_t invalidateEpilogueOffset_;
     186             : 
     187             :     // The offset immediately after the IonScript immediate.
     188             :     // NOTE: technically a constant delta from
     189             :     // |invalidateEpilogueOffset_|, so we could hard-code this
     190             :     // per-platform if we want.
     191             :     uint32_t invalidateEpilogueDataOffset_;
     192             : 
     193             :     // Number of times this script bailed out without invalidation.
     194             :     uint32_t numBailouts_;
     195             : 
     196             :     // Flag set if IonScript was compiled with profiling enabled.
     197             :     bool hasProfilingInstrumentation_;
     198             : 
     199             :     // Flag for if this script is getting recompiled.
     200             :     uint32_t recompiling_;
     201             : 
     202             :     // Any kind of data needed by the runtime, these can be either cache
     203             :     // information or profiling info.
     204             :     uint32_t runtimeData_;
     205             :     uint32_t runtimeSize_;
     206             : 
     207             :     // State for polymorphic caches in the compiled code. All caches are stored
     208             :     // in the runtimeData buffer and indexed by the icIndex which gives a
     209             :     // relative offset in the runtimeData array.
     210             :     uint32_t icIndex_;
     211             :     uint32_t icEntries_;
     212             : 
     213             :     // Map code displacement to safepoint / OSI-patch-delta.
     214             :     uint32_t safepointIndexOffset_;
     215             :     uint32_t safepointIndexEntries_;
     216             : 
     217             :     // Offset to and length of the safepoint table in bytes.
     218             :     uint32_t safepointsStart_;
     219             :     uint32_t safepointsSize_;
     220             : 
     221             :     // Number of bytes this function reserves on the stack.
     222             :     uint32_t frameSlots_;
     223             : 
     224             :     // Number of bytes used passed in as formal arguments or |this|.
     225             :     uint32_t argumentSlots_;
     226             : 
     227             :     // Frame size is the value that can be added to the StackPointer along
     228             :     // with the frame prefix to get a valid JitFrameLayout.
     229             :     uint32_t frameSize_;
     230             : 
     231             :     // Table mapping bailout IDs to snapshot offsets.
     232             :     uint32_t bailoutTable_;
     233             :     uint32_t bailoutEntries_;
     234             : 
     235             :     // Map OSI-point displacement to snapshot.
     236             :     uint32_t osiIndexOffset_;
     237             :     uint32_t osiIndexEntries_;
     238             : 
     239             :     // Offset from the start of the code buffer to its snapshot buffer.
     240             :     uint32_t snapshots_;
     241             :     uint32_t snapshotsListSize_;
     242             :     uint32_t snapshotsRVATableSize_;
     243             : 
     244             :     // List of instructions needed to recover stack frames.
     245             :     uint32_t recovers_;
     246             :     uint32_t recoversSize_;
     247             : 
     248             :     // Constant table for constants stored in snapshots.
     249             :     uint32_t constantTable_;
     250             :     uint32_t constantEntries_;
     251             : 
     252             :     // List of patchable backedges which are threaded into the runtime's list.
     253             :     uint32_t backedgeList_;
     254             :     uint32_t backedgeEntries_;
     255             : 
     256             :     // List of entries to the shared stub.
     257             :     uint32_t sharedStubList_;
     258             :     uint32_t sharedStubEntries_;
     259             : 
     260             :     // Number of references from invalidation records.
     261             :     uint32_t invalidationCount_;
     262             : 
     263             :     // Identifier of the compilation which produced this code.
     264             :     RecompileInfo recompileInfo_;
     265             : 
     266             :     // The optimization level this script was compiled in.
     267             :     OptimizationLevel optimizationLevel_;
     268             : 
     269             :     // Number of times we tried to enter this script via OSR but failed due to
     270             :     // a LOOPENTRY pc other than osrPc_.
     271             :     uint32_t osrPcMismatchCounter_;
     272             : 
     273             :     // Allocated space for fallback stubs.
     274             :     FallbackICStubSpace fallbackStubSpace_;
     275             : 
     276             :     // TraceLogger events that are baked into the IonScript.
     277             :     TraceLoggerEventVector traceLoggerEvents_;
     278             : 
     279             :   private:
     280        2608 :     inline uint8_t* bottomBuffer() {
     281        2608 :         return reinterpret_cast<uint8_t*>(this);
     282             :     }
     283             :     inline const uint8_t* bottomBuffer() const {
     284             :         return reinterpret_cast<const uint8_t*>(this);
     285             :     }
     286             : 
     287             :   public:
     288             : 
     289           0 :     SnapshotOffset* bailoutTable() {
     290           0 :         return (SnapshotOffset*) &bottomBuffer()[bailoutTable_];
     291             :     }
     292          15 :     PreBarrieredValue* constants() {
     293          15 :         return (PreBarrieredValue*) &bottomBuffer()[constantTable_];
     294             :     }
     295         840 :     const SafepointIndex* safepointIndices() const {
     296         840 :         return const_cast<IonScript*>(this)->safepointIndices();
     297             :     }
     298         844 :     SafepointIndex* safepointIndices() {
     299         844 :         return (SafepointIndex*) &bottomBuffer()[safepointIndexOffset_];
     300             :     }
     301        1680 :     const OsiIndex* osiIndices() const {
     302        1680 :         return const_cast<IonScript*>(this)->osiIndices();
     303             :     }
     304        1685 :     OsiIndex* osiIndices() {
     305        1685 :         return (OsiIndex*) &bottomBuffer()[osiIndexOffset_];
     306             :     }
     307          32 :     uint32_t* icIndex() {
     308          32 :         return (uint32_t*) &bottomBuffer()[icIndex_];
     309             :     }
     310          32 :     uint8_t* runtimeData() {
     311          32 :         return  &bottomBuffer()[runtimeData_];
     312             :     }
     313           0 :     PatchableBackedge* backedgeList() {
     314           0 :         return (PatchableBackedge*) &bottomBuffer()[backedgeList_];
     315             :     }
     316             : 
     317             :   private:
     318             :     void trace(JSTracer* trc);
     319             : 
     320             :   public:
     321             :     // Do not call directly, use IonScript::New. This is public for cx->new_.
     322             :     IonScript();
     323             : 
     324          10 :     ~IonScript() {
     325             :         // The contents of the fallback stub space are removed and freed
     326             :         // separately after the next minor GC. See IonScript::Destroy.
     327           5 :         MOZ_ASSERT(fallbackStubSpace_.isEmpty());
     328           5 :     }
     329             : 
     330             :     static IonScript* New(JSContext* cx, RecompileInfo recompileInfo,
     331             :                           uint32_t frameSlots, uint32_t argumentSlots, uint32_t frameSize,
     332             :                           size_t snapshotsListSize, size_t snapshotsRVATableSize,
     333             :                           size_t recoversSize, size_t bailoutEntries,
     334             :                           size_t constants, size_t safepointIndexEntries,
     335             :                           size_t osiIndexEntries, size_t icEntries,
     336             :                           size_t runtimeSize, size_t safepointsSize,
     337             :                           size_t backedgeEntries, size_t sharedStubEntries,
     338             :                           OptimizationLevel optimizationLevel);
     339             :     static void Trace(JSTracer* trc, IonScript* script);
     340             :     static void Destroy(FreeOp* fop, IonScript* script);
     341             : 
     342             :     static inline size_t offsetOfMethod() {
     343             :         return offsetof(IonScript, method_);
     344             :     }
     345             :     static inline size_t offsetOfOsrEntryOffset() {
     346             :         return offsetof(IonScript, osrEntryOffset_);
     347             :     }
     348             :     static inline size_t offsetOfSkipArgCheckEntryOffset() {
     349             :         return offsetof(IonScript, skipArgCheckEntryOffset_);
     350             :     }
     351         368 :     static inline size_t offsetOfInvalidationCount() {
     352         368 :         return offsetof(IonScript, invalidationCount_);
     353             :     }
     354           6 :     static inline size_t offsetOfRecompiling() {
     355           6 :         return offsetof(IonScript, recompiling_);
     356             :     }
     357             : 
     358             :   public:
     359       58891 :     JitCode* method() const {
     360       58891 :         return method_;
     361             :     }
     362           5 :     void setMethod(JitCode* code) {
     363           5 :         MOZ_ASSERT(!invalidated());
     364           5 :         method_ = code;
     365           5 :     }
     366           5 :     void setDeoptTable(JitCode* code) {
     367           5 :         deoptTable_ = code;
     368           5 :     }
     369           5 :     void setOsrPc(jsbytecode* osrPc) {
     370           5 :         osrPc_ = osrPc;
     371           5 :     }
     372           4 :     jsbytecode* osrPc() const {
     373           4 :         return osrPc_;
     374             :     }
     375           5 :     void setOsrEntryOffset(uint32_t offset) {
     376           5 :         MOZ_ASSERT(!osrEntryOffset_);
     377           5 :         osrEntryOffset_ = offset;
     378           5 :     }
     379           1 :     uint32_t osrEntryOffset() const {
     380           1 :         return osrEntryOffset_;
     381             :     }
     382           5 :     void setSkipArgCheckEntryOffset(uint32_t offset) {
     383           5 :         MOZ_ASSERT(!skipArgCheckEntryOffset_);
     384           5 :         skipArgCheckEntryOffset_ = offset;
     385           5 :     }
     386           5 :     uint32_t getSkipArgCheckEntryOffset() const {
     387           5 :         return skipArgCheckEntryOffset_;
     388             :     }
     389         840 :     bool containsCodeAddress(uint8_t* addr) const {
     390         840 :         return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
     391             :     }
     392       18480 :     bool containsReturnAddress(uint8_t* addr) const {
     393             :         // This accounts for an off by one error caused by the return address of a
     394             :         // bailout sitting outside the range of the containing function.
     395       18480 :         return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
     396             :     }
     397           5 :     void setInvalidationEpilogueOffset(uint32_t offset) {
     398           5 :         MOZ_ASSERT(!invalidateEpilogueOffset_);
     399           5 :         invalidateEpilogueOffset_ = offset;
     400           5 :     }
     401           0 :     uint32_t invalidateEpilogueOffset() const {
     402           0 :         MOZ_ASSERT(invalidateEpilogueOffset_);
     403           0 :         return invalidateEpilogueOffset_;
     404             :     }
     405           5 :     void setInvalidationEpilogueDataOffset(uint32_t offset) {
     406           5 :         MOZ_ASSERT(!invalidateEpilogueDataOffset_);
     407           5 :         invalidateEpilogueDataOffset_ = offset;
     408           5 :     }
     409           0 :     uint32_t invalidateEpilogueDataOffset() const {
     410           0 :         MOZ_ASSERT(invalidateEpilogueDataOffset_);
     411           0 :         return invalidateEpilogueDataOffset_;
     412             :     }
     413           0 :     void incNumBailouts() {
     414           0 :         numBailouts_++;
     415           0 :     }
     416          35 :     bool bailoutExpected() const {
     417          35 :         return numBailouts_ >= JitOptions.frequentBailoutThreshold;
     418             :     }
     419           0 :     void setHasProfilingInstrumentation() {
     420           0 :         hasProfilingInstrumentation_ = true;
     421           0 :     }
     422             :     void clearHasProfilingInstrumentation() {
     423             :         hasProfilingInstrumentation_ = false;
     424             :     }
     425           1 :     bool hasProfilingInstrumentation() const {
     426           1 :         return hasProfilingInstrumentation_;
     427             :     }
     428           0 :     MOZ_MUST_USE bool addTraceLoggerEvent(TraceLoggerEvent& event) {
     429           0 :         MOZ_ASSERT(event.hasTextId());
     430           0 :         return traceLoggerEvents_.append(Move(event));
     431             :     }
     432         840 :     const uint8_t* snapshots() const {
     433         840 :         return reinterpret_cast<const uint8_t*>(this) + snapshots_;
     434             :     }
     435         840 :     size_t snapshotsListSize() const {
     436         840 :         return snapshotsListSize_;
     437             :     }
     438         840 :     size_t snapshotsRVATableSize() const {
     439         840 :         return snapshotsRVATableSize_;
     440             :     }
     441         840 :     const uint8_t* recovers() const {
     442         840 :         return reinterpret_cast<const uint8_t*>(this) + recovers_;
     443             :     }
     444         840 :     size_t recoversSize() const {
     445         840 :         return recoversSize_;
     446             :     }
     447        3360 :     const uint8_t* safepoints() const {
     448        3360 :         return reinterpret_cast<const uint8_t*>(this) + safepointsStart_;
     449             :     }
     450        1680 :     size_t safepointsSize() const {
     451        1680 :         return safepointsSize_;
     452             :     }
     453           0 :     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
     454           0 :         return mallocSizeOf(this);
     455             :     }
     456           0 :     PreBarrieredValue& getConstant(size_t index) {
     457           0 :         MOZ_ASSERT(index < numConstants());
     458           0 :         return constants()[index];
     459             :     }
     460           0 :     size_t numConstants() const {
     461           0 :         return constantEntries_;
     462             :     }
     463        1680 :     uint32_t frameSlots() const {
     464        1680 :         return frameSlots_;
     465             :     }
     466        1680 :     uint32_t argumentSlots() const {
     467        1680 :         return argumentSlots_;
     468             :     }
     469         861 :     uint32_t frameSize() const {
     470         861 :         return frameSize_;
     471             :     }
     472             :     SnapshotOffset bailoutToSnapshot(uint32_t bailoutId) {
     473             :         MOZ_ASSERT(bailoutId < bailoutEntries_);
     474             :         return bailoutTable()[bailoutId];
     475             :     }
     476             :     const SafepointIndex* getSafepointIndex(uint32_t disp) const;
     477         840 :     const SafepointIndex* getSafepointIndex(uint8_t* retAddr) const {
     478         840 :         MOZ_ASSERT(containsCodeAddress(retAddr));
     479         840 :         return getSafepointIndex(retAddr - method()->raw());
     480             :     }
     481             :     const OsiIndex* getOsiIndex(uint32_t disp) const;
     482             :     const OsiIndex* getOsiIndex(uint8_t* retAddr) const;
     483             : 
     484          28 :     IonIC& getICFromIndex(uint32_t index) {
     485          28 :         MOZ_ASSERT(index < icEntries_);
     486          28 :         uint32_t offset = icIndex()[index];
     487          28 :         return getIC(offset);
     488             :     }
     489          28 :     inline IonIC& getIC(uint32_t offset) {
     490          28 :         MOZ_ASSERT(offset < runtimeSize_);
     491          28 :         return *(IonIC*) &runtimeData()[offset];
     492             :     }
     493          22 :     size_t numICs() const {
     494          22 :         return icEntries_;
     495             :     }
     496           0 :     IonICEntry* sharedStubList() {
     497           0 :         return (IonICEntry*) &bottomBuffer()[sharedStubList_];
     498             :     }
     499           0 :     size_t numSharedStubs() const {
     500           0 :         return sharedStubEntries_;
     501             :     }
     502           4 :     size_t runtimeSize() const {
     503           4 :         return runtimeSize_;
     504             :     }
     505             :     void purgeICs(Zone* zone);
     506             :     void unlinkFromRuntime(FreeOp* fop);
     507             :     void copySnapshots(const SnapshotWriter* writer);
     508             :     void copyRecovers(const RecoverWriter* writer);
     509             :     void copyBailoutTable(const SnapshotOffset* table);
     510             :     void copyConstants(const Value* vp);
     511             :     void copySafepointIndices(const SafepointIndex* firstSafepointIndex, MacroAssembler& masm);
     512             :     void copyOsiIndices(const OsiIndex* firstOsiIndex, MacroAssembler& masm);
     513             :     void copyRuntimeData(const uint8_t* data);
     514             :     void copyICEntries(const uint32_t* caches, MacroAssembler& masm);
     515             :     void copySafepoints(const SafepointWriter* writer);
     516             :     void copyPatchableBackedges(JSContext* cx, JitCode* code,
     517             :                                 PatchableBackedgeInfo* backedges,
     518             :                                 MacroAssembler& masm);
     519             : 
     520          51 :     bool invalidated() const {
     521          51 :         return invalidationCount_ != 0;
     522             :     }
     523             : 
     524             :     // Invalidate the current compilation.
     525             :     void invalidate(JSContext* cx, bool resetUses, const char* reason);
     526             : 
     527           0 :     size_t invalidationCount() const {
     528           0 :         return invalidationCount_;
     529             :     }
     530           0 :     void incrementInvalidationCount() {
     531           0 :         invalidationCount_++;
     532           0 :     }
     533           0 :     void decrementInvalidationCount(FreeOp* fop) {
     534           0 :         MOZ_ASSERT(invalidationCount_);
     535           0 :         invalidationCount_--;
     536           0 :         if (!invalidationCount_)
     537           0 :             Destroy(fop, this);
     538           0 :     }
     539           5 :     const RecompileInfo& recompileInfo() const {
     540           5 :         return recompileInfo_;
     541             :     }
     542           0 :     RecompileInfo& recompileInfoRef() {
     543           0 :         return recompileInfo_;
     544             :     }
     545          35 :     OptimizationLevel optimizationLevel() const {
     546          35 :         return optimizationLevel_;
     547             :     }
     548           0 :     uint32_t incrOsrPcMismatchCounter() {
     549           0 :         return ++osrPcMismatchCounter_;
     550             :     }
     551           0 :     void resetOsrPcMismatchCounter() {
     552           0 :         osrPcMismatchCounter_ = 0;
     553           0 :     }
     554             : 
     555           0 :     void setRecompiling() {
     556           0 :         recompiling_ = true;
     557           0 :     }
     558             : 
     559           0 :     bool isRecompiling() const {
     560           0 :         return recompiling_;
     561             :     }
     562             : 
     563           5 :     void clearRecompiling() {
     564           5 :         recompiling_ = false;
     565           5 :     }
     566             : 
     567           5 :     FallbackICStubSpace* fallbackStubSpace() {
     568           5 :         return &fallbackStubSpace_;
     569             :     }
     570             :     void adoptFallbackStubs(FallbackICStubSpace* stubSpace);
     571             :     void purgeOptimizedStubs(Zone* zone);
     572             : 
     573             :     enum ShouldIncreaseAge {
     574             :         IncreaseAge = true,
     575             :         KeepAge = false
     576             :     };
     577             : 
     578             :     static void writeBarrierPre(Zone* zone, IonScript* ionScript);
     579             : };
     580             : 
     581             : // Execution information for a basic block which may persist after the
     582             : // accompanying IonScript is destroyed, for use during profiling.
     583             : struct IonBlockCounts
     584             : {
     585             :   private:
     586             :     uint32_t id_;
     587             : 
     588             :     // Approximate bytecode in the outer (not inlined) script this block
     589             :     // was generated from.
     590             :     uint32_t offset_;
     591             : 
     592             :     // File and line of the inner script this block was generated from.
     593             :     char* description_;
     594             : 
     595             :     // ids for successors of this block.
     596             :     uint32_t numSuccessors_;
     597             :     uint32_t* successors_;
     598             : 
     599             :     // Hit count for this block.
     600             :     uint64_t hitCount_;
     601             : 
     602             :     // Text information about the code generated for this block.
     603             :     char* code_;
     604             : 
     605             :   public:
     606             : 
     607           0 :     MOZ_MUST_USE bool init(uint32_t id, uint32_t offset, char* description,
     608             :                            uint32_t numSuccessors) {
     609           0 :         id_ = id;
     610           0 :         offset_ = offset;
     611           0 :         description_ = description;
     612           0 :         numSuccessors_ = numSuccessors;
     613           0 :         if (numSuccessors) {
     614           0 :             successors_ = js_pod_calloc<uint32_t>(numSuccessors);
     615           0 :             if (!successors_)
     616           0 :                 return false;
     617             :         }
     618           0 :         return true;
     619             :     }
     620             : 
     621           0 :     void destroy() {
     622           0 :         js_free(description_);
     623           0 :         js_free(successors_);
     624           0 :         js_free(code_);
     625           0 :     }
     626             : 
     627           0 :     uint32_t id() const {
     628           0 :         return id_;
     629             :     }
     630             : 
     631           0 :     uint32_t offset() const {
     632           0 :         return offset_;
     633             :     }
     634             : 
     635           0 :     const char* description() const {
     636           0 :         return description_;
     637             :     }
     638             : 
     639           0 :     size_t numSuccessors() const {
     640           0 :         return numSuccessors_;
     641             :     }
     642             : 
     643           0 :     void setSuccessor(size_t i, uint32_t id) {
     644           0 :         MOZ_ASSERT(i < numSuccessors_);
     645           0 :         successors_[i] = id;
     646           0 :     }
     647             : 
     648           0 :     uint32_t successor(size_t i) const {
     649           0 :         MOZ_ASSERT(i < numSuccessors_);
     650           0 :         return successors_[i];
     651             :     }
     652             : 
     653           0 :     uint64_t* addressOfHitCount() {
     654           0 :         return &hitCount_;
     655             :     }
     656             : 
     657           0 :     uint64_t hitCount() const {
     658           0 :         return hitCount_;
     659             :     }
     660             : 
     661           0 :     void setCode(const char* code) {
     662           0 :         char* ncode = js_pod_malloc<char>(strlen(code) + 1);
     663           0 :         if (ncode) {
     664           0 :             strcpy(ncode, code);
     665           0 :             code_ = ncode;
     666             :         }
     667           0 :     }
     668             : 
     669           0 :     const char* code() const {
     670           0 :         return code_;
     671             :     }
     672             : };
     673             : 
     674             : // Execution information for a compiled script which may persist after the
     675             : // IonScript is destroyed, for use during profiling.
     676             : struct IonScriptCounts
     677             : {
     678             :   private:
     679             :     // Any previous invalidated compilation(s) for the script.
     680             :     IonScriptCounts* previous_;
     681             : 
     682             :     // Information about basic blocks in this script.
     683             :     size_t numBlocks_;
     684             :     IonBlockCounts* blocks_;
     685             : 
     686             :   public:
     687             : 
     688           0 :     IonScriptCounts() {
     689           0 :         mozilla::PodZero(this);
     690           0 :     }
     691             : 
     692           0 :     ~IonScriptCounts() {
     693           0 :         for (size_t i = 0; i < numBlocks_; i++)
     694           0 :             blocks_[i].destroy();
     695           0 :         js_free(blocks_);
     696             :         // The list can be long in some corner cases (bug 1140084), so
     697             :         // unroll the recursion.
     698           0 :         IonScriptCounts* victims = previous_;
     699           0 :         while (victims) {
     700           0 :             IonScriptCounts* victim = victims;
     701           0 :             victims = victim->previous_;
     702           0 :             victim->previous_ = nullptr;
     703           0 :             js_delete(victim);
     704             :         }
     705           0 :     }
     706             : 
     707           0 :     MOZ_MUST_USE bool init(size_t numBlocks) {
     708           0 :         blocks_ = js_pod_calloc<IonBlockCounts>(numBlocks);
     709           0 :         if (!blocks_)
     710           0 :             return false;
     711             : 
     712           0 :         numBlocks_ = numBlocks;
     713           0 :         return true;
     714             :     }
     715             : 
     716           0 :     size_t numBlocks() const {
     717           0 :         return numBlocks_;
     718             :     }
     719             : 
     720           0 :     IonBlockCounts& block(size_t i) {
     721           0 :         MOZ_ASSERT(i < numBlocks_);
     722           0 :         return blocks_[i];
     723             :     }
     724             : 
     725           0 :     void setPrevious(IonScriptCounts* previous) {
     726           0 :         previous_ = previous;
     727           0 :     }
     728             : 
     729           0 :     IonScriptCounts* previous() const {
     730           0 :         return previous_;
     731             :     }
     732             : };
     733             : 
     734             : struct VMFunction;
     735             : 
     736             : struct AutoFlushICache
     737             : {
     738             :   private:
     739             : #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
     740             :     uintptr_t start_;
     741             :     uintptr_t stop_;
     742             :     const char* name_;
     743             :     bool inhibit_;
     744             :     AutoFlushICache* prev_;
     745             : #endif
     746             : 
     747             :   public:
     748             :     static void setRange(uintptr_t p, size_t len);
     749             :     static void flush(uintptr_t p, size_t len);
     750             :     static void setInhibit();
     751             :     ~AutoFlushICache();
     752             :     explicit AutoFlushICache(const char* nonce, bool inhibit=false);
     753             : };
     754             : 
     755             : } // namespace jit
     756             : 
     757             : namespace gc {
     758             : 
     759             : inline bool
     760             : IsMarked(JSRuntime* rt, const jit::VMFunction*)
     761             : {
     762             :     // VMFunction are only static objects which are used by WeakMaps as keys.
     763             :     // It is considered as a root object which is always marked.
     764             :     return true;
     765             : }
     766             : 
     767             : } // namespace gc
     768             : 
     769             : } // namespace js
     770             : 
     771             : // JS::ubi::Nodes can point to js::jit::JitCode instances; they're js::gc::Cell
     772             : // instances with no associated compartment.
     773             : namespace JS {
     774             : namespace ubi {
     775             : template<>
     776             : class Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> {
     777             :   protected:
     778           0 :     explicit Concrete(js::jit::JitCode *ptr) : TracerConcrete<js::jit::JitCode>(ptr) { }
     779             : 
     780             :   public:
     781           0 :     static void construct(void *storage, js::jit::JitCode *ptr) { new (storage) Concrete(ptr); }
     782             : 
     783           0 :     CoarseType coarseType() const final { return CoarseType::Script; }
     784             : 
     785           0 :     Size size(mozilla::MallocSizeOf mallocSizeOf) const override {
     786           0 :         Size size = js::gc::Arena::thingSize(get().asTenured().getAllocKind());
     787           0 :         size += get().bufferSize();
     788           0 :         size += get().headerSize();
     789           0 :         return size;
     790             :     }
     791             : 
     792           0 :     const char16_t* typeName() const override { return concreteTypeName; }
     793             :     static const char16_t concreteTypeName[];
     794             : };
     795             : 
     796             : } // namespace ubi
     797             : 
     798             : template <>
     799             : struct DeletePolicy<js::jit::IonScript>
     800             : {
     801             :     explicit DeletePolicy(JSRuntime* rt) : rt_(rt) {}
     802             :     void operator()(const js::jit::IonScript* script);
     803             : 
     804             :   private:
     805             :     JSRuntime* rt_;
     806             : };
     807             : 
     808             : } // namespace JS
     809             : 
     810             : #endif /* jit_IonCode_h */

Generated by: LCOV version 1.13