blob: 0c039f2bbdb5ee7624a6b7c898e77b3cdcd0e19d [file] [log] [blame]
Nicolas Geoffray5550ca82015-08-21 18:38:30 +01001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "profiling_info.h"
18
19#include "art_method-inl.h"
20#include "dex_instruction.h"
21#include "jit/jit.h"
22#include "jit/jit_code_cache.h"
23#include "scoped_thread_state_change.h"
24#include "thread.h"
25
26namespace art {
27
28ProfilingInfo* ProfilingInfo::Create(ArtMethod* method) {
29 // Walk over the dex instructions of the method and keep track of
30 // instructions we are interested in profiling.
31 const uint16_t* code_ptr = nullptr;
32 const uint16_t* code_end = nullptr;
33 {
34 ScopedObjectAccess soa(Thread::Current());
35 DCHECK(!method->IsNative());
36 const DexFile::CodeItem& code_item = *method->GetCodeItem();
37 code_ptr = code_item.insns_;
38 code_end = code_item.insns_ + code_item.insns_size_in_code_units_;
39 }
40
41 uint32_t dex_pc = 0;
42 std::vector<uint32_t> entries;
43 while (code_ptr < code_end) {
44 const Instruction& instruction = *Instruction::At(code_ptr);
45 switch (instruction.Opcode()) {
46 case Instruction::INVOKE_VIRTUAL:
47 case Instruction::INVOKE_VIRTUAL_RANGE:
48 case Instruction::INVOKE_VIRTUAL_QUICK:
49 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
50 case Instruction::INVOKE_INTERFACE:
51 case Instruction::INVOKE_INTERFACE_RANGE:
52 entries.push_back(dex_pc);
53 break;
54
55 default:
56 break;
57 }
58 dex_pc += instruction.SizeInCodeUnits();
59 code_ptr += instruction.SizeInCodeUnits();
60 }
61
62 // If there is no instruction we are interested in, no need to create a `ProfilingInfo`
63 // object, it will never be filled.
64 if (entries.empty()) {
65 return nullptr;
66 }
67
68 // Allocate the `ProfilingInfo` object int the JIT's data space.
69 jit::JitCodeCache* code_cache = Runtime::Current()->GetJit()->GetCodeCache();
70 size_t profile_info_size = sizeof(ProfilingInfo) + sizeof(InlineCache) * entries.size();
71 uint8_t* data = code_cache->ReserveData(Thread::Current(), profile_info_size);
72
73 if (data == nullptr) {
74 VLOG(jit) << "Cannot allocate profiling info anymore";
75 return nullptr;
76 }
77
78 return new (data) ProfilingInfo(entries);
79}
80
81void ProfilingInfo::AddInvokeInfo(Thread* self, uint32_t dex_pc, mirror::Class* cls) {
82 InlineCache* cache = nullptr;
83 // TODO: binary search if array is too long.
84 for (size_t i = 0; i < number_of_inline_caches_; ++i) {
85 if (cache_[i].dex_pc == dex_pc) {
86 cache = &cache_[i];
87 break;
88 }
89 }
90 DCHECK(cache != nullptr);
91
92 ScopedObjectAccess soa(self);
93 for (size_t i = 0; i < InlineCache::kIndividualCacheSize; ++i) {
94 mirror::Class* existing = cache->classes_[i].Read<kWithoutReadBarrier>();
95 if (existing == cls) {
96 // Receiver type is already in the cache, nothing else to do.
97 return;
98 } else if (existing == nullptr) {
99 // Cache entry is empty, try to put `cls` in it.
100 GcRoot<mirror::Class> expected_root(nullptr);
101 GcRoot<mirror::Class> desired_root(cls);
102 if (!reinterpret_cast<Atomic<GcRoot<mirror::Class>>*>(&cache->classes_[i])->
103 CompareExchangeStrongSequentiallyConsistent(expected_root, desired_root)) {
104 // Some other thread put a class in the cache, continue iteration starting at this
105 // entry in case the entry contains `cls`.
106 --i;
107 } else {
108 // We successfully set `cls`, just return.
109 return;
110 }
111 }
112 }
113 // Unsuccessfull - cache is full, making it megamorphic.
114 DCHECK(cache->IsMegamorphic());
115}
116
117} // namespace art