compiler_driver.cc revision 5523ee070b005576c6f889415205d49ea77cf243
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
169ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
179ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom#include "compiler.h"
189ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
19d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes#include <vector>
20d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
2127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <sys/mman.h>
22d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes#include <unistd.h>
2327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
242cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom#include "assembler.h"
259ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom#include "class_linker.h"
261f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "class_loader.h"
279ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom#include "dex_cache.h"
28e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom#include "dex_verifier.h"
292cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom#include "jni_compiler.h"
309baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom#include "jni_internal.h"
313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "oat_file.h"
326d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
331f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h"
343320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "stl_util.h"
35601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes#include "timing_logger.h"
369ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
379ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstromnamespace art {
389ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
3911d1b0c31ddd710d26068da8e0e4621002205b4bElliott HughesCompiledMethod* oatCompileMethod(const Compiler& compiler, const DexFile::CodeItem* code_item,
4011d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes                                 uint32_t access_flags, uint32_t method_idx,
4111d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes                                 const ClassLoader* class_loader,
4211d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes                                 const DexFile& dex_file, InstructionSet);
4311d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
44c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liaonamespace arm {
45bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers  ByteArray* CreateAbstractMethodErrorStub();
460571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty);
471cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type);
488add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes  ByteArray* CreateJniDlsymLookupStub();
49c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liao}
50c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liaonamespace x86 {
51bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers  ByteArray* CreateAbstractMethodErrorStub();
520571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty);
531cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type);
548add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes  ByteArray* CreateJniDlsymLookupStub();
55e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
56e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
575523ee070b005576c6f889415205d49ea77cf243Elliott HughesCompiler::Compiler(InstructionSet instruction_set, bool image, size_t thread_count,
58ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                   const std::set<std::string>* image_classes)
59aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    : instruction_set_(instruction_set),
60aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      jni_compiler_(instruction_set),
61c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      compiled_classes_lock_("compiled classes lock"),
62c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      compiled_methods_lock_("compiled method lock"),
63c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      compiled_invoke_stubs_lock_("compiled invoke stubs lock"),
64aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      image_(image),
655523ee070b005576c6f889415205d49ea77cf243Elliott Hughes      thread_count_(thread_count),
664dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes      image_classes_(image_classes) {
6725c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom  CHECK(!Runtime::Current()->IsStarted());
68ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!image_) {
69ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    CHECK(image_classes_ == NULL);
70ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
71c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liao}
72c486c11a1c71ca9c118d57152427b741229cda49Shih-wei Liao
733320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromCompiler::~Compiler() {
74c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  {
75c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_classes_lock_);
76c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    STLDeleteValues(&compiled_classes_);
77c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  }
78c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  {
79c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_methods_lock_);
80c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    STLDeleteValues(&compiled_methods_);
81c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  }
82c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  {
83c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_invoke_stubs_lock_);
84c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    STLDeleteValues(&compiled_invoke_stubs_);
85bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  }
863320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
873320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
881cb0a1dfc32531c79a968aeac26ccb5525862497Ian RogersByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set,
891cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers                                          Runtime::TrampolineType type) {
90ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  if (instruction_set == kX86) {
911cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return x86::X86CreateResolutionTrampoline(type);
92ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  } else {
93ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    CHECK(instruction_set == kArm || instruction_set == kThumb2);
94ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    // Generates resolution stub using ARM instruction set
951cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers    return arm::ArmCreateResolutionTrampoline(type);
96ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  }
97ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
98ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
998add92dcf59568c72c17e9a979948b1a7a0b1264Elliott HughesByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) {
100169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  switch (instruction_set) {
101169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    case kArm:
102169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    case kThumb2:
1038add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes      return arm::CreateJniDlsymLookupStub();
104169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    case kX86:
1058add92dcf59568c72c17e9a979948b1a7a0b1264Elliott Hughes      return x86::CreateJniDlsymLookupStub();
106169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    default:
107ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      LOG(FATAL) << "Unknown InstructionSet: " << static_cast<int>(instruction_set);
108169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers      return NULL;
109169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  }
110169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers}
111169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers
112ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan RogersByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) {
113ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  if (instruction_set == kX86) {
114ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    return x86::CreateAbstractMethodErrorStub();
115ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  } else {
116ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    CHECK(instruction_set == kArm || instruction_set == kThumb2);
117ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    // Generates resolution stub using ARM instruction set
118ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    return arm::CreateAbstractMethodErrorStub();
119ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  }
120ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
121ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
122254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilsonvoid Compiler::CompileAll(const ClassLoader* class_loader,
123ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                          const std::vector<const DexFile*>& dex_files) {
12425c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom  DCHECK(!Runtime::Current()->IsStarted());
125ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
126601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  TimingLogger timings("compiler");
127601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
128601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  PreCompile(class_loader, dex_files, timings);
129601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
130ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Compile(class_loader, dex_files);
131601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("Compile");
132601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
133ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  PostCompile(class_loader, dex_files);
134601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("PostCompile");
135601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
136601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  if (timings.GetTotalNs() > MsToNs(1000)) {
137601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes    timings.Dump();
138601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  }
1398a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom}
1408a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom
1413320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstromvoid Compiler::CompileOne(const Method* method) {
14225c3325bf95036bf325fc7cb21b4fd6d40282857Brian Carlstrom  DCHECK(!Runtime::Current()->IsStarted());
143ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
1448a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom  const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
145ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
1460571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Find the dex_file
1470571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
1480571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
149ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  std::vector<const DexFile*> dex_files;
150ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  dex_files.push_back(&dex_file);
151ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
152601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  TimingLogger timings("CompileOne");
153601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  PreCompile(class_loader, dex_files, timings);
154ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
1550571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  uint32_t method_idx = method->GetDexMethodIndex();
156a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers  const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
157a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers  CompileMethod(code_item, method->GetAccessFlags(), method_idx, class_loader, dex_file);
158ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
159ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  PostCompile(class_loader, dex_files);
1609ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
1619ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
162ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::Resolve(const ClassLoader* class_loader,
163d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                       const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
164ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
165ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
1669ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom    CHECK(dex_file != NULL);
167d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    ResolveDexFile(class_loader, *dex_file, timings);
1689ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
1699ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
1709ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
171ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::PreCompile(const ClassLoader* class_loader,
172601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes                          const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
173d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Resolve(class_loader, dex_files, timings);
174601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
175ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Verify(class_loader, dex_files);
176601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("PreCompile.Verify");
177601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes
178ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  InitializeClassesWithoutClinit(class_loader, dex_files);
179601a12302407d8199503d2cc6cc0829d5996696dElliott Hughes  timings.AddSplit("PreCompile.InitializeClassesWithoutClinit");
180ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
181ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
182ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::PostCompile(const ClassLoader* class_loader,
183ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                           const std::vector<const DexFile*>& dex_files) {
184e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  SetGcMaps(class_loader, dex_files);
185ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  SetCodeAndDirectMethods(dex_files);
186ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
187ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
188ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool Compiler::IsImageClass(const std::string& descriptor) const {
189ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (image_classes_ == NULL) {
190ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return true;
191ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
192ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  return image_classes_->find(descriptor) != image_classes_->end();
193ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
194ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
1956d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogersbool Compiler::CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache,
1966d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers                                                uint32_t type_idx) const {
1976d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  if (!IsImage()) {
1986d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    return false;
1996d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  }
2006d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  Class* resolved_class = dex_cache->GetResolvedTypes()->Get(type_idx);
2016d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  if (resolved_class == NULL) {
2026d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    return false;
2036d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  }
2046d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  return IsImageClass(ClassHelper(resolved_class).GetDescriptor());
2056d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers}
2066d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers
2075ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// Return true if the class should be skipped during compilation. We
2085ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// never skip classes in the boot class loader. However, if we have a
2095ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// non-boot class loader and we can resolve the class in the boot
2105ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// class loader, we do skip the class. This happens if an app bundles
2115ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// classes found in the boot classpath. Since at runtime we will
2125ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// select the class from the boot classpath, do not attempt to resolve
2135ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom// or compile it now.
2145ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstromstatic bool SkipClass(const ClassLoader* class_loader,
2155ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom                      const DexFile& dex_file,
2165ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom                      const DexFile::ClassDef& class_def) {
2175ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  if (class_loader == NULL) {
2185ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    return false;
2195ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  }
2205ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  const char* descriptor = dex_file.GetClassDescriptor(class_def);
2215ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
2225ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  Class* klass = class_linker->FindClass(descriptor, NULL);
2235ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  if (klass == NULL) {
2245ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    Thread* self = Thread::Current();
2255ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    CHECK(self->IsExceptionPending());
2265ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    self->ClearException();
2275ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    return false;
2285ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  }
2295ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  return true;
2305ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom}
2315ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom
232d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstruct Context {
233d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassLinker* class_linker;
234d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const ClassLoader* class_loader;
235c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  Compiler* compiler;
236d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DexCache* dex_cache;
237d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile* dex_file;
238d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes};
2399ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
240d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughestypedef void Callback(Context* context, size_t index);
241d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
242d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesclass WorkerThread {
243d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes public:
244d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  WorkerThread(Context* context, size_t begin, size_t end, Callback callback, size_t stripe)
245d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      : context_(context), begin_(begin), end_(end), callback_(callback), stripe_(stripe) {
246d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK_PTHREAD_CALL(pthread_create, (&pthread_, NULL, &Init, this), "compiler worker thread");
247d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
248d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
249d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ~WorkerThread() {
250d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK_PTHREAD_CALL(pthread_join, (pthread_, NULL), "compiler worker shutdown");
251d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
252d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
253d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes private:
254d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  static void* Init(void* arg) {
255d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    WorkerThread* worker = reinterpret_cast<WorkerThread*>(arg);
256d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Runtime* runtime = Runtime::Current();
257d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    runtime->AttachCurrentThread("Compiler Worker", true);
258d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->SetState(Thread::kRunnable);
259d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    worker->Run();
260d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->SetState(Thread::kNative);
261d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    runtime->DetachCurrentThread();
262d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return NULL;
263d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
264d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
265d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  void Run() {
266d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    for (size_t i = begin_; i < end_; i += stripe_) {
267d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      callback_(context_, i);
268aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
2699ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
2709ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
271d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  pthread_t pthread_;
272d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
273d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Context* context_;
274d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  size_t begin_;
275d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  size_t end_;
276d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Callback* callback_;
277d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  size_t stripe_;
278d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes};
279d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
2805523ee070b005576c6f889415205d49ea77cf243Elliott Hughesvoid ForAll(Context* context, size_t begin, size_t end, Callback callback, size_t thread_count) {
28181d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  std::vector<WorkerThread*> threads;
282845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom
28381d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  for (size_t i = 0; i < thread_count; ++i) {
28481d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes    threads.push_back(new WorkerThread(context, begin + i, end, callback, thread_count));
285d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
286d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
28781d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  // Switch to kVmWait while we're blocked waiting for the other threads to finish.
28881d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
28981d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes  STLDeleteElements(&threads);
29081d9151c884a548ea2ff843a49704e1aaf9fe64fElliott Hughes}
291d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
292d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstatic void ResolveClassFieldsAndMethods(Context* context, size_t class_def_index) {
293d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile& dex_file = *context->dex_file;
294d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
295845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // Method and Field are the worst. We can't resolve without either
296845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // context from the code use (to disambiguate virtual vs direct
297845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // method and instance vs static field) or from class
298845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // definitions. While the compiler will resolve what it can as it
299845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // needs it, here we try to resolve fields and methods used in class
300845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // definitions, since many of them many never be referenced by
301845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom  // generated code.
302d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
303d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (SkipClass(context->class_loader, dex_file, class_def)) {
304d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return;
305d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
306845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom
307d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // Note the class_data pointer advances through the headers,
308d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // static fields, instance fields, direct methods, and virtual
309d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // methods.
310d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const byte* class_data = dex_file.GetClassData(class_def);
311d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (class_data == NULL) {
312d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // empty class such as a marker interface
313d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return;
314d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
315d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Thread* self = Thread::Current();
316d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassLinker* class_linker = context->class_linker;
317d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
318d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassDataItemIterator it(dex_file, class_data);
319d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextStaticField()) {
320d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
321d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                                              context->class_loader, true);
322d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (field == NULL) {
323d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
324d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
3250571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    }
326d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
327d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
328d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextInstanceField()) {
329d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
330d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                                              context->class_loader, false);
331d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (field == NULL) {
332d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
333d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
33420cfffabdc9e02b2df798bc4e6b6035d14bf4e36Brian Carlstrom    }
335d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
336d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
337d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextDirectMethod()) {
338d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
339d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                                                 context->class_loader, true);
340d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (method == NULL) {
341d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
342d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
343845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom    }
344d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
345d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
346d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  while (it.HasNextVirtualMethod()) {
347d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
348d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes                                                 context->class_loader, false);
349d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    if (method == NULL) {
350d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      CHECK(self->IsExceptionPending());
351d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      self->ClearException();
352845490bda68f7d025ea7f45775c847d2932e00dcBrian Carlstrom    }
353d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    it.Next();
354d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
355d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DCHECK(!it.HasNext());
356d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes}
357d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
358d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstatic void ResolveType(Context* context, size_t type_idx) {
359d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // Class derived values are more complicated, they require the linker and loader.
360d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Thread* self = Thread::Current();
361d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassLinker* class_linker = context->class_linker;
362d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile& dex_file = *context->dex_file;
363d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Class* klass = class_linker->ResolveType(dex_file, type_idx, context->dex_cache, context->class_loader);
364d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (klass == NULL) {
365d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK(self->IsExceptionPending());
366d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->ClearException();
367d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
368d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes}
369d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
370d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesvoid Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file, TimingLogger& timings) {
371d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
372d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
373d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
374d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  // Strings are easy in that they always are simply resolved to literals in the same file
375d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (image_ && image_classes_ == NULL) {
376d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // TODO: Add support for loading strings referenced by image_classes_
377d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // See also Compiler::CanAssumeTypeIsPresentInDexCache.
378d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    for (size_t string_idx = 0; string_idx < dex_cache->NumStrings(); string_idx++) {
379d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes      class_linker->ResolveString(dex_file, string_idx, dex_cache);
38020cfffabdc9e02b2df798bc4e6b6035d14bf4e36Brian Carlstrom    }
381ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes    timings.AddSplit("Resolve " + dex_file.GetLocation() + " Strings");
3829ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
383d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
384d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Context context;
385d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.class_linker = class_linker;
386d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.class_loader = class_loader;
387d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.dex_cache = dex_cache;
388d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.dex_file = &dex_file;
389d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
3905523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_cache->NumResolvedTypes(), ResolveType, thread_count_);
391ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes  timings.AddSplit("Resolve " + dex_file.GetLocation() + " Types");
392d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
3935523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods, thread_count_);
394ff7380681c50129ff689a11ac0f49512b4be7295Elliott Hughes  timings.AddSplit("Resolve " + dex_file.GetLocation() + " MethodsAndFields");
3959ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
3969ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
397ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::Verify(const ClassLoader* class_loader,
398ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                      const std::vector<const DexFile*>& dex_files) {
399ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
400ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
40198eacac683b78e60799323e8c7d59e7214808639jeffhao    CHECK(dex_file != NULL);
40298eacac683b78e60799323e8c7d59e7214808639jeffhao    VerifyDexFile(class_loader, *dex_file);
40398eacac683b78e60799323e8c7d59e7214808639jeffhao  }
40498eacac683b78e60799323e8c7d59e7214808639jeffhao}
40598eacac683b78e60799323e8c7d59e7214808639jeffhao
406d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughesstatic void VerifyClass(Context* context, size_t class_def_index) {
407d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const DexFile::ClassDef& class_def = context->dex_file->GetClassDef(class_def_index);
408d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  const char* descriptor = context->dex_file->GetClassDescriptor(class_def);
409d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Class* klass = context->class_linker->FindClass(descriptor, context->class_loader);
410d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (klass == NULL) {
411d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread* self = Thread::Current();
412d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK(self->IsExceptionPending());
413d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    self->ClearException();
414d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    return;
415d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
416d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  CHECK(klass->IsResolved()) << PrettyClass(klass);
417d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context->class_linker->VerifyClass(klass);
418d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
419d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  if (klass->IsErroneous()) {
420d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
421d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    CHECK(Thread::Current()->IsExceptionPending());
422d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    Thread::Current()->ClearException();
423d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    // We want to try verification again at run-time, so move back into the resolved state.
424d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes    klass->SetStatus(Class::kStatusResolved);
425d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  }
426d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
427d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  CHECK(klass->IsVerified() || klass->IsResolved()) << PrettyClass(klass);
428d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
429d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes}
430d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
43198eacac683b78e60799323e8c7d59e7214808639jeffhaovoid Compiler::VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
432b4df5146854c42bf03c4ca02f441b6db73bfde0cjeffhao  dex_file.ChangePermissions(PROT_READ | PROT_WRITE);
433d9cdfe91a4812a86d90a139569eac18e2b6de3fbElliott Hughes
434d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  Context context;
435d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.class_linker = Runtime::Current()->GetClassLinker();
436d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.class_loader = class_loader;
437d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes  context.dex_file = &dex_file;
4385523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_file.NumClassDefs(), VerifyClass, thread_count_);
439d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes
440b4df5146854c42bf03c4ca02f441b6db73bfde0cjeffhao  dex_file.ChangePermissions(PROT_READ);
441a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom}
442a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom
443ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader,
444ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                              const std::vector<const DexFile*>& dex_files) {
445ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
446ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
447a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    CHECK(dex_file != NULL);
448a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    InitializeClassesWithoutClinit(class_loader, *dex_file);
449a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom  }
450a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom}
451a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom
452a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstromvoid Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, const DexFile& dex_file) {
453a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
454ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
455ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
456a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    const char* descriptor = dex_file.GetClassDescriptor(class_def);
457a5a97a2bc1dfed70869da34650a5a2a3a3a06ac4Brian Carlstrom    Class* klass = class_linker->FindClass(descriptor, class_loader);
45827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    if (klass != NULL) {
45927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      class_linker->EnsureInitialized(klass, false);
4600755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      // record the final class status if necessary
4610755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      Class::Status status = klass->GetStatus();
4620755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      ClassReference ref(&dex_file, class_def_index);
463c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes      MutexLock mu(compiled_classes_lock_);
4640755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      CompiledClass* compiled_class = GetCompiledClass(ref);
4650755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      if (compiled_class == NULL) {
4660755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom        compiled_class = new CompiledClass(status);
4670755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom        compiled_classes_[ref] = compiled_class;
4680755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      } else {
4690755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom        DCHECK_EQ(status, compiled_class->GetStatus());
4700755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom      }
47127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    }
47227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    // clear any class not found or verification exceptions
47327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    Thread::Current()->ClearException();
474ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  }
475ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom
476ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
477ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom  for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
478ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom    Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
47927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    if (klass == NULL) {
48027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      Thread::Current()->ClearException();
48127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    } else if (klass->IsInitialized()) {
482ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom      dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
483ffca45dbd7e152b8c2cda375d2742f798827698eBrian Carlstrom    }
48498eacac683b78e60799323e8c7d59e7214808639jeffhao  }
48598eacac683b78e60799323e8c7d59e7214808639jeffhao}
48698eacac683b78e60799323e8c7d59e7214808639jeffhao
487ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::Compile(const ClassLoader* class_loader,
488ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       const std::vector<const DexFile*>& dex_files) {
489ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
490ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
49183db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom    CHECK(dex_file != NULL);
49283db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom    CompileDexFile(class_loader, *dex_file);
49383db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom  }
49483db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom}
49583db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom
496c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughesvoid Compiler::CompileClass(Context* context, size_t class_def_index) {
497c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  const ClassLoader* class_loader = context->class_loader;
498c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  const DexFile& dex_file = *context->dex_file;
499c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
5005ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  if (SkipClass(class_loader, dex_file, class_def)) {
5015ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom    return;
5025ead0950c661761e90e04aefd6ea2205532ce874Brian Carlstrom  }
5030571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const byte* class_data = dex_file.GetClassData(class_def);
5040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (class_data == NULL) {
5050571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    // empty class, probably a marker interface
5060571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    return;
5070571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
5080571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  ClassDataItemIterator it(dex_file, class_data);
5090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Skip fields
5100571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextStaticField()) {
5110571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
5120571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
5130571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextInstanceField()) {
5140571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
5150571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
5160571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Compile direct methods
5170571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextDirectMethod()) {
518c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    context->compiler->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
519c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes                                     it.GetMemberIndex(), class_loader, dex_file);
5200571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
5219ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
5220571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  // Compile virtual methods
5230571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  while (it.HasNextVirtualMethod()) {
524c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    context->compiler->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
525c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes                                     it.GetMemberIndex(), class_loader, dex_file);
5260571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    it.Next();
5279ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  }
5280571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  DCHECK(!it.HasNext());
5299ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
5309ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
531c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughesvoid Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
532c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  Context context;
533c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  context.class_loader = class_loader;
534c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  context.compiler = this;
535c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  context.dex_file = &dex_file;
5365523ee070b005576c6f889415205d49ea77cf243Elliott Hughes  ForAll(&context, 0, dex_file.NumClassDefs(), Compiler::CompileClass, thread_count_);
537c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes}
538c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes
539a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogersvoid Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
540a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers                             uint32_t method_idx, const ClassLoader* class_loader,
541a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers                             const DexFile& dex_file) {
542f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes  CompiledMethod* compiled_method = NULL;
543bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  uint64_t start_ns = NanoTime();
544169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  if ((access_flags & kAccNative) != 0) {
545169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    compiled_method = jni_compiler_.Compile(access_flags, method_idx, class_loader, dex_file);
5463320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    CHECK(compiled_method != NULL);
547169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  } else if ((access_flags & kAccAbstract) != 0) {
5482cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom  } else {
549a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers    compiled_method = oatCompileMethod(*this, code_item, access_flags, method_idx, class_loader,
550a3760aad59f41bb0b1d46733165a2d7219ecca73Ian Rogers                                       dex_file, kThumb2);
551bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes    CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
552bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes  }
5533bb17a644e2945c3913cfbde245d2f520d62a3ffIan Rogers  uint64_t duration_ns = NanoTime() - start_ns;
5545abfa3ea35781464df8fae60aaf03f48a295e965buzbee  if (duration_ns > MsToNs(100)) {
555bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes    LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
5563bb17a644e2945c3913cfbde245d2f520d62a3ffIan Rogers                 << " took " << PrettyDuration(duration_ns);
557f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes  }
558f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes
559f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes  if (compiled_method != NULL) {
5600571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    MethodReference ref(&dex_file, method_idx);
5610755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom    CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file);
562c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes    MutexLock mu(compiled_methods_lock_);
5630571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    compiled_methods_[ref] = compiled_method;
5640755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom    DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file);
5652cc022b653e1e84eed2522254ec684bd097572b8Brian Carlstrom  }
5669baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom
5670571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
568169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  bool is_static = (access_flags & kAccStatic) != 0;
5690571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
5700571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (compiled_invoke_stub == NULL) {
5710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    if (instruction_set_ == kX86) {
57211d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes      compiled_invoke_stub = ::art::x86::X86CreateInvokeStub(is_static, shorty);
5730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    } else {
5740571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
5750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      // Generates invocation stub using ARM instruction set
57611d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes      compiled_invoke_stub = ::art::arm::ArmCreateInvokeStub(is_static, shorty);
5770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    }
5780571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    CHECK(compiled_invoke_stub != NULL);
5790571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
5803320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
5810571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
5820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers}
58328ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers
5840571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersstatic std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
5850571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  std::string key(shorty);
5860571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (is_static) {
587bb551fa68ffc57f679b8c914ac856666f0348b77Elliott Hughes    key += "$";  // Must not be a shorty type character.
5880571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  }
5890571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  return key;
5903320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
5913320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
5920571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersconst CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
593c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_invoke_stubs_lock_);
594955724179c6c739524f610023287f56b24dc31deElliott Hughes  const std::string key(MakeInvokeStubKey(is_static, shorty));
5950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
5960571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (it == compiled_invoke_stubs_.end()) {
5973320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    return NULL;
5980571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  } else {
5990571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    DCHECK(it->second != NULL);
6000571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    return it->second;
6013320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
6023320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
6033320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
6040571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogersvoid Compiler::InsertInvokeStub(bool is_static, const char* shorty,
6050571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers                                const CompiledInvokeStub* compiled_invoke_stub) {
606c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_invoke_stubs_lock_);
607955724179c6c739524f610023287f56b24dc31deElliott Hughes  std::string key(MakeInvokeStubKey(is_static, shorty));
6080571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  compiled_invoke_stubs_[key] = compiled_invoke_stub;
6090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers}
6100571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers
6110755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromCompiledClass* Compiler::GetCompiledClass(ClassReference ref) const {
612c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_classes_lock_);
6130755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  ClassTable::const_iterator it = compiled_classes_.find(ref);
6140755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  if (it == compiled_classes_.end()) {
6150755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom    return NULL;
6160755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  }
6170755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  CHECK(it->second != NULL);
6180755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom  return it->second;
6190755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom}
6200755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom
6210571d357843c53e042f370f5f2c2e9aa3fe803a9Ian RogersCompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
622c225caa9715eeaeff87f27d5b6a3e7d4f6b7efadElliott Hughes  MutexLock mu(compiled_methods_lock_);
6230571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  MethodTable::const_iterator it = compiled_methods_.find(ref);
6240571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  if (it == compiled_methods_.end()) {
6253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    return NULL;
6262c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  }
6273320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  CHECK(it->second != NULL);
6283320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  return it->second;
6299ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}
6309ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom
631e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstromvoid Compiler::SetGcMaps(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files) {
632e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
633e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const DexFile* dex_file = dex_files[i];
634e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    CHECK(dex_file != NULL);
635e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    SetGcMapsDexFile(class_loader, *dex_file);
636e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
637e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom}
638e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
639e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstromvoid Compiler::SetGcMapsDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
640e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
641e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
642e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
643e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
644e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const char* descriptor = dex_file.GetClassDescriptor(class_def);
645e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    Class* klass = class_linker->FindClass(descriptor, class_loader);
646e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    if (klass == NULL || !klass->IsVerified()) {
647e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      Thread::Current()->ClearException();
648e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      continue;
649e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
650e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const byte* class_data = dex_file.GetClassData(class_def);
651e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    if (class_data == NULL) {
652e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      // empty class such as a marker interface
653e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      continue;
654e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
655e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    ClassDataItemIterator it(dex_file, class_data);
656e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextStaticField()) {
657e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
658e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
659e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextInstanceField()) {
660e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
661e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
662e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextDirectMethod()) {
663e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
664e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                                                   class_loader, true);
665e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      SetGcMapsMethod(dex_file, method);
666e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
667e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
668e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    while (it.HasNextVirtualMethod()) {
669e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
670e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                                                   class_loader, false);
671e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      SetGcMapsMethod(dex_file, method);
672e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom      it.Next();
673e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    }
674e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
675e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom}
676e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
677e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstromvoid Compiler::SetGcMapsMethod(const DexFile& dex_file, Method* method) {
678e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  if (method == NULL) {
679e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    Thread::Current()->ClearException();
680e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    return;
681e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
682e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  uint16_t method_idx = method->GetDexMethodIndex();
683e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  MethodReference ref(&dex_file, method_idx);
684e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  CompiledMethod* compiled_method = GetCompiledMethod(ref);
685e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  if (compiled_method == NULL) {
686e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    return;
687e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
688e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  const std::vector<uint8_t>* gc_map = verifier::DexVerifier::GetGcMap(ref);
689e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  if (gc_map == NULL) {
690e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    return;
691e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  }
692e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom  compiled_method->SetGcMap(*gc_map);
693e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom}
694e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
695ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid Compiler::SetCodeAndDirectMethods(const std::vector<const DexFile*>& dex_files) {
696ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i != dex_files.size(); ++i) {
697ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const DexFile* dex_file = dex_files[i];
69883db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom    CHECK(dex_file != NULL);
6998a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstrom    SetCodeAndDirectMethodsDexFile(*dex_file);
70083db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom  }
70183db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom}
70283db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom
7038a48741b96ca9cc5835cac72ac133c4ca480930fBrian Carlstromvoid Compiler::SetCodeAndDirectMethodsDexFile(const DexFile& dex_file) {
704ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  Runtime* runtime = Runtime::Current();
705ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  ClassLinker* class_linker = runtime->GetClassLinker();
70683db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
7079cc262e2ad5cb507c21cc83b8dc954e9354a469cBrian Carlstrom  CodeAndDirectMethods* code_and_direct_methods = dex_cache->GetCodeAndDirectMethods();
7081caa2c205e51dda670207828f25451fb7623cea6Brian Carlstrom  for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
70983db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom    Method* method = dex_cache->GetResolvedMethod(i);
7103320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    if (method == NULL || method->IsDirect()) {
7111cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      Runtime::TrampolineType type = Runtime::GetTrampolineType(method);
7121cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      ByteArray* res_trampoline = runtime->GetResolutionStubArray(type);
7133320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom      code_and_direct_methods->SetResolvedDirectMethodTrampoline(i, res_trampoline);
7149cc262e2ad5cb507c21cc83b8dc954e9354a469cBrian Carlstrom    } else {
7159cc262e2ad5cb507c21cc83b8dc954e9354a469cBrian Carlstrom      // TODO: we currently leave the entry blank for resolved
7169cc262e2ad5cb507c21cc83b8dc954e9354a469cBrian Carlstrom      // non-direct methods.  we could put in an error stub.
71783db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom    }
71883db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom  }
71983db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom}
72083db7721aef15df6919c0ec072e087bef6041e2dBrian Carlstrom
7219ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom}  // namespace art
722