JitHints.cpp (4697B)
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 #include "jit/JitHints-inl.h" 8 9 #include "gc/Pretenuring.h" 10 11 #include "vm/BytecodeLocation-inl.h" 12 #include "vm/JSScript-inl.h" 13 14 using namespace js; 15 using namespace js::jit; 16 17 JitHintsMap::~JitHintsMap() { 18 while (!ionHintQueue_.isEmpty()) { 19 IonHint* e = ionHintQueue_.popFirst(); 20 js_delete(e); 21 } 22 ionHintMap_.clear(); 23 } 24 25 JitHintsMap::IonHint* JitHintsMap::addIonHint(ScriptKey key, 26 ScriptToHintMap::AddPtr& p) { 27 UniquePtr<IonHint> hint = MakeUnique<IonHint>(key); 28 if (!hint) { 29 return nullptr; 30 } 31 32 if (!ionHintMap_.add(p, key, hint.get())) { 33 return nullptr; 34 } 35 36 ionHintQueue_.insertBack(hint.get()); 37 38 if (ionHintMap_.count() > IonHintMaxEntries) { 39 IonHint* h = ionHintQueue_.popFirst(); 40 ionHintMap_.remove(h->key()); 41 js_delete(h); 42 } 43 44 return hint.release(); 45 } 46 47 void JitHintsMap::updateAsRecentlyUsed(IonHint* hint) { 48 hint->remove(); 49 ionHintQueue_.insertBack(hint); 50 } 51 52 bool JitHintsMap::recordIonCompilation(JSScript* script) { 53 ScriptKey key = getScriptKey(script); 54 if (!key) { 55 return true; 56 } 57 58 // Only add hints for scripts that will be eager baseline compiled. 59 if (!baselineHintMap_.mightContain(key)) { 60 return true; 61 } 62 63 auto p = ionHintMap_.lookupForAdd(key); 64 IonHint* hint = nullptr; 65 if (p) { 66 // Don't modify existing threshold values. 67 hint = p->value(); 68 updateAsRecentlyUsed(hint); 69 } else { 70 hint = addIonHint(key, p); 71 if (!hint) { 72 return false; 73 } 74 } 75 76 uint32_t threshold = IonHintEagerThresholdValue( 77 script->warmUpCountAtLastICStub(), 78 script->jitScript()->hasPretenuredAllocSites()); 79 80 hint->initThreshold(threshold); 81 return true; 82 } 83 84 // static 85 uint32_t JitHintsMap::IonHintEagerThresholdValue(uint32_t lastStubCounter, 86 bool hasPretenuredAllocSites) { 87 // Use the counter when the last IC stub was attached as the initial 88 // threshold. 89 uint32_t eagerThreshold = lastStubCounter; 90 91 // Ensure we stay in baseline long enough to pretenure alloc sites. 92 if (hasPretenuredAllocSites) { 93 eagerThreshold = 94 std::max(eagerThreshold, uint32_t(gc::NormalSiteAttentionThreshold)); 95 } 96 97 // Add 10 for some wiggle room and to safeguard against cases where the 98 // lastStubCounter is 0. 99 eagerThreshold += 10; 100 101 // Do not exceed the default Ion threshold value set in the options. 102 return std::min(eagerThreshold, JitOptions.normalIonWarmUpThreshold); 103 } 104 105 bool JitHintsMap::getIonThresholdHint(JSScript* script, 106 uint32_t& thresholdOut) { 107 ScriptKey key = getScriptKey(script); 108 if (key) { 109 auto p = ionHintMap_.lookup(key); 110 if (p) { 111 IonHint* hint = p->value(); 112 // If the threshold is 0, the hint only contains 113 // monomorphic inlining location information and 114 // may not have entered Ion before. 115 if (hint->threshold() != 0) { 116 updateAsRecentlyUsed(hint); 117 thresholdOut = hint->threshold(); 118 return true; 119 } 120 } 121 } 122 return false; 123 } 124 125 void JitHintsMap::recordInvalidation(JSScript* script) { 126 ScriptKey key = getScriptKey(script); 127 if (key) { 128 auto p = ionHintMap_.lookup(key); 129 if (p) { 130 p->value()->incThreshold(InvalidationThresholdIncrement); 131 } 132 } 133 } 134 135 bool JitHintsMap::addMonomorphicInlineLocation(JSScript* script, 136 BytecodeLocation loc) { 137 ScriptKey key = getScriptKey(script); 138 if (!key) { 139 return true; 140 } 141 142 // Only add inline hints for scripts that will be eager baseline compiled. 143 if (!baselineHintMap_.mightContain(key)) { 144 return true; 145 } 146 147 auto p = ionHintMap_.lookupForAdd(key); 148 IonHint* hint = nullptr; 149 if (p) { 150 hint = p->value(); 151 } else { 152 hint = addIonHint(key, p); 153 if (!hint) { 154 return false; 155 } 156 } 157 158 if (!hint->hasSpaceForMonomorphicInlineEntry()) { 159 return true; 160 } 161 162 uint32_t offset = loc.bytecodeToOffset(script); 163 return hint->addMonomorphicInlineOffset(offset); 164 } 165 166 bool JitHintsMap::hasMonomorphicInlineHintAtOffset(JSScript* script, 167 uint32_t offset) { 168 ScriptKey key = getScriptKey(script); 169 if (!key) { 170 return false; 171 } 172 173 auto p = ionHintMap_.lookup(key); 174 if (p) { 175 return p->value()->hasMonomorphicInlineOffset(offset); 176 } 177 178 return false; 179 }