diff options
Diffstat (limited to 'runtime/jit/jit_code_cache.cc')
-rw-r--r-- | runtime/jit/jit_code_cache.cc | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc new file mode 100644 index 0000000000..8d4965e70f --- /dev/null +++ b/runtime/jit/jit_code_cache.cc @@ -0,0 +1,121 @@ +/* + * Copyright 2014 The Android Open Source Project + * + * 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 "jit_code_cache.h" + +#include <sstream> + +#include "mem_map.h" +#include "mirror/art_method-inl.h" +#include "oat_file-inl.h" + +namespace art { +namespace jit { + +JitCodeCache* JitCodeCache::Create(size_t capacity, std::string* error_msg) { + CHECK_GT(capacity, 0U); + CHECK_LT(capacity, kMaxCapacity); + std::string error_str; + // Map name specific for android_os_Debug.cpp accounting. + MemMap* map = MemMap::MapAnonymous("jit-code-cache", nullptr, capacity, + PROT_READ | PROT_WRITE | PROT_EXEC, false, &error_str); + if (map == nullptr) { + std::ostringstream oss; + oss << "Failed to create read write execute cache: " << error_str << " size=" << capacity; + *error_msg = oss.str(); + return nullptr; + } + return new JitCodeCache(map); +} + +JitCodeCache::JitCodeCache(MemMap* mem_map) + : lock_("Jit code cache", kJitCodeCacheLock), num_methods_(0) { + VLOG(jit) << "Created jit code cache size=" << PrettySize(mem_map->Size()); + mem_map_.reset(mem_map); + uint8_t* divider = mem_map->Begin() + RoundUp(mem_map->Size() / 4, kPageSize); + // Data cache is 1 / 4 of the map. TODO: Make this variable? + // Put data at the start. + data_cache_ptr_ = mem_map->Begin(); + data_cache_end_ = divider; + data_cache_begin_ = data_cache_ptr_; + mprotect(data_cache_ptr_, data_cache_end_ - data_cache_begin_, PROT_READ | PROT_WRITE); + // Code cache after. + code_cache_begin_ = divider; + code_cache_ptr_ = divider; + code_cache_end_ = mem_map->End(); +} + +bool JitCodeCache::ContainsMethod(mirror::ArtMethod* method) const { + return ContainsCodePtr(method->GetEntryPointFromQuickCompiledCode()); +} + +bool JitCodeCache::ContainsCodePtr(const void* ptr) const { + return ptr >= code_cache_begin_ && ptr < code_cache_end_; +} + +void JitCodeCache::FlushInstructionCache() { + UNIMPLEMENTED(FATAL); + // TODO: Investigate if we need to do this. + // __clear_cache(reinterpret_cast<char*>(code_cache_begin_), static_cast<int>(CodeCacheSize())); +} + +uint8_t* JitCodeCache::ReserveCode(Thread* self, size_t size) { + MutexLock mu(self, lock_); + if (size > CodeCacheRemain()) { + return nullptr; + } + code_cache_ptr_ += size; + return code_cache_ptr_ - size; +} + +uint8_t* JitCodeCache::AddDataArray(Thread* self, const uint8_t* begin, const uint8_t* end) { + MutexLock mu(self, lock_); + const size_t size = end - begin; + if (size > DataCacheRemain()) { + return nullptr; // Out of space in the data cache. + } + std::copy(begin, end, data_cache_ptr_); + data_cache_ptr_ += size; + return data_cache_ptr_ - size; +} + +const void* JitCodeCache::GetCodeFor(mirror::ArtMethod* method) { + const void* code = method->GetEntryPointFromQuickCompiledCode(); + if (ContainsCodePtr(code)) { + return code; + } + MutexLock mu(Thread::Current(), lock_); + auto it = method_code_map_.find(method); + if (it != method_code_map_.end()) { + return it->second; + } + return nullptr; +} + +void JitCodeCache::SaveCompiledCode(mirror::ArtMethod* method, const void* old_code_ptr) { + DCHECK_EQ(method->GetEntryPointFromQuickCompiledCode(), old_code_ptr); + DCHECK(ContainsCodePtr(old_code_ptr)) << PrettyMethod(method) << " old_code_ptr=" + << old_code_ptr; + MutexLock mu(Thread::Current(), lock_); + auto it = method_code_map_.find(method); + if (it != method_code_map_.end()) { + return; + } + method_code_map_.Put(method, old_code_ptr); +} + +} // namespace jit +} // namespace art |