compiler_driver.cc revision ba0668ecd2a6459ed7c77012995ad08d27f88725
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
21b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes#include <dlfcn.h>
2227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <sys/mman.h>
23d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes#include <unistd.h>
2427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
252cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom#include "assembler.h"
269ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom#include "class_linker.h"
271f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "class_loader.h"
289ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom#include "dex_cache.h"
29f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao#include "dex_verifier.h"
309baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom#include "jni_internal.h"
314dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien#include "oat_compilation_unit.h"
323320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "oat_file.h"
336d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
341f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h"
35b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes#include "space.h"
363320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "stl_util.h"
37601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes#include "timing_logger.h"
389ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
39059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes#if defined(__APPLE__)
40059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes#include <mach-o/dyld.h>
41059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes#endif
42059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes
439ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstromnamespace art {
449ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
45c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liaonamespace arm {
46bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers  ByteArray* CreateAbstractMethodErrorStub();
471cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type);
488add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes  ByteArray* CreateJniDlsymLookupStub();
49c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liao}
50c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liaonamespace x86 {
51bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers  ByteArray* CreateAbstractMethodErrorStub();
521cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type);
538add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes  ByteArray* CreateJniDlsymLookupStub();
54e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
55e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
56996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogersstatic double Percentage(size_t x, size_t y) {
57996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return 100.0 * ((double)x) / ((double)(x + y));
58996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers}
59996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
60996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogersstatic void DumpStat(size_t x, size_t y, const char* str) {
61996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (x == 0 && y == 0) {
62996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers    return;
63996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
64996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  LOG(INFO) << Percentage(x, y) << "% of " << str << " for " << (x + y) << " cases";
65996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers}
66996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
67c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogersclass AOTCompilationStats {
68c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers public:
69c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  AOTCompilationStats() : stats_lock_("AOT compilation statistics lock"),
70c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers     types_in_dex_cache_(0), types_not_in_dex_cache_(0),
71c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers     strings_in_dex_cache_(0), strings_not_in_dex_cache_(0),
72c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers     resolved_types_(0), unresolved_types_(0),
73c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers     resolved_instance_fields_(0), unresolved_instance_fields_(0),
742ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers     resolved_local_static_fields_(0), resolved_static_fields_(0), unresolved_static_fields_(0) {
752ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    for (size_t i = 0; i <= kMaxInvokeType; i++) {
76c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      resolved_methods_[i] = 0;
77c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      unresolved_methods_[i] = 0;
782ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      virtual_made_direct_[i] = 0;
792ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      direct_calls_to_boot_[i] = 0;
802ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      direct_methods_to_boot_[i] = 0;
812ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers   }
82c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
83c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
84c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void Dump() {
85c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(types_in_dex_cache_, types_not_in_dex_cache_, "types known to be in dex cache");
86c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(strings_in_dex_cache_, strings_not_in_dex_cache_, "strings known to be in dex cache");
87c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(resolved_types_, unresolved_types_, "types resolved");
88c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(resolved_instance_fields_, unresolved_instance_fields_, "instance fields resolved");
89c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(resolved_local_static_fields_ + resolved_static_fields_, unresolved_static_fields_,
90c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers             "static fields resolved");
91c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DumpStat(resolved_local_static_fields_, resolved_static_fields_ + unresolved_static_fields_,
92c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers             "static fields local to a class");
93c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
942ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    for (size_t i = 0; i <= kMaxInvokeType; i++) {
95c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      std::ostringstream oss;
962ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      oss << static_cast<InvokeType>(i) << " methods were AOT resolved";
97c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      DumpStat(resolved_methods_[i], unresolved_methods_[i], oss.str().c_str());
982ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      if (virtual_made_direct_[i] > 0) {
992ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        std::ostringstream oss2;
1002ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        oss2 << static_cast<InvokeType>(i) << " methods made direct";
1012ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        DumpStat(virtual_made_direct_[i],
1022ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                 resolved_methods_[i] + unresolved_methods_[i] - virtual_made_direct_[i],
1032ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                 oss2.str().c_str());
1042ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      }
1052ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      if (direct_calls_to_boot_[i] > 0) {
1062ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        std::ostringstream oss2;
1072ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        oss2 << static_cast<InvokeType>(i) << " method calls are direct into boot";
1082ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        DumpStat(direct_calls_to_boot_[i],
1092ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                 resolved_methods_[i] + unresolved_methods_[i] - direct_calls_to_boot_[i],
1102ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                 oss2.str().c_str());
1112ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      }
1122ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      if (direct_methods_to_boot_[i] > 0) {
1132ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        std::ostringstream oss2;
1142ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        oss2 << static_cast<InvokeType>(i) << " method calls have methods in boot";
1152ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        DumpStat(direct_methods_to_boot_[i],
1162ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                 resolved_methods_[i] + unresolved_methods_[i] - direct_methods_to_boot_[i],
1172ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                 oss2.str().c_str());
1182ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers      }
119c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    }
120c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
121996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
122996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers// Allow lossy statistics in non-debug builds
123996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#ifndef NDEBUG
124996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#define STATS_LOCK() MutexLock mu(stats_lock_)
125996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#else
126996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#define STATS_LOCK()
127996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers#endif
128996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
129c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void TypeInDexCache() {
130c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
131c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    types_in_dex_cache_++;
132c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
133996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
134c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void TypeNotInDexCache() {
135c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
136c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    types_not_in_dex_cache_++;
137c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
138996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
139c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void StringInDexCache() {
140c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
141c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    strings_in_dex_cache_++;
142c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
143996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
144c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void StringNotInDexCache() {
145c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
146c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    strings_not_in_dex_cache_++;
147c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
148996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
149c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void TypeDoesntNeedAccessCheck() {
150c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
151c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_types_++;
152c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
153996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
154c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void TypeNeedsAccessCheck() {
155c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
156c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    unresolved_types_++;
157c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
158996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
159c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void ResolvedInstanceField() {
160c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
161c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_instance_fields_++;
162c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
163996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
164c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void UnresolvedInstanceField(){
165c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
166c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    unresolved_instance_fields_++;
167c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
168996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
169c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void ResolvedLocalStaticField() {
170c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
171c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_local_static_fields_++;
172c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
173996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
174c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void ResolvedStaticField() {
175c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
176c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_static_fields_++;
177c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
178996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
179c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void UnresolvedStaticField() {
180c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
181c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    unresolved_static_fields_++;
182c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  }
183996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
184c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void ResolvedMethod(InvokeType type) {
185c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DCHECK_LE(type, kMaxInvokeType);
186c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
187c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    resolved_methods_[type]++;
188996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
189996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
190c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  void UnresolvedMethod(InvokeType type) {
191c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    DCHECK_LE(type, kMaxInvokeType);
192c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    STATS_LOCK();
193c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    unresolved_methods_[type]++;
194996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
195c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
1962ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  void VirtualMadeDirect(InvokeType type) {
1972ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    DCHECK_LE(type, kMaxInvokeType);
1982ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    STATS_LOCK();
1992ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    virtual_made_direct_[type]++;
2002ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  }
2012ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers
2022ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  void DirectCallsToBoot(InvokeType type) {
2032ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    DCHECK_LE(type, kMaxInvokeType);
2042ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    STATS_LOCK();
2052ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    direct_calls_to_boot_[type]++;
2062ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  }
2072ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers
2082ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  void DirectMethodsToBoot(InvokeType type) {
2092ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    DCHECK_LE(type, kMaxInvokeType);
210fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers    STATS_LOCK();
2112ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    direct_methods_to_boot_[type]++;
212fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers  }
2132ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers
214c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers private:
215c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  Mutex stats_lock_;
216c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
217c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t types_in_dex_cache_;
218c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t types_not_in_dex_cache_;
219c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
220c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t strings_in_dex_cache_;
221c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t strings_not_in_dex_cache_;
222c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
223c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_types_;
224c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t unresolved_types_;
225c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
226c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_instance_fields_;
227c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t unresolved_instance_fields_;
228c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
229c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_local_static_fields_;
230c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_static_fields_;
231c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t unresolved_static_fields_;
232c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
233c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t resolved_methods_[kMaxInvokeType + 1];
234c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  size_t unresolved_methods_[kMaxInvokeType + 1];
2352ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  size_t virtual_made_direct_[kMaxInvokeType + 1];
2362ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  size_t direct_calls_to_boot_[kMaxInvokeType + 1];
2372ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  size_t direct_methods_to_boot_[kMaxInvokeType + 1];
238c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers
239c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  DISALLOW_COPY_AND_ASSIGN(AOTCompilationStats);;
240c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers};
241996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
242b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughesstatic std::string MakeCompilerSoName(InstructionSet instruction_set) {
243b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  // TODO: is the ARM/Thumb2 instruction set distinction really buying us anything,
244b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  // or just causing hassle like this?
245b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  if (instruction_set == kThumb2) {
246b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    instruction_set = kArm;
247b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  }
248b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
249059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  // Capitalize the instruction set, because that's what we do in the build system.
250b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  std::ostringstream instruction_set_name_os;
251b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  instruction_set_name_os << instruction_set;
252b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  std::string instruction_set_name(instruction_set_name_os.str());
253b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  for (size_t i = 0; i < instruction_set_name.size(); ++i) {
254b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    instruction_set_name[i] = toupper(instruction_set_name[i]);
255b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  }
256059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes
257059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  // Bad things happen if we pull in the libartd-compiler to a libart dex2oat or vice versa,
258059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  // because we end up with both libart and libartd in the same address space!
259b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes#ifndef NDEBUG
260b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  const char* suffix = "d";
261b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes#else
262b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  const char* suffix = "";
263b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes#endif
264059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes
265059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  // Work out the filename for the compiler library.
266c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao#if !defined(ART_USE_LLVM_COMPILER)
267059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  std::string library_name(StringPrintf("art%s-compiler-%s", suffix, instruction_set_name.c_str()));
268c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao#else
269c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  std::string library_name(StringPrintf("art%s-compiler-llvm", suffix));
270c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao#endif
271059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  std::string filename(StringPrintf(OS_SHARED_LIB_FORMAT_STR, library_name.c_str()));
272059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes
273059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes#if defined(__APPLE__)
274059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  // On Linux, dex2oat will have been built with an RPATH of $ORIGIN/../lib, so dlopen(3) will find
275059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  // the .so by itself. On Mac OS, there isn't really an equivalent, so we have to manually do the
276059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  // same work.
277059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  std::vector<char> executable_path(1);
278059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  uint32_t executable_path_length = 0;
279059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  _NSGetExecutablePath(&executable_path[0], &executable_path_length);
280059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  while (_NSGetExecutablePath(&executable_path[0], &executable_path_length) == -1) {
281059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes    executable_path.resize(executable_path_length);
282059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  }
283059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes
284059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  executable_path.resize(executable_path.size() - 1); // Strip trailing NUL.
285059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  std::string path(&executable_path[0]);
286059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes
287059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  // Strip the "/dex2oat".
288059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  size_t last_slash = path.find_last_of('/');
289059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  CHECK_NE(last_slash, std::string::npos) << path;
290059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  path.resize(last_slash);
291059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes
292059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  // Strip the "/bin".
293059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  last_slash = path.find_last_of('/');
294059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  path.resize(last_slash);
295059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes
296059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  filename = path + "/lib/" + filename;
297059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes#endif
298059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  return filename;
299b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes}
300b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
30146f060a53fffc14333096f0a48f95730ee4768eeElliott Hughestemplate<typename Fn>
30246f060a53fffc14333096f0a48f95730ee4768eeElliott Hughesstatic Fn FindFunction(const std::string& compiler_so_name, void* library, const char* name) {
30346f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes  Fn fn = reinterpret_cast<Fn>(dlsym(library, name));
30446f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes  if (fn == NULL) {
30546f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes    LOG(FATAL) << "Couldn't find \"" << name << "\" in compiler library " << compiler_so_name << ": " << dlerror();
30646f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes  }
307059d5c142b0ef1fa421153cdcc2326c5c56fd530Elliott Hughes  VLOG(compiler) << "Found \"" << name << "\" at " << reinterpret_cast<void*>(fn);
30846f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes  return fn;
30946f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes}
31046f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes
3115523ee070b005576c6f889415205d49ea77cf243Elliott HughesCompiler::Compiler(InstructionSet instruction_set, bool image, size_t thread_count,
312ba0668ecd2a6459ed7c77012995ad08d27f88725Brian Carlstrom                   bool support_debugging, const std::set<std::string>* image_classes,
313ba0668ecd2a6459ed7c77012995ad08d27f88725Brian Carlstrom                   bool dump_stats, bool dump_timings)
314aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    : instruction_set_(instruction_set),
315c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      compiled_classes_lock_("compiled classes lock"),
316c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      compiled_methods_lock_("compiled method lock"),
317c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      compiled_invoke_stubs_lock_("compiled invoke stubs lock"),
318aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      image_(image),
3195523ee070b005576c6f889415205d49ea77cf243Elliott Hughes      thread_count_(thread_count),
320de6e4cf1b63acd7032a52826d9df21ff649d7128Elliott Hughes      support_debugging_(support_debugging),
321c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      stats_(new AOTCompilationStats),
322ba0668ecd2a6459ed7c77012995ad08d27f88725Brian Carlstrom      dump_stats_(dump_stats),
323ba0668ecd2a6459ed7c77012995ad08d27f88725Brian Carlstrom      dump_timings_(dump_timings),
324b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      image_classes_(image_classes),
325b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes      compiler_library_(NULL),
32646f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes      compiler_(NULL),
3276f4976c1a9fdaf108974143cd11e6b46037fd24eElliott Hughes      compiler_context_(NULL),
32846f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes      jni_compiler_(NULL),
32946f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes      create_invoke_stub_(NULL)
330b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes{
331c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  std::string compiler_so_name(MakeCompilerSoName(instruction_set_));
332b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  compiler_library_ = dlopen(compiler_so_name.c_str(), RTLD_LAZY);
333b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  if (compiler_library_ == NULL) {
334b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    LOG(FATAL) << "Couldn't find compiler library " << compiler_so_name << ": " << dlerror();
335b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  }
336b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  VLOG(compiler) << "dlopen(\"" << compiler_so_name << "\", RTLD_LAZY) returned " << compiler_library_;
337b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
3383fa1b7e7a7fc9785ba4e8335d730e5caf6343322Elliott Hughes  compiler_ = FindFunction<CompilerFn>(compiler_so_name, compiler_library_, "ArtCompileMethod");
33946f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes  jni_compiler_ = FindFunction<JniCompilerFn>(compiler_so_name, compiler_library_, "ArtJniCompileMethod");
34046f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes  create_invoke_stub_ = FindFunction<CreateInvokeStubFn>(compiler_so_name, compiler_library_, "ArtCreateInvokeStub");
341b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes
34225c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom  CHECK(!Runtime::Current()->IsStarted());
343ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!image_) {
344ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    CHECK(image_classes_ == NULL);
345ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
346c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liao}
347c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liao
3483320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromCompiler::~Compiler() {
349c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  {
350c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_classes_lock_);
351c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    STLDeleteValues(&compiled_classes_);
352c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  }
353c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  {
354c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_methods_lock_);
355c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    STLDeleteValues(&compiled_methods_);
356c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  }
357c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  {
358c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_invoke_stubs_lock_);
359c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    STLDeleteValues(&compiled_invoke_stubs_);
360bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  }
361f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom  {
362f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom    MutexLock mu(compiled_methods_lock_);
363f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom    STLDeleteElements(&code_to_patch_);
364f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom  }
365f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom  {
366f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom    MutexLock mu(compiled_methods_lock_);
367f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom    STLDeleteElements(&methods_to_patch_);
368f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom  }
369c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao#if defined(ART_USE_LLVM_COMPILER)
370c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  CompilerCallbackFn f = FindFunction<CompilerCallbackFn>(MakeCompilerSoName(instruction_set_),
371c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao                                                          compiler_library_,
372c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao                                                          "compilerLLVMDispose");
373c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  (*f)(*this);
374c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao#endif
375b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  if (compiler_library_ != NULL) {
376b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    VLOG(compiler) << "dlclose(" << compiler_library_ << ")";
377b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    dlclose(compiler_library_);
378b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  }
3793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
3803320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
3811cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set,
3821cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers                                          Runtime::TrampolineType type) {
383ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  if (instruction_set == kX86) {
3841cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return x86::X86CreateResolutionTrampoline(type);
385ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  } else {
386ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    CHECK(instruction_set == kArm || instruction_set == kThumb2);
387ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    // Generates resolution stub using ARM instruction set
3881cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return arm::ArmCreateResolutionTrampoline(type);
389ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  }
390ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
391ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
3928add92dcf59568c72c17e9a979948b1a7a0b1264Elliott HughesByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) {
393169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  switch (instruction_set) {
394169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    case kArm:
395169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    case kThumb2:
3968add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes      return arm::CreateJniDlsymLookupStub();
397169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    case kX86:
3988add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes      return x86::CreateJniDlsymLookupStub();
399169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    default:
40049c4894f76f6a7aec4d6a1ec2c901700c9108944Ian Rogers      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
401169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers      return NULL;
402169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  }
403169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers}
404169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers
405ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan RogersByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) {
406ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  if (instruction_set == kX86) {
407ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    return x86::CreateAbstractMethodErrorStub();
408ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  } else {
409ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    CHECK(instruction_set == kArm || instruction_set == kThumb2);
410ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    // Generates resolution stub using ARM instruction set
411ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    return arm::CreateAbstractMethodErrorStub();
412ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  }
413ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
414ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
415254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilsonvoid Compiler::CompileAll(const ClassLoader* class_loader,
416ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                          const std::vector<const DexFile*>& dex_files) {
41725c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom  DCHECK(!Runtime::Current()->IsStarted());
418ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
419601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  TimingLogger timings("compiler");
420601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
421601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  PreCompile(class_loader, dex_files, timings);
422601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
423ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Compile(class_loader, dex_files);
424601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("Compile");
425601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
426ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  PostCompile(class_loader, dex_files);
427601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("PostCompile");
428601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
429ba0668ecd2a6459ed7c77012995ad08d27f88725Brian Carlstrom  if (dump_timings_ && timings.GetTotalNs() > MsToNs(1000)) {
430601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes    timings.Dump();
431601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  }
432996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers
433ba0668ecd2a6459ed7c77012995ad08d27f88725Brian Carlstrom  if (dump_stats_) {
434ba0668ecd2a6459ed7c77012995ad08d27f88725Brian Carlstrom    stats_->Dump();
435ba0668ecd2a6459ed7c77012995ad08d27f88725Brian Carlstrom  }
4368a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom}
4378a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom
4383320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstromvoid Compiler::CompileOne(const Method* method) {
43925c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom  DCHECK(!Runtime::Current()->IsStarted());
440ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
4418a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom  const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
442ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
4430571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Find the dex_file
4440571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
4450571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
446ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  std::vector<const DexFile*> dex_files;
447ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  dex_files.push_back(&dex_file);
448ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
449601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  TimingLogger timings("CompileOne");
450601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  PreCompile(class_loader, dex_files, timings);
451ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
4520571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  uint32_t method_idx = method->GetDexMethodIndex();
453a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers  const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
454a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers  CompileMethod(code_item, method->GetAccessFlags(), method_idx, class_loader, dex_file);
455ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
456ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  PostCompile(class_loader, dex_files);
4579ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
4589ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
459ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::Resolve(const ClassLoader* class_loader,
460d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                       const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
461ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
462ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
4639ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom    CHECK(dex_file != NULL);
464d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    ResolveDexFile(class_loader, *dex_file, timings);
4659ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
4669ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
4679ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
468ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::PreCompile(const ClassLoader* class_loader,
469601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes                          const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
470d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Resolve(class_loader, dex_files, timings);
471601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
472ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Verify(class_loader, dex_files);
473601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("PreCompile.Verify");
474601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
475ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  InitializeClassesWithoutClinit(class_loader, dex_files);
476601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("PreCompile.InitializeClassesWithoutClinit");
477ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
478ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
479ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::PostCompile(const ClassLoader* class_loader,
480ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                           const std::vector<const DexFile*>& dex_files) {
481e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  SetGcMaps(class_loader, dex_files);
482d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#if defined(ART_USE_LLVM_COMPILER)
483c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  CompilerCallbackFn f = FindFunction<CompilerCallbackFn>(MakeCompilerSoName(instruction_set_),
484c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao                                                          compiler_library_,
485c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao                                                          "compilerLLVMMaterializeRemainder");
486c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  (*f)(*this);
487d1fec81868a3567560a3868350e0a945248e925bShih-wei Liao#endif
488ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
489ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
490ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool Compiler::IsImageClass(const std::string& descriptor) const {
491ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (image_classes_ == NULL) {
492ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return true;
493ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
494ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  return image_classes_->find(descriptor) != image_classes_->end();
495ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
496ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
4976d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogersbool Compiler::CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache,
498996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                                uint32_t type_idx) {
4996d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  if (!IsImage()) {
500c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNotInDexCache();
5016d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    return false;
5026d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  }
5031bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* resolved_class = dex_cache->GetResolvedType(type_idx);
5046d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  if (resolved_class == NULL) {
505c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNotInDexCache();
5066d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    return false;
5076d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  }
508996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  bool result = IsImageClass(ClassHelper(resolved_class).GetDescriptor());
509996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (result) {
510c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeInDexCache();
511996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  } else {
512c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNotInDexCache();
513996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
514996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return result;
5156d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers}
5166d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers
5171bddec3a6521f16df37499754000a3b1787a52e9Ian Rogersbool Compiler::CanAssumeStringIsPresentInDexCache(const DexCache* dex_cache,
518996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                                  uint32_t string_idx) {
5191bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // TODO: Add support for loading strings referenced by image_classes_
5201bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // See also Compiler::ResolveDexFile
5211bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
5221bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // The following is a test saying that if we're building the image without a restricted set of
5231bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // image classes then we can assume the string is present in the dex cache if it is there now
524996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  bool result = IsImage() && image_classes_ == NULL && dex_cache->GetResolvedString(string_idx) != NULL;
525996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (result) {
526c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->StringInDexCache();
527996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  } else {
528c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->StringNotInDexCache();
529996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
530996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return result;
5311bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
5321bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
5331bddec3a6521f16df37499754000a3b1787a52e9Ian Rogersbool Compiler::CanAccessTypeWithoutChecks(uint32_t referrer_idx, const DexCache* dex_cache,
534996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                          const DexFile& dex_file, uint32_t type_idx) {
5351bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Get type from dex cache assuming it was populated by the verifier
5361bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* resolved_class = dex_cache->GetResolvedType(type_idx);
5371bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (resolved_class == NULL) {
538c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
5391bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    return false;  // Unknown class needs access checks.
5401bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
5411bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
5421bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
5431bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (referrer_class == NULL) {
544c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
5451bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    return false;  // Incomplete referrer knowledge needs access check.
5461bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
5471bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Perform access check, will return true if access is ok or false if we're going to have to
5481bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // check this at runtime (for example for class loaders).
549996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  bool result = referrer_class->CanAccess(resolved_class);
550996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (result) {
551c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeDoesntNeedAccessCheck();
552996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  } else {
553c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
554996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
555996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return result;
5561bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
5571bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
5581bddec3a6521f16df37499754000a3b1787a52e9Ian Rogersbool Compiler::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx,
5591bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers                                                      const DexCache* dex_cache,
5601bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers                                                      const DexFile& dex_file,
561996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                                      uint32_t type_idx) {
5621bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Get type from dex cache assuming it was populated by the verifier.
5631bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* resolved_class = dex_cache->GetResolvedType(type_idx);
5641bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (resolved_class == NULL) {
565c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
5661bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    return false;  // Unknown class needs access checks.
5671bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
5681bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
5691bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
5701bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (referrer_class == NULL) {
571c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
5721bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    return false;  // Incomplete referrer knowledge needs access check.
5731bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
5741bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Perform access and instantiable checks, will return true if access is ok or false if we're
5751bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // going to have to check this at runtime (for example for class loaders).
576996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  bool result = referrer_class->CanAccess(resolved_class) && resolved_class->IsInstantiable();
577996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  if (result) {
578c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeDoesntNeedAccessCheck();
579996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  } else {
580c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers    stats_->TypeNeedsAccessCheck();
581996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  }
582996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers  return result;
5831bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
5841bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
5854dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienstatic Class* ComputeReferrerClass(OatCompilationUnit* mUnit) {
5864dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  const DexFile::MethodId& referrer_method_id =
5874dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    mUnit->dex_file_->GetMethodId(mUnit->method_idx_);
588a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
5894dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  return mUnit->class_linker_->ResolveType(
5904dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    *mUnit->dex_file_, referrer_method_id.class_idx_,
5914dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    mUnit->dex_cache_, mUnit->class_loader_);
5924dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien}
593a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
5944dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienstatic Field* ComputeReferrerField(OatCompilationUnit* mUnit, uint32_t field_idx) {
5954dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  return mUnit->class_linker_->ResolveField(
5964dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    *mUnit->dex_file_, field_idx, mUnit->dex_cache_,
5974dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    mUnit->class_loader_, false);
598a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers}
599a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
6004dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienstatic Method* ComputeReferrerMethod(OatCompilationUnit* mUnit, uint32_t method_idx) {
6014dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  return mUnit->class_linker_->ResolveMethod(
6024dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    *mUnit->dex_file_, method_idx, mUnit->dex_cache_,
6034dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    mUnit->class_loader_, true);
604a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers}
605a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
6064dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienbool Compiler::ComputeInstanceFieldInfo(uint32_t field_idx, OatCompilationUnit* mUnit,
6078cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao                                        int& field_offset, bool& is_volatile, bool is_put) {
6081bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Conservative defaults
6091bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  field_offset = -1;
6101bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  is_volatile = true;
6111bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Try to resolve field
6124dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  Field* resolved_field = ComputeReferrerField(mUnit, field_idx);
6131bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (resolved_field != NULL) {
6144dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    Class* referrer_class = ComputeReferrerClass(mUnit);
6151bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    // Try to resolve referring class then access check, failure to pass the
6161bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    Class* fields_class = resolved_field->GetDeclaringClass();
6178cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao    bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal() &&
6188cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao                                              fields_class != referrer_class;
6198cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao    if (referrer_class != NULL && referrer_class->CanAccess(fields_class) &&
6208cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao        referrer_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) &&
6218cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao        !is_write_to_final_from_wrong_class) {
6221bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      field_offset = resolved_field->GetOffset().Int32Value();
6231bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      is_volatile = resolved_field->IsVolatile();
624c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers      stats_->ResolvedInstanceField();
6251bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      return true;  // Fast path.
6261bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    }
6271bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
6281bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Clean up any exception left by field/type resolution
6291bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Thread* thread = Thread::Current();
6301bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (thread->IsExceptionPending()) {
6311bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      thread->ClearException();
6321bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
633c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  stats_->UnresolvedInstanceField();
6341bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  return false;  // Incomplete knowledge needs slow path.
6351bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
6361bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
6374dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chienbool Compiler::ComputeStaticFieldInfo(uint32_t field_idx, OatCompilationUnit* mUnit,
6381bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers                                      int& field_offset, int& ssb_index,
6398cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao                                      bool& is_referrers_class, bool& is_volatile, bool is_put) {
6401bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Conservative defaults
6411bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  field_offset = -1;
6421bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  ssb_index = -1;
6431bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  is_referrers_class = false;
6441bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  is_volatile = true;
6451bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Try to resolve field
6464dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  Field* resolved_field = ComputeReferrerField(mUnit, field_idx);
6471bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (resolved_field != NULL) {
648a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers    DCHECK(resolved_field->IsStatic());
6494dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    Class* referrer_class = ComputeReferrerClass(mUnit);
6501bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    if (referrer_class != NULL) {
6518cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao      Class* fields_class = resolved_field->GetDeclaringClass();
6528cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao      if (fields_class == referrer_class) {
6531bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        is_referrers_class = true;  // implies no worrying about class initialization
6541bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        field_offset = resolved_field->GetOffset().Int32Value();
6551bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        is_volatile = resolved_field->IsVolatile();
656c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers        stats_->ResolvedLocalStaticField();
6571bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        return true;  // fast path
6581bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      } else {
6598cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao        bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal();
6601bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        if (referrer_class->CanAccess(fields_class) &&
6618cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao            referrer_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) &&
6628cd6ddaeb78cc904e13bac88753654a04b2e15b8jeffhao            !is_write_to_final_from_wrong_class) {
6631bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          // We have the resolved field, we must make it into a ssbIndex for the referrer
6641bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          // in its static storage base (which may fail if it doesn't have a slot for it)
6654103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers          // TODO: for images we can elide the static storage base null check
6664103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers          // if we know there's a non-null entry in the image
6674dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien          if (fields_class->GetDexCache() == mUnit->dex_cache_) {
6684103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            // common case where the dex cache of both the referrer and the field are the same,
6694103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            // no need to search the dex file
6704103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            ssb_index = fields_class->GetDexTypeIndex();
6714103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            field_offset = resolved_field->GetOffset().Int32Value();
6724103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            is_volatile = resolved_field->IsVolatile();
673c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers            stats_->ResolvedStaticField();
6744103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers            return true;
6754103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers          }
6764103ad2ab59488fe4eb36b88259e402e8878878bIan Rogers          // Search dex file for localized ssb index
6771bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          std::string descriptor(FieldHelper(resolved_field).GetDeclaringClassDescriptor());
6781bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          const DexFile::StringId* string_id =
6794dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien          mUnit->dex_file_->FindStringId(descriptor);
6801bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          if (string_id != NULL) {
6811bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers            const DexFile::TypeId* type_id =
6824dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien               mUnit->dex_file_->FindTypeId(mUnit->dex_file_->GetIndexForStringId(*string_id));
6831bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers            if(type_id != NULL) {
6841bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers              // medium path, needs check of static storage base being initialized
6854dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien              ssb_index = mUnit->dex_file_->GetIndexForTypeId(*type_id);
6861bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers              field_offset = resolved_field->GetOffset().Int32Value();
6871bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers              is_volatile = resolved_field->IsVolatile();
688c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers              stats_->ResolvedStaticField();
6891bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers              return true;
6901bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers            }
6911bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers          }
6921bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers        }
6931bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      }
6941bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers    }
6951bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
6961bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  // Clean up any exception left by field/type resolution
6971bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  Thread* thread = Thread::Current();
6981bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  if (thread->IsExceptionPending()) {
6991bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers      thread->ClearException();
7001bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  }
701c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  stats_->UnresolvedStaticField();
7021bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers  return false;  // Incomplete knowledge needs slow path.
7031bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers}
7041bddec3a6521f16df37499754000a3b1787a52e9Ian Rogers
7052ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogersvoid Compiler::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType sharp_type, Method* method,
7062ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                                             uintptr_t& direct_code, uintptr_t& direct_method) {
7072ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  direct_code = 0;
7082ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  direct_method = 0;
7092ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  if (sharp_type != kStatic && sharp_type != kDirect) {
7102ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    return;
7112ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  }
7122ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  bool method_code_in_boot = method->GetDeclaringClass()->GetClassLoader() == NULL;
7132ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  if (!method_code_in_boot) {
7142ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    return;
7152ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  }
7162ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  bool has_clinit_trampoline = method->IsStatic() && !method->GetDeclaringClass()->IsInitialized();
7172ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  if (has_clinit_trampoline) {
7182ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers    return;
7192ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  }
7202ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  stats_->DirectCallsToBoot(type);
7212ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  stats_->DirectMethodsToBoot(type);
7223fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers  bool compiling_boot = Runtime::Current()->GetHeap()->GetSpaces().size() == 1;
7233fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers  if (compiling_boot) {
7240637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom    const bool kSupportBootImageFixup = true;
7253fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers    if (kSupportBootImageFixup) {
7263fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers      MethodHelper mh(method);
7273fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers      if (IsImageClass(mh.GetDeclaringClassDescriptor())) {
7280637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom        // We can only branch directly to Methods that are resolved in the DexCache.
7290637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom        // Otherwise we won't invoke the resolution trampoline.
7303fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers        direct_method = -1;
7310637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom        direct_code = -1;
7323fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers      }
7333fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers    }
7343fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers  } else {
7353fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers    if (Runtime::Current()->GetHeap()->GetImageSpace()->Contains(method)) {
7363fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers      direct_method = reinterpret_cast<uintptr_t>(method);
7373fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers    }
7383fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers    direct_code = reinterpret_cast<uintptr_t>(method->GetCode());
7392ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  }
7402ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers}
7412ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers
742fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogersbool Compiler::ComputeInvokeInfo(uint32_t method_idx, OatCompilationUnit* mUnit, InvokeType& type,
7432ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                                 int& vtable_idx, uintptr_t& direct_code,
7442ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                                 uintptr_t& direct_method) {
745a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  vtable_idx = -1;
7462ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  direct_code = 0;
7472ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers  direct_method = 0;
7484dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien  Method* resolved_method = ComputeReferrerMethod(mUnit, method_idx);
749a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  if (resolved_method != NULL) {
7504dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien    Class* referrer_class = ComputeReferrerClass(mUnit);
751a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers    if (referrer_class != NULL) {
752a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      Class* methods_class = resolved_method->GetDeclaringClass();
753a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      if (!referrer_class->CanAccess(methods_class) ||
754a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers          !referrer_class->CanAccessMember(methods_class,
755996cc586ce76235ee3efa1eff86de51dabcc5d53Ian Rogers                                           resolved_method->GetAccessFlags())) {
756a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        // The referring class can't access the resolved method, this may occur as a result of a
757a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        // protected method being made public by implementing an interface that re-declares the
758a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        // method public. Resort to the dex file to determine the correct class for the access check
7594dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien        const DexFile& dex_file = mUnit->class_linker_->FindDexFile(referrer_class->GetDexCache());
760a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        methods_class =
7614dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien            mUnit->class_linker_->ResolveType(dex_file,
7624dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien                                              dex_file.GetMethodId(method_idx).class_idx_,
7634dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien                                              referrer_class);
764a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
765a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      }
766a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      if (referrer_class->CanAccess(methods_class) &&
767a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers          referrer_class->CanAccessMember(methods_class,
768a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers                                          resolved_method->GetAccessFlags())) {
769a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        vtable_idx = resolved_method->GetMethodIndex();
770f320b639eee1ec0e9d99e8d6c2a805892d016807Ian Rogers        const bool kEnableSharpening = true;
7712ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        // Sharpen a virtual call into a direct call when the target is known.
7722ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        bool can_sharpen = type == kVirtual && (resolved_method->IsFinal() ||
7732ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                                                methods_class->IsFinal());
7742ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        // ensure the vtable index will be correct to dispatch in the vtable of the super class
7754155fcd385bebe869e04c50ff99f4d3d608097bbjeffhao        can_sharpen = can_sharpen || (type == kSuper && referrer_class != methods_class &&
7762ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers                                      referrer_class->IsSubClass(methods_class) &&
7774155fcd385bebe869e04c50ff99f4d3d608097bbjeffhao                                      vtable_idx < methods_class->GetVTable()->GetLength() &&
7784155fcd385bebe869e04c50ff99f4d3d608097bbjeffhao                                      methods_class->GetVTable()->Get(vtable_idx) == resolved_method);
7792ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        if (kEnableSharpening && can_sharpen) {
7802ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers          stats_->ResolvedMethod(type);
781fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          // Sharpen a virtual call into a direct call. The method_idx is into referrer's
782fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          // dex cache, check that this resolved method is where we expect it.
783fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          CHECK(referrer_class->GetDexCache()->GetResolvedMethod(method_idx) == resolved_method)
784fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers            << PrettyMethod(resolved_method);
7852ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers          stats_->VirtualMadeDirect(type);
7862ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers          GetCodeAndMethodForDirectCall(type, kDirect, resolved_method, direct_code, direct_method);
787fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          type = kDirect;
788fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers          return true;
7892ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        } else if (type == kSuper) {
7902ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers          // Unsharpened super calls are suspicious so go slowpath.
7912ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers        } else {
792c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers          stats_->ResolvedMethod(type);
7932ed3b9536ccfd7c7321cc18650820b093b22d6c9Ian Rogers          GetCodeAndMethodForDirectCall(type, type, resolved_method, direct_code, direct_method);
794a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers          return true;
795a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers        }
796a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      }
797a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers    }
798a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  }
799a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  // Clean up any exception left by method/type resolution
800a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  Thread* thread = Thread::Current();
801a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  if (thread->IsExceptionPending()) {
802a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers      thread->ClearException();
803a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  }
804c8b306f5221658c7e4b5516be8917dc8c9288e7eIan Rogers  stats_->UnresolvedMethod(type);
805a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers  return false;  // Incomplete knowledge needs slow path.
806a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers}
807a32a6fd4a781262dff4fec102da053d16b7ef6c0Ian Rogers
808f582258f0e296223a091fd64231a203ad71e9649Brian Carlstromvoid Compiler::AddCodePatch(DexCache* dex_cache,
809f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                            const DexFile* dex_file,
810f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                            uint32_t referrer_method_idx,
811f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                            uint32_t referrer_access_flags,
812f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                            uint32_t target_method_idx,
813f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                            bool target_is_direct,
8143fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers                            size_t literal_offset) {
8153fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers  MutexLock mu(compiled_methods_lock_);
816f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom  code_to_patch_.push_back(new PatchInformation(dex_cache,
817f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                dex_file,
818f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                referrer_method_idx,
819f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                referrer_access_flags,
820f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                target_method_idx,
821f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                target_is_direct,
822f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                literal_offset));
8233fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers}
824f582258f0e296223a091fd64231a203ad71e9649Brian Carlstromvoid Compiler::AddMethodPatch(DexCache* dex_cache,
825f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                              const DexFile* dex_file,
826f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                              uint32_t referrer_method_idx,
827f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                              uint32_t referrer_access_flags,
828f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                              uint32_t target_method_idx,
829f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                              bool target_is_direct,
8303fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers                              size_t literal_offset) {
8313fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers  MutexLock mu(compiled_methods_lock_);
832f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom  methods_to_patch_.push_back(new PatchInformation(dex_cache,
833f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                   dex_file,
834f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                   referrer_method_idx,
835f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                   referrer_access_flags,
836f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                   target_method_idx,
837f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                   target_is_direct,
838f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom                                                   literal_offset));
8393fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers}
8403fa13791c51985d9956d01bc465de6d36c3390d3Ian Rogers
8415ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// Return true if the class should be skipped during compilation. We
8425ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// never skip classes in the boot class loader. However, if we have a
8435ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// non-boot class loader and we can resolve the class in the boot
8445ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// class loader, we do skip the class. This happens if an app bundles
8455ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// classes found in the boot classpath. Since at runtime we will
8465ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// select the class from the boot classpath, do not attempt to resolve
8475ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// or compile it now.
8485ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstromstatic bool SkipClass(const ClassLoader* class_loader,
8495ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom                      const DexFile& dex_file,
8505ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom                      const DexFile::ClassDef& class_def) {
8515ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  if (class_loader == NULL) {
8525ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    return false;
8535ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  }
8545ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  const char* descriptor = dex_file.GetClassDescriptor(class_def);
8555ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
8565ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  Class* klass = class_linker->FindClass(descriptor, NULL);
8575ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  if (klass == NULL) {
8585ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    Thread* self = Thread::Current();
8595ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    CHECK(self->IsExceptionPending());
8605ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    self->ClearException();
8615ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    return false;
8625ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  }
8635ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  return true;
8645ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom}
8655ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom
866731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstromclass Context {
867731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom public:
868731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  Context(ClassLinker* class_linker,
869731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom          const ClassLoader* class_loader,
870731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom          Compiler* compiler,
871731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom          DexCache* dex_cache,
872731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom          const DexFile* dex_file)
873731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    : class_linker_(class_linker),
874731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom      class_loader_(class_loader),
875731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom      compiler_(compiler),
876731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom      dex_cache_(dex_cache),
877731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom      dex_file_(dex_file) {}
878731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom
879731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  ClassLinker* GetClassLinker() {
880731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    CHECK(class_linker_ != NULL);
881731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    return class_linker_;
882731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  }
883731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  const ClassLoader* GetClassLoader() {
884731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    return class_loader_;
885731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  }
886731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  Compiler* GetCompiler() {
887731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    CHECK(compiler_ != NULL);
888731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    return compiler_;
889731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  }
890731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  DexCache* GetDexCache() {
891731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    CHECK(dex_cache_ != NULL);
892731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    return dex_cache_;
893731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  }
894731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  const DexFile* GetDexFile() {
895731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    CHECK(dex_file_ != NULL);
896731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    return dex_file_;
897731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  }
898731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom
899731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom private:
900731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  ClassLinker* class_linker_;
901731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  const ClassLoader* class_loader_;
902731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  Compiler* compiler_;
903731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  DexCache* dex_cache_;
904731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  const DexFile* dex_file_;
905d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes};
9069ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
907d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughestypedef void Callback(Context* context, size_t index);
908d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
909d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesclass WorkerThread {
910d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes public:
9111e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  WorkerThread(Context* context, size_t begin, size_t end, Callback callback, size_t stripe, bool spawn)
9121e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      : spawn_(spawn), context_(context), begin_(begin), end_(end), callback_(callback), stripe_(stripe) {
9131e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    if (spawn_) {
9141e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      CHECK_PTHREAD_CALL(pthread_create, (&pthread_, NULL, &Go, this), "compiler worker thread");
9151e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    }
916d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
917d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
918d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ~WorkerThread() {
9191e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    if (spawn_) {
9201e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      CHECK_PTHREAD_CALL(pthread_join, (pthread_, NULL), "compiler worker shutdown");
9211e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    }
922d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
923d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
924d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes private:
9251e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  static void* Go(void* arg) {
926d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    WorkerThread* worker = reinterpret_cast<WorkerThread*>(arg);
927d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Runtime* runtime = Runtime::Current();
9281e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    if (worker->spawn_) {
929462c94449720e0dc6b93d7138d835d345ccf67aeElliott Hughes      runtime->AttachCurrentThread("Compiler Worker", true, NULL);
9301e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    }
931d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->SetState(Thread::kRunnable);
932d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    worker->Run();
9331e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    if (worker->spawn_) {
9341e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      Thread::Current()->SetState(Thread::kNative);
9351e4092589f1400915e6213014da103aab8728ef6Elliott Hughes      runtime->DetachCurrentThread();
9361e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    }
937d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return NULL;
938d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
939d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
9401e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  void Go() {
9411e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    Go(this);
9421e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  }
9431e4092589f1400915e6213014da103aab8728ef6Elliott Hughes
944d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  void Run() {
945d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    for (size_t i = begin_; i < end_; i += stripe_) {
946d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      callback_(context_, i);
947aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
9489ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
9499ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
950d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  pthread_t pthread_;
9511e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  bool spawn_;
952d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
953d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Context* context_;
954d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  size_t begin_;
955d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  size_t end_;
956d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Callback* callback_;
957d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  size_t stripe_;
9581e4092589f1400915e6213014da103aab8728ef6Elliott Hughes
9591e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  friend void ForAll(Context*, size_t, size_t, Callback, size_t);
960d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes};
961d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
9625523ee070b005576c6f889415205d49ea77cf243Elliott Hughesvoid ForAll(Context* context, size_t begin, size_t end, Callback callback, size_t thread_count) {
9631e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  CHECK_GT(thread_count, 0U);
964845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom
9651e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  std::vector<WorkerThread*> threads;
96681d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  for (size_t i = 0; i < thread_count; ++i) {
9671e4092589f1400915e6213014da103aab8728ef6Elliott Hughes    threads.push_back(new WorkerThread(context, begin + i, end, callback, thread_count, (i != 0)));
968d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
9691e4092589f1400915e6213014da103aab8728ef6Elliott Hughes  threads[0]->Go();
970d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
97181d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  // Switch to kVmWait while we're blocked waiting for the other threads to finish.
97281d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
97381d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  STLDeleteElements(&threads);
97481d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes}
975d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
976d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstatic void ResolveClassFieldsAndMethods(Context* context, size_t class_def_index) {
977731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  const DexFile& dex_file = *context->GetDexFile();
978d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
979845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // Method and Field are the worst. We can't resolve without either
980845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // context from the code use (to disambiguate virtual vs direct
981845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // method and instance vs static field) or from class
982845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // definitions. While the compiler will resolve what it can as it
983845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // needs it, here we try to resolve fields and methods used in class
984845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // definitions, since many of them many never be referenced by
985845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // generated code.
986d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
987731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  if (SkipClass(context->GetClassLoader(), dex_file, class_def)) {
988d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return;
989d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
990845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom
991d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // Note the class_data pointer advances through the headers,
992d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // static fields, instance fields, direct methods, and virtual
993d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // methods.
994d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const byte* class_data = dex_file.GetClassData(class_def);
995d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (class_data == NULL) {
996d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // empty class such as a marker interface
997d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return;
998d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
999d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Thread* self = Thread::Current();
1000731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  ClassLinker* class_linker = context->GetClassLinker();
1001d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
1002d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassDataItemIterator it(dex_file, class_data);
1003d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextStaticField()) {
1004d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
1005731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                                              context->GetClassLoader(), true);
1006d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (field == NULL) {
1007d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
1008d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
10090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    }
1010d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
1011d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
1012d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextInstanceField()) {
1013d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
1014731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                                              context->GetClassLoader(), false);
1015d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (field == NULL) {
1016d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
1017d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
101820cfffabdc9e02b2df798bc4e6b6035d14bf4e36Brian Carlstrom    }
1019d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
1020d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
1021d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextDirectMethod()) {
1022d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1023731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                                                 context->GetClassLoader(), true);
1024d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (method == NULL) {
1025d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
1026d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
1027845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom    }
1028d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
1029d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
1030d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextVirtualMethod()) {
1031d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1032731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                                                 context->GetClassLoader(), false);
1033d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (method == NULL) {
1034d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
1035d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
1036845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom    }
1037d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
1038d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
1039d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DCHECK(!it.HasNext());
1040d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes}
1041d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
1042d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstatic void ResolveType(Context* context, size_t type_idx) {
1043d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // Class derived values are more complicated, they require the linker and loader.
1044d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Thread* self = Thread::Current();
1045731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  Class* klass = context->GetClassLinker()->ResolveType(*context->GetDexFile(),
1046731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                                                        type_idx,
1047731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                                                        context->GetDexCache(),
1048731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                                                        context->GetClassLoader());
1049d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (klass == NULL) {
1050d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK(self->IsExceptionPending());
1051d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->ClearException();
1052d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
1053d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes}
1054d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
1055d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesvoid Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file, TimingLogger& timings) {
1056d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1057d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
1058d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
1059d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // Strings are easy in that they always are simply resolved to literals in the same file
1060d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (image_ && image_classes_ == NULL) {
1061d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // TODO: Add support for loading strings referenced by image_classes_
1062d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // See also Compiler::CanAssumeTypeIsPresentInDexCache.
1063d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    for (size_t string_idx = 0; string_idx < dex_cache->NumStrings(); string_idx++) {
1064d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      class_linker->ResolveString(dex_file, string_idx, dex_cache);
106520cfffabdc9e02b2df798bc4e6b6035d14bf4e36Brian Carlstrom    }
1066ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes    timings.AddSplit("Resolve " + dex_file.GetLocation() + " Strings");
10679ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
1068d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
1069731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  Context context(class_linker, class_loader, this, dex_cache, &dex_file);
10705523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_cache->NumResolvedTypes(), ResolveType, thread_count_);
1071ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes  timings.AddSplit("Resolve " + dex_file.GetLocation() + " Types");
1072d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
10735523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods, thread_count_);
1074ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes  timings.AddSplit("Resolve " + dex_file.GetLocation() + " MethodsAndFields");
10759ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
10769ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
1077ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::Verify(const ClassLoader* class_loader,
1078ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                      const std::vector<const DexFile*>& dex_files) {
1079ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
1080ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
108198eacac683b78e60799323e8c7d59e7214808639jeffhao    CHECK(dex_file != NULL);
108298eacac683b78e60799323e8c7d59e7214808639jeffhao    VerifyDexFile(class_loader, *dex_file);
108398eacac683b78e60799323e8c7d59e7214808639jeffhao  }
108498eacac683b78e60799323e8c7d59e7214808639jeffhao}
108598eacac683b78e60799323e8c7d59e7214808639jeffhao
1086d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstatic void VerifyClass(Context* context, size_t class_def_index) {
1087731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  const DexFile::ClassDef& class_def = context->GetDexFile()->GetClassDef(class_def_index);
1088731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  const char* descriptor = context->GetDexFile()->GetClassDescriptor(class_def);
1089731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  Class* klass = context->GetClassLinker()->FindClass(descriptor, context->GetClassLoader());
1090d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (klass == NULL) {
1091d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread* self = Thread::Current();
1092d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK(self->IsExceptionPending());
1093d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    self->ClearException();
1094f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao
1095f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao    /*
1096f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao     * At compile time, we can still structurally verify the class even if FindClass fails.
1097f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao     * This is to ensure the class is structurally sound for compilation. An unsound class
1098f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao     * will be rejected by the verifier and later skipped during compilation in the compiler.
1099f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao     */
1100f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao    std::string error_msg;
1101731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    if (!verifier::DexVerifier::VerifyClass(context->GetDexFile(), context->GetDexCache(),
1102731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom        context->GetClassLoader(), class_def_index, error_msg)) {
1103731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom      const DexFile::ClassDef& class_def = context->GetDexFile()->GetClassDef(class_def_index);
1104f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao      LOG(ERROR) << "Verification failed on class "
1105731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                 << PrettyDescriptor(context->GetDexFile()->GetClassDescriptor(class_def))
1106f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao                 << " because: " << error_msg;
1107f56197c5519395fcf8226a7148cc87367e0a7ad4jeffhao    }
1108d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return;
1109d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
1110d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  CHECK(klass->IsResolved()) << PrettyClass(klass);
1111731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  context->GetClassLinker()->VerifyClass(klass);
1112d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
1113d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (klass->IsErroneous()) {
1114d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
1115d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK(Thread::Current()->IsExceptionPending());
1116d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->ClearException();
11171ac29447d6053b142f257330d6e237660076911ejeffhao    art::Compiler::ClassReference ref(context->GetDexFile(), class_def_index);
11181ac29447d6053b142f257330d6e237660076911ejeffhao    if (!verifier::DexVerifier::IsClassRejected(ref)) {
11191ac29447d6053b142f257330d6e237660076911ejeffhao      // If the erroneous class wasn't rejected by the verifier, it was a soft error. We want
11201ac29447d6053b142f257330d6e237660076911ejeffhao      // to try verification again at run-time, so move back into the resolved state.
11211ac29447d6053b142f257330d6e237660076911ejeffhao      klass->SetStatus(Class::kStatusResolved);
11221ac29447d6053b142f257330d6e237660076911ejeffhao    }
1123d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
1124d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
11251ac29447d6053b142f257330d6e237660076911ejeffhao  CHECK(klass->IsVerified() || klass->IsResolved() || klass->IsErroneous()) << PrettyClass(klass);
1126d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
1127d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes}
1128d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
112998eacac683b78e60799323e8c7d59e7214808639jeffhaovoid Compiler::VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
1130b4df5146854c42bf03c4ca02f441b6db73bfde0cjeffhao  dex_file.ChangePermissions(PROT_READ | PROT_WRITE);
1131d9cdfe91a4812a86d90a139569eac18e2b6de3fbElliott Hughes
1132731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1133731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  Context context(class_linker, class_loader, this, class_linker->FindDexCache(dex_file), &dex_file);
11345523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_file.NumClassDefs(), VerifyClass, thread_count_);
1135d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
1136b4df5146854c42bf03c4ca02f441b6db73bfde0cjeffhao  dex_file.ChangePermissions(PROT_READ);
1137a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom}
1138a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom
1139ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader,
1140ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                              const std::vector<const DexFile*>& dex_files) {
1141ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
1142ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
1143a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    CHECK(dex_file != NULL);
1144a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    InitializeClassesWithoutClinit(class_loader, *dex_file);
1145a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom  }
1146a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom}
1147a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom
1148a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstromvoid Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, const DexFile& dex_file) {
1149a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1150ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
1151ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
1152a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    const char* descriptor = dex_file.GetClassDescriptor(class_def);
1153a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    Class* klass = class_linker->FindClass(descriptor, class_loader);
115427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    if (klass != NULL) {
11551ac29447d6053b142f257330d6e237660076911ejeffhao      if (klass->IsVerified()) {
11561ac29447d6053b142f257330d6e237660076911ejeffhao        // Only try to initialize classes that were successfully verified.
11571ac29447d6053b142f257330d6e237660076911ejeffhao        class_linker->EnsureInitialized(klass, false);
11581ac29447d6053b142f257330d6e237660076911ejeffhao      }
11590755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      // record the final class status if necessary
11600755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      Class::Status status = klass->GetStatus();
11610755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      ClassReference ref(&dex_file, class_def_index);
1162c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      MutexLock mu(compiled_classes_lock_);
11630755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      CompiledClass* compiled_class = GetCompiledClass(ref);
11640755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      if (compiled_class == NULL) {
11650755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom        compiled_class = new CompiledClass(status);
11660755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom        compiled_classes_[ref] = compiled_class;
11670755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      } else {
11680755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom        DCHECK_EQ(status, compiled_class->GetStatus());
11690755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      }
117027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    }
117127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    // clear any class not found or verification exceptions
117227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    Thread::Current()->ClearException();
1173ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  }
1174ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom
1175ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
1176ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
1177ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom    Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
117827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    if (klass == NULL) {
117927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      Thread::Current()->ClearException();
118027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    } else if (klass->IsInitialized()) {
1181ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom      dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
1182ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom    }
118398eacac683b78e60799323e8c7d59e7214808639jeffhao  }
118498eacac683b78e60799323e8c7d59e7214808639jeffhao}
118598eacac683b78e60799323e8c7d59e7214808639jeffhao
1186ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::Compile(const ClassLoader* class_loader,
1187ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       const std::vector<const DexFile*>& dex_files) {
1188ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
1189ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
119083db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom    CHECK(dex_file != NULL);
119183db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom    CompileDexFile(class_loader, *dex_file);
119283db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom  }
119383db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom}
119483db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom
1195c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughesvoid Compiler::CompileClass(Context* context, size_t class_def_index) {
1196731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  const ClassLoader* class_loader = context->GetClassLoader();
1197731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  const DexFile& dex_file = *context->GetDexFile();
1198c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
11997f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien#if defined(ART_USE_LLVM_COMPILER)
12007f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien  // TODO: Remove this.  We should not lock the compiler_lock_ in CompileClass()
1201c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  // However, without this mutex lock, we will get segmentation fault before
1202c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  // LLVM becomes multithreaded.
1203c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  Compiler* cmplr = context->GetCompiler();
1204c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  CompilerMutexLockFn f =
1205c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao      FindFunction<CompilerMutexLockFn>(MakeCompilerSoName(cmplr->GetInstructionSet()),
1206c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao                                        cmplr->compiler_library_,
1207c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao                                        "compilerLLVMMutexLock");
1208c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  UniquePtr<MutexLock> GUARD((*f)(*cmplr));
12097f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien#endif
12107f76761d8705b7aa5b1fdd2fc1ebb80250992f4cLogan Chien
12115ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  if (SkipClass(class_loader, dex_file, class_def)) {
12125ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    return;
12135ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  }
1214d1224c79631bd1801b067a0f212b91afa961a362jeffhao  ClassReference ref(&dex_file, class_def_index);
1215d1224c79631bd1801b067a0f212b91afa961a362jeffhao  // Skip compiling classes with generic verifier failures since they will still fail at runtime
1216d1224c79631bd1801b067a0f212b91afa961a362jeffhao  if (verifier::DexVerifier::IsClassRejected(ref)) {
1217d1224c79631bd1801b067a0f212b91afa961a362jeffhao    return;
1218d1224c79631bd1801b067a0f212b91afa961a362jeffhao  }
12190571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const byte* class_data = dex_file.GetClassData(class_def);
12200571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (class_data == NULL) {
12210571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    // empty class, probably a marker interface
12220571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    return;
12230571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
12240571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  ClassDataItemIterator it(dex_file, class_data);
12250571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Skip fields
12260571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextStaticField()) {
12270571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
12280571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
12290571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextInstanceField()) {
12300571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
12310571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
12320571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Compile direct methods
12330571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextDirectMethod()) {
1234731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    context->GetCompiler()->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
1235731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                                          it.GetMemberIndex(), class_loader, dex_file);
12360571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
12379ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
12380571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Compile virtual methods
12390571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextVirtualMethod()) {
1240731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom    context->GetCompiler()->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
1241731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom                                          it.GetMemberIndex(), class_loader, dex_file);
12420571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
12439ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
12440571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  DCHECK(!it.HasNext());
12459ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
12469ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
1247c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughesvoid Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
1248731b2abfccd8704d129e3b8e46a086660161fef3Brian Carlstrom  Context context(NULL, class_loader, this, NULL, &dex_file);
12495523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_file.NumClassDefs(), Compiler::CompileClass, thread_count_);
1250c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes}
1251c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes
1252a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogersvoid Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
1253a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers                             uint32_t method_idx, const ClassLoader* class_loader,
1254a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers                             const DexFile& dex_file) {
1255f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes  CompiledMethod* compiled_method = NULL;
1256bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  uint64_t start_ns = NanoTime();
12574dd96f56909ec35c83a3d468b0e47769988c1a1dLogan Chien
1258169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  if ((access_flags & kAccNative) != 0) {
125946f060a53fffc14333096f0a48f95730ee4768eeElliott Hughes    compiled_method = (*jni_compiler_)(*this, access_flags, method_idx, class_loader, dex_file);
12603320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    CHECK(compiled_method != NULL);
1261169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  } else if ((access_flags & kAccAbstract) != 0) {
12622cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom  } else {
1263b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    compiled_method = (*compiler_)(*this, code_item, access_flags, method_idx, class_loader,
1264b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes                                   dex_file);
1265bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes    CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
1266bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  }
12673bb17a644e2945c3913cfbde245d2f520d62a3ffIan Rogers  uint64_t duration_ns = NanoTime() - start_ns;
12685abfa3ea35781464df8fae60aaf03f48a295e965buzbee  if (duration_ns > MsToNs(100)) {
1269bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes    LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
12703bb17a644e2945c3913cfbde245d2f520d62a3ffIan Rogers                 << " took " << PrettyDuration(duration_ns);
1271f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes  }
1272f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes
1273f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes  if (compiled_method != NULL) {
12740571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    MethodReference ref(&dex_file, method_idx);
12750755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom    CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file);
1276c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_methods_lock_);
12770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    compiled_methods_[ref] = compiled_method;
12780755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom    DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file);
12792cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom  }
12809baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom
128145619fcc01fb6db1ac9481a91608eb46f90829e4Ian Rogers  uint32_t shorty_len;
128245619fcc01fb6db1ac9481a91608eb46f90829e4Ian Rogers  const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx), &shorty_len);
1283169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  bool is_static = (access_flags & kAccStatic) != 0;
12840571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
12850571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (compiled_invoke_stub == NULL) {
1286c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao    compiled_invoke_stub = (*create_invoke_stub_)(*this, is_static, shorty, shorty_len);
12870571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    CHECK(compiled_invoke_stub != NULL);
12880571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
12893320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
12900571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
12910571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers}
129228ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers
12930571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersstatic std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
12940571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  std::string key(shorty);
12950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (is_static) {
1296bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes    key += "$";  // Must not be a shorty type character.
12970571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
12980571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  return key;
12993320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
13003320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
13010571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersconst CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
1302c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_invoke_stubs_lock_);
1303955724179c6c739524f610023287f56b24dc31deElliott Hughes  const std::string key(MakeInvokeStubKey(is_static, shorty));
13040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
13050571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (it == compiled_invoke_stubs_.end()) {
13063320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    return NULL;
13070571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  } else {
13080571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    DCHECK(it->second != NULL);
13090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    return it->second;
13103320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
13113320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
13123320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
13130571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersvoid Compiler::InsertInvokeStub(bool is_static, const char* shorty,
13140571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers                                const CompiledInvokeStub* compiled_invoke_stub) {
1315c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_invoke_stubs_lock_);
1316955724179c6c739524f610023287f56b24dc31deElliott Hughes  std::string key(MakeInvokeStubKey(is_static, shorty));
13170571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  compiled_invoke_stubs_[key] = compiled_invoke_stub;
13180571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers}
13190571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers
13200755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromCompiledClass* Compiler::GetCompiledClass(ClassReference ref) const {
1321c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_classes_lock_);
13220755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  ClassTable::const_iterator it = compiled_classes_.find(ref);
13230755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  if (it == compiled_classes_.end()) {
13240755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom    return NULL;
13250755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  }
13260755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  CHECK(it->second != NULL);
13270755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  return it->second;
13280755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom}
13290755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
13300571d357843c53e042f370f5f2c2e9aa3fe803a9Ian RogersCompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
1331c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_methods_lock_);
13320571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  MethodTable::const_iterator it = compiled_methods_.find(ref);
13330571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (it == compiled_methods_.end()) {
13343320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    return NULL;
13352c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  }
13363320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  CHECK(it->second != NULL);
13373320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  return it->second;
13389ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
13399ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
1340e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstromvoid Compiler::SetGcMaps(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files) {
1341e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
1342e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const DexFile* dex_file = dex_files[i];
1343e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    CHECK(dex_file != NULL);
1344e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    SetGcMapsDexFile(class_loader, *dex_file);
1345e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1346e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom}
1347e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
1348e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstromvoid Compiler::SetGcMapsDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
1349e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1350e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
1351e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
1352e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
1353e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const char* descriptor = dex_file.GetClassDescriptor(class_def);
1354e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    Class* klass = class_linker->FindClass(descriptor, class_loader);
1355e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    if (klass == NULL || !klass->IsVerified()) {
1356e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      Thread::Current()->ClearException();
1357e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      continue;
1358e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1359e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const byte* class_data = dex_file.GetClassData(class_def);
1360e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    if (class_data == NULL) {
1361e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      // empty class such as a marker interface
1362e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      continue;
1363e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1364e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    ClassDataItemIterator it(dex_file, class_data);
1365e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextStaticField()) {
1366e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
1367e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1368e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextInstanceField()) {
1369e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
1370e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1371e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextDirectMethod()) {
1372e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1373e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                                                   class_loader, true);
1374e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      SetGcMapsMethod(dex_file, method);
1375e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
1376e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1377e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextVirtualMethod()) {
1378e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1379e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                                                   class_loader, false);
1380e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      SetGcMapsMethod(dex_file, method);
1381e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
1382e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
1383e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1384e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom}
1385e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
1386e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstromvoid Compiler::SetGcMapsMethod(const DexFile& dex_file, Method* method) {
1387e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  if (method == NULL) {
1388e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    Thread::Current()->ClearException();
1389e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    return;
1390e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1391e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  uint16_t method_idx = method->GetDexMethodIndex();
1392e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  MethodReference ref(&dex_file, method_idx);
1393e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  CompiledMethod* compiled_method = GetCompiledMethod(ref);
1394e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  if (compiled_method == NULL) {
1395e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    return;
1396e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1397e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  const std::vector<uint8_t>* gc_map = verifier::DexVerifier::GetGcMap(ref);
1398e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  if (gc_map == NULL) {
1399e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    return;
1400e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
1401e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  compiled_method->SetGcMap(*gc_map);
1402e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom}
1403e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
14048b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien#if defined(ART_USE_LLVM_COMPILER)
14058b977d38483aaa08abcbdaa5fa888076c1142169Logan Chienvoid Compiler::SetElfFileName(std::string const& filename) {
1406c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  elf_filename_ = filename;
14078b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien}
14088b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien
14098b977d38483aaa08abcbdaa5fa888076c1142169Logan Chienvoid Compiler::SetBitcodeFileName(std::string const& filename) {
1410c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  bitcode_filename_ = filename;
1411c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao}
1412c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liaostd::string const& Compiler::GetElfFileName() {
1413c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  return elf_filename_;
1414c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao}
1415c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liaostd::string const& Compiler::GetBitcodeFileName() {
1416c4c9881e5d22432f3f1a30eeec5aa109dfc08a7dShih-wei Liao  return bitcode_filename_;
14178b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien}
14188b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien#endif
14198b977d38483aaa08abcbdaa5fa888076c1142169Logan Chien
14209ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}  // namespace art
1421