1e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier/*
2e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * Copyright 2014 The Android Open Source Project
3e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *
4e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License");
5e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * you may not use this file except in compliance with the License.
6e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * You may obtain a copy of the License at
7e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *
8e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *      http://www.apache.org/licenses/LICENSE-2.0
9e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier *
10e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * Unless required by applicable law or agreed to in writing, software
11e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS,
12e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * See the License for the specific language governing permissions and
14e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * limitations under the License.
15e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier */
16e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
17e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "jit_code_cache.h"
18e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
19e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include <sstream>
20e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
21e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h"
2266f55237679db90cb0a0a265043a787932b466f8Calin Juravle#include "base/stl_util.h"
2332ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier#include "base/systrace.h"
2431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle#include "base/time_utils.h"
255cc349f3dd578e974f78314c50b6a0267c23e591David Srbecky#include "debugger_interface.h"
261dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray#include "entrypoints/runtime_asm_entrypoints.h"
271dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray#include "gc/accounting/bitmap-inl.h"
2899c959f3868512bb95432cf02a1f0ad3971698bfNicolas Geoffray#include "gc/scoped_gc_critical_section.h"
29bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray#include "jit/jit.h"
3026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray#include "jit/profiling_info.h"
311dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray#include "linear_alloc.h"
32e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "mem_map.h"
33e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "oat_file-inl.h"
3462623401fe994ff2f2719faf3cdb3c23b92ccd96Nicolas Geoffray#include "scoped_thread_state_change.h"
351dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray#include "thread_list.h"
36e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
37e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace art {
38e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace jit {
39e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
400c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraystatic constexpr int kProtAll = PROT_READ | PROT_WRITE | PROT_EXEC;
410c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraystatic constexpr int kProtData = PROT_READ | PROT_WRITE;
420c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraystatic constexpr int kProtCode = PROT_READ | PROT_EXEC;
430c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
44933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffraystatic constexpr size_t kCodeSizeLogThreshold = 50 * KB;
45933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffraystatic constexpr size_t kStackMapSizeLogThreshold = 50 * KB;
46933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray
470c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray#define CHECKED_MPROTECT(memory, size, prot)                \
480c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  do {                                                      \
490c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    int rc = mprotect(memory, size, prot);                  \
500c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    if (UNLIKELY(rc != 0)) {                                \
510c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray      errno = rc;                                           \
520c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray      PLOG(FATAL) << "Failed to mprotect jit code cache";   \
530c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    }                                                       \
540c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  } while (false)                                           \
550c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
560a3be1620a3560253cfa789cb9819013293c5654Nicolas GeoffrayJitCodeCache* JitCodeCache::Create(size_t initial_capacity,
570a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray                                   size_t max_capacity,
58a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray                                   bool generate_debug_info,
590a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray                                   std::string* error_msg) {
6032ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__PRETTY_FUNCTION__);
610a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  CHECK_GE(max_capacity, initial_capacity);
62a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray
63a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray  // Generating debug information is mostly for using the 'perf' tool, which does
64a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray  // not work with ashmem.
65a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray  bool use_ashmem = !generate_debug_info;
66a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray  // With 'perf', we want a 1-1 mapping between an address and a method.
67a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray  bool garbage_collect_code = !generate_debug_info;
68a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray
690a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  // We need to have 32 bit offsets from method headers in code cache which point to things
700a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  // in the data cache. If the maps are more than 4G apart, having multiple maps wouldn't work.
710a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  // Ensure we're below 1 GB to be safe.
720a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  if (max_capacity > 1 * GB) {
730a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    std::ostringstream oss;
740a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    oss << "Maxium code cache capacity is limited to 1 GB, "
750a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray        << PrettySize(max_capacity) << " is too big";
760a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    *error_msg = oss.str();
770a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    return nullptr;
780a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  }
790a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
80e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  std::string error_str;
81e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // Map name specific for android_os_Debug.cpp accounting.
820c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  MemMap* data_map = MemMap::MapAnonymous(
83a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray      "data-code-cache", nullptr, max_capacity, kProtAll, false, false, &error_str, use_ashmem);
840c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  if (data_map == nullptr) {
850c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    std::ostringstream oss;
860a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    oss << "Failed to create read write execute cache: " << error_str << " size=" << max_capacity;
870c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    *error_msg = oss.str();
880c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    return nullptr;
890c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  }
900c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
910a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  // Align both capacities to page size, as that's the unit mspaces use.
920a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  initial_capacity = RoundDown(initial_capacity, 2 * kPageSize);
930a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  max_capacity = RoundDown(max_capacity, 2 * kPageSize);
940a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
954e915fbc2be5fc43c782389bbbb7306cd76a523aNicolas Geoffray  // Data cache is 1 / 2 of the map.
960c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  // TODO: Make this variable?
970a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  size_t data_size = max_capacity / 2;
980a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  size_t code_size = max_capacity - data_size;
990a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  DCHECK_EQ(code_size + data_size, max_capacity);
1000c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  uint8_t* divider = data_map->Begin() + data_size;
1010c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
102a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray  MemMap* code_map =
103a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray      data_map->RemapAtEnd(divider, "jit-code-cache", kProtAll, &error_str, use_ashmem);
1040c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  if (code_map == nullptr) {
105e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier    std::ostringstream oss;
1060a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    oss << "Failed to create read write execute cache: " << error_str << " size=" << max_capacity;
107e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier    *error_msg = oss.str();
108e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier    return nullptr;
109e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  }
1100c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  DCHECK_EQ(code_map->Begin(), divider);
1110a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  data_size = initial_capacity / 2;
1120a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  code_size = initial_capacity - data_size;
1130a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  DCHECK_EQ(code_size + data_size, initial_capacity);
114a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray  return new JitCodeCache(
115c3fec4c4ca01055d4d5920f363620b5726ebbbefNicolas Geoffray      code_map, data_map, code_size, data_size, max_capacity, garbage_collect_code);
116e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
117e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
1180a3be1620a3560253cfa789cb9819013293c5654Nicolas GeoffrayJitCodeCache::JitCodeCache(MemMap* code_map,
1190a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray                           MemMap* data_map,
1200a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray                           size_t initial_code_capacity,
1210a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray                           size_t initial_data_capacity,
122a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray                           size_t max_capacity,
123a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray                           bool garbage_collect_code)
1240c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    : lock_("Jit code cache", kJitCodeCacheLock),
1251dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      lock_cond_("Jit code cache variable", lock_),
1261dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      collection_in_progress_(false),
1270c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray      code_map_(code_map),
1280a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray      data_map_(data_map),
1290a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray      max_capacity_(max_capacity),
1300a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray      current_capacity_(initial_code_capacity + initial_data_capacity),
1310a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray      code_end_(initial_code_capacity),
1320a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray      data_end_(initial_data_capacity),
13335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      last_collection_increased_code_cache_(false),
134a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray      last_update_time_ns_(0),
1350a52223d9173315aeaca05217b8c792b3088ea7dNicolas Geoffray      garbage_collect_code_(garbage_collect_code),
136b0d220835f2ddc03510f17fcc4fb4c64b426a0f5Nicolas Geoffray      used_memory_for_data_(0),
137b0d220835f2ddc03510f17fcc4fb4c64b426a0f5Nicolas Geoffray      used_memory_for_code_(0),
138fcdd72941810f03460a8efca0c6255439be80c35Nicolas Geoffray      number_of_compilations_(0),
139bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      number_of_osr_compilations_(0),
140bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      number_of_deoptimizations_(0),
141933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray      number_of_collections_(0),
142933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray      histogram_stack_map_memory_use_("Memory used for stack maps", 16),
143933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray      histogram_code_memory_use_("Memory used for compiled code", 16),
144933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray      histogram_profiling_info_memory_use_("Memory used for profiling info", 16) {
1450c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
146c3fec4c4ca01055d4d5920f363620b5726ebbbefNicolas Geoffray  DCHECK_GE(max_capacity, initial_code_capacity + initial_data_capacity);
1470a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  code_mspace_ = create_mspace_with_base(code_map_->Begin(), code_end_, false /*locked*/);
1480a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  data_mspace_ = create_mspace_with_base(data_map_->Begin(), data_end_, false /*locked*/);
1490c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
1500c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  if (code_mspace_ == nullptr || data_mspace_ == nullptr) {
1510c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    PLOG(FATAL) << "create_mspace_with_base failed";
1520c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  }
1530c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
1540a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  SetFootprintLimit(current_capacity_);
1550c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
1560c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  CHECKED_MPROTECT(code_map_->Begin(), code_map_->Size(), kProtCode);
1570c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  CHECKED_MPROTECT(data_map_->Begin(), data_map_->Size(), kProtData);
158e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
1590a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  VLOG(jit) << "Created jit code cache: initial data size="
1600a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray            << PrettySize(initial_data_capacity)
1610a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray            << ", initial code size="
1620a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray            << PrettySize(initial_code_capacity);
163e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
164e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
1651dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffraybool JitCodeCache::ContainsPc(const void* ptr) const {
1660c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  return code_map_->Begin() <= ptr && ptr < code_map_->End();
167e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
168e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
169a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffraybool JitCodeCache::ContainsMethod(ArtMethod* method) {
170a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  MutexLock mu(Thread::Current(), lock_);
171a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  for (auto& it : method_code_map_) {
172a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray    if (it.second == method) {
173a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray      return true;
174a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray    }
175a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  }
176a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  return false;
177a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray}
178a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray
17933fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartierclass ScopedCodeCacheWrite : ScopedTrace {
1800c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray public:
18133fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier  explicit ScopedCodeCacheWrite(MemMap* code_map)
18233fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier      : ScopedTrace("ScopedCodeCacheWrite"),
18333fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier        code_map_(code_map) {
18433fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier    ScopedTrace trace("mprotect all");
1850c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    CHECKED_MPROTECT(code_map_->Begin(), code_map_->Size(), kProtAll);
1860c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  }
1870c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  ~ScopedCodeCacheWrite() {
18833fbf37feb959293b10d0b6e26d5e8ee7dff786cMathieu Chartier    ScopedTrace trace("mprotect code");
1890c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    CHECKED_MPROTECT(code_map_->Begin(), code_map_->Size(), kProtCode);
1900c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  }
1910c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray private:
1920c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  MemMap* const code_map_;
1930c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
1940c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(ScopedCodeCacheWrite);
1950c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray};
1960c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
1970c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffrayuint8_t* JitCodeCache::CommitCode(Thread* self,
1981dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                  ArtMethod* method,
1990c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray                                  const uint8_t* vmap_table,
2000c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray                                  size_t frame_size_in_bytes,
2010c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray                                  size_t core_spill_mask,
2020c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray                                  size_t fp_spill_mask,
2030c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray                                  const uint8_t* code,
204b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray                                  size_t code_size,
205b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray                                  bool osr) {
2061dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  uint8_t* result = CommitCodeInternal(self,
2071dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                       method,
2081dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                       vmap_table,
2091dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                       frame_size_in_bytes,
2101dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                       core_spill_mask,
2111dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                       fp_spill_mask,
2121dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                       code,
213b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray                                       code_size,
214b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray                                       osr);
2151dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  if (result == nullptr) {
2161dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    // Retry.
2171dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    GarbageCollectCache(self);
2181dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    result = CommitCodeInternal(self,
2191dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                method,
2201dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                vmap_table,
2211dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                frame_size_in_bytes,
2221dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                core_spill_mask,
2231dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                fp_spill_mask,
2241dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                code,
225b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray                                code_size,
226b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray                                osr);
2271dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
2281dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  return result;
2291dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray}
2301dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
2311dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffraybool JitCodeCache::WaitForPotentialCollectionToComplete(Thread* self) {
2321dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  bool in_collection = false;
2331dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  while (collection_in_progress_) {
2341dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    in_collection = true;
2351dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    lock_cond_.Wait(self);
2361dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
2371dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  return in_collection;
2381dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray}
2391dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
2401dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffraystatic uintptr_t FromCodeToAllocation(const void* code) {
2411dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
2421dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  return reinterpret_cast<uintptr_t>(code) - RoundUp(sizeof(OatQuickMethodHeader), alignment);
2431dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray}
2441dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
2451dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayvoid JitCodeCache::FreeCode(const void* code_ptr, ArtMethod* method ATTRIBUTE_UNUSED) {
2461dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  uintptr_t allocation = FromCodeToAllocation(code_ptr);
2471dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
2485cc349f3dd578e974f78314c50b6a0267c23e591David Srbecky  // Notify native debugger that we are about to remove the code.
2495cc349f3dd578e974f78314c50b6a0267c23e591David Srbecky  // It does nothing if we are not using native debugger.
2505cc349f3dd578e974f78314c50b6a0267c23e591David Srbecky  DeleteJITCodeEntryForAddress(reinterpret_cast<uintptr_t>(code_ptr));
25138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray
2521dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  // Use the offset directly to prevent sanity check that the method is
2531dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  // compiled with optimizing.
2541dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  // TODO(ngeoffray): Clean up.
2551dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  if (method_header->vmap_table_offset_ != 0) {
25638ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray    const uint8_t* data = method_header->code_ - method_header->vmap_table_offset_;
25738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray    FreeData(const_cast<uint8_t*>(data));
2581dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
25938ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  FreeCode(reinterpret_cast<uint8_t*>(allocation));
2601dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray}
2611dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
2621dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayvoid JitCodeCache::RemoveMethodsIn(Thread* self, const LinearAlloc& alloc) {
26332ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__PRETTY_FUNCTION__);
2641dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  MutexLock mu(self, lock_);
2651dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  // We do not check if a code cache GC is in progress, as this method comes
2661dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  // with the classlinker_classes_lock_ held, and suspending ourselves could
2671dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  // lead to a deadlock.
26826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  {
26926705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray    ScopedCodeCacheWrite scc(code_map_.get());
27026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray    for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
27126705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray      if (alloc.ContainsUnsafe(it->second)) {
27226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray        FreeCode(it->first, it->second);
27326705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray        it = method_code_map_.erase(it);
27426705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray      } else {
27526705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray        ++it;
27626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray      }
27726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray    }
27826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  }
279a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray  for (auto it = osr_code_map_.begin(); it != osr_code_map_.end();) {
280a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray    if (alloc.ContainsUnsafe(it->first)) {
281a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray      // Note that the code has already been removed in the loop above.
282a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray      it = osr_code_map_.erase(it);
283a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray    } else {
284a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray      ++it;
285a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray    }
286a9b91313cee629d81d4784798d03419fc7fa9e11Nicolas Geoffray  }
28726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  for (auto it = profiling_infos_.begin(); it != profiling_infos_.end();) {
28826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray    ProfilingInfo* info = *it;
28926705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray    if (alloc.ContainsUnsafe(info->GetMethod())) {
29026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray      info->GetMethod()->SetProfilingInfo(nullptr);
29138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray      FreeData(reinterpret_cast<uint8_t*>(info));
29226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray      it = profiling_infos_.erase(it);
2931dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    } else {
2941dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      ++it;
2951dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    }
2961dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
2971dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray}
2981dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
299b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffrayvoid JitCodeCache::ClearGcRootsInInlineCaches(Thread* self) {
300b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray  MutexLock mu(self, lock_);
301b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray  for (ProfilingInfo* info : profiling_infos_) {
302b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray    if (!info->IsInUseByCompiler()) {
303b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray      info->ClearGcRootsInInlineCaches();
304b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray    }
305b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray  }
306b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray}
307b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray
3081dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayuint8_t* JitCodeCache::CommitCodeInternal(Thread* self,
3091dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                          ArtMethod* method,
3101dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                          const uint8_t* vmap_table,
3111dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                          size_t frame_size_in_bytes,
3121dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                          size_t core_spill_mask,
3131dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                          size_t fp_spill_mask,
3141dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray                                          const uint8_t* code,
315b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray                                          size_t code_size,
316b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray                                          bool osr) {
3171e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray  size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
3181e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray  // Ensure the header ends up at expected instruction alignment.
3191e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray  size_t header_size = RoundUp(sizeof(OatQuickMethodHeader), alignment);
3201e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray  size_t total_size = header_size + code_size;
3211e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray
3220c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  OatQuickMethodHeader* method_header = nullptr;
3231e7de6cfcabc87ebd36bf6f2c9ed466152d21d4eNicolas Geoffray  uint8_t* code_ptr = nullptr;
32438ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  uint8_t* memory = nullptr;
3250c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  {
326d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray    ScopedThreadSuspension sts(self, kSuspended);
327d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray    MutexLock mu(self, lock_);
328d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray    WaitForPotentialCollectionToComplete(self);
329d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray    {
330d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray      ScopedCodeCacheWrite scc(code_map_.get());
33138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray      memory = AllocateCode(total_size);
33238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray      if (memory == nullptr) {
333d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray        return nullptr;
334d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray      }
33538ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray      code_ptr = memory + header_size;
336d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray
337d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray      std::copy(code, code + code_size, code_ptr);
338d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray      method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
339d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray      new (method_header) OatQuickMethodHeader(
340d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray          (vmap_table == nullptr) ? 0 : code_ptr - vmap_table,
341d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray          frame_size_in_bytes,
342d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray          core_spill_mask,
343d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray          fp_spill_mask,
344d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray          code_size);
3450c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray    }
346d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray
347324302696c0a93511fef1310d309a54ebfb25a46Roland Levillain    FlushInstructionCache(reinterpret_cast<char*>(code_ptr),
348324302696c0a93511fef1310d309a54ebfb25a46Roland Levillain                          reinterpret_cast<char*>(code_ptr + code_size));
3490a52223d9173315aeaca05217b8c792b3088ea7dNicolas Geoffray    number_of_compilations_++;
350a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  }
351a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  // We need to update the entry point in the runnable state for the instrumentation.
352a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  {
353a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray    MutexLock mu(self, lock_);
354d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray    method_code_map_.Put(code_ptr, method);
355b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    if (osr) {
356fcdd72941810f03460a8efca0c6255439be80c35Nicolas Geoffray      number_of_osr_compilations_++;
357b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray      osr_code_map_.Put(method, code_ptr);
358c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray    } else {
359b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray      Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
360b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray          method, method_header->GetEntryPoint());
361b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    }
362a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray    if (collection_in_progress_) {
363a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray      // We need to update the live bitmap if there is a GC to ensure it sees this new
364a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray      // code.
365a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray      GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(code_ptr));
366a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray    }
3674d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle    last_update_time_ns_.StoreRelease(NanoTime());
368a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray    VLOG(jit)
369f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray        << "JIT added (osr=" << std::boolalpha << osr << std::noboolalpha << ") "
370a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray        << PrettyMethod(method) << "@" << method
371a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray        << " ccache_size=" << PrettySize(CodeCacheSizeLocked()) << ": "
372a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray        << " dcache_size=" << PrettySize(DataCacheSizeLocked()) << ": "
373a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray        << reinterpret_cast<const void*>(method_header->GetEntryPoint()) << ","
374a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray        << reinterpret_cast<const void*>(method_header->GetEntryPoint() + method_header->code_size_);
375933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray    histogram_code_memory_use_.AddValue(code_size);
376933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray    if (code_size > kCodeSizeLogThreshold) {
377933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray      LOG(INFO) << "JIT allocated "
378933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray                << PrettySize(code_size)
379933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray                << " for compiled code of "
380933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray                << PrettyMethod(method);
381933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray    }
382e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  }
3830c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
3840c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  return reinterpret_cast<uint8_t*>(method_header);
3850c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray}
3860c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
3870c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraysize_t JitCodeCache::CodeCacheSize() {
3880c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  MutexLock mu(Thread::Current(), lock_);
389a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  return CodeCacheSizeLocked();
390a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray}
391a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray
392a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffraysize_t JitCodeCache::CodeCacheSizeLocked() {
39338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  return used_memory_for_code_;
3940c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray}
3950c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray
3960c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffraysize_t JitCodeCache::DataCacheSize() {
3970c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  MutexLock mu(Thread::Current(), lock_);
398a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  return DataCacheSizeLocked();
399a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray}
400a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray
401a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffraysize_t JitCodeCache::DataCacheSizeLocked() {
40238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  return used_memory_for_data_;
403e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
404e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
405d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffrayvoid JitCodeCache::ClearData(Thread* self, void* data) {
406d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray  MutexLock mu(self, lock_);
40738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  FreeData(reinterpret_cast<uint8_t*>(data));
408d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray}
409d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray
410933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffrayuint8_t* JitCodeCache::ReserveData(Thread* self, size_t size, ArtMethod* method) {
4115550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray  size = RoundUp(size, sizeof(void*));
4121dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  uint8_t* result = nullptr;
4131dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
4141dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  {
4151dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    ScopedThreadSuspension sts(self, kSuspended);
4161dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    MutexLock mu(self, lock_);
4171dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    WaitForPotentialCollectionToComplete(self);
41838ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray    result = AllocateData(size);
4191dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
4201dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
4211dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  if (result == nullptr) {
4221dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    // Retry.
4231dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    GarbageCollectCache(self);
4241dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    ScopedThreadSuspension sts(self, kSuspended);
4251dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    MutexLock mu(self, lock_);
4261dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    WaitForPotentialCollectionToComplete(self);
42738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray    result = AllocateData(size);
4281dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
4291dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
430933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray  MutexLock mu(self, lock_);
431933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray  histogram_stack_map_memory_use_.AddValue(size);
432933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray  if (size > kStackMapSizeLogThreshold) {
433933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray    LOG(INFO) << "JIT allocated "
434933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray              << PrettySize(size)
435933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray              << " for stack maps of "
436933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray              << PrettyMethod(method);
437e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  }
4380c3c2668ef44fdbd18d97f9134a85d1a7d561aa4Nicolas Geoffray  return result;
439e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
440e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
4411dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayclass MarkCodeVisitor FINAL : public StackVisitor {
4421dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray public:
4431dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  MarkCodeVisitor(Thread* thread_in, JitCodeCache* code_cache_in)
4441dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kSkipInlinedFrames),
4451dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray        code_cache_(code_cache_in),
4461dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray        bitmap_(code_cache_->GetLiveBitmap()) {}
4471dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
4481dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  bool VisitFrame() OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
4491dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
4501dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    if (method_header == nullptr) {
4511dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      return true;
4521dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    }
4531dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    const void* code = method_header->GetCode();
4541dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    if (code_cache_->ContainsPc(code)) {
4551dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      // Use the atomic set version, as multiple threads are executing this code.
4561dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      bitmap_->AtomicTestAndSet(FromCodeToAllocation(code));
4571dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    }
4581dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    return true;
459e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  }
4601dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
4611dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray private:
4621dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  JitCodeCache* const code_cache_;
4631dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  CodeCacheBitmap* const bitmap_;
4641dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray};
4651dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
4661dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffrayclass MarkCodeClosure FINAL : public Closure {
4671dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray public:
4681dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  MarkCodeClosure(JitCodeCache* code_cache, Barrier* barrier)
4691dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      : code_cache_(code_cache), barrier_(barrier) {}
4701dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
4711dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  void Run(Thread* thread) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
47232ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier    ScopedTrace trace(__PRETTY_FUNCTION__);
4731dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    DCHECK(thread == Thread::Current() || thread->IsSuspended());
4741dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    MarkCodeVisitor visitor(thread, code_cache_);
4751dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    visitor.WalkStack();
4765a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray    if (kIsDebugBuild) {
4775a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray      // The stack walking code queries the side instrumentation stack if it
4785a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray      // sees an instrumentation exit pc, so the JIT code of methods in that stack
4795a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray      // must have been seen. We sanity check this below.
4805a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray      for (const instrumentation::InstrumentationStackFrame& frame
4815a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray              : *thread->GetInstrumentationStack()) {
4825a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray        // The 'method_' in InstrumentationStackFrame is the one that has return_pc_ in
4835a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray        // its stack frame, it is not the method owning return_pc_. We just pass null to
4845a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray        // LookupMethodHeader: the method is only checked against in debug builds.
4855a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray        OatQuickMethodHeader* method_header =
4865a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray            code_cache_->LookupMethodHeader(frame.return_pc_, nullptr);
4875a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray        if (method_header != nullptr) {
4885a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray          const void* code = method_header->GetCode();
4895a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray          CHECK(code_cache_->GetLiveBitmap()->Test(FromCodeToAllocation(code)));
4905a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray        }
4915a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray      }
4925a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray    }
49310d2508b105427ef1bcaf0c222873bae7acc66d3Mathieu Chartier    barrier_->Pass(Thread::Current());
4941dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
4951dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
4961dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray private:
4971dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  JitCodeCache* const code_cache_;
4981dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  Barrier* const barrier_;
4991dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray};
5001dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
5010a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffrayvoid JitCodeCache::NotifyCollectionDone(Thread* self) {
5020a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  collection_in_progress_ = false;
5030a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  lock_cond_.Broadcast(self);
5040a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray}
5050a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
5060a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffrayvoid JitCodeCache::SetFootprintLimit(size_t new_footprint) {
5070a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  size_t per_space_footprint = new_footprint / 2;
5080a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  DCHECK(IsAlignedParam(per_space_footprint, kPageSize));
5090a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  DCHECK_EQ(per_space_footprint * 2, new_footprint);
5100a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  mspace_set_footprint_limit(data_mspace_, per_space_footprint);
5110a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  {
5120a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    ScopedCodeCacheWrite scc(code_map_.get());
5130a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    mspace_set_footprint_limit(code_mspace_, per_space_footprint);
5140a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  }
5150a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray}
5160a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
5170a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffraybool JitCodeCache::IncreaseCodeCacheCapacity() {
5180a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  if (current_capacity_ == max_capacity_) {
5190a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    return false;
5200a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  }
5210a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
5220a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  // Double the capacity if we're below 1MB, or increase it by 1MB if
5230a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  // we're above.
5240a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  if (current_capacity_ < 1 * MB) {
5250a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    current_capacity_ *= 2;
5260a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  } else {
5270a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    current_capacity_ += 1 * MB;
5280a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  }
5290a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  if (current_capacity_ > max_capacity_) {
5300a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    current_capacity_ = max_capacity_;
5310a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  }
5320a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
5331dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  if (!kIsDebugBuild || VLOG_IS_ON(jit)) {
5340a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    LOG(INFO) << "Increasing code cache capacity to " << PrettySize(current_capacity_);
5351dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
5361dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
5370a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  SetFootprintLimit(current_capacity_);
5380a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
5390a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  return true;
5400a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray}
5410a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
5428d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffrayvoid JitCodeCache::MarkCompiledCodeOnThreadStacks(Thread* self) {
5438d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  Barrier barrier(0);
5448d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  size_t threads_running_checkpoint = 0;
5458d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  MarkCodeClosure closure(this, &barrier);
5468d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  threads_running_checkpoint = Runtime::Current()->GetThreadList()->RunCheckpoint(&closure);
5478d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  // Now that we have run our checkpoint, move to a suspended state and wait
5488d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  // for other threads to run the checkpoint.
5498d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  ScopedThreadSuspension sts(self, kSuspended);
5508d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  if (threads_running_checkpoint != 0) {
5518d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray    barrier.Increment(self, threads_running_checkpoint);
5528d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  }
5538d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray}
5548d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray
55535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffraybool JitCodeCache::ShouldDoFullCollection() {
55635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  if (current_capacity_ == max_capacity_) {
55735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    // Always do a full collection when the code cache is full.
55835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    return true;
55935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  } else if (current_capacity_ < kReservedCapacity) {
56035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    // Always do partial collection when the code cache size is below the reserved
56135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    // capacity.
56235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    return false;
56335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  } else if (last_collection_increased_code_cache_) {
56435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    // This time do a full collection.
56535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    return true;
56635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  } else {
56735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    // This time do a partial collection.
56835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    return false;
5698d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  }
5708d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray}
5718d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray
5720a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffrayvoid JitCodeCache::GarbageCollectCache(Thread* self) {
57332ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__FUNCTION__);
5748d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  if (!garbage_collect_code_) {
5758d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray    MutexLock mu(self, lock_);
5768d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray    IncreaseCodeCacheCapacity();
5778d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray    return;
5788d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  }
5791dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
580a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  // Wait for an existing collection, or let everyone know we are starting one.
5811dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  {
582a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray    ScopedThreadSuspension sts(self, kSuspended);
5831dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    MutexLock mu(self, lock_);
5841dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    if (WaitForPotentialCollectionToComplete(self)) {
5851dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray      return;
586a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray    } else {
587bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      number_of_collections_++;
5888d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray      live_bitmap_.reset(CodeCacheBitmap::Create(
5898d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray          "code-cache-bitmap",
5908d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray          reinterpret_cast<uintptr_t>(code_map_->Begin()),
5918d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray          reinterpret_cast<uintptr_t>(code_map_->Begin() + current_capacity_ / 2)));
592a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray      collection_in_progress_ = true;
5931dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    }
594a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  }
5950a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
596bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray  TimingLogger logger("JIT code cache timing logger", true, VLOG_IS_ON(jit));
5978d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  {
598bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    TimingLogger::ScopedTiming st("Code cache collection", &logger);
5998d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray
600bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    bool do_full_collection = false;
601bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    {
602bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      MutexLock mu(self, lock_);
603bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      do_full_collection = ShouldDoFullCollection();
604bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    }
60535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray
606bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    if (!kIsDebugBuild || VLOG_IS_ON(jit)) {
607bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      LOG(INFO) << "Do "
608bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray                << (do_full_collection ? "full" : "partial")
609bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray                << " code cache collection, code="
610bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray                << PrettySize(CodeCacheSize())
611bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray                << ", data=" << PrettySize(DataCacheSize());
612bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    }
6138d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray
614bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    DoCollection(self, /* collect_profiling_info */ do_full_collection);
61535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray
616bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    if (!kIsDebugBuild || VLOG_IS_ON(jit)) {
617bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      LOG(INFO) << "After code cache collection, code="
618bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray                << PrettySize(CodeCacheSize())
619bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray                << ", data=" << PrettySize(DataCacheSize());
62035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    }
62135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray
622bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    {
623bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      MutexLock mu(self, lock_);
624bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray
625bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      // Increase the code cache only when we do partial collections.
626bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      // TODO: base this strategy on how full the code cache is?
627bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      if (do_full_collection) {
628bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray        last_collection_increased_code_cache_ = false;
629bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      } else {
630bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray        last_collection_increased_code_cache_ = true;
631bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray        IncreaseCodeCacheCapacity();
632bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      }
63335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray
634bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      bool next_collection_will_be_full = ShouldDoFullCollection();
635bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray
636bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      // Start polling the liveness of compiled code to prepare for the next full collection.
637c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray      if (next_collection_will_be_full) {
638bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray        // Save the entry point of methods we have compiled, and update the entry
639bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray        // point of those methods to the interpreter. If the method is invoked, the
640bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray        // interpreter will update its entry point to the compiled code and call it.
641bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray        for (ProfilingInfo* info : profiling_infos_) {
642bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray          const void* entry_point = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
643bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray          if (ContainsPc(entry_point)) {
644bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray            info->SetSavedEntryPoint(entry_point);
645c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray            Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
646c8a4f2c632afd44fc558aa37c98b9cf042b4bb5bNicolas Geoffray                info->GetMethod(), GetQuickToInterpreterBridge());
647bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray          }
64835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        }
64935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray
650bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray        DCHECK(CheckLiveCompiledCodeHasProfilingInfo());
651bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      }
652bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      live_bitmap_.reset(nullptr);
653bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray      NotifyCollectionDone(self);
6540a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    }
6550a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  }
656bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray  Runtime::Current()->GetJit()->AddTimingLogger(logger);
65735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray}
6580a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
6599abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffrayvoid JitCodeCache::RemoveUnmarkedCode(Thread* self) {
66032ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__FUNCTION__);
66135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  MutexLock mu(self, lock_);
66235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  ScopedCodeCacheWrite scc(code_map_.get());
6639abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray  // Iterate over all compiled code and remove entries that are not marked.
66435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  for (auto it = method_code_map_.begin(); it != method_code_map_.end();) {
66535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    const void* code_ptr = it->first;
66635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    ArtMethod* method = it->second;
66735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    uintptr_t allocation = FromCodeToAllocation(code_ptr);
6689abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray    if (GetLiveBitmap()->Test(allocation)) {
66935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      ++it;
67035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    } else {
67135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      FreeCode(code_ptr, method);
67235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      it = method_code_map_.erase(it);
67335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    }
6740a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  }
6758d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray}
6768d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray
67735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffrayvoid JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) {
67832ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__FUNCTION__);
679a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray  {
680a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray    MutexLock mu(self, lock_);
68135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    if (collect_profiling_info) {
68235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      // Clear the profiling info of methods that do not have compiled code as entrypoint.
68335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      // Also remove the saved entry point from the ProfilingInfo objects.
68435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      for (ProfilingInfo* info : profiling_infos_) {
68535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
686b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray        if (!ContainsPc(ptr) && !info->IsInUseByCompiler()) {
68735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray          info->GetMethod()->SetProfilingInfo(nullptr);
68835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        }
689b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray
690b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray        if (info->GetSavedEntryPoint() != nullptr) {
691b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray          info->SetSavedEntryPoint(nullptr);
692b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray          // We are going to move this method back to interpreter. Clear the counter now to
693b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray          // give it a chance to be hot again.
694b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray          info->GetMethod()->ClearCounter();
695b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray        }
69635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      }
69735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    } else if (kIsDebugBuild) {
69835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      // Sanity check that the profiling infos do not have a dangling entry point.
69935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      for (ProfilingInfo* info : profiling_infos_) {
70035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        DCHECK(info->GetSavedEntryPoint() == nullptr);
70173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray      }
70226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray    }
703b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray
7049abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray    // Mark compiled code that are entrypoints of ArtMethods. Compiled code that is not
7059abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray    // an entry point is either:
7069abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray    // - an osr compiled code, that will be removed if not in a thread call stack.
7079abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray    // - discarded compiled code, that will be removed if not in a thread call stack.
7089abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray    for (const auto& it : method_code_map_) {
7099abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray      ArtMethod* method = it.second;
7109abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray      const void* code_ptr = it.first;
7119abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray      const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
7129abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray      if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) {
7139abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray        GetLiveBitmap()->AtomicTestAndSet(FromCodeToAllocation(code_ptr));
7149abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray      }
7159abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray    }
7169abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray
717d9994f069dfeaa32ba929ca78816b5b83e2a4134Nicolas Geoffray    // Empty osr method map, as osr compiled code will be deleted (except the ones
718b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    // on thread stacks).
719b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    osr_code_map_.clear();
7201dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
7211dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
7221dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  // Run a checkpoint on all threads to mark the JIT compiled code they are running.
7238d37250f7b9a7839b11488f45a1842b025026f94Nicolas Geoffray  MarkCompiledCodeOnThreadStacks(self);
7241dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
7259abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray  // At this point, mutator threads are still running, and entrypoints of methods can
7269abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray  // change. We do know they cannot change to a code cache entry that is not marked,
7279abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray  // therefore we can safely remove those entries.
7289abb2978f09643227664ab70c0677744b8f6e946Nicolas Geoffray  RemoveUnmarkedCode(self);
729a96917a6983a5abbe973255a3846fda549fb1657Nicolas Geoffray
73035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  if (collect_profiling_info) {
73199c959f3868512bb95432cf02a1f0ad3971698bfNicolas Geoffray    ScopedThreadSuspension sts(self, kSuspended);
73299c959f3868512bb95432cf02a1f0ad3971698bfNicolas Geoffray    gc::ScopedGCCriticalSection gcs(
73399c959f3868512bb95432cf02a1f0ad3971698bfNicolas Geoffray        self, gc::kGcCauseJitCodeCache, gc::kCollectorTypeJitCodeCache);
73435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    MutexLock mu(self, lock_);
73535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    // Free all profiling infos of methods not compiled nor being compiled.
73673be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray    auto profiling_kept_end = std::remove_if(profiling_infos_.begin(), profiling_infos_.end(),
73738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray      [this] (ProfilingInfo* info) NO_THREAD_SAFETY_ANALYSIS {
73835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        const void* ptr = info->GetMethod()->GetEntryPointFromQuickCompiledCode();
739511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray        // We have previously cleared the ProfilingInfo pointer in the ArtMethod in the hope
740511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray        // that the compiled code would not get revived. As mutator threads run concurrently,
741511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray        // they may have revived the compiled code, and now we are in the situation where
742511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray        // a method has compiled code but no ProfilingInfo.
743511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray        // We make sure compiled methods have a ProfilingInfo object. It is needed for
744511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray        // code cache collection.
74535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        if (ContainsPc(ptr) && info->GetMethod()->GetProfilingInfo(sizeof(void*)) == nullptr) {
746511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray          // We clear the inline caches as classes in it might be stalled.
747b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray          info->ClearGcRootsInInlineCaches();
748511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray          // Do a fence to make sure the clearing is seen before attaching to the method.
749511e41b4ec2d378a5c434598ebd0b3d6136fff9dNicolas Geoffray          QuasiAtomic::ThreadFenceRelease();
75035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray          info->GetMethod()->SetProfilingInfo(info);
75135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        } else if (info->GetMethod()->GetProfilingInfo(sizeof(void*)) != info) {
75235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray          // No need for this ProfilingInfo object anymore.
75338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray          FreeData(reinterpret_cast<uint8_t*>(info));
75473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray          return true;
75573be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray        }
75673be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray        return false;
75773be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray      });
75873be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray    profiling_infos_.erase(profiling_kept_end, profiling_infos_.end());
75935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    DCHECK(CheckLiveCompiledCodeHasProfilingInfo());
760e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  }
761e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
762e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
76335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffraybool JitCodeCache::CheckLiveCompiledCodeHasProfilingInfo() {
76432ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__FUNCTION__);
76535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  // Check that methods we have compiled do have a ProfilingInfo object. We would
76635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  // have memory leaks of compiled code otherwise.
76735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  for (const auto& it : method_code_map_) {
76835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    ArtMethod* method = it.second;
76935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    if (method->GetProfilingInfo(sizeof(void*)) == nullptr) {
77035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      const void* code_ptr = it.first;
77135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      const OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
77235122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      if (method_header->GetEntryPoint() == method->GetEntryPointFromQuickCompiledCode()) {
77335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        // If the code is not dead, then we have a problem. Note that this can even
77435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        // happen just after a collection, as mutator threads are running in parallel
77535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        // and could deoptimize an existing compiled code.
77635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray        return false;
77735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      }
77835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    }
77935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  }
78035122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  return true;
78135122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray}
7821dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
7831dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas GeoffrayOatQuickMethodHeader* JitCodeCache::LookupMethodHeader(uintptr_t pc, ArtMethod* method) {
7841dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  static_assert(kRuntimeISA != kThumb2, "kThumb2 cannot be a runtime ISA");
7851dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  if (kRuntimeISA == kArm) {
7861dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    // On Thumb-2, the pc is offset by one.
7871dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    --pc;
7881dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
7891dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  if (!ContainsPc(reinterpret_cast<const void*>(pc))) {
7901dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    return nullptr;
7911dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
7921dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
793e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  MutexLock mu(Thread::Current(), lock_);
7941dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  if (method_code_map_.empty()) {
7951dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    return nullptr;
7961dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  }
7971dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  auto it = method_code_map_.lower_bound(reinterpret_cast<const void*>(pc));
7981dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  --it;
7991dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray
8001dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  const void* code_ptr = it->first;
8011dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  OatQuickMethodHeader* method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
8021dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  if (!method_header->Contains(pc)) {
8031dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray    return nullptr;
804e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  }
8055a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray  if (kIsDebugBuild && method != nullptr) {
8065a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray    DCHECK_EQ(it->second, method)
8075a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray        << PrettyMethod(method) << " " << PrettyMethod(it->second) << " " << std::hex << pc;
8085a23d2ea6e0d89112ff11ec765e676c03818b7c2Nicolas Geoffray  }
8091dad3f68b7f5a4a4cb2b281413357adc2309a8fdNicolas Geoffray  return method_header;
810e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
811e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
812b331febbab8e916680faba722cc84b66b84218a3Nicolas GeoffrayOatQuickMethodHeader* JitCodeCache::LookupOsrMethodHeader(ArtMethod* method) {
813b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  MutexLock mu(Thread::Current(), lock_);
814b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  auto it = osr_code_map_.find(method);
815b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  if (it == osr_code_map_.end()) {
816b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    return nullptr;
817b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  }
818b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  return OatQuickMethodHeader::FromCodePointer(it->second);
819b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray}
820b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray
82126705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas GeoffrayProfilingInfo* JitCodeCache::AddProfilingInfo(Thread* self,
82226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray                                              ArtMethod* method,
82326705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray                                              const std::vector<uint32_t>& entries,
8241e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray                                              bool retry_allocation)
8251e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    // No thread safety analysis as we are using TryLock/Unlock explicitly.
8261e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    NO_THREAD_SAFETY_ANALYSIS {
8271e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray  ProfilingInfo* info = nullptr;
8281e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray  if (!retry_allocation) {
8291e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    // If we are allocating for the interpreter, just try to lock, to avoid
8301e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    // lock contention with the JIT.
8311e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    if (lock_.ExclusiveTryLock(self)) {
8321e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray      info = AddProfilingInfoInternal(self, method, entries);
8331e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray      lock_.ExclusiveUnlock(self);
8341e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    }
8351e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray  } else {
8361e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    {
8371e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray      MutexLock mu(self, lock_);
8381e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray      info = AddProfilingInfoInternal(self, method, entries);
8391e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    }
84026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray
8411e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    if (info == nullptr) {
8421e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray      GarbageCollectCache(self);
8431e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray      MutexLock mu(self, lock_);
8441e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray      info = AddProfilingInfoInternal(self, method, entries);
8451e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas Geoffray    }
84626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  }
84726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  return info;
84826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray}
84926705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray
8501e7da9bd04bdd2664a4196f1d7e285c010f8881fNicolas GeoffrayProfilingInfo* JitCodeCache::AddProfilingInfoInternal(Thread* self ATTRIBUTE_UNUSED,
85126705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray                                                      ArtMethod* method,
85226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray                                                      const std::vector<uint32_t>& entries) {
85326705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  size_t profile_info_size = RoundUp(
85473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray      sizeof(ProfilingInfo) + sizeof(InlineCache) * entries.size(),
85526705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray      sizeof(void*));
85626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray
85726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  // Check whether some other thread has concurrently created it.
85826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*));
85926705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  if (info != nullptr) {
86026705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray    return info;
86126705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  }
86226705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray
86338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  uint8_t* data = AllocateData(profile_info_size);
86426705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  if (data == nullptr) {
86526705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray    return nullptr;
86626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  }
86726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  info = new (data) ProfilingInfo(method, entries);
86807f3564d73550495a937bc667d03721106315400Nicolas Geoffray
86907f3564d73550495a937bc667d03721106315400Nicolas Geoffray  // Make sure other threads see the data in the profiling info object before the
87007f3564d73550495a937bc667d03721106315400Nicolas Geoffray  // store in the ArtMethod's ProfilingInfo pointer.
87107f3564d73550495a937bc667d03721106315400Nicolas Geoffray  QuasiAtomic::ThreadFenceRelease();
87207f3564d73550495a937bc667d03721106315400Nicolas Geoffray
87326705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  method->SetProfilingInfo(info);
87426705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  profiling_infos_.push_back(info);
875933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray  histogram_profiling_info_memory_use_.AddValue(profile_info_size);
87626705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray  return info;
87726705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray}
87826705e2b1245b65989a0341b24c5dbf2658d4bb6Nicolas Geoffray
8790a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray// NO_THREAD_SAFETY_ANALYSIS as this is called from mspace code, at which point the lock
8800a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray// is already held.
8810a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffrayvoid* JitCodeCache::MoreCore(const void* mspace, intptr_t increment) NO_THREAD_SAFETY_ANALYSIS {
8820a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  if (code_mspace_ == mspace) {
8830a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    size_t result = code_end_;
8840a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    code_end_ += increment;
8850a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    return reinterpret_cast<void*>(result + code_map_->Begin());
8860a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  } else {
8870a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    DCHECK_EQ(data_mspace_, mspace);
8880a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    size_t result = data_end_;
8890a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    data_end_ += increment;
8900a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray    return reinterpret_cast<void*>(result + data_map_->Begin());
8910a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray  }
8920a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray}
8930a3be1620a3560253cfa789cb9819013293c5654Nicolas Geoffray
894e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravlevoid JitCodeCache::GetProfiledMethods(const std::set<std::string>& dex_base_locations,
895e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle                                      std::vector<MethodReference>& methods) {
89632ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier  ScopedTrace trace(__FUNCTION__);
89731f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle  MutexLock mu(Thread::Current(), lock_);
898e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle  for (const ProfilingInfo* info : profiling_infos_) {
899e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle    ArtMethod* method = info->GetMethod();
900e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle    const DexFile* dex_file = method->GetDexFile();
901e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle    if (ContainsElement(dex_base_locations, dex_file->GetBaseLocation())) {
902e2d066d0337b7c81d47e4806e6025b70d83fcd56Calin Juravle      methods.emplace_back(dex_file,  method->GetDexMethodIndex());
90331f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle    }
90431f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle  }
90531f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle}
90631f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle
9074d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravleuint64_t JitCodeCache::GetLastUpdateTimeNs() const {
9084d77b6a511659f26fdc711e23825ffa6e7feed7aCalin Juravle  return last_update_time_ns_.LoadAcquire();
90931f2c155975c5794d481df03eb0947cb48d2c6b5Calin Juravle}
91073be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray
911f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffraybool JitCodeCache::IsOsrCompiled(ArtMethod* method) {
912f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray  MutexLock mu(Thread::Current(), lock_);
913f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray  return osr_code_map_.find(method) != osr_code_map_.end();
914f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray}
915f3f9cf6b65c4bcf9ea44253188d8d910b7cf7e64Nicolas Geoffray
916b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffraybool JitCodeCache::NotifyCompilationOf(ArtMethod* method, Thread* self, bool osr) {
917b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  if (!osr && ContainsPc(method->GetEntryPointFromQuickCompiledCode())) {
91873be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray    return false;
91973be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray  }
920a42363f79832a6e14f348514664dc6dc3edf9da2Nicolas Geoffray
921a42363f79832a6e14f348514664dc6dc3edf9da2Nicolas Geoffray  MutexLock mu(self, lock_);
922b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  if (osr && (osr_code_map_.find(method) != osr_code_map_.end())) {
923b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray    return false;
924b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  }
925bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray
926c26f1288aaf9141ac4b2150869f0c594d52dbf36Nicolas Geoffray  ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*));
927bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray  if (info == nullptr) {
928bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    VLOG(jit) << PrettyMethod(method) << " needs a ProfilingInfo to be compiled";
929b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray    // Because the counter is not atomic, there are some rare cases where we may not
930b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray    // hit the threshold for creating the ProfilingInfo. Reset the counter now to
931b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray    // "correct" this.
932b9a639df2f21dd67b9f4379f31b7ccc5dd48ebd6Nicolas Geoffray    method->ClearCounter();
933bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray    return false;
934bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray  }
935bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray
936454b3b6774fe07765273b917ccc97da2eba776acbuzbee  if (info->IsMethodBeingCompiled(osr)) {
93773be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray    return false;
93873be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray  }
939bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray
940454b3b6774fe07765273b917ccc97da2eba776acbuzbee  info->SetIsMethodBeingCompiled(true, osr);
94173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray  return true;
94273be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray}
94373be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray
94407e3ca9a46801990d662c48d0fddedc63c4c053cNicolas GeoffrayProfilingInfo* JitCodeCache::NotifyCompilerUse(ArtMethod* method, Thread* self) {
945b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray  MutexLock mu(self, lock_);
946b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray  ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*));
947b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray  if (info != nullptr) {
948b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray    info->IncrementInlineUse();
949b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray  }
95007e3ca9a46801990d662c48d0fddedc63c4c053cNicolas Geoffray  return info;
951b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray}
952b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray
95307e3ca9a46801990d662c48d0fddedc63c4c053cNicolas Geoffrayvoid JitCodeCache::DoneCompilerUse(ArtMethod* method, Thread* self) {
954b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray  MutexLock mu(self, lock_);
955b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray  ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*));
95607e3ca9a46801990d662c48d0fddedc63c4c053cNicolas Geoffray  DCHECK(info != nullptr);
95707e3ca9a46801990d662c48d0fddedc63c4c053cNicolas Geoffray  info->DecrementInlineUse();
958b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray}
959b6e20ae17d0881a66c22532e4152ce6779454a92Nicolas Geoffray
960454b3b6774fe07765273b917ccc97da2eba776acbuzbeevoid JitCodeCache::DoneCompiling(ArtMethod* method, Thread* self ATTRIBUTE_UNUSED, bool osr) {
96173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray  ProfilingInfo* info = method->GetProfilingInfo(sizeof(void*));
962454b3b6774fe07765273b917ccc97da2eba776acbuzbee  DCHECK(info->IsMethodBeingCompiled(osr));
963454b3b6774fe07765273b917ccc97da2eba776acbuzbee  info->SetIsMethodBeingCompiled(false, osr);
96473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray}
96573be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray
966a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffraysize_t JitCodeCache::GetMemorySizeOfCodePointer(const void* ptr) {
967a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray  MutexLock mu(Thread::Current(), lock_);
968a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray  return mspace_usable_size(reinterpret_cast<const void*>(FromCodeToAllocation(ptr)));
969a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray}
970a25dce9b452ba17ef7cef768926c884177a3025eNicolas Geoffray
971b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffrayvoid JitCodeCache::InvalidateCompiledCodeFor(ArtMethod* method,
972b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray                                             const OatQuickMethodHeader* header) {
97335122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  ProfilingInfo* profiling_info = method->GetProfilingInfo(sizeof(void*));
97435122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  if ((profiling_info != nullptr) &&
97535122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray      (profiling_info->GetSavedEntryPoint() == header->GetEntryPoint())) {
97635122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    // Prevent future uses of the compiled code.
97735122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray    profiling_info->SetSavedEntryPoint(nullptr);
97835122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray  }
97935122443e5f8606cc5a660ac32745a06aefb341bNicolas Geoffray
980b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray  if (method->GetEntryPointFromQuickCompiledCode() == header->GetEntryPoint()) {
981b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray    // The entrypoint is the one to invalidate, so we just update
982b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray    // it to the interpreter entry point and clear the counter to get the method
983b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray    // Jitted again.
984b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray    Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
985b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray        method, GetQuickToInterpreterBridge());
986b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray    method->ClearCounter();
987b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray  } else {
988b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray    MutexLock mu(Thread::Current(), lock_);
989b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray    auto it = osr_code_map_.find(method);
990b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray    if (it != osr_code_map_.end() && OatQuickMethodHeader::FromCodePointer(it->second) == header) {
991b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray      // Remove the OSR method, to avoid using it again.
992b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray      osr_code_map_.erase(it);
993b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray    }
994b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray  }
995bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray  MutexLock mu(Thread::Current(), lock_);
996bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray  number_of_deoptimizations_++;
997b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray}
998b88d59ef4fe611fe47e50a6a19785e03bbd5f93bNicolas Geoffray
99938ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffrayuint8_t* JitCodeCache::AllocateCode(size_t code_size) {
100038ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
100138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  uint8_t* result = reinterpret_cast<uint8_t*>(
100238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray      mspace_memalign(code_mspace_, alignment, code_size));
100338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  size_t header_size = RoundUp(sizeof(OatQuickMethodHeader), alignment);
100438ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  // Ensure the header ends up at expected instruction alignment.
100538ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  DCHECK_ALIGNED_PARAM(reinterpret_cast<uintptr_t>(result + header_size), alignment);
100638ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  used_memory_for_code_ += mspace_usable_size(result);
100738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  return result;
100838ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray}
100938ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray
101038ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffrayvoid JitCodeCache::FreeCode(uint8_t* code) {
101138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  used_memory_for_code_ -= mspace_usable_size(code);
101238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  mspace_free(code_mspace_, code);
101338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray}
101438ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray
101538ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffrayuint8_t* JitCodeCache::AllocateData(size_t data_size) {
101638ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  void* result = mspace_malloc(data_mspace_, data_size);
101738ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  used_memory_for_data_ += mspace_usable_size(result);
101838ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  return reinterpret_cast<uint8_t*>(result);
101938ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray}
102038ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray
102138ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffrayvoid JitCodeCache::FreeData(uint8_t* data) {
102238ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  used_memory_for_data_ -= mspace_usable_size(data);
102338ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray  mspace_free(data_mspace_, data);
102438ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray}
102538ea9bd50debc63ceb77ec1e65036d8e2070ec7dNicolas Geoffray
1026bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffrayvoid JitCodeCache::Dump(std::ostream& os) {
1027bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray  MutexLock mu(Thread::Current(), lock_);
1028bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray  os << "Current JIT code cache size: " << PrettySize(used_memory_for_code_) << "\n"
1029bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray     << "Current JIT data cache size: " << PrettySize(used_memory_for_data_) << "\n"
1030bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray     << "Current JIT capacity: " << PrettySize(current_capacity_) << "\n"
1031bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray     << "Current number of JIT code cache entries: " << method_code_map_.size() << "\n"
1032bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray     << "Total number of JIT compilations: " << number_of_compilations_ << "\n"
1033bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray     << "Total number of JIT compilations for on stack replacement: "
1034bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray        << number_of_osr_compilations_ << "\n"
1035bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray     << "Total number of deoptimizations: " << number_of_deoptimizations_ << "\n"
1036bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray     << "Total number of JIT code cache collections: " << number_of_collections_ << std::endl;
1037933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray  histogram_stack_map_memory_use_.PrintMemoryUse(os);
1038933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray  histogram_code_memory_use_.PrintMemoryUse(os);
1039933330a192d43d7c7304120999907857a89c2f96Nicolas Geoffray  histogram_profiling_info_memory_use_.PrintMemoryUse(os);
1040bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray}
1041bcd94c8ea9bde4e075c25fbdfb3a2ef6858eed7bNicolas Geoffray
1042e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}  // namespace jit
1043e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}  // namespace art
1044