LCOV - code coverage report
Current view: top level - js/src/jit - JitRealm.h (source / functions) Hit Total Coverage
Test: output.info Lines: 72 142 50.7 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * 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_JitRealm_h
       8             : #define jit_JitRealm_h
       9             : 
      10             : #include "mozilla/Array.h"
      11             : #include "mozilla/DebugOnly.h"
      12             : #include "mozilla/MemoryReporting.h"
      13             : 
      14             : #include <utility>
      15             : 
      16             : #include "builtin/TypedObject.h"
      17             : #include "jit/CompileInfo.h"
      18             : #include "jit/ICStubSpace.h"
      19             : #include "jit/IonCode.h"
      20             : #include "jit/IonControlFlow.h"
      21             : #include "jit/JitFrames.h"
      22             : #include "jit/shared/Assembler-shared.h"
      23             : #include "js/GCHashTable.h"
      24             : #include "js/Value.h"
      25             : #include "vm/Stack.h"
      26             : 
      27             : namespace js {
      28             : namespace jit {
      29             : 
      30             : class FrameSizeClass;
      31             : 
      32         195 : struct EnterJitData
      33             : {
      34             :     explicit EnterJitData(JSContext* cx)
      35         195 :       : envChain(cx),
      36         585 :         result(cx)
      37             :     {}
      38             : 
      39             :     uint8_t* jitcode;
      40             :     InterpreterFrame* osrFrame;
      41             : 
      42             :     void* calleeToken;
      43             : 
      44             :     Value* maxArgv;
      45             :     unsigned maxArgc;
      46             :     unsigned numActualArgs;
      47             :     unsigned osrNumStackValues;
      48             : 
      49             :     RootedObject envChain;
      50             :     RootedValue result;
      51             : 
      52             :     bool constructing;
      53             : };
      54             : 
      55             : typedef void (*EnterJitCode)(void* code, unsigned argc, Value* argv, InterpreterFrame* fp,
      56             :                              CalleeToken calleeToken, JSObject* envChain,
      57             :                              size_t numStackValues, Value* vp);
      58             : 
      59             : class JitcodeGlobalTable;
      60             : 
      61             : class JitRuntime
      62             : {
      63             :   private:
      64             :     friend class JitRealm;
      65             : 
      66             :     // Executable allocator for all code except wasm code.
      67             :     MainThreadData<ExecutableAllocator> execAlloc_;
      68             : 
      69             :     MainThreadData<uint64_t> nextCompilationId_;
      70             : 
      71             :     // Shared exception-handler tail.
      72             :     ExclusiveAccessLockWriteOnceData<uint32_t> exceptionTailOffset_;
      73             : 
      74             :     // Shared post-bailout-handler tail.
      75             :     ExclusiveAccessLockWriteOnceData<uint32_t> bailoutTailOffset_;
      76             : 
      77             :     // Shared profiler exit frame tail.
      78             :     ExclusiveAccessLockWriteOnceData<uint32_t> profilerExitFrameTailOffset_;
      79             : 
      80             :     // Trampoline for entering JIT code.
      81             :     ExclusiveAccessLockWriteOnceData<uint32_t> enterJITOffset_;
      82             : 
      83             :     // Vector mapping frame class sizes to bailout tables.
      84             :     struct BailoutTable {
      85             :         uint32_t startOffset;
      86             :         uint32_t size;
      87             :         BailoutTable(uint32_t startOffset, uint32_t size)
      88             :           : startOffset(startOffset), size(size)
      89             :         {}
      90             :     };
      91             :     typedef Vector<BailoutTable, 4, SystemAllocPolicy> BailoutTableVector;
      92             :     ExclusiveAccessLockWriteOnceData<BailoutTableVector> bailoutTables_;
      93             : 
      94             :     // Generic bailout table; used if the bailout table overflows.
      95             :     ExclusiveAccessLockWriteOnceData<uint32_t> bailoutHandlerOffset_;
      96             : 
      97             :     // Argument-rectifying thunk, in the case of insufficient arguments passed
      98             :     // to a function call site.
      99             :     ExclusiveAccessLockWriteOnceData<uint32_t> argumentsRectifierOffset_;
     100             :     ExclusiveAccessLockWriteOnceData<uint32_t> argumentsRectifierReturnOffset_;
     101             : 
     102             :     // Thunk that invalides an (Ion compiled) caller on the Ion stack.
     103             :     ExclusiveAccessLockWriteOnceData<uint32_t> invalidatorOffset_;
     104             : 
     105             :     // Thunk that calls the GC pre barrier.
     106             :     ExclusiveAccessLockWriteOnceData<uint32_t> valuePreBarrierOffset_;
     107             :     ExclusiveAccessLockWriteOnceData<uint32_t> stringPreBarrierOffset_;
     108             :     ExclusiveAccessLockWriteOnceData<uint32_t> objectPreBarrierOffset_;
     109             :     ExclusiveAccessLockWriteOnceData<uint32_t> shapePreBarrierOffset_;
     110             :     ExclusiveAccessLockWriteOnceData<uint32_t> objectGroupPreBarrierOffset_;
     111             : 
     112             :     // Thunk to call malloc/free.
     113             :     ExclusiveAccessLockWriteOnceData<uint32_t> mallocStubOffset_;
     114             :     ExclusiveAccessLockWriteOnceData<uint32_t> freeStubOffset_;
     115             : 
     116             :     // Thunk called to finish compilation of an IonScript.
     117             :     ExclusiveAccessLockWriteOnceData<uint32_t> lazyLinkStubOffset_;
     118             : 
     119             :     // Thunk to enter the interpreter from JIT code.
     120             :     ExclusiveAccessLockWriteOnceData<uint32_t> interpreterStubOffset_;
     121             : 
     122             :     // Thunk used by the debugger for breakpoint and step mode.
     123             :     ExclusiveAccessLockWriteOnceData<JitCode*> debugTrapHandler_;
     124             : 
     125             :     // Thunk used to fix up on-stack recompile of baseline scripts.
     126             :     ExclusiveAccessLockWriteOnceData<JitCode*> baselineDebugModeOSRHandler_;
     127             :     ExclusiveAccessLockWriteOnceData<void*> baselineDebugModeOSRHandlerNoFrameRegPopAddr_;
     128             : 
     129             :     // Code for trampolines and VMFunction wrappers.
     130             :     ExclusiveAccessLockWriteOnceData<JitCode*> trampolineCode_;
     131             : 
     132             :     // Map VMFunction addresses to the offset of the wrapper in
     133             :     // trampolineCode_.
     134             :     using VMWrapperMap = HashMap<const VMFunction*, uint32_t, VMFunction>;
     135             :     ExclusiveAccessLockWriteOnceData<VMWrapperMap*> functionWrappers_;
     136             : 
     137             :     // Global table of jitcode native address => bytecode address mappings.
     138             :     UnprotectedData<JitcodeGlobalTable*> jitcodeGlobalTable_;
     139             : 
     140             : #ifdef DEBUG
     141             :     // The number of possible bailing places encounters before forcefully bailing
     142             :     // in that place. Zero means inactive.
     143             :     MainThreadData<uint32_t> ionBailAfter_;
     144             : #endif
     145             : 
     146             :     // Number of Ion compilations which were finished off thread and are
     147             :     // waiting to be lazily linked. This is only set while holding the helper
     148             :     // thread state lock, but may be read from at other times.
     149             :     mozilla::Atomic<size_t> numFinishedBuilders_;
     150             : 
     151             :     // List of Ion compilation waiting to get linked.
     152             :     using IonBuilderList = mozilla::LinkedList<js::jit::IonBuilder>;
     153             :     MainThreadData<IonBuilderList> ionLazyLinkList_;
     154             :     MainThreadData<size_t> ionLazyLinkListSize_;
     155             : 
     156             :   private:
     157             :     void generateLazyLinkStub(MacroAssembler& masm);
     158             :     void generateInterpreterStub(MacroAssembler& masm);
     159             :     void generateProfilerExitFrameTailStub(MacroAssembler& masm, Label* profilerExitTail);
     160             :     void generateExceptionTailStub(MacroAssembler& masm, void* handler, Label* profilerExitTail);
     161             :     void generateBailoutTailStub(MacroAssembler& masm, Label* bailoutTail);
     162             :     void generateEnterJIT(JSContext* cx, MacroAssembler& masm);
     163             :     void generateArgumentsRectifier(MacroAssembler& masm);
     164             :     BailoutTable generateBailoutTable(MacroAssembler& masm, Label* bailoutTail, uint32_t frameClass);
     165             :     void generateBailoutHandler(MacroAssembler& masm, Label* bailoutTail);
     166             :     void generateInvalidator(MacroAssembler& masm, Label* bailoutTail);
     167             :     uint32_t generatePreBarrier(JSContext* cx, MacroAssembler& masm, MIRType type);
     168             :     void generateMallocStub(MacroAssembler& masm);
     169             :     void generateFreeStub(MacroAssembler& masm);
     170             :     JitCode* generateDebugTrapHandler(JSContext* cx);
     171             :     JitCode* generateBaselineDebugModeOSRHandler(JSContext* cx, uint32_t* noFrameRegPopOffsetOut);
     172             :     bool generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunction& f);
     173             : 
     174             :     bool generateTLEventVM(MacroAssembler& masm, const VMFunction& f, bool enter);
     175             : 
     176             :     inline bool generateTLEnterVM(MacroAssembler& masm, const VMFunction& f) {
     177         908 :         return generateTLEventVM(masm, f, /* enter = */ true);
     178             :     }
     179             :     inline bool generateTLExitVM(MacroAssembler& masm, const VMFunction& f) {
     180         908 :         return generateTLEventVM(masm, f, /* enter = */ false);
     181             :     }
     182             : 
     183             :     uint32_t startTrampolineCode(MacroAssembler& masm);
     184             : 
     185           0 :     TrampolinePtr trampolineCode(uint32_t offset) const {
     186           0 :         MOZ_ASSERT(offset > 0);
     187       84634 :         MOZ_ASSERT(offset < trampolineCode_->instructionsSize());
     188       84634 :         return TrampolinePtr(trampolineCode_->raw() + offset);
     189             :     }
     190             : 
     191             :   public:
     192             :     JitRuntime();
     193             :     ~JitRuntime();
     194             :     MOZ_MUST_USE bool initialize(JSContext* cx, js::AutoLockForExclusiveAccess& lock);
     195             : 
     196             :     static void Trace(JSTracer* trc, js::AutoLockForExclusiveAccess& lock);
     197             :     static void TraceJitcodeGlobalTableForMinorGC(JSTracer* trc);
     198             :     static MOZ_MUST_USE bool MarkJitcodeGlobalTableIteratively(GCMarker* marker);
     199             :     static void SweepJitcodeGlobalTable(JSRuntime* rt);
     200             : 
     201             :     ExecutableAllocator& execAlloc() {
     202        2809 :         return execAlloc_.ref();
     203             :     }
     204             : 
     205             :     IonCompilationId nextCompilationId() {
     206         135 :         return IonCompilationId(nextCompilationId_++);
     207             :     }
     208             : 
     209             :     TrampolinePtr getVMWrapper(const VMFunction& f) const;
     210             :     JitCode* debugTrapHandler(JSContext* cx);
     211             :     JitCode* getBaselineDebugModeOSRHandler(JSContext* cx);
     212             :     void* getBaselineDebugModeOSRHandlerAddress(JSContext* cx, bool popFrameReg);
     213             : 
     214             :     TrampolinePtr getGenericBailoutHandler() const {
     215          96 :         return trampolineCode(bailoutHandlerOffset_);
     216             :     }
     217             : 
     218             :     TrampolinePtr getExceptionTail() const {
     219         172 :         return trampolineCode(exceptionTailOffset_);
     220             :     }
     221             : 
     222             :     TrampolinePtr getBailoutTail() const {
     223           0 :         return trampolineCode(bailoutTailOffset_);
     224             :     }
     225             : 
     226             :     TrampolinePtr getProfilerExitFrameTail() const {
     227        1628 :         return trampolineCode(profilerExitFrameTailOffset_);
     228             :     }
     229             : 
     230             :     TrampolinePtr getBailoutTable(const FrameSizeClass& frameClass) const;
     231             :     uint32_t getBailoutTableSize(const FrameSizeClass& frameClass) const;
     232             : 
     233             :     TrampolinePtr getArgumentsRectifier() const {
     234        2242 :         return trampolineCode(argumentsRectifierOffset_);
     235             :     }
     236             : 
     237             :     TrampolinePtr getArgumentsRectifierReturnAddr() const {
     238           0 :         return trampolineCode(argumentsRectifierReturnOffset_);
     239             :     }
     240             : 
     241             :     TrampolinePtr getInvalidationThunk() const {
     242          96 :         return trampolineCode(invalidatorOffset_);
     243             :     }
     244             : 
     245             :     EnterJitCode enterJit() const {
     246       46986 :         return JS_DATA_TO_FUNC_PTR(EnterJitCode, trampolineCode(enterJITOffset_).value);
     247             :     }
     248             : 
     249         957 :     TrampolinePtr preBarrier(MIRType type) const {
     250           0 :         switch (type) {
     251             :           case MIRType::Value:
     252           0 :             return trampolineCode(valuePreBarrierOffset_);
     253             :           case MIRType::String:
     254           0 :             return trampolineCode(stringPreBarrierOffset_);
     255             :           case MIRType::Object:
     256           0 :             return trampolineCode(objectPreBarrierOffset_);
     257             :           case MIRType::Shape:
     258           0 :             return trampolineCode(shapePreBarrierOffset_);
     259             :           case MIRType::ObjectGroup:
     260          10 :             return trampolineCode(objectGroupPreBarrierOffset_);
     261           0 :           default: MOZ_CRASH();
     262             :         }
     263             :     }
     264             : 
     265             :     TrampolinePtr mallocStub() const {
     266           0 :         return trampolineCode(mallocStubOffset_);
     267             :     }
     268             : 
     269             :     TrampolinePtr freeStub() const {
     270          24 :         return trampolineCode(freeStubOffset_);
     271             :     }
     272             : 
     273             :     TrampolinePtr lazyLinkStub() const {
     274          94 :         return trampolineCode(lazyLinkStubOffset_);
     275             :     }
     276             :     TrampolinePtr interpreterStub() const {
     277       30964 :         return trampolineCode(interpreterStubOffset_);
     278             :     }
     279             : 
     280             :     bool hasJitcodeGlobalTable() const {
     281        1706 :         return jitcodeGlobalTable_ != nullptr;
     282             :     }
     283             : 
     284           0 :     JitcodeGlobalTable* getJitcodeGlobalTable() {
     285         853 :         MOZ_ASSERT(hasJitcodeGlobalTable());
     286        1706 :         return jitcodeGlobalTable_;
     287             :     }
     288             : 
     289             :     bool isProfilerInstrumentationEnabled(JSRuntime* rt) {
     290         977 :         return rt->geckoProfiler().enabled();
     291             :     }
     292             : 
     293             :     bool isOptimizationTrackingEnabled(JSRuntime* rt) {
     294          76 :         return isProfilerInstrumentationEnabled(rt);
     295             :     }
     296             : 
     297             : #ifdef DEBUG
     298        1134 :     void* addressOfIonBailAfter() { return &ionBailAfter_; }
     299             : 
     300             :     // Set after how many bailing places we should forcefully bail.
     301             :     // Zero disables this feature.
     302             :     void setIonBailAfter(uint32_t after) {
     303           0 :         ionBailAfter_ = after;
     304             :     }
     305             : #endif
     306             : 
     307             :     size_t numFinishedBuilders() const {
     308         196 :         return numFinishedBuilders_;
     309             :     }
     310             :     mozilla::Atomic<size_t>& numFinishedBuildersRef(const AutoLockHelperThreadState& locked) {
     311             :         return numFinishedBuilders_;
     312             :     }
     313             : 
     314             :     IonBuilderList& ionLazyLinkList(JSRuntime* rt);
     315             : 
     316             :     size_t ionLazyLinkListSize() const {
     317          94 :         return ionLazyLinkListSize_;
     318             :     }
     319             : 
     320             :     void ionLazyLinkListRemove(JSRuntime* rt, js::jit::IonBuilder* builder);
     321             :     void ionLazyLinkListAdd(JSRuntime* rt, js::jit::IonBuilder* builder);
     322             : };
     323             : 
     324             : enum class CacheKind : uint8_t;
     325             : class CacheIRStubInfo;
     326             : 
     327             : enum class ICStubEngine : uint8_t {
     328             :     // Baseline IC, see SharedIC.h and BaselineIC.h.
     329             :     Baseline = 0,
     330             : 
     331             :     // Ion IC that reuses Baseline IC code, see SharedIC.h.
     332             :     IonSharedIC,
     333             : 
     334             :     // Ion IC, see IonIC.h.
     335             :     IonIC
     336             : };
     337             : 
     338        1305 : struct CacheIRStubKey : public DefaultHasher<CacheIRStubKey> {
     339             :     struct Lookup {
     340             :         CacheKind kind;
     341             :         ICStubEngine engine;
     342             :         const uint8_t* code;
     343             :         uint32_t length;
     344             : 
     345             :         Lookup(CacheKind kind, ICStubEngine engine, const uint8_t* code, uint32_t length)
     346       11687 :           : kind(kind), engine(engine), code(code), length(length)
     347             :         {}
     348             :     };
     349             : 
     350             :     static HashNumber hash(const Lookup& l);
     351             :     static bool match(const CacheIRStubKey& entry, const Lookup& l);
     352             : 
     353             :     UniquePtr<CacheIRStubInfo, JS::FreePolicy> stubInfo;
     354             : 
     355         844 :     explicit CacheIRStubKey(CacheIRStubInfo* info) : stubInfo(info) {}
     356        1708 :     CacheIRStubKey(CacheIRStubKey&& other) : stubInfo(std::move(other.stubInfo)) { }
     357             : 
     358             :     void operator=(CacheIRStubKey&& other) {
     359           0 :         stubInfo = std::move(other.stubInfo);
     360             :     }
     361             : };
     362             : 
     363             : template<typename Key>
     364             : struct IcStubCodeMapGCPolicy
     365             : {
     366             :     static bool needsSweep(Key*, ReadBarrieredJitCode* value) {
     367           0 :         return IsAboutToBeFinalized(value);
     368             :     }
     369             : };
     370             : 
     371          50 : class JitZone
     372             : {
     373             :     // Allocated space for optimized baseline stubs.
     374             :     OptimizedICStubSpace optimizedStubSpace_;
     375             :     // Allocated space for cached cfg.
     376             :     CFGSpace cfgSpace_;
     377             : 
     378             :     // Set of CacheIRStubInfo instances used by Ion stubs in this Zone.
     379             :     using IonCacheIRStubInfoSet = HashSet<CacheIRStubKey, CacheIRStubKey, SystemAllocPolicy>;
     380             :     IonCacheIRStubInfoSet ionCacheIRStubInfoSet_;
     381             : 
     382             :     // Map CacheIRStubKey to shared JitCode objects.
     383             :     using BaselineCacheIRStubCodeMap = GCHashMap<CacheIRStubKey,
     384             :                                                  ReadBarrieredJitCode,
     385             :                                                  CacheIRStubKey,
     386             :                                                  SystemAllocPolicy,
     387             :                                                  IcStubCodeMapGCPolicy<CacheIRStubKey>>;
     388             :     BaselineCacheIRStubCodeMap baselineCacheIRStubCodes_;
     389             : 
     390             :   public:
     391             :     MOZ_MUST_USE bool init(JSContext* cx);
     392             :     void sweep();
     393             : 
     394             :     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
     395             :                                 size_t* jitZone,
     396             :                                 size_t* baselineStubsOptimized,
     397             :                                 size_t* cachedCFG) const;
     398             : 
     399             :     OptimizedICStubSpace* optimizedStubSpace() {
     400       24944 :         return &optimizedStubSpace_;
     401             :     }
     402             :     CFGSpace* cfgSpace() {
     403             :         return &cfgSpace_;
     404             :     }
     405             : 
     406           0 :     JitCode* getBaselineCacheIRStubCode(const CacheIRStubKey::Lookup& key,
     407             :                                         CacheIRStubInfo** stubInfo) {
     408           0 :         auto p = baselineCacheIRStubCodes_.lookup(key);
     409           0 :         if (p) {
     410       21530 :             *stubInfo = p->key().stubInfo.get();
     411           0 :             return p->value();
     412             :         }
     413         379 :         *stubInfo = nullptr;
     414           0 :         return nullptr;
     415             :     }
     416         379 :     MOZ_MUST_USE bool putBaselineCacheIRStubCode(const CacheIRStubKey::Lookup& lookup,
     417             :                                                  CacheIRStubKey& key,
     418             :                                                  JitCode* stubCode)
     419             :     {
     420           0 :         auto p = baselineCacheIRStubCodes_.lookupForAdd(lookup);
     421         379 :         MOZ_ASSERT(!p);
     422         758 :         return baselineCacheIRStubCodes_.add(p, std::move(key), stubCode);
     423             :     }
     424             : 
     425         543 :     CacheIRStubInfo* getIonCacheIRStubInfo(const CacheIRStubKey::Lookup& key) {
     426           0 :         if (!ionCacheIRStubInfoSet_.initialized())
     427             :             return nullptr;
     428        1084 :         IonCacheIRStubInfoSet::Ptr p = ionCacheIRStubInfoSet_.lookup(key);
     429           0 :         return p ? p->stubInfo.get() : nullptr;
     430             :     }
     431          43 :     MOZ_MUST_USE bool putIonCacheIRStubInfo(const CacheIRStubKey::Lookup& lookup,
     432             :                                             CacheIRStubKey& key)
     433             :     {
     434           0 :         if (!ionCacheIRStubInfoSet_.initialized() && !ionCacheIRStubInfoSet_.init())
     435             :             return false;
     436           0 :         IonCacheIRStubInfoSet::AddPtr p = ionCacheIRStubInfoSet_.lookupForAdd(lookup);
     437          43 :         MOZ_ASSERT(!p);
     438          86 :         return ionCacheIRStubInfoSet_.add(p, std::move(key));
     439             :     }
     440             :     void purgeIonCacheIRStubInfo() {
     441           0 :         ionCacheIRStubInfoSet_.finish();
     442             :     }
     443             : };
     444             : 
     445             : enum class BailoutReturnStub {
     446             :     GetProp,
     447             :     GetPropSuper,
     448             :     SetProp,
     449             :     Call,
     450             :     New,
     451             :     Count
     452             : };
     453             : 
     454             : class JitRealm
     455             : {
     456             :     friend class JitActivation;
     457             : 
     458             :     // Map ICStub keys to ICStub shared code objects.
     459             :     using ICStubCodeMap = GCHashMap<uint32_t,
     460             :                                     ReadBarrieredJitCode,
     461             :                                     DefaultHasher<uint32_t>,
     462             :                                     ZoneAllocPolicy,
     463             :                                     IcStubCodeMapGCPolicy<uint32_t>>;
     464             :     ICStubCodeMap* stubCodes_;
     465             : 
     466             :     // Keep track of offset into various baseline stubs' code at return
     467             :     // point from called script.
     468             :     struct BailoutReturnStubInfo
     469             :     {
     470             :         void* addr;
     471             :         uint32_t key;
     472             : 
     473         135 :         BailoutReturnStubInfo() : addr(nullptr), key(0) { }
     474             :         BailoutReturnStubInfo(void* addr_, uint32_t key_) : addr(addr_), key(key_) { }
     475             :     };
     476             :     mozilla::EnumeratedArray<BailoutReturnStub,
     477             :                              BailoutReturnStub::Count,
     478             :                              BailoutReturnStubInfo> bailoutReturnStubInfo_;
     479             : 
     480             :     // The JitRealm stores stubs to concatenate strings inline and perform
     481             :     // RegExp calls inline.  These bake in zone and realm specific pointers
     482             :     // and can't be stored in JitRuntime.
     483             :     //
     484             :     // These are weak pointers, but they can by accessed during off-thread Ion
     485             :     // compilation and therefore can't use the usual read barrier. Instead, we
     486             :     // record which stubs have been read and perform the appropriate barriers in
     487             :     // CodeGenerator::link().
     488             : 
     489             :     enum StubIndex : uint32_t
     490             :     {
     491             :         StringConcat = 0,
     492             :         RegExpMatcher,
     493             :         RegExpSearcher,
     494             :         RegExpTester,
     495             :         Count
     496             :     };
     497             : 
     498             :     mozilla::EnumeratedArray<StubIndex, StubIndex::Count, ReadBarrieredJitCode> stubs_;
     499             : 
     500             :     // The same approach is taken for SIMD template objects.
     501             : 
     502             :     mozilla::EnumeratedArray<SimdType, SimdType::Count, ReadBarrieredObject> simdTemplateObjects_;
     503             : 
     504             :     JitCode* generateStringConcatStub(JSContext* cx);
     505             :     JitCode* generateRegExpMatcherStub(JSContext* cx);
     506             :     JitCode* generateRegExpSearcherStub(JSContext* cx);
     507             :     JitCode* generateRegExpTesterStub(JSContext* cx);
     508             : 
     509           0 :     JitCode* getStubNoBarrier(StubIndex stub, uint32_t* requiredBarriersOut) const {
     510           0 :         MOZ_ASSERT(CurrentThreadIsIonCompiling());
     511          54 :         *requiredBarriersOut |= 1 << uint32_t(stub);
     512         108 :         return stubs_[stub].unbarrieredGet();
     513             :     }
     514             : 
     515             :   public:
     516           0 :     JSObject* getSimdTemplateObjectFor(JSContext* cx, Handle<SimdTypeDescr*> descr) {
     517           0 :         ReadBarrieredObject& tpl = simdTemplateObjects_[descr->type()];
     518           0 :         if (!tpl)
     519           0 :             tpl.set(TypedObject::createZeroed(cx, descr, gc::TenuredHeap));
     520           0 :         return tpl.get();
     521             :     }
     522             : 
     523           0 :     JSObject* maybeGetSimdTemplateObjectFor(SimdType type) const {
     524             :         // This function is used by Eager Simd Unbox phase which can run
     525             :         // off-thread, so we cannot use the usual read barrier. For more
     526             :         // information, see the comment above
     527             :         // CodeGenerator::simdRefreshTemplatesDuringLink_.
     528             : 
     529           0 :         MOZ_ASSERT(CurrentThreadIsIonCompiling());
     530           0 :         return simdTemplateObjects_[type].unbarrieredGet();
     531             :     }
     532             : 
     533           0 :     JitCode* getStubCode(uint32_t key) {
     534           0 :         ICStubCodeMap::Ptr p = stubCodes_->lookup(key);
     535       54719 :         if (p)
     536      107947 :             return p->value();
     537             :         return nullptr;
     538             :     }
     539           0 :     MOZ_MUST_USE bool putStubCode(JSContext* cx, uint32_t key, Handle<JitCode*> stubCode) {
     540           0 :         MOZ_ASSERT(stubCode);
     541           0 :         if (!stubCodes_->putNew(key, stubCode.get())) {
     542           0 :             ReportOutOfMemory(cx);
     543           0 :             return false;
     544             :         }
     545             :         return true;
     546             :     }
     547           0 :     void initBailoutReturnAddr(void* addr, uint32_t key, BailoutReturnStub kind) {
     548           0 :         MOZ_ASSERT(bailoutReturnStubInfo_[kind].addr == nullptr);
     549           0 :         bailoutReturnStubInfo_[kind] = BailoutReturnStubInfo { addr, key };
     550           0 :     }
     551           0 :     void* bailoutReturnAddr(BailoutReturnStub kind) {
     552           2 :         MOZ_ASSERT(bailoutReturnStubInfo_[kind].addr);
     553           2 :         return bailoutReturnStubInfo_[kind].addr;
     554             :     }
     555             : 
     556             :     JitRealm();
     557             :     ~JitRealm();
     558             : 
     559             :     MOZ_MUST_USE bool initialize(JSContext* cx);
     560             : 
     561             :     // Initialize code stubs only used by Ion, not Baseline.
     562          52 :     MOZ_MUST_USE bool ensureIonStubsExist(JSContext* cx) {
     563           0 :         if (stubs_[StringConcat])
     564             :             return true;
     565           5 :         stubs_[StringConcat] = generateStringConcatStub(cx);
     566           3 :         return stubs_[StringConcat];
     567             :     }
     568             : 
     569             :     void sweep(JS::Realm* realm);
     570             : 
     571           0 :     void discardStubs() {
     572           0 :         for (ReadBarrieredJitCode& stubRef : stubs_)
     573           0 :             stubRef = nullptr;
     574           0 :     }
     575             : 
     576             :     JitCode* stringConcatStubNoBarrier(uint32_t* requiredBarriersOut) const {
     577          48 :         return getStubNoBarrier(StringConcat, requiredBarriersOut);
     578             :     }
     579             : 
     580             :     JitCode* regExpMatcherStubNoBarrier(uint32_t* requiredBarriersOut) const {
     581           1 :         return getStubNoBarrier(RegExpMatcher, requiredBarriersOut);
     582             :     }
     583             : 
     584           8 :     MOZ_MUST_USE bool ensureRegExpMatcherStubExists(JSContext* cx) {
     585           0 :         if (stubs_[RegExpMatcher])
     586             :             return true;
     587           5 :         stubs_[RegExpMatcher] = generateRegExpMatcherStub(cx);
     588           3 :         return stubs_[RegExpMatcher];
     589             :     }
     590             : 
     591             :     JitCode* regExpSearcherStubNoBarrier(uint32_t* requiredBarriersOut) const {
     592           1 :         return getStubNoBarrier(RegExpSearcher, requiredBarriersOut);
     593             :     }
     594             : 
     595           1 :     MOZ_MUST_USE bool ensureRegExpSearcherStubExists(JSContext* cx) {
     596           0 :         if (stubs_[RegExpSearcher])
     597             :             return true;
     598           5 :         stubs_[RegExpSearcher] = generateRegExpSearcherStub(cx);
     599           3 :         return stubs_[RegExpSearcher];
     600             :     }
     601             : 
     602             :     JitCode* regExpTesterStubNoBarrier(uint32_t* requiredBarriersOut) const {
     603           4 :         return getStubNoBarrier(RegExpTester, requiredBarriersOut);
     604             :     }
     605             : 
     606           8 :     MOZ_MUST_USE bool ensureRegExpTesterStubExists(JSContext* cx) {
     607           0 :         if (stubs_[RegExpTester])
     608             :             return true;
     609           5 :         stubs_[RegExpTester] = generateRegExpTesterStub(cx);
     610           3 :         return stubs_[RegExpTester];
     611             :     }
     612             : 
     613             :     // Perform the necessary read barriers on stubs and SIMD template object
     614             :     // described by the bitmasks passed in. This function can only be called
     615             :     // from the main thread.
     616             :     //
     617             :     // The stub and template object pointers must still be valid by the time
     618             :     // these methods are called. This is arranged by cancelling off-thread Ion
     619             :     // compilation at the start of GC and at the start of sweeping.
     620             :     void performStubReadBarriers(uint32_t stubsToBarrier) const;
     621             :     void performSIMDTemplateReadBarriers(uint32_t simdTemplatesToBarrier) const;
     622             : 
     623             :     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     624             : 
     625             :     bool stringsCanBeInNursery;
     626             : };
     627             : 
     628             : // Called from Zone::discardJitCode().
     629             : void InvalidateAll(FreeOp* fop, JS::Zone* zone);
     630             : void FinishInvalidation(FreeOp* fop, JSScript* script);
     631             : 
     632             : // On windows systems, really large frames need to be incrementally touched.
     633             : // The following constant defines the minimum increment of the touch.
     634             : #ifdef XP_WIN
     635             : const unsigned WINDOWS_BIG_FRAME_TOUCH_INCREMENT = 4096 - 1;
     636             : #endif
     637             : 
     638             : // If NON_WRITABLE_JIT_CODE is enabled, this class will ensure
     639             : // JIT code is writable (has RW permissions) in its scope.
     640             : // Otherwise it's a no-op.
     641             : class MOZ_STACK_CLASS AutoWritableJitCode
     642             : {
     643             :     JSRuntime* rt_;
     644             :     void* addr_;
     645             :     size_t size_;
     646             : 
     647             :   public:
     648        2815 :     AutoWritableJitCode(JSRuntime* rt, void* addr, size_t size)
     649           0 :       : rt_(rt), addr_(addr), size_(size)
     650             :     {
     651           1 :         rt_->toggleAutoWritableJitCodeActive(true);
     652           0 :         if (!ExecutableAllocator::makeWritable(addr_, size_))
     653           0 :             MOZ_CRASH();
     654           0 :     }
     655           0 :     AutoWritableJitCode(void* addr, size_t size)
     656           0 :       : AutoWritableJitCode(TlsContext.get()->runtime(), addr, size)
     657           0 :     {}
     658           0 :     explicit AutoWritableJitCode(JitCode* code)
     659           0 :       : AutoWritableJitCode(code->runtimeFromMainThread(), code->raw(), code->bufferSize())
     660           0 :     {}
     661           1 :     ~AutoWritableJitCode() {
     662           0 :         if (!ExecutableAllocator::makeExecutable(addr_, size_))
     663           0 :             MOZ_CRASH();
     664        2815 :         rt_->toggleAutoWritableJitCodeActive(false);
     665        2815 :     }
     666             : };
     667             : 
     668           0 : class MOZ_STACK_CLASS MaybeAutoWritableJitCode
     669             : {
     670             :     mozilla::Maybe<AutoWritableJitCode> awjc_;
     671             : 
     672             :   public:
     673             :     MaybeAutoWritableJitCode(void* addr, size_t size, ReprotectCode reprotect) {
     674             :         if (reprotect)
     675             :             awjc_.emplace(addr, size);
     676             :     }
     677           0 :     MaybeAutoWritableJitCode(JitCode* code, ReprotectCode reprotect) {
     678             :         if (reprotect)
     679             :             awjc_.emplace(code);
     680             :     }
     681             : };
     682             : 
     683             : } // namespace jit
     684             : } // namespace js
     685             : 
     686             : #endif /* jit_JitRealm_h */

Generated by: LCOV version 1.13-14-ga5dd952