js/src/jit/IonCode.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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_IonCode_h
     8 #define jit_IonCode_h
    10 #include "mozilla/Atomics.h"
    11 #include "mozilla/MemoryReporting.h"
    12 #include "mozilla/PodOperations.h"
    14 #include "jsinfer.h"
    15 #include "jstypes.h"
    17 #include "assembler/jit/ExecutableAllocator.h"
    18 #include "gc/Heap.h"
    19 #include "jit/IonOptimizationLevels.h"
    20 #include "jit/IonTypes.h"
    22 namespace JSC {
    23     class ExecutablePool;
    24 }
    26 namespace js {
    28 class AsmJSModule;
    30 namespace jit {
    32 class MacroAssembler;
    33 class CodeOffsetLabel;
    34 class PatchableBackedge;
    36 class JitCode : public gc::BarrieredCell<JitCode>
    37 {
    38   protected:
    39     uint8_t *code_;
    40     JSC::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     uint32_t preBarrierTableBytes_;   // Size of the prebarrier table.
    47     uint8_t headerSize_ : 5;          // Number of bytes allocated before codeStart.
    48     uint8_t kind_ : 3;                // JSC::CodeKind, for the memory reporters.
    49     bool invalidated_ : 1;            // Whether the code object has been invalidated.
    50                                       // This is necessary to prevent GC tracing.
    52 #if JS_BITS_PER_WORD == 32
    53     // Ensure JitCode is gc::Cell aligned.
    54     uint32_t padding_;
    55 #endif
    57     JitCode()
    58       : code_(nullptr),
    59         pool_(nullptr)
    60     { }
    61     JitCode(uint8_t *code, uint32_t bufferSize, uint32_t headerSize, JSC::ExecutablePool *pool,
    62             JSC::CodeKind kind)
    63       : code_(code),
    64         pool_(pool),
    65         bufferSize_(bufferSize),
    66         insnSize_(0),
    67         dataSize_(0),
    68         jumpRelocTableBytes_(0),
    69         dataRelocTableBytes_(0),
    70         preBarrierTableBytes_(0),
    71         headerSize_(headerSize),
    72         kind_(kind),
    73         invalidated_(false)
    74     {
    75         MOZ_ASSERT(JSC::CodeKind(kind_) == kind);
    76         MOZ_ASSERT(headerSize_ == headerSize);
    77     }
    79     uint32_t dataOffset() const {
    80         return insnSize_;
    81     }
    82     uint32_t jumpRelocTableOffset() const {
    83         return dataOffset() + dataSize_;
    84     }
    85     uint32_t dataRelocTableOffset() const {
    86         return jumpRelocTableOffset() + jumpRelocTableBytes_;
    87     }
    88     uint32_t preBarrierTableOffset() const {
    89         return dataRelocTableOffset() + dataRelocTableBytes_;
    90     }
    92   public:
    93     uint8_t *raw() const {
    94         return code_;
    95     }
    96     size_t instructionsSize() const {
    97         return insnSize_;
    98     }
    99     void trace(JSTracer *trc);
   100     void finalize(FreeOp *fop);
   101     void setInvalidated() {
   102         invalidated_ = true;
   103     }
   105     void togglePreBarriers(bool enabled);
   107     // If this JitCode object has been, effectively, corrupted due to
   108     // invalidation patching, then we have to remember this so we don't try and
   109     // trace relocation entries that may now be corrupt.
   110     bool invalidated() const {
   111         return !!invalidated_;
   112     }
   114     template <typename T> T as() const {
   115         return JS_DATA_TO_FUNC_PTR(T, raw());
   116     }
   118     void copyFrom(MacroAssembler &masm);
   120     static JitCode *FromExecutable(uint8_t *buffer) {
   121         JitCode *code = *(JitCode **)(buffer - sizeof(JitCode *));
   122         JS_ASSERT(code->raw() == buffer);
   123         return code;
   124     }
   126     static size_t offsetOfCode() {
   127         return offsetof(JitCode, code_);
   128     }
   130     uint8_t *jumpRelocTable() {
   131         return code_ + jumpRelocTableOffset();
   132     }
   134     // Allocates a new JitCode object which will be managed by the GC. If no
   135     // object can be allocated, nullptr is returned. On failure, |pool| is
   136     // automatically released, so the code may be freed.
   137     template <AllowGC allowGC>
   138     static JitCode *New(JSContext *cx, uint8_t *code, uint32_t bufferSize, uint32_t headerSize,
   139                         JSC::ExecutablePool *pool, JSC::CodeKind kind);
   141   public:
   142     static inline ThingRootKind rootKind() { return THING_ROOT_JIT_CODE; }
   143 };
   145 class SnapshotWriter;
   146 class RecoverWriter;
   147 class SafepointWriter;
   148 class SafepointIndex;
   149 class OsiIndex;
   150 class IonCache;
   151 struct PatchableBackedgeInfo;
   152 struct CacheLocation;
   154 // Describes a single AsmJSModule which jumps (via an FFI exit with the given
   155 // index) directly into an IonScript.
   156 struct DependentAsmJSModuleExit
   157 {
   158     const AsmJSModule *module;
   159     size_t exitIndex;
   161     DependentAsmJSModuleExit(const AsmJSModule *module, size_t exitIndex)
   162       : module(module),
   163         exitIndex(exitIndex)
   164     { }
   165 };
   167 // An IonScript attaches Ion-generated information to a JSScript.
   168 struct IonScript
   169 {
   170   private:
   171     // Code pointer containing the actual method.
   172     EncapsulatedPtr<JitCode> method_;
   174     // Deoptimization table used by this method.
   175     EncapsulatedPtr<JitCode> deoptTable_;
   177     // Entrypoint for OSR, or nullptr.
   178     jsbytecode *osrPc_;
   180     // Offset to OSR entrypoint from method_->raw(), or 0.
   181     uint32_t osrEntryOffset_;
   183     // Offset to entrypoint skipping type arg check from method_->raw().
   184     uint32_t skipArgCheckEntryOffset_;
   186     // Offset of the invalidation epilogue (which pushes this IonScript
   187     // and calls the invalidation thunk).
   188     uint32_t invalidateEpilogueOffset_;
   190     // The offset immediately after the IonScript immediate.
   191     // NOTE: technically a constant delta from
   192     // |invalidateEpilogueOffset_|, so we could hard-code this
   193     // per-platform if we want.
   194     uint32_t invalidateEpilogueDataOffset_;
   196     // Number of times this script bailed out without invalidation.
   197     uint32_t numBailouts_;
   199     // Flag set when it is likely that one of our (transitive) call
   200     // targets is not compiled.  Used in ForkJoin.cpp to decide when
   201     // we should add call targets to the worklist.
   202     mozilla::Atomic<bool, mozilla::Relaxed> hasUncompiledCallTarget_;
   204     // Flag set when this script is used as an entry script to parallel
   205     // execution. If this is true, then the parent JSScript must be in its
   206     // JitCompartment's parallel entry script set.
   207     bool isParallelEntryScript_;
   209     // Flag set if IonScript was compiled with SPS profiling enabled.
   210     bool hasSPSInstrumentation_;
   212     // Flag for if this script is getting recompiled.
   213     uint32_t recompiling_;
   215     // Any kind of data needed by the runtime, these can be either cache
   216     // information or profiling info.
   217     uint32_t runtimeData_;
   218     uint32_t runtimeSize_;
   220     // State for polymorphic caches in the compiled code. All caches are stored
   221     // in the runtimeData buffer and indexed by the cacheIndex which give a
   222     // relative offset in the runtimeData array.
   223     uint32_t cacheIndex_;
   224     uint32_t cacheEntries_;
   226     // Map code displacement to safepoint / OSI-patch-delta.
   227     uint32_t safepointIndexOffset_;
   228     uint32_t safepointIndexEntries_;
   230     // Offset to and length of the safepoint table in bytes.
   231     uint32_t safepointsStart_;
   232     uint32_t safepointsSize_;
   234     // Number of bytes this function reserves on the stack.
   235     uint32_t frameSlots_;
   237     // Frame size is the value that can be added to the StackPointer along
   238     // with the frame prefix to get a valid IonJSFrameLayout.
   239     uint32_t frameSize_;
   241     // Table mapping bailout IDs to snapshot offsets.
   242     uint32_t bailoutTable_;
   243     uint32_t bailoutEntries_;
   245     // Map OSI-point displacement to snapshot.
   246     uint32_t osiIndexOffset_;
   247     uint32_t osiIndexEntries_;
   249     // Offset from the start of the code buffer to its snapshot buffer.
   250     uint32_t snapshots_;
   251     uint32_t snapshotsListSize_;
   252     uint32_t snapshotsRVATableSize_;
   254     // List of instructions needed to recover stack frames.
   255     uint32_t recovers_;
   256     uint32_t recoversSize_;
   258     // Constant table for constants stored in snapshots.
   259     uint32_t constantTable_;
   260     uint32_t constantEntries_;
   262     // List of scripts that we call.
   263     //
   264     // Currently this is only non-nullptr for parallel IonScripts.
   265     uint32_t callTargetList_;
   266     uint32_t callTargetEntries_;
   268     // List of patchable backedges which are threaded into the runtime's list.
   269     uint32_t backedgeList_;
   270     uint32_t backedgeEntries_;
   272     // Number of references from invalidation records.
   273     uint32_t refcount_;
   275     // If this is a parallel script, the number of major GC collections it has
   276     // been idle, otherwise 0.
   277     //
   278     // JSScripts with parallel IonScripts are preserved across GC if the
   279     // parallel age is < MAX_PARALLEL_AGE.
   280     uint32_t parallelAge_;
   282     // Identifier of the compilation which produced this code.
   283     types::RecompileInfo recompileInfo_;
   285     // The optimization level this script was compiled in.
   286     OptimizationLevel optimizationLevel_;
   288     // Number of times we tried to enter this script via OSR but failed due to
   289     // a LOOPENTRY pc other than osrPc_.
   290     uint32_t osrPcMismatchCounter_;
   292     // If non-null, the list of AsmJSModules
   293     // that contain an optimized call directly into this IonScript.
   294     Vector<DependentAsmJSModuleExit> *dependentAsmJSModules;
   296   private:
   297     inline uint8_t *bottomBuffer() {
   298         return reinterpret_cast<uint8_t *>(this);
   299     }
   300     inline const uint8_t *bottomBuffer() const {
   301         return reinterpret_cast<const uint8_t *>(this);
   302     }
   304   public:
   305     SnapshotOffset *bailoutTable() {
   306         return (SnapshotOffset *) &bottomBuffer()[bailoutTable_];
   307     }
   308     EncapsulatedValue *constants() {
   309         return (EncapsulatedValue *) &bottomBuffer()[constantTable_];
   310     }
   311     const SafepointIndex *safepointIndices() const {
   312         return const_cast<IonScript *>(this)->safepointIndices();
   313     }
   314     SafepointIndex *safepointIndices() {
   315         return (SafepointIndex *) &bottomBuffer()[safepointIndexOffset_];
   316     }
   317     const OsiIndex *osiIndices() const {
   318         return const_cast<IonScript *>(this)->osiIndices();
   319     }
   320     OsiIndex *osiIndices() {
   321         return (OsiIndex *) &bottomBuffer()[osiIndexOffset_];
   322     }
   323     uint32_t *cacheIndex() {
   324         return (uint32_t *) &bottomBuffer()[cacheIndex_];
   325     }
   326     uint8_t *runtimeData() {
   327         return  &bottomBuffer()[runtimeData_];
   328     }
   329     JSScript **callTargetList() {
   330         return (JSScript **) &bottomBuffer()[callTargetList_];
   331     }
   332     PatchableBackedge *backedgeList() {
   333         return (PatchableBackedge *) &bottomBuffer()[backedgeList_];
   334     }
   335     bool addDependentAsmJSModule(JSContext *cx, DependentAsmJSModuleExit exit);
   336     void removeDependentAsmJSModule(DependentAsmJSModuleExit exit) {
   337         if (!dependentAsmJSModules)
   338             return;
   339         for (size_t i = 0; i < dependentAsmJSModules->length(); i++) {
   340             if (dependentAsmJSModules->begin()[i].module == exit.module &&
   341                 dependentAsmJSModules->begin()[i].exitIndex == exit.exitIndex)
   342             {
   343                 dependentAsmJSModules->erase(dependentAsmJSModules->begin() + i);
   344                 break;
   345             }
   346         }
   347     }
   349   private:
   350     void trace(JSTracer *trc);
   352   public:
   353     // Do not call directly, use IonScript::New. This is public for cx->new_.
   354     IonScript();
   356     static IonScript *New(JSContext *cx, types::RecompileInfo recompileInfo,
   357                           uint32_t frameLocals, uint32_t frameSize,
   358                           size_t snapshotsListSize, size_t snapshotsRVATableSize,
   359                           size_t recoversSize, size_t bailoutEntries,
   360                           size_t constants, size_t safepointIndexEntries,
   361                           size_t osiIndexEntries, size_t cacheEntries,
   362                           size_t runtimeSize, size_t safepointsSize,
   363                           size_t callTargetEntries, size_t backedgeEntries,
   364                           OptimizationLevel optimizationLevel);
   365     static void Trace(JSTracer *trc, IonScript *script);
   366     static void Destroy(FreeOp *fop, IonScript *script);
   368     static inline size_t offsetOfMethod() {
   369         return offsetof(IonScript, method_);
   370     }
   371     static inline size_t offsetOfOsrEntryOffset() {
   372         return offsetof(IonScript, osrEntryOffset_);
   373     }
   374     static inline size_t offsetOfSkipArgCheckEntryOffset() {
   375         return offsetof(IonScript, skipArgCheckEntryOffset_);
   376     }
   377     static inline size_t offsetOfRefcount() {
   378         return offsetof(IonScript, refcount_);
   379     }
   380     static inline size_t offsetOfRecompiling() {
   381         return offsetof(IonScript, recompiling_);
   382     }
   384   public:
   385     JitCode *method() const {
   386         return method_;
   387     }
   388     void setMethod(JitCode *code) {
   389         JS_ASSERT(!invalidated());
   390         method_ = code;
   391     }
   392     void setDeoptTable(JitCode *code) {
   393         deoptTable_ = code;
   394     }
   395     void setOsrPc(jsbytecode *osrPc) {
   396         osrPc_ = osrPc;
   397     }
   398     jsbytecode *osrPc() const {
   399         return osrPc_;
   400     }
   401     void setOsrEntryOffset(uint32_t offset) {
   402         JS_ASSERT(!osrEntryOffset_);
   403         osrEntryOffset_ = offset;
   404     }
   405     uint32_t osrEntryOffset() const {
   406         return osrEntryOffset_;
   407     }
   408     void setSkipArgCheckEntryOffset(uint32_t offset) {
   409         JS_ASSERT(!skipArgCheckEntryOffset_);
   410         skipArgCheckEntryOffset_ = offset;
   411     }
   412     uint32_t getSkipArgCheckEntryOffset() const {
   413         return skipArgCheckEntryOffset_;
   414     }
   415     bool containsCodeAddress(uint8_t *addr) const {
   416         return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
   417     }
   418     bool containsReturnAddress(uint8_t *addr) const {
   419         // This accounts for an off by one error caused by the return address of a
   420         // bailout sitting outside the range of the containing function.
   421         return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
   422     }
   423     void setInvalidationEpilogueOffset(uint32_t offset) {
   424         JS_ASSERT(!invalidateEpilogueOffset_);
   425         invalidateEpilogueOffset_ = offset;
   426     }
   427     uint32_t invalidateEpilogueOffset() const {
   428         JS_ASSERT(invalidateEpilogueOffset_);
   429         return invalidateEpilogueOffset_;
   430     }
   431     void setInvalidationEpilogueDataOffset(uint32_t offset) {
   432         JS_ASSERT(!invalidateEpilogueDataOffset_);
   433         invalidateEpilogueDataOffset_ = offset;
   434     }
   435     uint32_t invalidateEpilogueDataOffset() const {
   436         JS_ASSERT(invalidateEpilogueDataOffset_);
   437         return invalidateEpilogueDataOffset_;
   438     }
   439     void incNumBailouts() {
   440         numBailouts_++;
   441     }
   442     uint32_t numBailouts() const {
   443         return numBailouts_;
   444     }
   445     bool bailoutExpected() const {
   446         return numBailouts_ > 0;
   447     }
   448     void setHasUncompiledCallTarget() {
   449         hasUncompiledCallTarget_ = true;
   450     }
   451     void clearHasUncompiledCallTarget() {
   452         hasUncompiledCallTarget_ = false;
   453     }
   454     bool hasUncompiledCallTarget() const {
   455         return hasUncompiledCallTarget_;
   456     }
   457     void setIsParallelEntryScript() {
   458         isParallelEntryScript_ = true;
   459     }
   460     bool isParallelEntryScript() const {
   461         return isParallelEntryScript_;
   462     }
   463     void setHasSPSInstrumentation() {
   464         hasSPSInstrumentation_ = true;
   465     }
   466     void clearHasSPSInstrumentation() {
   467         hasSPSInstrumentation_ = false;
   468     }
   469     bool hasSPSInstrumentation() const {
   470         return hasSPSInstrumentation_;
   471     }
   472     const uint8_t *snapshots() const {
   473         return reinterpret_cast<const uint8_t *>(this) + snapshots_;
   474     }
   475     size_t snapshotsListSize() const {
   476         return snapshotsListSize_;
   477     }
   478     size_t snapshotsRVATableSize() const {
   479         return snapshotsRVATableSize_;
   480     }
   481     const uint8_t *recovers() const {
   482         return reinterpret_cast<const uint8_t *>(this) + recovers_;
   483     }
   484     size_t recoversSize() const {
   485         return recoversSize_;
   486     }
   487     const uint8_t *safepoints() const {
   488         return reinterpret_cast<const uint8_t *>(this) + safepointsStart_;
   489     }
   490     size_t safepointsSize() const {
   491         return safepointsSize_;
   492     }
   493     size_t callTargetEntries() const {
   494         return callTargetEntries_;
   495     }
   496     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
   497         return mallocSizeOf(this);
   498     }
   499     EncapsulatedValue &getConstant(size_t index) {
   500         JS_ASSERT(index < numConstants());
   501         return constants()[index];
   502     }
   503     size_t numConstants() const {
   504         return constantEntries_;
   505     }
   506     uint32_t frameSlots() const {
   507         return frameSlots_;
   508     }
   509     uint32_t frameSize() const {
   510         return frameSize_;
   511     }
   512     SnapshotOffset bailoutToSnapshot(uint32_t bailoutId) {
   513         JS_ASSERT(bailoutId < bailoutEntries_);
   514         return bailoutTable()[bailoutId];
   515     }
   516     const SafepointIndex *getSafepointIndex(uint32_t disp) const;
   517     const SafepointIndex *getSafepointIndex(uint8_t *retAddr) const {
   518         JS_ASSERT(containsCodeAddress(retAddr));
   519         return getSafepointIndex(retAddr - method()->raw());
   520     }
   521     const OsiIndex *getOsiIndex(uint32_t disp) const;
   522     const OsiIndex *getOsiIndex(uint8_t *retAddr) const;
   523     inline IonCache &getCacheFromIndex(uint32_t index) {
   524         JS_ASSERT(index < cacheEntries_);
   525         uint32_t offset = cacheIndex()[index];
   526         return getCache(offset);
   527     }
   528     inline IonCache &getCache(uint32_t offset) {
   529         JS_ASSERT(offset < runtimeSize_);
   530         return *(IonCache *) &runtimeData()[offset];
   531     }
   532     size_t numCaches() const {
   533         return cacheEntries_;
   534     }
   535     size_t runtimeSize() const {
   536         return runtimeSize_;
   537     }
   538     CacheLocation *getCacheLocs(uint32_t locIndex) {
   539         JS_ASSERT(locIndex < runtimeSize_);
   540         return (CacheLocation *) &runtimeData()[locIndex];
   541     }
   542     void toggleBarriers(bool enabled);
   543     void purgeCaches();
   544     void destroyCaches();
   545     void unlinkFromRuntime(FreeOp *fop);
   546     void copySnapshots(const SnapshotWriter *writer);
   547     void copyRecovers(const RecoverWriter *writer);
   548     void copyBailoutTable(const SnapshotOffset *table);
   549     void copyConstants(const Value *vp);
   550     void copySafepointIndices(const SafepointIndex *firstSafepointIndex, MacroAssembler &masm);
   551     void copyOsiIndices(const OsiIndex *firstOsiIndex, MacroAssembler &masm);
   552     void copyRuntimeData(const uint8_t *data);
   553     void copyCacheEntries(const uint32_t *caches, MacroAssembler &masm);
   554     void copySafepoints(const SafepointWriter *writer);
   555     void copyCallTargetEntries(JSScript **callTargets);
   556     void copyPatchableBackedges(JSContext *cx, JitCode *code,
   557                                 PatchableBackedgeInfo *backedges);
   559     bool invalidated() const {
   560         return refcount_ != 0;
   561     }
   562     size_t refcount() const {
   563         return refcount_;
   564     }
   565     void incref() {
   566         refcount_++;
   567     }
   568     void decref(FreeOp *fop) {
   569         JS_ASSERT(refcount_);
   570         refcount_--;
   571         if (!refcount_)
   572             Destroy(fop, this);
   573     }
   574     const types::RecompileInfo& recompileInfo() const {
   575         return recompileInfo_;
   576     }
   577     types::RecompileInfo& recompileInfoRef() {
   578         return recompileInfo_;
   579     }
   580     OptimizationLevel optimizationLevel() const {
   581         return optimizationLevel_;
   582     }
   583     uint32_t incrOsrPcMismatchCounter() {
   584         return ++osrPcMismatchCounter_;
   585     }
   586     void resetOsrPcMismatchCounter() {
   587         osrPcMismatchCounter_ = 0;
   588     }
   590     void setRecompiling() {
   591         recompiling_ = true;
   592     }
   594     bool isRecompiling() const {
   595         return recompiling_;
   596     }
   598     void clearRecompiling() {
   599         recompiling_ = false;
   600     }
   602     static const uint32_t MAX_PARALLEL_AGE = 5;
   604     void resetParallelAge() {
   605         MOZ_ASSERT(isParallelEntryScript());
   606         parallelAge_ = 0;
   607     }
   608     uint32_t parallelAge() const {
   609         return parallelAge_;
   610     }
   611     uint32_t increaseParallelAge() {
   612         MOZ_ASSERT(isParallelEntryScript());
   613         return ++parallelAge_;
   614     }
   616     static void writeBarrierPre(Zone *zone, IonScript *ionScript);
   617 };
   619 // Execution information for a basic block which may persist after the
   620 // accompanying IonScript is destroyed, for use during profiling.
   621 struct IonBlockCounts
   622 {
   623   private:
   624     uint32_t id_;
   626     // Approximate bytecode in the outer (not inlined) script this block
   627     // was generated from.
   628     uint32_t offset_;
   630     // ids for successors of this block.
   631     uint32_t numSuccessors_;
   632     uint32_t *successors_;
   634     // Hit count for this block.
   635     uint64_t hitCount_;
   637     // Text information about the code generated for this block.
   638     char *code_;
   640   public:
   642     bool init(uint32_t id, uint32_t offset, uint32_t numSuccessors) {
   643         id_ = id;
   644         offset_ = offset;
   645         numSuccessors_ = numSuccessors;
   646         if (numSuccessors) {
   647             successors_ = js_pod_calloc<uint32_t>(numSuccessors);
   648             if (!successors_)
   649                 return false;
   650         }
   651         return true;
   652     }
   654     void destroy() {
   655         js_free(successors_);
   656         js_free(code_);
   657     }
   659     uint32_t id() const {
   660         return id_;
   661     }
   663     uint32_t offset() const {
   664         return offset_;
   665     }
   667     size_t numSuccessors() const {
   668         return numSuccessors_;
   669     }
   671     void setSuccessor(size_t i, uint32_t id) {
   672         JS_ASSERT(i < numSuccessors_);
   673         successors_[i] = id;
   674     }
   676     uint32_t successor(size_t i) const {
   677         JS_ASSERT(i < numSuccessors_);
   678         return successors_[i];
   679     }
   681     uint64_t *addressOfHitCount() {
   682         return &hitCount_;
   683     }
   685     uint64_t hitCount() const {
   686         return hitCount_;
   687     }
   689     void setCode(const char *code) {
   690         char *ncode = (char *) js_malloc(strlen(code) + 1);
   691         if (ncode) {
   692             strcpy(ncode, code);
   693             code_ = ncode;
   694         }
   695     }
   697     const char *code() const {
   698         return code_;
   699     }
   700 };
   702 // Execution information for a compiled script which may persist after the
   703 // IonScript is destroyed, for use during profiling.
   704 struct IonScriptCounts
   705 {
   706   private:
   707     // Any previous invalidated compilation(s) for the script.
   708     IonScriptCounts *previous_;
   710     // Information about basic blocks in this script.
   711     size_t numBlocks_;
   712     IonBlockCounts *blocks_;
   714   public:
   716     IonScriptCounts() {
   717         mozilla::PodZero(this);
   718     }
   720     ~IonScriptCounts() {
   721         for (size_t i = 0; i < numBlocks_; i++)
   722             blocks_[i].destroy();
   723         js_free(blocks_);
   724         js_delete(previous_);
   725     }
   727     bool init(size_t numBlocks) {
   728         numBlocks_ = numBlocks;
   729         blocks_ = js_pod_calloc<IonBlockCounts>(numBlocks);
   730         return blocks_ != nullptr;
   731     }
   733     size_t numBlocks() const {
   734         return numBlocks_;
   735     }
   737     IonBlockCounts &block(size_t i) {
   738         JS_ASSERT(i < numBlocks_);
   739         return blocks_[i];
   740     }
   742     void setPrevious(IonScriptCounts *previous) {
   743         previous_ = previous;
   744     }
   746     IonScriptCounts *previous() const {
   747         return previous_;
   748     }
   749 };
   751 struct VMFunction;
   753 class JitCompartment;
   754 class JitRuntime;
   756 struct AutoFlushICache
   757 {
   758   private:
   759     uintptr_t start_;
   760     uintptr_t stop_;
   761     const char *name_;
   762     bool inhibit_;
   763     AutoFlushICache *prev_;
   765   public:
   766     static void setRange(uintptr_t p, size_t len);
   767     static void flush(uintptr_t p, size_t len);
   768     static void setInhibit();
   769     ~AutoFlushICache();
   770     AutoFlushICache(const char *nonce, bool inhibit=false);
   771 };
   773 } // namespace jit
   775 namespace gc {
   777 inline bool
   778 IsMarked(const jit::VMFunction *)
   779 {
   780     // VMFunction are only static objects which are used by WeakMaps as keys.
   781     // It is considered as a root object which is always marked.
   782     return true;
   783 }
   785 } // namespace gc
   787 } // namespace js
   789 #endif /* jit_IonCode_h */

mercurial