compiler_driver.cc revision fb6adba0d5d5505610fbd325e7911db700a2f1e8
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
169ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
179ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom#include "compiler.h"
189ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
19d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes#include <vector>
20d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
2127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <sys/mman.h>
22d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes#include <unistd.h>
2327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
242cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom#include "assembler.h"
259ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom#include "class_linker.h"
261f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "class_loader.h"
279ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom#include "dex_cache.h"
282cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom#include "jni_compiler.h"
299baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom#include "jni_internal.h"
304dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien#include "oat_compilation_unit.h"
313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "oat_file.h"
326d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
331f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h"
343320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "stl_util.h"
35601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes#include "timing_logger.h"
369ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
37d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#if defined(ART_USE_LLVM_COMPILER)
38d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#include "compiler_llvm/compiler_llvm.h"
39d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#endif
40d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao
419ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstromnamespace art {
429ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
43d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#if !defined(ART_USE_LLVM_COMPILER)
44996cc586ce76235ee3efa1eff86de51dabcc5d53Ian RogersCompiledMethod* oatCompileMethod(Compiler& compiler, const DexFile::CodeItem* code_item,
4511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes                                 uint32_t access_flags, uint32_t method_idx,
4611d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes                                 const ClassLoader* class_loader,
4711d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes                                 const DexFile& dex_file, InstructionSet);
48d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#endif
4911d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
50c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liaonamespace arm {
51bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers  ByteArray* CreateAbstractMethodErrorStub();
5245619fcc01fb6db1ac9481a91608eb46f90829e4Ian Rogers  CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty, uint32_t shorty_len);
531cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type);
548add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes  ByteArray* CreateJniDlsymLookupStub();
55c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liao}
56c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liaonamespace x86 {
57bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers  ByteArray* CreateAbstractMethodErrorStub();
5845619fcc01fb6db1ac9481a91608eb46f90829e4Ian Rogers  CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty, uint32_t shorty_len);
591cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type);
608add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes  ByteArray* CreateJniDlsymLookupStub();
61e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
62e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
63d1224c79631bd1801b067a0f212b91afa961a362jeffhaonamespace verifier {
64d1224c79631bd1801b067a0f212b91afa961a362jeffhao  class DexVerifier {
65d1224c79631bd1801b067a0f212b91afa961a362jeffhao   public:
66d1224c79631bd1801b067a0f212b91afa961a362jeffhao    static const std::vector<uint8_t>* GetGcMap(Compiler::MethodReference ref);
67d1224c79631bd1801b067a0f212b91afa961a362jeffhao    static bool IsClassRejected(Compiler::ClassReference ref);
68d1224c79631bd1801b067a0f212b91afa961a362jeffhao  };
69d1224c79631bd1801b067a0f212b91afa961a362jeffhao}
70d1224c79631bd1801b067a0f212b91afa961a362jeffhao
71996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogersstatic double Percentage(size_t x, size_t y) {
72996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return 100.0 * ((double)x) / ((double)(x + y));
73996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers}
74996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
75996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogersstatic void DumpStat(size_t x, size_t y, const char* str) {
76996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (x == 0 && y == 0) {
77996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers    return;
78996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
79996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  LOG(INFO) << Percentage(x, y) << "% of " << str << " for " << (x + y) << " cases";
80996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers}
81996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
82c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogersclass AOTCompilationStats {
83c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers public:
84c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  AOTCompilationStats() : stats_lock_("AOT compilation statistics lock"),
85c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers     types_in_dex_cache_(0), types_not_in_dex_cache_(0),
86c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers     strings_in_dex_cache_(0), strings_not_in_dex_cache_(0),
87c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers     resolved_types_(0), unresolved_types_(0),
88c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers     resolved_instance_fields_(0), unresolved_instance_fields_(0),
89fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers     resolved_local_static_fields_(0), resolved_static_fields_(0), unresolved_static_fields_(0),
90fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers     virtual_made_direct_(0) {
91c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    for (size_t i = 0; i < kMaxInvokeType; i++) {
92c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      resolved_methods_[i] = 0;
93c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      unresolved_methods_[i] = 0;
94c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    }
95c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
96c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
97c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void Dump() {
98c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(types_in_dex_cache_, types_not_in_dex_cache_, "types known to be in dex cache");
99c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(strings_in_dex_cache_, strings_not_in_dex_cache_, "strings known to be in dex cache");
100c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(resolved_types_, unresolved_types_, "types resolved");
101c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(resolved_instance_fields_, unresolved_instance_fields_, "instance fields resolved");
102c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(resolved_local_static_fields_ + resolved_static_fields_, unresolved_static_fields_,
103c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers             "static fields resolved");
104c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(resolved_local_static_fields_, resolved_static_fields_ + unresolved_static_fields_,
105c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers             "static fields local to a class");
106c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
107c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    for (size_t i = 0; i < kMaxInvokeType; i++) {
108c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      std::ostringstream oss;
109c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      oss << "resolved " << static_cast<InvokeType>(i) << " methods";
110c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      DumpStat(resolved_methods_[i], unresolved_methods_[i], oss.str().c_str());
111c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    }
112fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers    DumpStat(virtual_made_direct_, resolved_methods_[kVirtual] + unresolved_methods_[kVirtual],
113fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers             "made direct from virtual");
114c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
115996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
116996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers// Allow lossy statistics in non-debug builds
117996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#ifndef NDEBUG
118996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#define STATS_LOCK() MutexLock mu(stats_lock_)
119996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#else
120996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#define STATS_LOCK()
121996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#endif
122996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
123c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void TypeInDexCache() {
124c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
125c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    types_in_dex_cache_++;
126c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
127996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
128c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void TypeNotInDexCache() {
129c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
130c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    types_not_in_dex_cache_++;
131c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
132996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
133c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void StringInDexCache() {
134c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
135c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    strings_in_dex_cache_++;
136c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
137996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
138c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void StringNotInDexCache() {
139c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
140c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    strings_not_in_dex_cache_++;
141c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
142996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
143c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void TypeDoesntNeedAccessCheck() {
144c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
145c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_types_++;
146c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
147996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
148c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void TypeNeedsAccessCheck() {
149c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
150c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    unresolved_types_++;
151c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
152996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
153c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void ResolvedInstanceField() {
154c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
155c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_instance_fields_++;
156c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
157996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
158c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void UnresolvedInstanceField(){
159c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
160c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    unresolved_instance_fields_++;
161c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
162996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
163c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void ResolvedLocalStaticField() {
164c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
165c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_local_static_fields_++;
166c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
167996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
168c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void ResolvedStaticField() {
169c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
170c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_static_fields_++;
171c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
172996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
173c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void UnresolvedStaticField() {
174c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
175c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    unresolved_static_fields_++;
176c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
177996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
178c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void ResolvedMethod(InvokeType type) {
179c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DCHECK_LE(type, kMaxInvokeType);
180c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
181c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_methods_[type]++;
182996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
183996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
184c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void UnresolvedMethod(InvokeType type) {
185c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DCHECK_LE(type, kMaxInvokeType);
186c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
187c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    unresolved_methods_[type]++;
188996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
189c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
190fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers  void VirtualMadeDirect() {
191fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers    STATS_LOCK();
192fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers    virtual_made_direct_++;
193fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers  }
194c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers private:
195c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  Mutex stats_lock_;
196c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
197c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t types_in_dex_cache_;
198c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t types_not_in_dex_cache_;
199c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
200c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t strings_in_dex_cache_;
201c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t strings_not_in_dex_cache_;
202c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
203c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_types_;
204c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t unresolved_types_;
205c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
206c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_instance_fields_;
207c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t unresolved_instance_fields_;
208c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
209c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_local_static_fields_;
210c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_static_fields_;
211c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t unresolved_static_fields_;
212c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
213c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_methods_[kMaxInvokeType + 1];
214c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t unresolved_methods_[kMaxInvokeType + 1];
215fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers  size_t virtual_made_direct_;
216c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
217c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  DISALLOW_COPY_AND_ASSIGN(AOTCompilationStats);;
218c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers};
219996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
2205523ee070b005576c6f889415205d49ea77cf243Elliott HughesCompiler::Compiler(InstructionSet instruction_set, bool image, size_t thread_count,
221de6e4cf1b63acd7032a52826d9df21ff649d7128Elliott Hughes                   bool support_debugging, const std::set<std::string>* image_classes)
222aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    : instruction_set_(instruction_set),
223aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      jni_compiler_(instruction_set),
224c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      compiled_classes_lock_("compiled classes lock"),
225c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      compiled_methods_lock_("compiled method lock"),
226c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      compiled_invoke_stubs_lock_("compiled invoke stubs lock"),
227aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      image_(image),
2285523ee070b005576c6f889415205d49ea77cf243Elliott Hughes      thread_count_(thread_count),
229de6e4cf1b63acd7032a52826d9df21ff649d7128Elliott Hughes      support_debugging_(support_debugging),
230c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      stats_(new AOTCompilationStats),
231d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao      image_classes_(image_classes)
232d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#if defined(ART_USE_LLVM_COMPILER)
233d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao      ,
234d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao      compiler_llvm_(new compiler_llvm::CompilerLLVM(this, instruction_set))
235d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#endif
236d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao      {
23725c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom  CHECK(!Runtime::Current()->IsStarted());
238ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!image_) {
239ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    CHECK(image_classes_ == NULL);
240ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
241c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liao}
242c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liao
2433320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromCompiler::~Compiler() {
244c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  {
245c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_classes_lock_);
246c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    STLDeleteValues(&compiled_classes_);
247c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  }
248c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  {
249c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_methods_lock_);
250c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    STLDeleteValues(&compiled_methods_);
251c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  }
252c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  {
253c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_invoke_stubs_lock_);
254c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    STLDeleteValues(&compiled_invoke_stubs_);
255bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  }
2563320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
2573320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
2581cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set,
2591cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers                                          Runtime::TrampolineType type) {
260ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  if (instruction_set == kX86) {
2611cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return x86::X86CreateResolutionTrampoline(type);
262ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  } else {
263ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    CHECK(instruction_set == kArm || instruction_set == kThumb2);
264ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    // Generates resolution stub using ARM instruction set
2651cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return arm::ArmCreateResolutionTrampoline(type);
266ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  }
267ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
268ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
2698add92dcf59568c72c17e9a979948b1a7a0b1264Elliott HughesByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) {
270169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  switch (instruction_set) {
271169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    case kArm:
272169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    case kThumb2:
2738add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes      return arm::CreateJniDlsymLookupStub();
274169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    case kX86:
2758add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes      return x86::CreateJniDlsymLookupStub();
276169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    default:
277ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      LOG(FATAL) << "Unknown InstructionSet: " << static_cast<int>(instruction_set);
278169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers      return NULL;
279169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  }
280169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers}
281169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers
282ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan RogersByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) {
283ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  if (instruction_set == kX86) {
284ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    return x86::CreateAbstractMethodErrorStub();
285ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  } else {
286ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    CHECK(instruction_set == kArm || instruction_set == kThumb2);
287ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    // Generates resolution stub using ARM instruction set
288ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    return arm::CreateAbstractMethodErrorStub();
289ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  }
290ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
291ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
292254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilsonvoid Compiler::CompileAll(const ClassLoader* class_loader,
293ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                          const std::vector<const DexFile*>& dex_files) {
29425c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom  DCHECK(!Runtime::Current()->IsStarted());
295ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
296601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  TimingLogger timings("compiler");
297601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
298601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  PreCompile(class_loader, dex_files, timings);
299601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
300ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Compile(class_loader, dex_files);
301601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("Compile");
302601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
303ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  PostCompile(class_loader, dex_files);
304601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("PostCompile");
305601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
306601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  if (timings.GetTotalNs() > MsToNs(1000)) {
307601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes    timings.Dump();
308601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  }
309996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
310c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  stats_->Dump();
3118a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom}
3128a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom
3133320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstromvoid Compiler::CompileOne(const Method* method) {
31425c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom  DCHECK(!Runtime::Current()->IsStarted());
315ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
3168a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom  const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
317ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
3180571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Find the dex_file
3190571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3200571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
321ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  std::vector<const DexFile*> dex_files;
322ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  dex_files.push_back(&dex_file);
323ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
324601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  TimingLogger timings("CompileOne");
325601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  PreCompile(class_loader, dex_files, timings);
326ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
3270571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  uint32_t method_idx = method->GetDexMethodIndex();
328a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers  const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
329a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers  CompileMethod(code_item, method->GetAccessFlags(), method_idx, class_loader, dex_file);
330ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
331ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  PostCompile(class_loader, dex_files);
3329ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
3339ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
334ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::Resolve(const ClassLoader* class_loader,
335d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                       const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
336ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
337ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
3389ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom    CHECK(dex_file != NULL);
339d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    ResolveDexFile(class_loader, *dex_file, timings);
3409ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
3419ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
3429ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
343ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::PreCompile(const ClassLoader* class_loader,
344601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes                          const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
345d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Resolve(class_loader, dex_files, timings);
346601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
347ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Verify(class_loader, dex_files);
348601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("PreCompile.Verify");
349601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
350ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  InitializeClassesWithoutClinit(class_loader, dex_files);
351601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("PreCompile.InitializeClassesWithoutClinit");
352ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
353ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
354ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::PostCompile(const ClassLoader* class_loader,
355ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                           const std::vector<const DexFile*>& dex_files) {
356e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  SetGcMaps(class_loader, dex_files);
357d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#if defined(ART_USE_LLVM_COMPILER)
3587f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien  compiler_llvm_->MaterializeRemainder();
359d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#endif
360ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
361ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
362ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool Compiler::IsImageClass(const std::string& descriptor) const {
363ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (image_classes_ == NULL) {
364ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return true;
365ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
366ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  return image_classes_->find(descriptor) != image_classes_->end();
367ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
368ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
3696d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogersbool Compiler::CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache,
370996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                                uint32_t type_idx) {
3716d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  if (!IsImage()) {
372c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNotInDexCache();
3736d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    return false;
3746d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  }
3751bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* resolved_class = dex_cache->GetResolvedType(type_idx);
3766d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  if (resolved_class == NULL) {
377c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNotInDexCache();
3786d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    return false;
3796d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  }
380996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  bool result = IsImageClass(ClassHelper(resolved_class).GetDescriptor());
381996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (result) {
382c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeInDexCache();
383996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  } else {
384c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNotInDexCache();
385996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
386996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return result;
3876d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers}
3886d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers
3891bddec3a6521f16df37499754000a3b1787a52e9Ian Rogersbool Compiler::CanAssumeStringIsPresentInDexCache(const DexCache* dex_cache,
390996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                                  uint32_t string_idx) {
3911bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // TODO: Add support for loading strings referenced by image_classes_
3921bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // See also Compiler::ResolveDexFile
3931bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
3941bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // The following is a test saying that if we're building the image without a restricted set of
3951bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // image classes then we can assume the string is present in the dex cache if it is there now
396996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  bool result = IsImage() && image_classes_ == NULL && dex_cache->GetResolvedString(string_idx) != NULL;
397996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (result) {
398c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->StringInDexCache();
399996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  } else {
400c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->StringNotInDexCache();
401996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
402996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return result;
4031bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
4041bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
4051bddec3a6521f16df37499754000a3b1787a52e9Ian Rogersbool Compiler::CanAccessTypeWithoutChecks(uint32_t referrer_idx, const DexCache* dex_cache,
406996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                          const DexFile& dex_file, uint32_t type_idx) {
4071bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Get type from dex cache assuming it was populated by the verifier
4081bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* resolved_class = dex_cache->GetResolvedType(type_idx);
4091bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (resolved_class == NULL) {
410c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
4111bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    return false;  // Unknown class needs access checks.
4121bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
4131bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
4141bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
4151bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (referrer_class == NULL) {
416c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
4171bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    return false;  // Incomplete referrer knowledge needs access check.
4181bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
4191bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Perform access check, will return true if access is ok or false if we're going to have to
4201bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // check this at runtime (for example for class loaders).
421996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  bool result = referrer_class->CanAccess(resolved_class);
422996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (result) {
423c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeDoesntNeedAccessCheck();
424996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  } else {
425c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
426996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
427996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return result;
4281bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
4291bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
4301bddec3a6521f16df37499754000a3b1787a52e9Ian Rogersbool Compiler::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx,
4311bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers                                                      const DexCache* dex_cache,
4321bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers                                                      const DexFile& dex_file,
433996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                                      uint32_t type_idx) {
4341bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Get type from dex cache assuming it was populated by the verifier.
4351bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* resolved_class = dex_cache->GetResolvedType(type_idx);
4361bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (resolved_class == NULL) {
437c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
4381bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    return false;  // Unknown class needs access checks.
4391bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
4401bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
4411bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
4421bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (referrer_class == NULL) {
443c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
4441bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    return false;  // Incomplete referrer knowledge needs access check.
4451bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
4461bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Perform access and instantiable checks, will return true if access is ok or false if we're
4471bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // going to have to check this at runtime (for example for class loaders).
448996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  bool result = referrer_class->CanAccess(resolved_class) && resolved_class->IsInstantiable();
449996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (result) {
450c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeDoesntNeedAccessCheck();
451996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  } else {
452c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
453996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
454996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return result;
4551bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
4561bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
4574dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienstatic Class* ComputeReferrerClass(OatCompilationUnit* mUnit) {
4584dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  const DexFile::MethodId& referrer_method_id =
4594dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    mUnit->dex_file_->GetMethodId(mUnit->method_idx_);
460a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
4614dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  return mUnit->class_linker_->ResolveType(
4624dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    *mUnit->dex_file_, referrer_method_id.class_idx_,
4634dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    mUnit->dex_cache_, mUnit->class_loader_);
4644dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien}
465a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
4664dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienstatic Field* ComputeReferrerField(OatCompilationUnit* mUnit, uint32_t field_idx) {
4674dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  return mUnit->class_linker_->ResolveField(
4684dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    *mUnit->dex_file_, field_idx, mUnit->dex_cache_,
4694dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    mUnit->class_loader_, false);
470a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers}
471a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
4724dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienstatic Method* ComputeReferrerMethod(OatCompilationUnit* mUnit, uint32_t method_idx) {
4734dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  return mUnit->class_linker_->ResolveMethod(
4744dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    *mUnit->dex_file_, method_idx, mUnit->dex_cache_,
4754dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    mUnit->class_loader_, true);
476a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers}
477a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
4784dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienbool Compiler::ComputeInstanceFieldInfo(uint32_t field_idx, OatCompilationUnit* mUnit,
4798cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao                                        int& field_offset, bool& is_volatile, bool is_put) {
4801bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Conservative defaults
4811bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  field_offset = -1;
4821bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  is_volatile = true;
4831bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Try to resolve field
4844dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  Field* resolved_field = ComputeReferrerField(mUnit, field_idx);
4851bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (resolved_field != NULL) {
4864dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    Class* referrer_class = ComputeReferrerClass(mUnit);
4871bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    // Try to resolve referring class then access check, failure to pass the
4881bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    Class* fields_class = resolved_field->GetDeclaringClass();
4898cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao    bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal() &&
4908cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao                                              fields_class != referrer_class;
4918cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao    if (referrer_class != NULL && referrer_class->CanAccess(fields_class) &&
4928cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao        referrer_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) &&
4938cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao        !is_write_to_final_from_wrong_class) {
4941bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      field_offset = resolved_field->GetOffset().Int32Value();
4951bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      is_volatile = resolved_field->IsVolatile();
496c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      stats_->ResolvedInstanceField();
4971bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      return true;  // Fast path.
4981bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    }
4991bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
5001bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Clean up any exception left by field/type resolution
5011bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Thread* thread = Thread::Current();
5021bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (thread->IsExceptionPending()) {
5031bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      thread->ClearException();
5041bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
505c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  stats_->UnresolvedInstanceField();
5061bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  return false;  // Incomplete knowledge needs slow path.
5071bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
5081bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
5094dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienbool Compiler::ComputeStaticFieldInfo(uint32_t field_idx, OatCompilationUnit* mUnit,
5101bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers                                      int& field_offset, int& ssb_index,
5118cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao                                      bool& is_referrers_class, bool& is_volatile, bool is_put) {
5121bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Conservative defaults
5131bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  field_offset = -1;
5141bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  ssb_index = -1;
5151bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  is_referrers_class = false;
5161bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  is_volatile = true;
5171bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Try to resolve field
5184dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  Field* resolved_field = ComputeReferrerField(mUnit, field_idx);
5191bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (resolved_field != NULL) {
520a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers    DCHECK(resolved_field->IsStatic());
5214dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    Class* referrer_class = ComputeReferrerClass(mUnit);
5221bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    if (referrer_class != NULL) {
5238cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao      Class* fields_class = resolved_field->GetDeclaringClass();
5248cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao      if (fields_class == referrer_class) {
5251bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        is_referrers_class = true;  // implies no worrying about class initialization
5261bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        field_offset = resolved_field->GetOffset().Int32Value();
5271bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        is_volatile = resolved_field->IsVolatile();
528c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers        stats_->ResolvedLocalStaticField();
5291bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        return true;  // fast path
5301bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      } else {
5318cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao        bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal();
5321bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        if (referrer_class->CanAccess(fields_class) &&
5338cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao            referrer_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) &&
5348cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao            !is_write_to_final_from_wrong_class) {
5351bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          // We have the resolved field, we must make it into a ssbIndex for the referrer
5361bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          // in its static storage base (which may fail if it doesn't have a slot for it)
5374103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers          // TODO: for images we can elide the static storage base null check
5384103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers          // if we know there's a non-null entry in the image
5394dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien          if (fields_class->GetDexCache() == mUnit->dex_cache_) {
5404103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            // common case where the dex cache of both the referrer and the field are the same,
5414103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            // no need to search the dex file
5424103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            ssb_index = fields_class->GetDexTypeIndex();
5434103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            field_offset = resolved_field->GetOffset().Int32Value();
5444103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            is_volatile = resolved_field->IsVolatile();
545c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers            stats_->ResolvedStaticField();
5464103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            return true;
5474103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers          }
5484103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers          // Search dex file for localized ssb index
5491bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          std::string descriptor(FieldHelper(resolved_field).GetDeclaringClassDescriptor());
5501bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          const DexFile::StringId* string_id =
5514dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien          mUnit->dex_file_->FindStringId(descriptor);
5521bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          if (string_id != NULL) {
5531bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers            const DexFile::TypeId* type_id =
5544dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien               mUnit->dex_file_->FindTypeId(mUnit->dex_file_->GetIndexForStringId(*string_id));
5551bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers            if(type_id != NULL) {
5561bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers              // medium path, needs check of static storage base being initialized
5574dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien              ssb_index = mUnit->dex_file_->GetIndexForTypeId(*type_id);
5581bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers              field_offset = resolved_field->GetOffset().Int32Value();
5591bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers              is_volatile = resolved_field->IsVolatile();
560c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers              stats_->ResolvedStaticField();
5611bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers              return true;
5621bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers            }
5631bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          }
5641bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        }
5651bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      }
5661bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    }
5671bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
5681bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Clean up any exception left by field/type resolution
5691bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Thread* thread = Thread::Current();
5701bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (thread->IsExceptionPending()) {
5711bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      thread->ClearException();
5721bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
573c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  stats_->UnresolvedStaticField();
5741bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  return false;  // Incomplete knowledge needs slow path.
5751bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
5761bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
577fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogersbool Compiler::ComputeInvokeInfo(uint32_t method_idx, OatCompilationUnit* mUnit, InvokeType& type,
578996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                 int& vtable_idx) {
579a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  vtable_idx = -1;
5804dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  Method* resolved_method = ComputeReferrerMethod(mUnit, method_idx);
581a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  if (resolved_method != NULL) {
5824dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    Class* referrer_class = ComputeReferrerClass(mUnit);
583a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers    if (referrer_class != NULL) {
584a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      Class* methods_class = resolved_method->GetDeclaringClass();
585a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      if (!referrer_class->CanAccess(methods_class) ||
586a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers          !referrer_class->CanAccessMember(methods_class,
587996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                           resolved_method->GetAccessFlags())) {
588a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        // The referring class can't access the resolved method, this may occur as a result of a
589a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        // protected method being made public by implementing an interface that re-declares the
590a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        // method public. Resort to the dex file to determine the correct class for the access check
5914dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien        const DexFile& dex_file = mUnit->class_linker_->FindDexFile(referrer_class->GetDexCache());
592a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        methods_class =
5934dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien            mUnit->class_linker_->ResolveType(dex_file,
5944dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien                                              dex_file.GetMethodId(method_idx).class_idx_,
5954dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien                                              referrer_class);
596a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
597a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      }
598a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      if (referrer_class->CanAccess(methods_class) &&
599a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers          referrer_class->CanAccessMember(methods_class,
600a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers                                          resolved_method->GetAccessFlags())) {
601a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        vtable_idx = resolved_method->GetMethodIndex();
602fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers        if (type == kVirtual && (resolved_method->IsFinal() || methods_class->IsFinal())) {
603fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          stats_->ResolvedMethod(kVirtual);
604fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          // Sharpen a virtual call into a direct call. The method_idx is into referrer's
605fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          // dex cache, check that this resolved method is where we expect it.
606fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          CHECK(referrer_class->GetDexCache()->GetResolvedMethod(method_idx) == resolved_method)
607fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers            << PrettyMethod(resolved_method);
608fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          type = kDirect;
609fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          stats_->VirtualMadeDirect();
610fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          return true;
611fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers        } else if (type != kSuper) {
612c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers          // nothing left to do for static/direct/virtual/interface dispatch
613c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers          stats_->ResolvedMethod(type);
614a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers          return true;
615a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        } else {
616a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers          // ensure the vtable index will be correct to dispatch in the vtable of the super class
617996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers          if (referrer_class->IsSubClass(methods_class) &&
618996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers              vtable_idx < methods_class->GetVTable()->GetLength()) {
619c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers            stats_->ResolvedMethod(type);
620a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers            return true;
621a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers          }
622a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        }
623a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      }
624a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers    }
625a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  }
626a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  // Clean up any exception left by method/type resolution
627a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  Thread* thread = Thread::Current();
628a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  if (thread->IsExceptionPending()) {
629a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      thread->ClearException();
630a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  }
631c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  stats_->UnresolvedMethod(type);
632a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  return false;  // Incomplete knowledge needs slow path.
633a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers}
634a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
6355ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// Return true if the class should be skipped during compilation. We
6365ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// never skip classes in the boot class loader. However, if we have a
6375ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// non-boot class loader and we can resolve the class in the boot
6385ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// class loader, we do skip the class. This happens if an app bundles
6395ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// classes found in the boot classpath. Since at runtime we will
6405ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// select the class from the boot classpath, do not attempt to resolve
6415ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// or compile it now.
6425ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstromstatic bool SkipClass(const ClassLoader* class_loader,
6435ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom                      const DexFile& dex_file,
6445ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom                      const DexFile::ClassDef& class_def) {
6455ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  if (class_loader == NULL) {
6465ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    return false;
6475ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  }
6485ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  const char* descriptor = dex_file.GetClassDescriptor(class_def);
6495ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
6505ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  Class* klass = class_linker->FindClass(descriptor, NULL);
6515ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  if (klass == NULL) {
6525ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    Thread* self = Thread::Current();
6535ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    CHECK(self->IsExceptionPending());
6545ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    self->ClearException();
6555ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    return false;
6565ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  }
6575ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  return true;
6585ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom}
6595ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom
660d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstruct Context {
661d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassLinker* class_linker;
662d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const ClassLoader* class_loader;
663c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  Compiler* compiler;
664d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DexCache* dex_cache;
665d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile* dex_file;
666d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes};
6679ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
668d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughestypedef void Callback(Context* context, size_t index);
669d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
670d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesclass WorkerThread {
671d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes public:
6721e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  WorkerThread(Context* context, size_t begin, size_t end, Callback callback, size_t stripe, bool spawn)
6731e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      : spawn_(spawn), context_(context), begin_(begin), end_(end), callback_(callback), stripe_(stripe) {
6741e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    if (spawn_) {
6751e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      CHECK_PTHREAD_CALL(pthread_create, (&pthread_, NULL, &Go, this), "compiler worker thread");
6761e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    }
677d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
678d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
679d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ~WorkerThread() {
6801e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    if (spawn_) {
6811e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      CHECK_PTHREAD_CALL(pthread_join, (pthread_, NULL), "compiler worker shutdown");
6821e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    }
683d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
684d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
685d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes private:
6861e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  static void* Go(void* arg) {
687d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    WorkerThread* worker = reinterpret_cast<WorkerThread*>(arg);
688d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Runtime* runtime = Runtime::Current();
6891e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    if (worker->spawn_) {
6901e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      runtime->AttachCurrentThread("Compiler Worker", true);
6911e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    }
692d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->SetState(Thread::kRunnable);
693d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    worker->Run();
6941e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    if (worker->spawn_) {
6951e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      Thread::Current()->SetState(Thread::kNative);
6961e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      runtime->DetachCurrentThread();
6971e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    }
698d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return NULL;
699d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
700d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
7011e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  void Go() {
7021e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    Go(this);
7031e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  }
7041e4092589f1400915e6213014da103aab8728ef6Elliott Hughes
705d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  void Run() {
706d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    for (size_t i = begin_; i < end_; i += stripe_) {
707d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      callback_(context_, i);
708aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
7099ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
7109ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
711d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  pthread_t pthread_;
7121e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  bool spawn_;
713d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
714d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Context* context_;
715d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  size_t begin_;
716d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  size_t end_;
717d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Callback* callback_;
718d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  size_t stripe_;
7191e4092589f1400915e6213014da103aab8728ef6Elliott Hughes
7201e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  friend void ForAll(Context*, size_t, size_t, Callback, size_t);
721d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes};
722d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
7235523ee070b005576c6f889415205d49ea77cf243Elliott Hughesvoid ForAll(Context* context, size_t begin, size_t end, Callback callback, size_t thread_count) {
7241e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  CHECK_GT(thread_count, 0U);
725845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom
7261e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  std::vector<WorkerThread*> threads;
72781d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  for (size_t i = 0; i < thread_count; ++i) {
7281e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    threads.push_back(new WorkerThread(context, begin + i, end, callback, thread_count, (i != 0)));
729d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
7301e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  threads[0]->Go();
731d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
73281d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  // Switch to kVmWait while we're blocked waiting for the other threads to finish.
73381d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
73481d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  STLDeleteElements(&threads);
73581d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes}
736d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
737d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstatic void ResolveClassFieldsAndMethods(Context* context, size_t class_def_index) {
738d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile& dex_file = *context->dex_file;
739d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
740845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // Method and Field are the worst. We can't resolve without either
741845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // context from the code use (to disambiguate virtual vs direct
742845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // method and instance vs static field) or from class
743845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // definitions. While the compiler will resolve what it can as it
744845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // needs it, here we try to resolve fields and methods used in class
745845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // definitions, since many of them many never be referenced by
746845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // generated code.
747d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
748d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (SkipClass(context->class_loader, dex_file, class_def)) {
749d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return;
750d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
751845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom
752d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // Note the class_data pointer advances through the headers,
753d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // static fields, instance fields, direct methods, and virtual
754d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // methods.
755d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const byte* class_data = dex_file.GetClassData(class_def);
756d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (class_data == NULL) {
757d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // empty class such as a marker interface
758d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return;
759d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
760d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Thread* self = Thread::Current();
761d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassLinker* class_linker = context->class_linker;
762d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
763d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassDataItemIterator it(dex_file, class_data);
764d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextStaticField()) {
765d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
766d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                                              context->class_loader, true);
767d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (field == NULL) {
768d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
769d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
7700571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    }
771d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
772d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
773d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextInstanceField()) {
774d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
775d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                                              context->class_loader, false);
776d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (field == NULL) {
777d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
778d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
77920cfffabdc9e02b2df798bc4e6b6035d14bf4e36Brian Carlstrom    }
780d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
781d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
782d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextDirectMethod()) {
783d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
784d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                                                 context->class_loader, true);
785d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (method == NULL) {
786d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
787d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
788845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom    }
789d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
790d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
791d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextVirtualMethod()) {
792d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
793d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                                                 context->class_loader, false);
794d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (method == NULL) {
795d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
796d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
797845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom    }
798d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
799d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
800d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DCHECK(!it.HasNext());
801d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes}
802d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
803d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstatic void ResolveType(Context* context, size_t type_idx) {
804d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // Class derived values are more complicated, they require the linker and loader.
805d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Thread* self = Thread::Current();
806d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassLinker* class_linker = context->class_linker;
807d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile& dex_file = *context->dex_file;
808d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Class* klass = class_linker->ResolveType(dex_file, type_idx, context->dex_cache, context->class_loader);
809d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (klass == NULL) {
810d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK(self->IsExceptionPending());
811d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->ClearException();
812d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
813d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes}
814d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
815d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesvoid Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file, TimingLogger& timings) {
816d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
817d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
818d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
819d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // Strings are easy in that they always are simply resolved to literals in the same file
820d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (image_ && image_classes_ == NULL) {
821d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // TODO: Add support for loading strings referenced by image_classes_
822d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // See also Compiler::CanAssumeTypeIsPresentInDexCache.
823d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    for (size_t string_idx = 0; string_idx < dex_cache->NumStrings(); string_idx++) {
824d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      class_linker->ResolveString(dex_file, string_idx, dex_cache);
82520cfffabdc9e02b2df798bc4e6b6035d14bf4e36Brian Carlstrom    }
826ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes    timings.AddSplit("Resolve " + dex_file.GetLocation() + " Strings");
8279ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
828d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
829d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Context context;
830d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.class_linker = class_linker;
831d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.class_loader = class_loader;
832d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.dex_cache = dex_cache;
833d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.dex_file = &dex_file;
834d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
8355523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_cache->NumResolvedTypes(), ResolveType, thread_count_);
836ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes  timings.AddSplit("Resolve " + dex_file.GetLocation() + " Types");
837d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
8385523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods, thread_count_);
839ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes  timings.AddSplit("Resolve " + dex_file.GetLocation() + " MethodsAndFields");
8409ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
8419ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
842ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::Verify(const ClassLoader* class_loader,
843ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                      const std::vector<const DexFile*>& dex_files) {
844ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
845ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
84698eacac683b78e60799323e8c7d59e7214808639jeffhao    CHECK(dex_file != NULL);
84798eacac683b78e60799323e8c7d59e7214808639jeffhao    VerifyDexFile(class_loader, *dex_file);
84898eacac683b78e60799323e8c7d59e7214808639jeffhao  }
84998eacac683b78e60799323e8c7d59e7214808639jeffhao}
85098eacac683b78e60799323e8c7d59e7214808639jeffhao
851d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstatic void VerifyClass(Context* context, size_t class_def_index) {
852d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile::ClassDef& class_def = context->dex_file->GetClassDef(class_def_index);
853d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const char* descriptor = context->dex_file->GetClassDescriptor(class_def);
854d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Class* klass = context->class_linker->FindClass(descriptor, context->class_loader);
855d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (klass == NULL) {
856d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread* self = Thread::Current();
857d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK(self->IsExceptionPending());
858d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    self->ClearException();
859d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return;
860d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
861d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  CHECK(klass->IsResolved()) << PrettyClass(klass);
862d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context->class_linker->VerifyClass(klass);
863d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
864d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (klass->IsErroneous()) {
865d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
866d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK(Thread::Current()->IsExceptionPending());
867d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->ClearException();
868d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // We want to try verification again at run-time, so move back into the resolved state.
869d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    klass->SetStatus(Class::kStatusResolved);
870d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
871d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
872d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  CHECK(klass->IsVerified() || klass->IsResolved()) << PrettyClass(klass);
873d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
874d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes}
875d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
87698eacac683b78e60799323e8c7d59e7214808639jeffhaovoid Compiler::VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
877b4df5146854c42bf03c4ca02f441b6db73bfde0cjeffhao  dex_file.ChangePermissions(PROT_READ | PROT_WRITE);
878d9cdfe91a4812a86d90a139569eac18e2b6de3fbElliott Hughes
879d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Context context;
880d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.class_linker = Runtime::Current()->GetClassLinker();
881d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.class_loader = class_loader;
882d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.dex_file = &dex_file;
8835523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_file.NumClassDefs(), VerifyClass, thread_count_);
884d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
885b4df5146854c42bf03c4ca02f441b6db73bfde0cjeffhao  dex_file.ChangePermissions(PROT_READ);
886a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom}
887a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom
888ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader,
889ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                              const std::vector<const DexFile*>& dex_files) {
890ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
891ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
892a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    CHECK(dex_file != NULL);
893a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    InitializeClassesWithoutClinit(class_loader, *dex_file);
894a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom  }
895a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom}
896a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom
897a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstromvoid Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, const DexFile& dex_file) {
898a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
899ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
900ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
901a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    const char* descriptor = dex_file.GetClassDescriptor(class_def);
902a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    Class* klass = class_linker->FindClass(descriptor, class_loader);
90327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    if (klass != NULL) {
90427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      class_linker->EnsureInitialized(klass, false);
9050755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      // record the final class status if necessary
9060755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      Class::Status status = klass->GetStatus();
9070755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      ClassReference ref(&dex_file, class_def_index);
908c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      MutexLock mu(compiled_classes_lock_);
9090755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      CompiledClass* compiled_class = GetCompiledClass(ref);
9100755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      if (compiled_class == NULL) {
9110755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom        compiled_class = new CompiledClass(status);
9120755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom        compiled_classes_[ref] = compiled_class;
9130755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      } else {
9140755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom        DCHECK_EQ(status, compiled_class->GetStatus());
9150755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      }
91627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    }
91727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    // clear any class not found or verification exceptions
91827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    Thread::Current()->ClearException();
919ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  }
920ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom
921ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
922ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
923ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom    Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
92427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    if (klass == NULL) {
92527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      Thread::Current()->ClearException();
92627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    } else if (klass->IsInitialized()) {
927ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom      dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
928ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom    }
92998eacac683b78e60799323e8c7d59e7214808639jeffhao  }
93098eacac683b78e60799323e8c7d59e7214808639jeffhao}
93198eacac683b78e60799323e8c7d59e7214808639jeffhao
932ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::Compile(const ClassLoader* class_loader,
933ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       const std::vector<const DexFile*>& dex_files) {
934ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
935ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
93683db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom    CHECK(dex_file != NULL);
93783db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom    CompileDexFile(class_loader, *dex_file);
93883db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom  }
93983db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom}
94083db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom
941c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughesvoid Compiler::CompileClass(Context* context, size_t class_def_index) {
942c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  const ClassLoader* class_loader = context->class_loader;
943c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  const DexFile& dex_file = *context->dex_file;
944c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
9457f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien
9467f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien#if defined(ART_USE_LLVM_COMPILER)
9477f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien  compiler_llvm::CompilerLLVM* compiler_llvm = context->compiler->GetCompilerLLVM();
9487f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien
9497f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien  MutexLock GUARD(compiler_llvm->compiler_lock_);
9507f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien  // TODO: Remove this.  We should not lock the compiler_lock_ in CompileClass()
9517f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien  // However, without this mutex lock, we will get segmentation fault.
9527f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien#endif
9537f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien
9545ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  if (SkipClass(class_loader, dex_file, class_def)) {
9555ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    return;
9565ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  }
957d1224c79631bd1801b067a0f212b91afa961a362jeffhao  ClassReference ref(&dex_file, class_def_index);
958d1224c79631bd1801b067a0f212b91afa961a362jeffhao  // Skip compiling classes with generic verifier failures since they will still fail at runtime
959d1224c79631bd1801b067a0f212b91afa961a362jeffhao  if (verifier::DexVerifier::IsClassRejected(ref)) {
960d1224c79631bd1801b067a0f212b91afa961a362jeffhao    return;
961d1224c79631bd1801b067a0f212b91afa961a362jeffhao  }
9620571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const byte* class_data = dex_file.GetClassData(class_def);
9630571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (class_data == NULL) {
9640571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    // empty class, probably a marker interface
9650571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    return;
9660571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
9670571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  ClassDataItemIterator it(dex_file, class_data);
9680571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Skip fields
9690571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextStaticField()) {
9700571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
9710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
9720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextInstanceField()) {
9730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
9740571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
9750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Compile direct methods
9760571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextDirectMethod()) {
977c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    context->compiler->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
978c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes                                     it.GetMemberIndex(), class_loader, dex_file);
9790571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
9809ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
9810571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Compile virtual methods
9820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextVirtualMethod()) {
983c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    context->compiler->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
984c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes                                     it.GetMemberIndex(), class_loader, dex_file);
9850571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
9869ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
9870571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  DCHECK(!it.HasNext());
9887f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien
9897f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien#if defined(ART_USE_LLVM_COMPILER)
9907f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien  compiler_llvm->MaterializeIfThresholdReached();
9917f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien#endif
9929ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
9939ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
994c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughesvoid Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
995c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  Context context;
996c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  context.class_loader = class_loader;
997c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  context.compiler = this;
998c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  context.dex_file = &dex_file;
9995523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_file.NumClassDefs(), Compiler::CompileClass, thread_count_);
1000c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes}
1001c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes
1002a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogersvoid Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
1003a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers                             uint32_t method_idx, const ClassLoader* class_loader,
1004a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers                             const DexFile& dex_file) {
1005f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes  CompiledMethod* compiled_method = NULL;
1006bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  uint64_t start_ns = NanoTime();
10074dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien
10084dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien#if defined(ART_USE_LLVM_COMPILER)
10094dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  ClassLinker *class_linker = Runtime::Current()->GetClassLinker();
10104dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  DexCache *dex_cache = class_linker->FindDexCache(dex_file);
10114dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien
1012dbe72bde0815ad53d26ec26da581c163d7928656Logan Chien  OatCompilationUnit oat_compilation_unit(
1013dbe72bde0815ad53d26ec26da581c163d7928656Logan Chien    class_loader, class_linker, dex_file, *dex_cache, code_item,
1014dbe72bde0815ad53d26ec26da581c163d7928656Logan Chien    method_idx, access_flags);
10154dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien#endif
10164dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien
1017169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  if ((access_flags & kAccNative) != 0) {
101888894ee835411de72025cd8a5d8d111a6f2a004aLogan Chien#if defined(ART_USE_LLVM_COMPILER)
1019dbe72bde0815ad53d26ec26da581c163d7928656Logan Chien    compiled_method = compiler_llvm_->CompileNativeMethod(&oat_compilation_unit);
102088894ee835411de72025cd8a5d8d111a6f2a004aLogan Chien#else
1021169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    compiled_method = jni_compiler_.Compile(access_flags, method_idx, class_loader, dex_file);
102288894ee835411de72025cd8a5d8d111a6f2a004aLogan Chien#endif
10233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    CHECK(compiled_method != NULL);
1024169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  } else if ((access_flags & kAccAbstract) != 0) {
10252cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom  } else {
1026d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#if defined(ART_USE_LLVM_COMPILER)
1027dbe72bde0815ad53d26ec26da581c163d7928656Logan Chien    compiled_method = compiler_llvm_->CompileDexMethod(&oat_compilation_unit);
1028d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#else
1029a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers    compiled_method = oatCompileMethod(*this, code_item, access_flags, method_idx, class_loader,
1030a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers                                       dex_file, kThumb2);
1031d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#endif
1032bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes    CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
1033bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  }
10343bb17a644e2945c3913cfbde245d2f520d62a3ffIan Rogers  uint64_t duration_ns = NanoTime() - start_ns;
10355abfa3ea35781464df8fae60aaf03f48a295e965buzbee  if (duration_ns > MsToNs(100)) {
1036bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes    LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
10373bb17a644e2945c3913cfbde245d2f520d62a3ffIan Rogers                 << " took " << PrettyDuration(duration_ns);
1038f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes  }
1039f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes
1040f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes  if (compiled_method != NULL) {
10410571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    MethodReference ref(&dex_file, method_idx);
10420755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom    CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file);
1043c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_methods_lock_);
10440571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    compiled_methods_[ref] = compiled_method;
10450755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom    DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file);
10462cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom  }
10479baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom
104845619fcc01fb6db1ac9481a91608eb46f90829e4Ian Rogers  uint32_t shorty_len;
104945619fcc01fb6db1ac9481a91608eb46f90829e4Ian Rogers  const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx), &shorty_len);
1050169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  bool is_static = (access_flags & kAccStatic) != 0;
10510571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
10520571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (compiled_invoke_stub == NULL) {
1053f04364f0ff789935d05490ee684f01c3de431780Logan Chien#if defined(ART_USE_LLVM_COMPILER)
1054f04364f0ff789935d05490ee684f01c3de431780Logan Chien    compiled_invoke_stub = compiler_llvm_->CreateInvokeStub(is_static, shorty);
1055f04364f0ff789935d05490ee684f01c3de431780Logan Chien#else
10560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    if (instruction_set_ == kX86) {
105745619fcc01fb6db1ac9481a91608eb46f90829e4Ian Rogers      compiled_invoke_stub = ::art::x86::X86CreateInvokeStub(is_static, shorty, shorty_len);
10580571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    } else {
10590571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
10600571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      // Generates invocation stub using ARM instruction set
106145619fcc01fb6db1ac9481a91608eb46f90829e4Ian Rogers      compiled_invoke_stub = ::art::arm::ArmCreateInvokeStub(is_static, shorty, shorty_len);
10620571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    }
1063f04364f0ff789935d05490ee684f01c3de431780Logan Chien#endif
1064f04364f0ff789935d05490ee684f01c3de431780Logan Chien
10650571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    CHECK(compiled_invoke_stub != NULL);
10660571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
10673320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
10680571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
10690571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers}
107028ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers
10710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersstatic std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
10720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  std::string key(shorty);
10730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (is_static) {
1074bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes    key += "$";  // Must not be a shorty type character.
10750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
10760571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  return key;
10773320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
10783320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
10790571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersconst CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
1080c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_invoke_stubs_lock_);
1081955724179c6c739524f610023287f56b24dc31deElliott Hughes  const std::string key(MakeInvokeStubKey(is_static, shorty));
10820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
10830571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (it == compiled_invoke_stubs_.end()) {
10843320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    return NULL;
10850571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  } else {
10860571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    DCHECK(it->second != NULL);
10870571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    return it->second;
10883320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
10893320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
10903320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
10910571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersvoid Compiler::InsertInvokeStub(bool is_static, const char* shorty,
10920571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers                                const CompiledInvokeStub* compiled_invoke_stub) {
1093c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_invoke_stubs_lock_);
1094955724179c6c739524f610023287f56b24dc31deElliott Hughes  std::string key(MakeInvokeStubKey(is_static, shorty));
10950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  compiled_invoke_stubs_[key] = compiled_invoke_stub;
10960571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers}
10970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers
10980755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromCompiledClass* Compiler::GetCompiledClass(ClassReference ref) const {
1099c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_classes_lock_);
11000755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  ClassTable::const_iterator it = compiled_classes_.find(ref);
11010755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  if (it == compiled_classes_.end()) {
11020755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom    return NULL;
11030755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  }
11040755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  CHECK(it->second != NULL);
11050755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  return it->second;
11060755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom}
11070755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
11080571d357843c53e042f370f5f2c2e9aa3fe803a9Ian RogersCompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
1109c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_methods_lock_);
11100571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  MethodTable::const_iterator it = compiled_methods_.find(ref);
11110571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (it == compiled_methods_.end()) {
11123320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    return NULL;
11132c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  }
11143320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  CHECK(it->second != NULL);
11153320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  return it->second;
11169ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
11179ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
1118e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstromvoid Compiler::SetGcMaps(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files) {
1119e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
1120e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const DexFile* dex_file = dex_files[i];
1121e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    CHECK(dex_file != NULL);
1122e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    SetGcMapsDexFile(class_loader, *dex_file);
1123e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1124e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom}
1125e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
1126e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstromvoid Compiler::SetGcMapsDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
1127e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1128e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
1129e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
1130e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
1131e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const char* descriptor = dex_file.GetClassDescriptor(class_def);
1132e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    Class* klass = class_linker->FindClass(descriptor, class_loader);
1133e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    if (klass == NULL || !klass->IsVerified()) {
1134e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      Thread::Current()->ClearException();
1135e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      continue;
1136e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1137e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const byte* class_data = dex_file.GetClassData(class_def);
1138e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    if (class_data == NULL) {
1139e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      // empty class such as a marker interface
1140e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      continue;
1141e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1142e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    ClassDataItemIterator it(dex_file, class_data);
1143e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextStaticField()) {
1144e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
1145e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1146e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextInstanceField()) {
1147e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
1148e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1149e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextDirectMethod()) {
1150e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1151e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                                                   class_loader, true);
1152e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      SetGcMapsMethod(dex_file, method);
1153e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
1154e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1155e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextVirtualMethod()) {
1156e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1157e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                                                   class_loader, false);
1158e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      SetGcMapsMethod(dex_file, method);
1159e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
1160e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1161e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1162e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom}
1163e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
1164e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstromvoid Compiler::SetGcMapsMethod(const DexFile& dex_file, Method* method) {
1165e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  if (method == NULL) {
1166e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    Thread::Current()->ClearException();
1167e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    return;
1168e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1169e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  uint16_t method_idx = method->GetDexMethodIndex();
1170e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  MethodReference ref(&dex_file, method_idx);
1171e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  CompiledMethod* compiled_method = GetCompiledMethod(ref);
1172e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  if (compiled_method == NULL) {
1173e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    return;
1174e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1175e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  const std::vector<uint8_t>* gc_map = verifier::DexVerifier::GetGcMap(ref);
1176e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  if (gc_map == NULL) {
1177e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    return;
1178e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1179e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  compiled_method->SetGcMap(*gc_map);
1180e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom}
1181e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
11828b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien#if defined(ART_USE_LLVM_COMPILER)
11838b977d38483aaa08abcbdaa5fa888076c1142169Logan Chienvoid Compiler::SetElfFileName(std::string const& filename) {
11848b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien  compiler_llvm_->SetElfFileName(filename);
11858b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien}
11868b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien
11878b977d38483aaa08abcbdaa5fa888076c1142169Logan Chienvoid Compiler::SetBitcodeFileName(std::string const& filename) {
11888b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien  compiler_llvm_->SetBitcodeFileName(filename);
11898b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien}
11908b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien#endif
11918b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien
11929ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}  // namespace art
1193