1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "compilers.h"
18
19 #include "dex/mir_graph.h"
20 #include "dex/quick/mir_to_lir.h"
21 #include "elf_writer_quick.h"
22 #include "mirror/art_method-inl.h"
23
24 namespace art {
25
26 extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver* driver);
27 extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver* driver);
28 extern "C" art::CompiledMethod* ArtQuickCompileMethod(art::CompilerDriver* driver,
29 const art::DexFile::CodeItem* code_item,
30 uint32_t access_flags,
31 art::InvokeType invoke_type,
32 uint16_t class_def_idx,
33 uint32_t method_idx,
34 jobject class_loader,
35 const art::DexFile& dex_file);
36
37 extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver* driver,
38 uint32_t access_flags, uint32_t method_idx,
39 const art::DexFile& dex_file);
40
41 // Hack for CFI CIE initialization
42 extern std::vector<uint8_t>* X86CFIInitialization(bool is_x86_64);
43
Init() const44 void QuickCompiler::Init() const {
45 ArtInitQuickCompilerContext(GetCompilerDriver());
46 }
47
UnInit() const48 void QuickCompiler::UnInit() const {
49 ArtUnInitQuickCompilerContext(GetCompilerDriver());
50 }
51
Compile(const DexFile::CodeItem * code_item,uint32_t access_flags,InvokeType invoke_type,uint16_t class_def_idx,uint32_t method_idx,jobject class_loader,const DexFile & dex_file) const52 CompiledMethod* QuickCompiler::Compile(const DexFile::CodeItem* code_item,
53 uint32_t access_flags,
54 InvokeType invoke_type,
55 uint16_t class_def_idx,
56 uint32_t method_idx,
57 jobject class_loader,
58 const DexFile& dex_file) const {
59 CompiledMethod* method = TryCompileWithSeaIR(code_item,
60 access_flags,
61 invoke_type,
62 class_def_idx,
63 method_idx,
64 class_loader,
65 dex_file);
66 if (method != nullptr) {
67 return method;
68 }
69
70 return ArtQuickCompileMethod(GetCompilerDriver(),
71 code_item,
72 access_flags,
73 invoke_type,
74 class_def_idx,
75 method_idx,
76 class_loader,
77 dex_file);
78 }
79
JniCompile(uint32_t access_flags,uint32_t method_idx,const DexFile & dex_file) const80 CompiledMethod* QuickCompiler::JniCompile(uint32_t access_flags,
81 uint32_t method_idx,
82 const DexFile& dex_file) const {
83 return ArtQuickJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
84 }
85
GetEntryPointOf(mirror::ArtMethod * method) const86 uintptr_t QuickCompiler::GetEntryPointOf(mirror::ArtMethod* method) const {
87 size_t pointer_size = InstructionSetPointerSize(GetCompilerDriver()->GetInstructionSet());
88 return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCodePtrSize(
89 pointer_size));
90 }
91
WriteElf(art::File * file,OatWriter * oat_writer,const std::vector<const art::DexFile * > & dex_files,const std::string & android_root,bool is_host) const92 bool QuickCompiler::WriteElf(art::File* file,
93 OatWriter* oat_writer,
94 const std::vector<const art::DexFile*>& dex_files,
95 const std::string& android_root,
96 bool is_host) const {
97 return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host,
98 *GetCompilerDriver());
99 }
100
GetCodeGenerator(CompilationUnit * cu,void * compilation_unit) const101 Backend* QuickCompiler::GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
102 Mir2Lir* mir_to_lir = nullptr;
103 switch (cu->instruction_set) {
104 case kThumb2:
105 mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
106 break;
107 case kArm64:
108 mir_to_lir = Arm64CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
109 break;
110 case kMips:
111 mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
112 break;
113 case kX86:
114 // Fall-through.
115 case kX86_64:
116 mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
117 break;
118 default:
119 LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
120 }
121
122 /* The number of compiler temporaries depends on backend so set it up now if possible */
123 if (mir_to_lir) {
124 size_t max_temps = mir_to_lir->GetMaxPossibleCompilerTemps();
125 bool set_max = cu->mir_graph->SetMaxAvailableNonSpecialCompilerTemps(max_temps);
126 CHECK(set_max);
127 }
128 return mir_to_lir;
129 }
130
GetCallFrameInformationInitialization(const CompilerDriver & driver) const131 std::vector<uint8_t>* QuickCompiler::GetCallFrameInformationInitialization(
132 const CompilerDriver& driver) const {
133 if (driver.GetInstructionSet() == kX86) {
134 return X86CFIInitialization(false);
135 }
136 if (driver.GetInstructionSet() == kX86_64) {
137 return X86CFIInitialization(true);
138 }
139 return nullptr;
140 }
141
Compile(const DexFile::CodeItem * code_item,uint32_t access_flags,InvokeType invoke_type,uint16_t class_def_idx,uint32_t method_idx,jobject class_loader,const DexFile & dex_file) const142 CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
143 uint32_t access_flags,
144 InvokeType invoke_type,
145 uint16_t class_def_idx,
146 uint32_t method_idx,
147 jobject class_loader,
148 const DexFile& dex_file) const {
149 CompiledMethod* method = TryCompile(code_item, access_flags, invoke_type, class_def_idx,
150 method_idx, class_loader, dex_file);
151 if (method != nullptr) {
152 return method;
153 }
154
155 return QuickCompiler::Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx,
156 class_loader, dex_file);
157 }
158
159 } // namespace art
160