1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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_JitZone_h 8 #define jit_JitZone_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/HashFunctions.h" 12 #include "mozilla/Maybe.h" 13 #include "mozilla/MemoryReporting.h" 14 15 #include <stddef.h> 16 #include <stdint.h> 17 #include <utility> 18 19 #include "gc/Barrier.h" 20 #include "jit/ExecutableAllocator.h" 21 #include "jit/ICStubSpace.h" 22 #include "jit/Invalidation.h" 23 #include "js/AllocPolicy.h" 24 #include "js/GCHashTable.h" 25 #include "js/HashTable.h" 26 #include "js/TracingAPI.h" 27 #include "js/TypeDecls.h" 28 #include "js/UniquePtr.h" 29 #include "js/Utility.h" 30 #include "threading/ProtectedData.h" 31 32 namespace JS { 33 struct CodeSizes; 34 } 35 36 namespace js { 37 namespace jit { 38 39 enum class CacheKind : uint8_t; 40 class CacheIRStubInfo; 41 class JitCode; 42 43 enum class ICStubEngine : uint8_t { 44 // Baseline IC, see BaselineIC.h. 45 Baseline = 0, 46 47 // Ion IC, see IonIC.h. 48 IonIC 49 }; 50 51 struct CacheIRStubKey : public DefaultHasher<CacheIRStubKey> { 52 struct Lookup { 53 CacheKind kind; 54 ICStubEngine engine; 55 const uint8_t* code; 56 uint32_t length; 57 LookupCacheIRStubKey::Lookup58 Lookup(CacheKind kind, ICStubEngine engine, const uint8_t* code, 59 uint32_t length) 60 : kind(kind), engine(engine), code(code), length(length) {} 61 }; 62 63 static HashNumber hash(const Lookup& l); 64 static bool match(const CacheIRStubKey& entry, const Lookup& l); 65 66 UniquePtr<CacheIRStubInfo, JS::FreePolicy> stubInfo; 67 CacheIRStubKeyCacheIRStubKey68 explicit CacheIRStubKey(CacheIRStubInfo* info) : stubInfo(info) {} CacheIRStubKeyCacheIRStubKey69 CacheIRStubKey(CacheIRStubKey&& other) 70 : stubInfo(std::move(other.stubInfo)) {} 71 72 void operator=(CacheIRStubKey&& other) { 73 stubInfo = std::move(other.stubInfo); 74 } 75 }; 76 77 struct BaselineCacheIRStubCodeMapGCPolicy { traceWeakBaselineCacheIRStubCodeMapGCPolicy78 static bool traceWeak(JSTracer* trc, CacheIRStubKey*, 79 WeakHeapPtrJitCode* value) { 80 return TraceWeakEdge(trc, value, "traceWeak"); 81 } 82 }; 83 84 class JitZone { 85 // Allocated space for optimized baseline stubs. 86 OptimizedICStubSpace optimizedStubSpace_; 87 88 // Set of CacheIRStubInfo instances used by Ion stubs in this Zone. 89 using IonCacheIRStubInfoSet = 90 HashSet<CacheIRStubKey, CacheIRStubKey, SystemAllocPolicy>; 91 IonCacheIRStubInfoSet ionCacheIRStubInfoSet_; 92 93 // Map CacheIRStubKey to shared JitCode objects. 94 using BaselineCacheIRStubCodeMap = 95 GCHashMap<CacheIRStubKey, WeakHeapPtrJitCode, CacheIRStubKey, 96 SystemAllocPolicy, BaselineCacheIRStubCodeMapGCPolicy>; 97 BaselineCacheIRStubCodeMap baselineCacheIRStubCodes_; 98 99 // Executable allocator for all code except wasm code. 100 MainThreadData<ExecutableAllocator> execAlloc_; 101 102 // HashMap that maps scripts to compilations inlining those scripts. 103 using InlinedScriptMap = 104 GCHashMap<WeakHeapPtr<BaseScript*>, RecompileInfoVector, 105 MovableCellHasher<WeakHeapPtr<BaseScript*>>, SystemAllocPolicy>; 106 InlinedScriptMap inlinedCompilations_; 107 108 mozilla::Maybe<IonCompilationId> currentCompilationId_; 109 bool keepJitScripts_ = false; 110 111 public: ~JitZone()112 ~JitZone() { MOZ_ASSERT(!keepJitScripts_); } 113 114 void traceWeak(JSTracer* trc); 115 116 void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, 117 JS::CodeSizes* code, size_t* jitZone, 118 size_t* baselineStubsOptimized) const; 119 optimizedStubSpace()120 OptimizedICStubSpace* optimizedStubSpace() { return &optimizedStubSpace_; } 121 getBaselineCacheIRStubCode(const CacheIRStubKey::Lookup & key,CacheIRStubInfo ** stubInfo)122 JitCode* getBaselineCacheIRStubCode(const CacheIRStubKey::Lookup& key, 123 CacheIRStubInfo** stubInfo) { 124 auto p = baselineCacheIRStubCodes_.lookup(key); 125 if (p) { 126 *stubInfo = p->key().stubInfo.get(); 127 return p->value(); 128 } 129 *stubInfo = nullptr; 130 return nullptr; 131 } putBaselineCacheIRStubCode(const CacheIRStubKey::Lookup & lookup,CacheIRStubKey & key,JitCode * stubCode)132 [[nodiscard]] bool putBaselineCacheIRStubCode( 133 const CacheIRStubKey::Lookup& lookup, CacheIRStubKey& key, 134 JitCode* stubCode) { 135 auto p = baselineCacheIRStubCodes_.lookupForAdd(lookup); 136 MOZ_ASSERT(!p); 137 return baselineCacheIRStubCodes_.add(p, std::move(key), stubCode); 138 } 139 getIonCacheIRStubInfo(const CacheIRStubKey::Lookup & key)140 CacheIRStubInfo* getIonCacheIRStubInfo(const CacheIRStubKey::Lookup& key) { 141 IonCacheIRStubInfoSet::Ptr p = ionCacheIRStubInfoSet_.lookup(key); 142 return p ? p->stubInfo.get() : nullptr; 143 } putIonCacheIRStubInfo(const CacheIRStubKey::Lookup & lookup,CacheIRStubKey & key)144 [[nodiscard]] bool putIonCacheIRStubInfo(const CacheIRStubKey::Lookup& lookup, 145 CacheIRStubKey& key) { 146 IonCacheIRStubInfoSet::AddPtr p = 147 ionCacheIRStubInfoSet_.lookupForAdd(lookup); 148 MOZ_ASSERT(!p); 149 return ionCacheIRStubInfoSet_.add(p, std::move(key)); 150 } purgeIonCacheIRStubInfo()151 void purgeIonCacheIRStubInfo() { ionCacheIRStubInfoSet_.clearAndCompact(); } 152 execAlloc()153 ExecutableAllocator& execAlloc() { return execAlloc_.ref(); } execAlloc()154 const ExecutableAllocator& execAlloc() const { return execAlloc_.ref(); } 155 156 [[nodiscard]] bool addInlinedCompilation(const RecompileInfo& info, 157 JSScript* inlined); 158 maybeInlinedCompilations(JSScript * inlined)159 RecompileInfoVector* maybeInlinedCompilations(JSScript* inlined) { 160 auto p = inlinedCompilations_.lookup(inlined); 161 return p ? &p->value() : nullptr; 162 } 163 removeInlinedCompilations(JSScript * inlined)164 void removeInlinedCompilations(JSScript* inlined) { 165 inlinedCompilations_.remove(inlined); 166 } 167 keepJitScripts()168 bool keepJitScripts() const { return keepJitScripts_; } setKeepJitScripts(bool keep)169 void setKeepJitScripts(bool keep) { keepJitScripts_ = keep; } 170 currentCompilationId()171 mozilla::Maybe<IonCompilationId> currentCompilationId() const { 172 return currentCompilationId_; 173 } currentCompilationIdRef()174 mozilla::Maybe<IonCompilationId>& currentCompilationIdRef() { 175 return currentCompilationId_; 176 } 177 }; 178 179 } // namespace jit 180 } // namespace js 181 182 #endif /* jit_JitZone_h */ 183