michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jit_PcScriptCache_h michael@0: #define jit_PcScriptCache_h michael@0: michael@0: // Defines a fixed-size hash table solely for the purpose of caching jit::GetPcScript(). michael@0: // One cache is attached to each JSRuntime; it functions as if cleared on GC. michael@0: michael@0: struct JSRuntime; michael@0: michael@0: namespace js { michael@0: namespace jit { michael@0: michael@0: struct PcScriptCacheEntry michael@0: { michael@0: uint8_t *returnAddress; // Key into the hash table. michael@0: jsbytecode *pc; // Cached PC. michael@0: JSScript *script; // Cached script. michael@0: }; michael@0: michael@0: struct PcScriptCache michael@0: { michael@0: static const uint32_t Length = 73; michael@0: michael@0: // GC number at the time the cache was filled or created. michael@0: // Storing and checking against this number allows us to not bother michael@0: // clearing this cache on every GC -- only when actually necessary. michael@0: uint64_t gcNumber; michael@0: michael@0: // List of cache entries. michael@0: mozilla::Array entries; michael@0: michael@0: void clear(uint64_t gcNumber) { michael@0: for (uint32_t i = 0; i < Length; i++) michael@0: entries[i].returnAddress = nullptr; michael@0: this->gcNumber = gcNumber; michael@0: } michael@0: michael@0: // Get a value from the cache. May perform lazy allocation. michael@0: bool get(JSRuntime *rt, uint32_t hash, uint8_t *addr, michael@0: JSScript **scriptRes, jsbytecode **pcRes) michael@0: { michael@0: // If a GC occurred, lazily clear the cache now. michael@0: if (gcNumber != rt->gcNumber) { michael@0: clear(rt->gcNumber); michael@0: return false; michael@0: } michael@0: michael@0: if (entries[hash].returnAddress != addr) michael@0: return false; michael@0: michael@0: *scriptRes = entries[hash].script; michael@0: if (pcRes) michael@0: *pcRes = entries[hash].pc; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: void add(uint32_t hash, uint8_t *addr, jsbytecode *pc, JSScript *script) { michael@0: entries[hash].returnAddress = addr; michael@0: entries[hash].pc = pc; michael@0: entries[hash].script = script; michael@0: } michael@0: michael@0: static uint32_t Hash(uint8_t *addr) { michael@0: uint32_t key = (uint32_t)((uintptr_t)addr); michael@0: return ((key >> 3) * 2654435761u) % Length; michael@0: } michael@0: }; michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif /* jit_PcScriptCache_h */