// Copyright 2021 The Tint Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "fuzzers/tint_spirv_tools_fuzzer/mutator_cache.h" namespace tint { namespace fuzzers { namespace spvtools_fuzzer { MutatorCache::MutatorCache(size_t max_size) : map_(), entries_(), max_size_(max_size) { assert(max_size && "`max_size` may not be 0"); } MutatorCache::Value::pointer MutatorCache::Get(const Key& key) { auto it = map_.find(key); if (it == map_.end()) { return nullptr; } UpdateUsage(it); return entries_.front().second.get(); } void MutatorCache::Put(const Key& key, Value value) { assert(value && "Mutator cache can't have nullptr unique_ptr"); auto it = map_.find(key); if (it != map_.end()) { it->second->second = std::move(value); UpdateUsage(it); } else { if (map_.size() == max_size_) { Remove(*entries_.back().first); } entries_.emplace_front(nullptr, std::move(value)); auto pair = map_.emplace(key, entries_.begin()); assert(pair.second && "The key must be unique"); entries_.front().first = &pair.first->first; } } MutatorCache::Value MutatorCache::Remove(const Key& key) { auto it = map_.find(key); if (it == map_.end()) { return nullptr; } auto result = std::move(it->second->second); entries_.erase(it->second); map_.erase(it); return result; } size_t MutatorCache::KeyHash::operator()( const std::vector<uint32_t>& vec) const { return std::hash<std::u32string>()({vec.begin(), vec.end()}); } void MutatorCache::UpdateUsage(Map::iterator it) { auto entry = std::move(*it->second); entries_.erase(it->second); entries_.push_front(std::move(entry)); it->second = entries_.begin(); } } // namespace spvtools_fuzzer } // namespace fuzzers } // namespace tint