blob: ed760f190dfb5e4047f30c6ae62646c6f71d2f6b [file] [log] [blame]
David Brazdildee58d62016-04-07 09:54:26 +00001/*
2 * Copyright (C) 2016 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 "instruction_builder.h"
18
Matthew Gharrity465ecc82016-07-19 21:32:52 +000019#include "art_method-inl.h"
Vladimir Marko69d310e2017-10-09 14:12:23 +010020#include "base/arena_bit_vector.h"
21#include "base/bit_vector-inl.h"
Andreas Gampe85f1c572018-11-21 13:52:48 -080022#include "base/logging.h"
Vladimir Marko69d310e2017-10-09 14:12:23 +010023#include "block_builder.h"
Vladimir Marko3b506202018-10-31 14:33:58 +000024#include "class_linker-inl.h"
25#include "code_generator.h"
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010026#include "data_type-inl.h"
David Sehr312f3b22018-03-19 08:39:26 -070027#include "dex/bytecode_utils.h"
David Sehr9e734c72018-01-04 17:56:19 -080028#include "dex/dex_instruction-inl.h"
Vladimir Marko69d310e2017-10-09 14:12:23 +010029#include "driver/dex_compilation_unit.h"
David Brazdildee58d62016-04-07 09:54:26 +000030#include "driver/compiler_options.h"
Andreas Gampe75a7db62016-09-26 12:04:26 -070031#include "imtable-inl.h"
Andra Danciud0f71f22020-09-17 09:00:15 +000032#include "intrinsics.h"
33#include "intrinsics_utils.h"
Nicolas Geoffraya48c3df2019-06-27 13:11:12 +000034#include "jit/jit.h"
Vladimir Marko69d310e2017-10-09 14:12:23 +010035#include "mirror/dex_cache.h"
Nicolas Geoffray58cc1cb2017-11-20 13:27:29 +000036#include "oat_file.h"
Vladimir Marko69d310e2017-10-09 14:12:23 +010037#include "optimizing_compiler_stats.h"
Nicolas Geoffray396198b2020-06-16 12:02:45 +010038#include "reflective_handle_scope-inl.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070039#include "scoped_thread_state_change-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070040#include "sharpening.h"
Vladimir Marko69d310e2017-10-09 14:12:23 +010041#include "ssa_builder.h"
Andreas Gampea7c83ac2017-09-11 08:14:23 -070042#include "well_known_classes.h"
David Brazdildee58d62016-04-07 09:54:26 +000043
Vladimir Marko0a516052019-10-14 13:00:44 +000044namespace art {
David Brazdildee58d62016-04-07 09:54:26 +000045
Vladimir Markocfd65802020-08-18 09:29:51 +010046namespace {
47
48class SamePackageCompare {
49 public:
50 explicit SamePackageCompare(const DexCompilationUnit& dex_compilation_unit)
51 : dex_compilation_unit_(dex_compilation_unit) {}
52
53 bool operator()(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
54 if (klass->GetClassLoader() != dex_compilation_unit_.GetClassLoader().Get()) {
55 return false;
56 }
57 if (referrers_descriptor_ == nullptr) {
58 const DexFile* dex_file = dex_compilation_unit_.GetDexFile();
59 uint32_t referrers_method_idx = dex_compilation_unit_.GetDexMethodIndex();
60 referrers_descriptor_ =
61 dex_file->StringByTypeIdx(dex_file->GetMethodId(referrers_method_idx).class_idx_);
62 referrers_package_length_ = PackageLength(referrers_descriptor_);
63 }
64 std::string temp;
65 const char* klass_descriptor = klass->GetDescriptor(&temp);
66 size_t klass_package_length = PackageLength(klass_descriptor);
67 return (referrers_package_length_ == klass_package_length) &&
68 memcmp(referrers_descriptor_, klass_descriptor, referrers_package_length_) == 0;
69 };
70
71 private:
72 static size_t PackageLength(const char* descriptor) {
73 const char* slash_pos = strrchr(descriptor, '/');
74 return (slash_pos != nullptr) ? static_cast<size_t>(slash_pos - descriptor) : 0u;
75 }
76
77 const DexCompilationUnit& dex_compilation_unit_;
78 const char* referrers_descriptor_ = nullptr;
79 size_t referrers_package_length_ = 0u;
80};
81
82} // anonymous namespace
83
Mathieu Chartier808c7a52017-12-15 11:19:33 -080084HInstructionBuilder::HInstructionBuilder(HGraph* graph,
85 HBasicBlockBuilder* block_builder,
86 SsaBuilder* ssa_builder,
87 const DexFile* dex_file,
88 const CodeItemDebugInfoAccessor& accessor,
89 DataType::Type return_type,
90 const DexCompilationUnit* dex_compilation_unit,
91 const DexCompilationUnit* outer_compilation_unit,
Mathieu Chartier808c7a52017-12-15 11:19:33 -080092 CodeGenerator* code_generator,
Mathieu Chartier808c7a52017-12-15 11:19:33 -080093 OptimizingCompilerStats* compiler_stats,
Mathieu Chartier808c7a52017-12-15 11:19:33 -080094 ScopedArenaAllocator* local_allocator)
95 : allocator_(graph->GetAllocator()),
96 graph_(graph),
Mathieu Chartier808c7a52017-12-15 11:19:33 -080097 dex_file_(dex_file),
98 code_item_accessor_(accessor),
99 return_type_(return_type),
100 block_builder_(block_builder),
101 ssa_builder_(ssa_builder),
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800102 code_generator_(code_generator),
103 dex_compilation_unit_(dex_compilation_unit),
104 outer_compilation_unit_(outer_compilation_unit),
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800105 compilation_stats_(compiler_stats),
106 local_allocator_(local_allocator),
107 locals_for_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
108 current_block_(nullptr),
109 current_locals_(nullptr),
110 latest_result_(nullptr),
111 current_this_parameter_(nullptr),
Vladimir Marko3b506202018-10-31 14:33:58 +0000112 loop_headers_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
113 class_cache_(std::less<dex::TypeIndex>(), local_allocator->Adapter(kArenaAllocGraphBuilder)) {
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800114 loop_headers_.reserve(kDefaultNumberOfLoops);
115}
116
David Brazdildee58d62016-04-07 09:54:26 +0000117HBasicBlock* HInstructionBuilder::FindBlockStartingAt(uint32_t dex_pc) const {
118 return block_builder_->GetBlockAt(dex_pc);
119}
120
Vladimir Marko69d310e2017-10-09 14:12:23 +0100121inline ScopedArenaVector<HInstruction*>* HInstructionBuilder::GetLocalsFor(HBasicBlock* block) {
122 ScopedArenaVector<HInstruction*>* locals = &locals_for_[block->GetBlockId()];
David Brazdildee58d62016-04-07 09:54:26 +0000123 const size_t vregs = graph_->GetNumberOfVRegs();
Mingyao Yang01b47b02017-02-03 12:09:57 -0800124 if (locals->size() == vregs) {
125 return locals;
126 }
127 return GetLocalsForWithAllocation(block, locals, vregs);
128}
David Brazdildee58d62016-04-07 09:54:26 +0000129
Vladimir Marko69d310e2017-10-09 14:12:23 +0100130ScopedArenaVector<HInstruction*>* HInstructionBuilder::GetLocalsForWithAllocation(
Mingyao Yang01b47b02017-02-03 12:09:57 -0800131 HBasicBlock* block,
Vladimir Marko69d310e2017-10-09 14:12:23 +0100132 ScopedArenaVector<HInstruction*>* locals,
Mingyao Yang01b47b02017-02-03 12:09:57 -0800133 const size_t vregs) {
134 DCHECK_NE(locals->size(), vregs);
135 locals->resize(vregs, nullptr);
136 if (block->IsCatchBlock()) {
137 // We record incoming inputs of catch phis at throwing instructions and
138 // must therefore eagerly create the phis. Phis for undefined vregs will
139 // be deleted when the first throwing instruction with the vreg undefined
140 // is encountered. Unused phis will be removed by dead phi analysis.
141 for (size_t i = 0; i < vregs; ++i) {
142 // No point in creating the catch phi if it is already undefined at
143 // the first throwing instruction.
144 HInstruction* current_local_value = (*current_locals_)[i];
145 if (current_local_value != nullptr) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100146 HPhi* phi = new (allocator_) HPhi(
147 allocator_,
Mingyao Yang01b47b02017-02-03 12:09:57 -0800148 i,
149 0,
150 current_local_value->GetType());
151 block->AddPhi(phi);
152 (*locals)[i] = phi;
David Brazdildee58d62016-04-07 09:54:26 +0000153 }
154 }
155 }
156 return locals;
157}
158
Mingyao Yang01b47b02017-02-03 12:09:57 -0800159inline HInstruction* HInstructionBuilder::ValueOfLocalAt(HBasicBlock* block, size_t local) {
Vladimir Marko69d310e2017-10-09 14:12:23 +0100160 ScopedArenaVector<HInstruction*>* locals = GetLocalsFor(block);
David Brazdildee58d62016-04-07 09:54:26 +0000161 return (*locals)[local];
162}
163
164void HInstructionBuilder::InitializeBlockLocals() {
165 current_locals_ = GetLocalsFor(current_block_);
166
167 if (current_block_->IsCatchBlock()) {
168 // Catch phis were already created and inputs collected from throwing sites.
169 if (kIsDebugBuild) {
170 // Make sure there was at least one throwing instruction which initialized
171 // locals (guaranteed by HGraphBuilder) and that all try blocks have been
172 // visited already (from HTryBoundary scoping and reverse post order).
173 bool catch_block_visited = false;
Vladimir Marko2c45bc92016-10-25 16:54:12 +0100174 for (HBasicBlock* current : graph_->GetReversePostOrder()) {
David Brazdildee58d62016-04-07 09:54:26 +0000175 if (current == current_block_) {
176 catch_block_visited = true;
177 } else if (current->IsTryBlock()) {
178 const HTryBoundary& try_entry = current->GetTryCatchInformation()->GetTryEntry();
179 if (try_entry.HasExceptionHandler(*current_block_)) {
180 DCHECK(!catch_block_visited) << "Catch block visited before its try block.";
181 }
182 }
183 }
184 DCHECK_EQ(current_locals_->size(), graph_->GetNumberOfVRegs())
185 << "No instructions throwing into a live catch block.";
186 }
187 } else if (current_block_->IsLoopHeader()) {
188 // If the block is a loop header, we know we only have visited the pre header
189 // because we are visiting in reverse post order. We create phis for all initialized
190 // locals from the pre header. Their inputs will be populated at the end of
191 // the analysis.
192 for (size_t local = 0; local < current_locals_->size(); ++local) {
193 HInstruction* incoming =
194 ValueOfLocalAt(current_block_->GetLoopInformation()->GetPreHeader(), local);
195 if (incoming != nullptr) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100196 HPhi* phi = new (allocator_) HPhi(
197 allocator_,
David Brazdildee58d62016-04-07 09:54:26 +0000198 local,
199 0,
200 incoming->GetType());
201 current_block_->AddPhi(phi);
202 (*current_locals_)[local] = phi;
203 }
204 }
205
206 // Save the loop header so that the last phase of the analysis knows which
207 // blocks need to be updated.
208 loop_headers_.push_back(current_block_);
209 } else if (current_block_->GetPredecessors().size() > 0) {
210 // All predecessors have already been visited because we are visiting in reverse post order.
211 // We merge the values of all locals, creating phis if those values differ.
212 for (size_t local = 0; local < current_locals_->size(); ++local) {
213 bool one_predecessor_has_no_value = false;
214 bool is_different = false;
215 HInstruction* value = ValueOfLocalAt(current_block_->GetPredecessors()[0], local);
216
217 for (HBasicBlock* predecessor : current_block_->GetPredecessors()) {
218 HInstruction* current = ValueOfLocalAt(predecessor, local);
219 if (current == nullptr) {
220 one_predecessor_has_no_value = true;
221 break;
222 } else if (current != value) {
223 is_different = true;
224 }
225 }
226
227 if (one_predecessor_has_no_value) {
228 // If one predecessor has no value for this local, we trust the verifier has
229 // successfully checked that there is a store dominating any read after this block.
230 continue;
231 }
232
233 if (is_different) {
234 HInstruction* first_input = ValueOfLocalAt(current_block_->GetPredecessors()[0], local);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100235 HPhi* phi = new (allocator_) HPhi(
236 allocator_,
David Brazdildee58d62016-04-07 09:54:26 +0000237 local,
238 current_block_->GetPredecessors().size(),
239 first_input->GetType());
240 for (size_t i = 0; i < current_block_->GetPredecessors().size(); i++) {
241 HInstruction* pred_value = ValueOfLocalAt(current_block_->GetPredecessors()[i], local);
242 phi->SetRawInputAt(i, pred_value);
243 }
244 current_block_->AddPhi(phi);
245 value = phi;
246 }
247 (*current_locals_)[local] = value;
248 }
249 }
250}
251
252void HInstructionBuilder::PropagateLocalsToCatchBlocks() {
253 const HTryBoundary& try_entry = current_block_->GetTryCatchInformation()->GetTryEntry();
254 for (HBasicBlock* catch_block : try_entry.GetExceptionHandlers()) {
Vladimir Marko69d310e2017-10-09 14:12:23 +0100255 ScopedArenaVector<HInstruction*>* handler_locals = GetLocalsFor(catch_block);
David Brazdildee58d62016-04-07 09:54:26 +0000256 DCHECK_EQ(handler_locals->size(), current_locals_->size());
257 for (size_t vreg = 0, e = current_locals_->size(); vreg < e; ++vreg) {
258 HInstruction* handler_value = (*handler_locals)[vreg];
259 if (handler_value == nullptr) {
260 // Vreg was undefined at a previously encountered throwing instruction
261 // and the catch phi was deleted. Do not record the local value.
262 continue;
263 }
264 DCHECK(handler_value->IsPhi());
265
266 HInstruction* local_value = (*current_locals_)[vreg];
267 if (local_value == nullptr) {
268 // This is the first instruction throwing into `catch_block` where
269 // `vreg` is undefined. Delete the catch phi.
270 catch_block->RemovePhi(handler_value->AsPhi());
271 (*handler_locals)[vreg] = nullptr;
272 } else {
273 // Vreg has been defined at all instructions throwing into `catch_block`
274 // encountered so far. Record the local value in the catch phi.
275 handler_value->AsPhi()->AddInput(local_value);
276 }
277 }
278 }
279}
280
281void HInstructionBuilder::AppendInstruction(HInstruction* instruction) {
282 current_block_->AddInstruction(instruction);
283 InitializeInstruction(instruction);
284}
285
286void HInstructionBuilder::InsertInstructionAtTop(HInstruction* instruction) {
287 if (current_block_->GetInstructions().IsEmpty()) {
288 current_block_->AddInstruction(instruction);
289 } else {
290 current_block_->InsertInstructionBefore(instruction, current_block_->GetFirstInstruction());
291 }
292 InitializeInstruction(instruction);
293}
294
295void HInstructionBuilder::InitializeInstruction(HInstruction* instruction) {
296 if (instruction->NeedsEnvironment()) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100297 HEnvironment* environment = new (allocator_) HEnvironment(
298 allocator_,
David Brazdildee58d62016-04-07 09:54:26 +0000299 current_locals_->size(),
Nicolas Geoffray5d37c152017-01-12 13:25:19 +0000300 graph_->GetArtMethod(),
David Brazdildee58d62016-04-07 09:54:26 +0000301 instruction->GetDexPc(),
David Brazdildee58d62016-04-07 09:54:26 +0000302 instruction);
Vladimir Marko69d310e2017-10-09 14:12:23 +0100303 environment->CopyFrom(ArrayRef<HInstruction* const>(*current_locals_));
David Brazdildee58d62016-04-07 09:54:26 +0000304 instruction->SetRawEnvironment(environment);
305 }
306}
307
David Brazdilc120bbe2016-04-22 16:57:00 +0100308HInstruction* HInstructionBuilder::LoadNullCheckedLocal(uint32_t register_index, uint32_t dex_pc) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100309 HInstruction* ref = LoadLocal(register_index, DataType::Type::kReference);
David Brazdilc120bbe2016-04-22 16:57:00 +0100310 if (!ref->CanBeNull()) {
311 return ref;
312 }
313
Vladimir Markoca6fff82017-10-03 14:49:14 +0100314 HNullCheck* null_check = new (allocator_) HNullCheck(ref, dex_pc);
David Brazdilc120bbe2016-04-22 16:57:00 +0100315 AppendInstruction(null_check);
316 return null_check;
317}
318
David Brazdildee58d62016-04-07 09:54:26 +0000319void HInstructionBuilder::SetLoopHeaderPhiInputs() {
320 for (size_t i = loop_headers_.size(); i > 0; --i) {
321 HBasicBlock* block = loop_headers_[i - 1];
322 for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
323 HPhi* phi = it.Current()->AsPhi();
324 size_t vreg = phi->GetRegNumber();
325 for (HBasicBlock* predecessor : block->GetPredecessors()) {
326 HInstruction* value = ValueOfLocalAt(predecessor, vreg);
327 if (value == nullptr) {
328 // Vreg is undefined at this predecessor. Mark it dead and leave with
329 // fewer inputs than predecessors. SsaChecker will fail if not removed.
330 phi->SetDead();
331 break;
332 } else {
333 phi->AddInput(value);
334 }
335 }
336 }
337 }
338}
339
340static bool IsBlockPopulated(HBasicBlock* block) {
341 if (block->IsLoopHeader()) {
342 // Suspend checks were inserted into loop headers during building of dominator tree.
343 DCHECK(block->GetFirstInstruction()->IsSuspendCheck());
344 return block->GetFirstInstruction() != block->GetLastInstruction();
345 } else {
346 return !block->GetInstructions().IsEmpty();
347 }
348}
349
350bool HInstructionBuilder::Build() {
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800351 DCHECK(code_item_accessor_.HasCodeItem());
Vladimir Marko69d310e2017-10-09 14:12:23 +0100352 locals_for_.resize(
353 graph_->GetBlocks().size(),
354 ScopedArenaVector<HInstruction*>(local_allocator_->Adapter(kArenaAllocGraphBuilder)));
David Brazdildee58d62016-04-07 09:54:26 +0000355
356 // Find locations where we want to generate extra stackmaps for native debugging.
357 // This allows us to generate the info only at interesting points (for example,
358 // at start of java statement) rather than before every dex instruction.
Vladimir Marko3b506202018-10-31 14:33:58 +0000359 const bool native_debuggable = code_generator_ != nullptr &&
360 code_generator_->GetCompilerOptions().GetNativeDebuggable();
David Brazdildee58d62016-04-07 09:54:26 +0000361 ArenaBitVector* native_debug_info_locations = nullptr;
362 if (native_debuggable) {
Vladimir Marko69d310e2017-10-09 14:12:23 +0100363 native_debug_info_locations = FindNativeDebugInfoLocations();
David Brazdildee58d62016-04-07 09:54:26 +0000364 }
365
Vladimir Marko2c45bc92016-10-25 16:54:12 +0100366 for (HBasicBlock* block : graph_->GetReversePostOrder()) {
367 current_block_ = block;
David Brazdildee58d62016-04-07 09:54:26 +0000368 uint32_t block_dex_pc = current_block_->GetDexPc();
369
370 InitializeBlockLocals();
371
372 if (current_block_->IsEntryBlock()) {
373 InitializeParameters();
Vladimir Markoca6fff82017-10-03 14:49:14 +0100374 AppendInstruction(new (allocator_) HSuspendCheck(0u));
Mythri Alle2d4feeb2021-10-13 15:39:37 +0000375 if (graph_->IsDebuggable() && code_generator_->GetCompilerOptions().IsJitCompiler()) {
376 AppendInstruction(new (allocator_) HMethodEntryHook(0u));
377 }
Vladimir Markoca6fff82017-10-03 14:49:14 +0100378 AppendInstruction(new (allocator_) HGoto(0u));
David Brazdildee58d62016-04-07 09:54:26 +0000379 continue;
380 } else if (current_block_->IsExitBlock()) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100381 AppendInstruction(new (allocator_) HExit());
David Brazdildee58d62016-04-07 09:54:26 +0000382 continue;
383 } else if (current_block_->IsLoopHeader()) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100384 HSuspendCheck* suspend_check = new (allocator_) HSuspendCheck(current_block_->GetDexPc());
David Brazdildee58d62016-04-07 09:54:26 +0000385 current_block_->GetLoopInformation()->SetSuspendCheck(suspend_check);
386 // This is slightly odd because the loop header might not be empty (TryBoundary).
387 // But we're still creating the environment with locals from the top of the block.
388 InsertInstructionAtTop(suspend_check);
389 }
390
391 if (block_dex_pc == kNoDexPc || current_block_ != block_builder_->GetBlockAt(block_dex_pc)) {
392 // Synthetic block that does not need to be populated.
393 DCHECK(IsBlockPopulated(current_block_));
394 continue;
395 }
396
397 DCHECK(!IsBlockPopulated(current_block_));
398
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800399 for (const DexInstructionPcPair& pair : code_item_accessor_.InstructionsFrom(block_dex_pc)) {
David Brazdildee58d62016-04-07 09:54:26 +0000400 if (current_block_ == nullptr) {
401 // The previous instruction ended this block.
402 break;
403 }
404
Mathieu Chartier0021feb2017-11-07 00:08:52 -0800405 const uint32_t dex_pc = pair.DexPc();
David Brazdildee58d62016-04-07 09:54:26 +0000406 if (dex_pc != block_dex_pc && FindBlockStartingAt(dex_pc) != nullptr) {
407 // This dex_pc starts a new basic block.
408 break;
409 }
410
Mathieu Chartier0021feb2017-11-07 00:08:52 -0800411 if (current_block_->IsTryBlock() && IsThrowingDexInstruction(pair.Inst())) {
David Brazdildee58d62016-04-07 09:54:26 +0000412 PropagateLocalsToCatchBlocks();
413 }
414
415 if (native_debuggable && native_debug_info_locations->IsBitSet(dex_pc)) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100416 AppendInstruction(new (allocator_) HNativeDebugInfo(dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000417 }
418
Vladimir Markof91fc122020-05-13 09:21:00 +0100419 // Note: There may be no Thread for gtests.
420 DCHECK(Thread::Current() == nullptr || !Thread::Current()->IsExceptionPending())
Nicolas Geoffray605c5912020-04-08 15:12:39 +0100421 << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
422 << " " << pair.Inst().Name() << "@" << dex_pc;
Nicolas Geoffray4924ea92021-03-23 08:25:31 +0000423 if (!ProcessDexInstruction(pair.Inst(), dex_pc)) {
David Brazdildee58d62016-04-07 09:54:26 +0000424 return false;
425 }
Vladimir Markof91fc122020-05-13 09:21:00 +0100426 DCHECK(Thread::Current() == nullptr || !Thread::Current()->IsExceptionPending())
Nicolas Geoffrayfbf53b52020-04-01 15:20:14 +0100427 << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
Nicolas Geoffray605c5912020-04-08 15:12:39 +0100428 << " " << pair.Inst().Name() << "@" << dex_pc;
David Brazdildee58d62016-04-07 09:54:26 +0000429 }
430
431 if (current_block_ != nullptr) {
432 // Branching instructions clear current_block, so we know the last
433 // instruction of the current block is not a branching instruction.
434 // We add an unconditional Goto to the next block.
435 DCHECK_EQ(current_block_->GetSuccessors().size(), 1u);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100436 AppendInstruction(new (allocator_) HGoto());
David Brazdildee58d62016-04-07 09:54:26 +0000437 }
438 }
439
440 SetLoopHeaderPhiInputs();
441
442 return true;
443}
444
Vladimir Marko92f7f3c2017-10-31 11:38:30 +0000445void HInstructionBuilder::BuildIntrinsic(ArtMethod* method) {
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800446 DCHECK(!code_item_accessor_.HasCodeItem());
Vladimir Marko92f7f3c2017-10-31 11:38:30 +0000447 DCHECK(method->IsIntrinsic());
Vladimir Marko43d57552020-09-07 12:30:17 +0000448 if (kIsDebugBuild) {
449 ScopedObjectAccess soa(Thread::Current());
450 CHECK(!method->IsSignaturePolymorphic());
451 }
Vladimir Marko92f7f3c2017-10-31 11:38:30 +0000452
453 locals_for_.resize(
454 graph_->GetBlocks().size(),
455 ScopedArenaVector<HInstruction*>(local_allocator_->Adapter(kArenaAllocGraphBuilder)));
456
457 // Fill the entry block. Do not add suspend check, we do not want a suspend
458 // check in intrinsics; intrinsic methods are supposed to be fast.
459 current_block_ = graph_->GetEntryBlock();
460 InitializeBlockLocals();
461 InitializeParameters();
462 AppendInstruction(new (allocator_) HGoto(0u));
463
464 // Fill the body.
465 current_block_ = current_block_->GetSingleSuccessor();
466 InitializeBlockLocals();
467 DCHECK(!IsBlockPopulated(current_block_));
468
Vladimir Marko5f846072020-04-09 13:20:11 +0100469 // Add the intermediate representation, if available, or invoke instruction.
Vladimir Marko92f7f3c2017-10-31 11:38:30 +0000470 size_t in_vregs = graph_->GetNumberOfInVRegs();
471 size_t number_of_arguments =
472 in_vregs - std::count(current_locals_->end() - in_vregs, current_locals_->end(), nullptr);
473 uint32_t method_idx = dex_compilation_unit_->GetDexMethodIndex();
Vladimir Marko5f846072020-04-09 13:20:11 +0100474 const char* shorty = dex_file_->GetMethodShorty(method_idx);
Treehugger Robot2c5827a2018-05-17 22:26:08 +0000475 RangeInstructionOperands operands(graph_->GetNumberOfVRegs() - in_vregs, in_vregs);
Vladimir Marko5f846072020-04-09 13:20:11 +0100476 if (!BuildSimpleIntrinsic(method, kNoDexPc, operands, shorty)) {
477 // Some intrinsics without intermediate representation still yield a leaf method,
478 // so build the invoke. Use HInvokeStaticOrDirect even for methods that would
479 // normally use an HInvokeVirtual (sharpen the call).
480 MethodReference target_method(dex_file_, method_idx);
481 HInvokeStaticOrDirect::DispatchInfo dispatch_info = {
Nicolas Geoffray6d69b522020-09-23 14:47:28 +0100482 MethodLoadKind::kRuntimeCall,
483 CodePtrLocation::kCallArtMethod,
Vladimir Marko5f846072020-04-09 13:20:11 +0100484 /* method_load_data= */ 0u
485 };
486 InvokeType invoke_type = dex_compilation_unit_->IsStatic() ? kStatic : kDirect;
487 HInvokeStaticOrDirect* invoke = new (allocator_) HInvokeStaticOrDirect(
488 allocator_,
489 number_of_arguments,
490 return_type_,
491 kNoDexPc,
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +0100492 target_method,
Vladimir Marko5f846072020-04-09 13:20:11 +0100493 method,
494 dispatch_info,
495 invoke_type,
496 target_method,
497 HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
498 HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
499 }
Vladimir Marko92f7f3c2017-10-31 11:38:30 +0000500
501 // Add the return instruction.
502 if (return_type_ == DataType::Type::kVoid) {
503 AppendInstruction(new (allocator_) HReturnVoid());
504 } else {
Vladimir Marko5f846072020-04-09 13:20:11 +0100505 AppendInstruction(new (allocator_) HReturn(latest_result_));
Vladimir Marko92f7f3c2017-10-31 11:38:30 +0000506 }
507
508 // Fill the exit block.
509 DCHECK_EQ(current_block_->GetSingleSuccessor(), graph_->GetExitBlock());
510 current_block_ = graph_->GetExitBlock();
511 InitializeBlockLocals();
512 AppendInstruction(new (allocator_) HExit());
513}
514
Vladimir Marko69d310e2017-10-09 14:12:23 +0100515ArenaBitVector* HInstructionBuilder::FindNativeDebugInfoLocations() {
Vladimir Marko69d310e2017-10-09 14:12:23 +0100516 ArenaBitVector* locations = ArenaBitVector::Create(local_allocator_,
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800517 code_item_accessor_.InsnsSizeInCodeUnits(),
Andreas Gampe3db70682018-12-26 15:12:03 -0800518 /* expandable= */ false,
Vladimir Marko69d310e2017-10-09 14:12:23 +0100519 kArenaAllocGraphBuilder);
520 locations->ClearAllBits();
Mathieu Chartier3e2e1232018-09-11 12:35:30 -0700521 // The visitor gets called when the line number changes.
522 // In other words, it marks the start of new java statement.
523 code_item_accessor_.DecodeDebugPositionInfo([&](const DexFile::PositionInfo& entry) {
524 locations->SetBit(entry.address_);
525 return false;
526 });
David Brazdildee58d62016-04-07 09:54:26 +0000527 // Instruction-specific tweaks.
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800528 for (const DexInstructionPcPair& inst : code_item_accessor_) {
Mathieu Chartier0021feb2017-11-07 00:08:52 -0800529 switch (inst->Opcode()) {
David Brazdildee58d62016-04-07 09:54:26 +0000530 case Instruction::MOVE_EXCEPTION: {
531 // Stop in native debugger after the exception has been moved.
532 // The compiler also expects the move at the start of basic block so
533 // we do not want to interfere by inserting native-debug-info before it.
Mathieu Chartier0021feb2017-11-07 00:08:52 -0800534 locations->ClearBit(inst.DexPc());
535 DexInstructionIterator next = std::next(DexInstructionIterator(inst));
536 DCHECK(next.DexPc() != inst.DexPc());
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800537 if (next != code_item_accessor_.end()) {
Mathieu Chartier2b2bef22017-10-26 17:10:19 -0700538 locations->SetBit(next.DexPc());
David Brazdildee58d62016-04-07 09:54:26 +0000539 }
540 break;
541 }
542 default:
543 break;
544 }
545 }
Vladimir Marko69d310e2017-10-09 14:12:23 +0100546 return locations;
David Brazdildee58d62016-04-07 09:54:26 +0000547}
548
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100549HInstruction* HInstructionBuilder::LoadLocal(uint32_t reg_number, DataType::Type type) const {
David Brazdildee58d62016-04-07 09:54:26 +0000550 HInstruction* value = (*current_locals_)[reg_number];
551 DCHECK(value != nullptr);
552
553 // If the operation requests a specific type, we make sure its input is of that type.
554 if (type != value->GetType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100555 if (DataType::IsFloatingPointType(type)) {
Aart Bik31883642016-06-06 15:02:44 -0700556 value = ssa_builder_->GetFloatOrDoubleEquivalent(value, type);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100557 } else if (type == DataType::Type::kReference) {
Aart Bik31883642016-06-06 15:02:44 -0700558 value = ssa_builder_->GetReferenceTypeEquivalent(value);
David Brazdildee58d62016-04-07 09:54:26 +0000559 }
Aart Bik31883642016-06-06 15:02:44 -0700560 DCHECK(value != nullptr);
David Brazdildee58d62016-04-07 09:54:26 +0000561 }
562
563 return value;
564}
565
566void HInstructionBuilder::UpdateLocal(uint32_t reg_number, HInstruction* stored_value) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100567 DataType::Type stored_type = stored_value->GetType();
568 DCHECK_NE(stored_type, DataType::Type::kVoid);
David Brazdildee58d62016-04-07 09:54:26 +0000569
570 // Storing into vreg `reg_number` may implicitly invalidate the surrounding
571 // registers. Consider the following cases:
572 // (1) Storing a wide value must overwrite previous values in both `reg_number`
573 // and `reg_number+1`. We store `nullptr` in `reg_number+1`.
574 // (2) If vreg `reg_number-1` holds a wide value, writing into `reg_number`
575 // must invalidate it. We store `nullptr` in `reg_number-1`.
576 // Consequently, storing a wide value into the high vreg of another wide value
577 // will invalidate both `reg_number-1` and `reg_number+1`.
578
579 if (reg_number != 0) {
580 HInstruction* local_low = (*current_locals_)[reg_number - 1];
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100581 if (local_low != nullptr && DataType::Is64BitType(local_low->GetType())) {
David Brazdildee58d62016-04-07 09:54:26 +0000582 // The vreg we are storing into was previously the high vreg of a pair.
583 // We need to invalidate its low vreg.
584 DCHECK((*current_locals_)[reg_number] == nullptr);
585 (*current_locals_)[reg_number - 1] = nullptr;
586 }
587 }
588
589 (*current_locals_)[reg_number] = stored_value;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100590 if (DataType::Is64BitType(stored_type)) {
David Brazdildee58d62016-04-07 09:54:26 +0000591 // We are storing a pair. Invalidate the instruction in the high vreg.
592 (*current_locals_)[reg_number + 1] = nullptr;
593 }
594}
595
596void HInstructionBuilder::InitializeParameters() {
597 DCHECK(current_block_->IsEntryBlock());
598
Vladimir Marko69d310e2017-10-09 14:12:23 +0100599 // outer_compilation_unit_ is null only when unit testing.
600 if (outer_compilation_unit_ == nullptr) {
David Brazdildee58d62016-04-07 09:54:26 +0000601 return;
602 }
603
604 const char* shorty = dex_compilation_unit_->GetShorty();
605 uint16_t number_of_parameters = graph_->GetNumberOfInVRegs();
606 uint16_t locals_index = graph_->GetNumberOfLocalVRegs();
607 uint16_t parameter_index = 0;
608
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800609 const dex::MethodId& referrer_method_id =
David Brazdildee58d62016-04-07 09:54:26 +0000610 dex_file_->GetMethodId(dex_compilation_unit_->GetDexMethodIndex());
611 if (!dex_compilation_unit_->IsStatic()) {
612 // Add the implicit 'this' argument, not expressed in the signature.
Vladimir Markoca6fff82017-10-03 14:49:14 +0100613 HParameterValue* parameter = new (allocator_) HParameterValue(*dex_file_,
David Brazdildee58d62016-04-07 09:54:26 +0000614 referrer_method_id.class_idx_,
615 parameter_index++,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100616 DataType::Type::kReference,
Andreas Gampe3db70682018-12-26 15:12:03 -0800617 /* is_this= */ true);
David Brazdildee58d62016-04-07 09:54:26 +0000618 AppendInstruction(parameter);
619 UpdateLocal(locals_index++, parameter);
620 number_of_parameters--;
Igor Murashkind01745e2017-04-05 16:40:31 -0700621 current_this_parameter_ = parameter;
622 } else {
623 DCHECK(current_this_parameter_ == nullptr);
David Brazdildee58d62016-04-07 09:54:26 +0000624 }
625
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800626 const dex::ProtoId& proto = dex_file_->GetMethodPrototype(referrer_method_id);
627 const dex::TypeList* arg_types = dex_file_->GetProtoParameters(proto);
David Brazdildee58d62016-04-07 09:54:26 +0000628 for (int i = 0, shorty_pos = 1; i < number_of_parameters; i++) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100629 HParameterValue* parameter = new (allocator_) HParameterValue(
David Brazdildee58d62016-04-07 09:54:26 +0000630 *dex_file_,
631 arg_types->GetTypeItem(shorty_pos - 1).type_idx_,
632 parameter_index++,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100633 DataType::FromShorty(shorty[shorty_pos]),
Andreas Gampe3db70682018-12-26 15:12:03 -0800634 /* is_this= */ false);
David Brazdildee58d62016-04-07 09:54:26 +0000635 ++shorty_pos;
636 AppendInstruction(parameter);
637 // Store the parameter value in the local that the dex code will use
638 // to reference that parameter.
639 UpdateLocal(locals_index++, parameter);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100640 if (DataType::Is64BitType(parameter->GetType())) {
David Brazdildee58d62016-04-07 09:54:26 +0000641 i++;
642 locals_index++;
643 parameter_index++;
644 }
645 }
646}
647
648template<typename T>
649void HInstructionBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100650 HInstruction* first = LoadLocal(instruction.VRegA(), DataType::Type::kInt32);
651 HInstruction* second = LoadLocal(instruction.VRegB(), DataType::Type::kInt32);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100652 T* comparison = new (allocator_) T(first, second, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +0000653 AppendInstruction(comparison);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100654 AppendInstruction(new (allocator_) HIf(comparison, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000655 current_block_ = nullptr;
656}
657
658template<typename T>
659void HInstructionBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100660 HInstruction* value = LoadLocal(instruction.VRegA(), DataType::Type::kInt32);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100661 T* comparison = new (allocator_) T(value, graph_->GetIntConstant(0, dex_pc), dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +0000662 AppendInstruction(comparison);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100663 AppendInstruction(new (allocator_) HIf(comparison, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000664 current_block_ = nullptr;
665}
666
667template<typename T>
668void HInstructionBuilder::Unop_12x(const Instruction& instruction,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100669 DataType::Type type,
David Brazdildee58d62016-04-07 09:54:26 +0000670 uint32_t dex_pc) {
671 HInstruction* first = LoadLocal(instruction.VRegB(), type);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100672 AppendInstruction(new (allocator_) T(type, first, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000673 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
674}
675
676void HInstructionBuilder::Conversion_12x(const Instruction& instruction,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100677 DataType::Type input_type,
678 DataType::Type result_type,
David Brazdildee58d62016-04-07 09:54:26 +0000679 uint32_t dex_pc) {
680 HInstruction* first = LoadLocal(instruction.VRegB(), input_type);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100681 AppendInstruction(new (allocator_) HTypeConversion(result_type, first, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000682 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
683}
684
685template<typename T>
686void HInstructionBuilder::Binop_23x(const Instruction& instruction,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100687 DataType::Type type,
David Brazdildee58d62016-04-07 09:54:26 +0000688 uint32_t dex_pc) {
689 HInstruction* first = LoadLocal(instruction.VRegB(), type);
690 HInstruction* second = LoadLocal(instruction.VRegC(), type);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100691 AppendInstruction(new (allocator_) T(type, first, second, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000692 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
693}
694
695template<typename T>
696void HInstructionBuilder::Binop_23x_shift(const Instruction& instruction,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100697 DataType::Type type,
David Brazdildee58d62016-04-07 09:54:26 +0000698 uint32_t dex_pc) {
699 HInstruction* first = LoadLocal(instruction.VRegB(), type);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100700 HInstruction* second = LoadLocal(instruction.VRegC(), DataType::Type::kInt32);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100701 AppendInstruction(new (allocator_) T(type, first, second, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000702 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
703}
704
705void HInstructionBuilder::Binop_23x_cmp(const Instruction& instruction,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100706 DataType::Type type,
David Brazdildee58d62016-04-07 09:54:26 +0000707 ComparisonBias bias,
708 uint32_t dex_pc) {
709 HInstruction* first = LoadLocal(instruction.VRegB(), type);
710 HInstruction* second = LoadLocal(instruction.VRegC(), type);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100711 AppendInstruction(new (allocator_) HCompare(type, first, second, bias, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000712 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
713}
714
715template<typename T>
716void HInstructionBuilder::Binop_12x_shift(const Instruction& instruction,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100717 DataType::Type type,
David Brazdildee58d62016-04-07 09:54:26 +0000718 uint32_t dex_pc) {
719 HInstruction* first = LoadLocal(instruction.VRegA(), type);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100720 HInstruction* second = LoadLocal(instruction.VRegB(), DataType::Type::kInt32);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100721 AppendInstruction(new (allocator_) T(type, first, second, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000722 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
723}
724
725template<typename T>
726void HInstructionBuilder::Binop_12x(const Instruction& instruction,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100727 DataType::Type type,
David Brazdildee58d62016-04-07 09:54:26 +0000728 uint32_t dex_pc) {
729 HInstruction* first = LoadLocal(instruction.VRegA(), type);
730 HInstruction* second = LoadLocal(instruction.VRegB(), type);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100731 AppendInstruction(new (allocator_) T(type, first, second, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000732 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
733}
734
735template<typename T>
736void HInstructionBuilder::Binop_22s(const Instruction& instruction, bool reverse, uint32_t dex_pc) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100737 HInstruction* first = LoadLocal(instruction.VRegB(), DataType::Type::kInt32);
David Brazdildee58d62016-04-07 09:54:26 +0000738 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s(), dex_pc);
739 if (reverse) {
740 std::swap(first, second);
741 }
Vladimir Markoca6fff82017-10-03 14:49:14 +0100742 AppendInstruction(new (allocator_) T(DataType::Type::kInt32, first, second, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000743 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
744}
745
746template<typename T>
747void HInstructionBuilder::Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100748 HInstruction* first = LoadLocal(instruction.VRegB(), DataType::Type::kInt32);
David Brazdildee58d62016-04-07 09:54:26 +0000749 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b(), dex_pc);
750 if (reverse) {
751 std::swap(first, second);
752 }
Vladimir Markoca6fff82017-10-03 14:49:14 +0100753 AppendInstruction(new (allocator_) T(DataType::Type::kInt32, first, second, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000754 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
755}
756
Igor Murashkind01745e2017-04-05 16:40:31 -0700757// Does the method being compiled need any constructor barriers being inserted?
758// (Always 'false' for methods that aren't <init>.)
Vladimir Markoc1c34522018-10-31 13:56:49 +0000759static bool RequiresConstructorBarrier(const DexCompilationUnit* cu) {
Igor Murashkin032cacd2017-04-06 14:40:08 -0700760 // Can be null in unit tests only.
761 if (UNLIKELY(cu == nullptr)) {
762 return false;
763 }
764
Vladimir Markoc1c34522018-10-31 13:56:49 +0000765 // Constructor barriers are applicable only for <init> methods.
766 if (LIKELY(!cu->IsConstructor() || cu->IsStatic())) {
767 return false;
768 }
769
770 return cu->RequiresConstructorBarrier();
David Brazdildee58d62016-04-07 09:54:26 +0000771}
772
773// Returns true if `block` has only one successor which starts at the next
774// dex_pc after `instruction` at `dex_pc`.
775static bool IsFallthroughInstruction(const Instruction& instruction,
776 uint32_t dex_pc,
777 HBasicBlock* block) {
778 uint32_t next_dex_pc = dex_pc + instruction.SizeInCodeUnits();
779 return block->GetSingleSuccessor()->GetDexPc() == next_dex_pc;
780}
781
782void HInstructionBuilder::BuildSwitch(const Instruction& instruction, uint32_t dex_pc) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100783 HInstruction* value = LoadLocal(instruction.VRegA(), DataType::Type::kInt32);
David Brazdildee58d62016-04-07 09:54:26 +0000784 DexSwitchTable table(instruction, dex_pc);
785
786 if (table.GetNumEntries() == 0) {
787 // Empty Switch. Code falls through to the next block.
788 DCHECK(IsFallthroughInstruction(instruction, dex_pc, current_block_));
Vladimir Markoca6fff82017-10-03 14:49:14 +0100789 AppendInstruction(new (allocator_) HGoto(dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000790 } else if (table.ShouldBuildDecisionTree()) {
791 for (DexSwitchTableIterator it(table); !it.Done(); it.Advance()) {
792 HInstruction* case_value = graph_->GetIntConstant(it.CurrentKey(), dex_pc);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100793 HEqual* comparison = new (allocator_) HEqual(value, case_value, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +0000794 AppendInstruction(comparison);
Vladimir Markoca6fff82017-10-03 14:49:14 +0100795 AppendInstruction(new (allocator_) HIf(comparison, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000796
797 if (!it.IsLast()) {
798 current_block_ = FindBlockStartingAt(it.GetDexPcForCurrentIndex());
799 }
800 }
801 } else {
802 AppendInstruction(
Vladimir Markoca6fff82017-10-03 14:49:14 +0100803 new (allocator_) HPackedSwitch(table.GetEntryAt(0), table.GetNumEntries(), value, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000804 }
805
806 current_block_ = nullptr;
807}
808
809void HInstructionBuilder::BuildReturn(const Instruction& instruction,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100810 DataType::Type type,
David Brazdildee58d62016-04-07 09:54:26 +0000811 uint32_t dex_pc) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100812 if (type == DataType::Type::kVoid) {
Igor Murashkind01745e2017-04-05 16:40:31 -0700813 // Only <init> (which is a return-void) could possibly have a constructor fence.
Igor Murashkin032cacd2017-04-06 14:40:08 -0700814 // This may insert additional redundant constructor fences from the super constructors.
815 // TODO: remove redundant constructor fences (b/36656456).
Vladimir Markoc1c34522018-10-31 13:56:49 +0000816 if (RequiresConstructorBarrier(dex_compilation_unit_)) {
Igor Murashkind01745e2017-04-05 16:40:31 -0700817 // Compiling instance constructor.
Vladimir Markoba118822017-06-12 15:41:56 +0100818 DCHECK_STREQ("<init>", graph_->GetMethodName());
Igor Murashkind01745e2017-04-05 16:40:31 -0700819
820 HInstruction* fence_target = current_this_parameter_;
821 DCHECK(fence_target != nullptr);
822
Vladimir Markoca6fff82017-10-03 14:49:14 +0100823 AppendInstruction(new (allocator_) HConstructorFence(fence_target, dex_pc, allocator_));
Igor Murashkin6ef45672017-08-08 13:59:55 -0700824 MaybeRecordStat(
825 compilation_stats_,
826 MethodCompilationStat::kConstructorFenceGeneratedFinal);
David Brazdildee58d62016-04-07 09:54:26 +0000827 }
Mythri Alle2d4feeb2021-10-13 15:39:37 +0000828 if (graph_->IsDebuggable() && code_generator_->GetCompilerOptions().IsJitCompiler()) {
829 // Return value is not used for void functions. We pass NullConstant to
830 // avoid special cases when generating code.
831 AppendInstruction(new (allocator_) HMethodExitHook(graph_->GetNullConstant(), dex_pc));
832 }
Vladimir Markoca6fff82017-10-03 14:49:14 +0100833 AppendInstruction(new (allocator_) HReturnVoid(dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000834 } else {
Vladimir Markoc1c34522018-10-31 13:56:49 +0000835 DCHECK(!RequiresConstructorBarrier(dex_compilation_unit_));
David Brazdildee58d62016-04-07 09:54:26 +0000836 HInstruction* value = LoadLocal(instruction.VRegA(), type);
Mythri Alle2d4feeb2021-10-13 15:39:37 +0000837 if (graph_->IsDebuggable() && code_generator_->GetCompilerOptions().IsJitCompiler()) {
838 AppendInstruction(new (allocator_) HMethodExitHook(value, dex_pc));
839 }
Vladimir Markoca6fff82017-10-03 14:49:14 +0100840 AppendInstruction(new (allocator_) HReturn(value, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +0000841 }
842 current_block_ = nullptr;
843}
844
845static InvokeType GetInvokeTypeFromOpCode(Instruction::Code opcode) {
846 switch (opcode) {
847 case Instruction::INVOKE_STATIC:
848 case Instruction::INVOKE_STATIC_RANGE:
849 return kStatic;
850 case Instruction::INVOKE_DIRECT:
851 case Instruction::INVOKE_DIRECT_RANGE:
852 return kDirect;
853 case Instruction::INVOKE_VIRTUAL:
David Brazdildee58d62016-04-07 09:54:26 +0000854 case Instruction::INVOKE_VIRTUAL_RANGE:
David Brazdildee58d62016-04-07 09:54:26 +0000855 return kVirtual;
856 case Instruction::INVOKE_INTERFACE:
857 case Instruction::INVOKE_INTERFACE_RANGE:
858 return kInterface;
859 case Instruction::INVOKE_SUPER_RANGE:
860 case Instruction::INVOKE_SUPER:
861 return kSuper;
862 default:
863 LOG(FATAL) << "Unexpected invoke opcode: " << opcode;
864 UNREACHABLE();
865 }
866}
867
Vladimir Marko2f40d242020-04-08 12:56:45 +0100868// Try to resolve a method using the class linker. Return null if a method could
869// not be resolved or the resolved method cannot be used for some reason.
870// Also retrieve method data needed for creating the invoke intermediate
871// representation while we hold the mutator lock here.
872static ArtMethod* ResolveMethod(uint16_t method_idx,
873 ArtMethod* referrer,
874 const DexCompilationUnit& dex_compilation_unit,
875 /*inout*/InvokeType* invoke_type,
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +0100876 /*out*/MethodReference* resolved_method_info,
877 /*out*/uint16_t* imt_or_vtable_index,
Vladimir Marko2f40d242020-04-08 12:56:45 +0100878 /*out*/bool* is_string_constructor) {
David Brazdildee58d62016-04-07 09:54:26 +0000879 ScopedObjectAccess soa(Thread::Current());
David Brazdildee58d62016-04-07 09:54:26 +0000880
Vladimir Marko2f40d242020-04-08 12:56:45 +0100881 ClassLinker* class_linker = dex_compilation_unit.GetClassLinker();
882 Handle<mirror::ClassLoader> class_loader = dex_compilation_unit.GetClassLoader();
Nicolas Geoffray393fdb82016-04-25 14:58:06 +0100883
Vladimir Markoba118822017-06-12 15:41:56 +0100884 ArtMethod* resolved_method =
885 class_linker->ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
Vladimir Markoba118822017-06-12 15:41:56 +0100886 method_idx,
Vladimir Marko2f40d242020-04-08 12:56:45 +0100887 dex_compilation_unit.GetDexCache(),
Vladimir Markoba118822017-06-12 15:41:56 +0100888 class_loader,
Vladimir Marko2f40d242020-04-08 12:56:45 +0100889 referrer,
890 *invoke_type);
David Brazdildee58d62016-04-07 09:54:26 +0000891
892 if (UNLIKELY(resolved_method == nullptr)) {
893 // Clean up any exception left by type resolution.
894 soa.Self()->ClearException();
895 return nullptr;
896 }
Nicolas Geoffray605c5912020-04-08 15:12:39 +0100897 DCHECK(!soa.Self()->IsExceptionPending());
David Brazdildee58d62016-04-07 09:54:26 +0000898
Vladimir Markoba118822017-06-12 15:41:56 +0100899 // The referrer may be unresolved for AOT if we're compiling a class that cannot be
900 // resolved because, for example, we don't find a superclass in the classpath.
Vladimir Marko2f40d242020-04-08 12:56:45 +0100901 if (referrer == nullptr) {
Vladimir Markoba118822017-06-12 15:41:56 +0100902 // The class linker cannot check access without a referrer, so we have to do it.
Vladimir Markocfd65802020-08-18 09:29:51 +0100903 // Check if the declaring class or referencing class is accessible.
904 SamePackageCompare same_package(dex_compilation_unit);
905 ObjPtr<mirror::Class> declaring_class = resolved_method->GetDeclaringClass();
906 bool declaring_class_accessible = declaring_class->IsPublic() || same_package(declaring_class);
907 if (!declaring_class_accessible) {
908 // It is possible to access members from an inaccessible superclass
909 // by referencing them through an accessible subclass.
910 ObjPtr<mirror::Class> referenced_class = class_linker->LookupResolvedType(
911 dex_compilation_unit.GetDexFile()->GetMethodId(method_idx).class_idx_,
912 dex_compilation_unit.GetDexCache().Get(),
913 class_loader.Get());
914 DCHECK(referenced_class != nullptr); // Must have been resolved when resolving the method.
915 if (!referenced_class->IsPublic() && !same_package(referenced_class)) {
916 return nullptr;
917 }
918 }
919 // Check whether the method itself is accessible.
920 // Since the referrer is unresolved but the method is resolved, it cannot be
921 // inside the same class, so a private method is known to be inaccessible.
922 // And without a resolved referrer, we cannot check for protected member access
923 // in superlass, so we handle only access to public member or within the package.
924 if (resolved_method->IsPrivate() ||
925 (!resolved_method->IsPublic() && !declaring_class_accessible)) {
David Brazdildee58d62016-04-07 09:54:26 +0000926 return nullptr;
927 }
David Brazdildee58d62016-04-07 09:54:26 +0000928 }
929
930 // We have to special case the invoke-super case, as ClassLinker::ResolveMethod does not.
931 // We need to look at the referrer's super class vtable. We need to do this to know if we need to
932 // make this an invoke-unresolved to handle cross-dex invokes or abstract super methods, both of
933 // which require runtime handling.
Vladimir Marko2f40d242020-04-08 12:56:45 +0100934 if (*invoke_type == kSuper) {
935 ObjPtr<mirror::Class> compiling_class = dex_compilation_unit.GetCompilingClass().Get();
Andreas Gampefa4333d2017-02-14 11:10:34 -0800936 if (compiling_class == nullptr) {
David Brazdildee58d62016-04-07 09:54:26 +0000937 // We could not determine the method's class we need to wait until runtime.
938 DCHECK(Runtime::Current()->IsAotCompiler());
939 return nullptr;
940 }
Vladimir Markoba118822017-06-12 15:41:56 +0100941 ObjPtr<mirror::Class> referenced_class = class_linker->LookupResolvedType(
Vladimir Marko2f40d242020-04-08 12:56:45 +0100942 dex_compilation_unit.GetDexFile()->GetMethodId(method_idx).class_idx_,
943 dex_compilation_unit.GetDexCache().Get(),
Vladimir Markoba118822017-06-12 15:41:56 +0100944 class_loader.Get());
945 DCHECK(referenced_class != nullptr); // We have already resolved a method from this class.
946 if (!referenced_class->IsAssignableFrom(compiling_class)) {
Aart Bikf663e342016-04-04 17:28:59 -0700947 // We cannot statically determine the target method. The runtime will throw a
948 // NoSuchMethodError on this one.
949 return nullptr;
950 }
Nicolas Geoffray393fdb82016-04-25 14:58:06 +0100951 ArtMethod* actual_method;
Vladimir Markoba118822017-06-12 15:41:56 +0100952 if (referenced_class->IsInterface()) {
953 actual_method = referenced_class->FindVirtualMethodForInterfaceSuper(
Nicolas Geoffray393fdb82016-04-25 14:58:06 +0100954 resolved_method, class_linker->GetImagePointerSize());
David Brazdildee58d62016-04-07 09:54:26 +0000955 } else {
Nicolas Geoffray393fdb82016-04-25 14:58:06 +0100956 uint16_t vtable_index = resolved_method->GetMethodIndex();
Nicolas Geoffraybd570592020-12-23 16:37:44 +0000957 if (vtable_index >= static_cast<uint32_t>(
958 compiling_class->GetSuperClass()->GetVTableLength())) {
959 // No super method. The runtime will throw a NoSuchMethodError.
960 return nullptr;
961 }
Nicolas Geoffray393fdb82016-04-25 14:58:06 +0100962 actual_method = compiling_class->GetSuperClass()->GetVTableEntry(
963 vtable_index, class_linker->GetImagePointerSize());
David Brazdildee58d62016-04-07 09:54:26 +0000964 }
Nicolas Geoffray393fdb82016-04-25 14:58:06 +0100965 if (!actual_method->IsInvokable()) {
966 // Fail if the actual method cannot be invoked. Otherwise, the runtime resolution stub
967 // could resolve the callee to the wrong method.
968 return nullptr;
969 }
Nicolas Geoffray25b9c7d2020-09-17 17:34:34 +0100970 // Call GetCanonicalMethod in case the resolved method is a copy: for super calls, the encoding
971 // of ArtMethod in BSS relies on not having copies there.
972 resolved_method = actual_method->GetCanonicalMethod(class_linker->GetImagePointerSize());
David Brazdildee58d62016-04-07 09:54:26 +0000973 }
974
Vladimir Marko2f40d242020-04-08 12:56:45 +0100975 if (*invoke_type == kInterface) {
976 if (resolved_method->GetDeclaringClass()->IsObjectClass()) {
977 // If the resolved method is from j.l.Object, emit a virtual call instead.
978 // The IMT conflict stub only handles interface methods.
979 *invoke_type = kVirtual;
980 } else {
981 DCHECK(resolved_method->GetDeclaringClass()->IsInterface());
982 }
983 }
David Brazdildee58d62016-04-07 09:54:26 +0000984
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +0100985 *resolved_method_info =
Vladimir Marko2f40d242020-04-08 12:56:45 +0100986 MethodReference(resolved_method->GetDexFile(), resolved_method->GetDexMethodIndex());
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +0100987 if (*invoke_type == kVirtual) {
Vladimir Marko2f40d242020-04-08 12:56:45 +0100988 // For HInvokeVirtual we need the vtable index.
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +0100989 *imt_or_vtable_index = resolved_method->GetVtableIndex();
Andra Danciua0130e82020-07-23 12:34:56 +0000990 } else if (*invoke_type == kInterface) {
Vladimir Marko2f40d242020-04-08 12:56:45 +0100991 // For HInvokeInterface we need the IMT index.
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +0100992 *imt_or_vtable_index = ImTable::GetImtIndex(resolved_method);
Vladimir Marko2f40d242020-04-08 12:56:45 +0100993 }
994
995 *is_string_constructor =
996 resolved_method->IsConstructor() && resolved_method->GetDeclaringClass()->IsStringClass();
997
998 return resolved_method;
Nicolas Geoffrayda079bb2016-09-26 17:56:07 +0100999}
1000
David Brazdildee58d62016-04-07 09:54:26 +00001001bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
1002 uint32_t dex_pc,
1003 uint32_t method_idx,
Treehugger Robot2c5827a2018-05-17 22:26:08 +00001004 const InstructionOperands& operands) {
David Brazdildee58d62016-04-07 09:54:26 +00001005 InvokeType invoke_type = GetInvokeTypeFromOpCode(instruction.Opcode());
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001006 const char* shorty = dex_file_->GetMethodShorty(method_idx);
1007 DataType::Type return_type = DataType::FromShorty(shorty[0]);
David Brazdildee58d62016-04-07 09:54:26 +00001008
1009 // Remove the return type from the 'proto'.
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001010 size_t number_of_arguments = strlen(shorty) - 1;
David Brazdildee58d62016-04-07 09:54:26 +00001011 if (invoke_type != kStatic) { // instance call
1012 // One extra argument for 'this'.
1013 number_of_arguments++;
1014 }
1015
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001016 MethodReference resolved_method_reference(nullptr, 0u);
Vladimir Marko2f40d242020-04-08 12:56:45 +01001017 bool is_string_constructor = false;
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001018 uint16_t imt_or_vtable_index = DexFile::kDexNoIndex16;
Vladimir Marko2f40d242020-04-08 12:56:45 +01001019 ArtMethod* resolved_method = ResolveMethod(method_idx,
1020 graph_->GetArtMethod(),
1021 *dex_compilation_unit_,
1022 &invoke_type,
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001023 &resolved_method_reference,
1024 &imt_or_vtable_index,
Vladimir Marko2f40d242020-04-08 12:56:45 +01001025 &is_string_constructor);
David Brazdildee58d62016-04-07 09:54:26 +00001026
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001027 MethodReference method_reference(&graph_->GetDexFile(), method_idx);
David Brazdildee58d62016-04-07 09:54:26 +00001028 if (UNLIKELY(resolved_method == nullptr)) {
Nicolas Geoffray605c5912020-04-08 15:12:39 +01001029 DCHECK(!Thread::Current()->IsExceptionPending());
Igor Murashkin1e065a52017-08-09 13:20:34 -07001030 MaybeRecordStat(compilation_stats_,
1031 MethodCompilationStat::kUnresolvedMethod);
Vladimir Markoca6fff82017-10-03 14:49:14 +01001032 HInvoke* invoke = new (allocator_) HInvokeUnresolved(allocator_,
1033 number_of_arguments,
1034 return_type,
1035 dex_pc,
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001036 method_reference,
Vladimir Markoca6fff82017-10-03 14:49:14 +01001037 invoke_type);
Andreas Gampe3db70682018-12-26 15:12:03 -08001038 return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ true);
David Brazdildee58d62016-04-07 09:54:26 +00001039 }
1040
Nicolas Geoffrayda079bb2016-09-26 17:56:07 +01001041 // Replace calls to String.<init> with StringFactory.
Vladimir Marko2f40d242020-04-08 12:56:45 +01001042 if (is_string_constructor) {
Nicolas Geoffrayda079bb2016-09-26 17:56:07 +01001043 uint32_t string_init_entry_point = WellKnownClasses::StringInitToEntryPoint(resolved_method);
1044 HInvokeStaticOrDirect::DispatchInfo dispatch_info = {
Nicolas Geoffray6d69b522020-09-23 14:47:28 +01001045 MethodLoadKind::kStringInit,
1046 CodePtrLocation::kCallArtMethod,
Nicolas Geoffrayc1a42cf2016-12-18 15:52:36 +00001047 dchecked_integral_cast<uint64_t>(string_init_entry_point)
Nicolas Geoffrayda079bb2016-09-26 17:56:07 +01001048 };
Nicolas Geoffrayf665f842018-02-15 12:29:06 +00001049 // We pass null for the resolved_method to ensure optimizations
1050 // don't rely on it.
Vladimir Markoca6fff82017-10-03 14:49:14 +01001051 HInvoke* invoke = new (allocator_) HInvokeStaticOrDirect(
1052 allocator_,
Nicolas Geoffrayda079bb2016-09-26 17:56:07 +01001053 number_of_arguments - 1,
Andreas Gampe3db70682018-12-26 15:12:03 -08001054 /* return_type= */ DataType::Type::kReference,
Nicolas Geoffrayda079bb2016-09-26 17:56:07 +01001055 dex_pc,
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001056 method_reference,
Andreas Gampe3db70682018-12-26 15:12:03 -08001057 /* resolved_method= */ nullptr,
Nicolas Geoffrayda079bb2016-09-26 17:56:07 +01001058 dispatch_info,
1059 invoke_type,
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001060 resolved_method_reference,
Nicolas Geoffrayda079bb2016-09-26 17:56:07 +01001061 HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit);
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001062 return HandleStringInit(invoke, operands, shorty);
Nicolas Geoffrayda079bb2016-09-26 17:56:07 +01001063 }
1064
David Brazdildee58d62016-04-07 09:54:26 +00001065 // Potential class initialization check, in the case of a static method call.
Vladimir Marko2f40d242020-04-08 12:56:45 +01001066 HInvokeStaticOrDirect::ClinitCheckRequirement clinit_check_requirement =
1067 HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
David Brazdildee58d62016-04-07 09:54:26 +00001068 HClinitCheck* clinit_check = nullptr;
Vladimir Marko2f40d242020-04-08 12:56:45 +01001069 if (invoke_type == kStatic) {
1070 clinit_check = ProcessClinitCheckForInvoke(dex_pc, resolved_method, &clinit_check_requirement);
1071 }
1072
Vladimir Marko5f846072020-04-09 13:20:11 +01001073 // Try to build an HIR replacement for the intrinsic.
1074 if (UNLIKELY(resolved_method->IsIntrinsic())) {
1075 // All intrinsics are in the primary boot image, so their class can always be referenced
1076 // and we do not need to rely on the implicit class initialization check. The class should
1077 // be initialized but we do not require that here.
1078 DCHECK_NE(clinit_check_requirement, HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit);
1079 if (BuildSimpleIntrinsic(resolved_method, dex_pc, operands, shorty)) {
1080 return true;
1081 }
1082 }
1083
David Brazdildee58d62016-04-07 09:54:26 +00001084 HInvoke* invoke = nullptr;
1085 if (invoke_type == kDirect || invoke_type == kStatic || invoke_type == kSuper) {
Nicolas Geoffray1fef8772020-09-09 13:57:17 +01001086 // For sharpening, we create another MethodReference, to account for the
1087 // kSuper case below where we cannot find a dex method index.
1088 bool has_method_id = true;
Vladimir Marko2f40d242020-04-08 12:56:45 +01001089 if (invoke_type == kSuper) {
Nicolas Geoffray1fef8772020-09-09 13:57:17 +01001090 uint32_t dex_method_index = method_reference.index;
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001091 if (IsSameDexFile(*resolved_method_reference.dex_file,
1092 *dex_compilation_unit_->GetDexFile())) {
Nicolas Geoffray5e4e11e2016-09-22 13:17:41 +01001093 // Update the method index to the one resolved. Note that this may be a no-op if
David Brazdildee58d62016-04-07 09:54:26 +00001094 // we resolved to the method referenced by the instruction.
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001095 dex_method_index = resolved_method_reference.index;
Nicolas Geoffray1fef8772020-09-09 13:57:17 +01001096 } else {
1097 // Try to find a dex method index in this caller's dex file.
1098 ScopedObjectAccess soa(Thread::Current());
1099 dex_method_index = resolved_method->FindDexMethodIndexInOtherDexFile(
1100 *dex_compilation_unit_->GetDexFile(), method_idx);
1101 }
1102 if (dex_method_index == dex::kDexNoIndex) {
1103 has_method_id = false;
1104 } else {
1105 method_reference.index = dex_method_index;
David Brazdildee58d62016-04-07 09:54:26 +00001106 }
1107 }
Nicolas Geoffraybdb2ecc2018-09-18 14:33:55 +01001108 HInvokeStaticOrDirect::DispatchInfo dispatch_info =
Nicolas Geoffray8d34a182020-09-16 09:46:58 +01001109 HSharpening::SharpenLoadMethod(resolved_method,
1110 has_method_id,
Nicolas Geoffrayd5a86952021-01-19 10:35:54 +00001111 /* for_interface_call= */ false,
Nicolas Geoffray8d34a182020-09-16 09:46:58 +01001112 code_generator_);
Nicolas Geoffray6d69b522020-09-23 14:47:28 +01001113 if (dispatch_info.code_ptr_location == CodePtrLocation::kCallCriticalNative) {
Vladimir Markod3e9c622020-08-05 12:20:28 +01001114 graph_->SetHasDirectCriticalNativeCall(true);
1115 }
Vladimir Markoca6fff82017-10-03 14:49:14 +01001116 invoke = new (allocator_) HInvokeStaticOrDirect(allocator_,
1117 number_of_arguments,
1118 return_type,
1119 dex_pc,
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001120 method_reference,
Vladimir Markoca6fff82017-10-03 14:49:14 +01001121 resolved_method,
1122 dispatch_info,
1123 invoke_type,
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001124 resolved_method_reference,
Vladimir Markoca6fff82017-10-03 14:49:14 +01001125 clinit_check_requirement);
Vladimir Marko5f846072020-04-09 13:20:11 +01001126 if (clinit_check != nullptr) {
1127 // Add the class initialization check as last input of `invoke`.
1128 DCHECK_EQ(clinit_check_requirement, HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit);
1129 size_t clinit_check_index = invoke->InputCount() - 1u;
1130 DCHECK(invoke->InputAt(clinit_check_index) == nullptr);
1131 invoke->SetArgumentAt(clinit_check_index, clinit_check);
1132 }
David Brazdildee58d62016-04-07 09:54:26 +00001133 } else if (invoke_type == kVirtual) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001134 invoke = new (allocator_) HInvokeVirtual(allocator_,
1135 number_of_arguments,
1136 return_type,
1137 dex_pc,
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001138 method_reference,
Vladimir Markoca6fff82017-10-03 14:49:14 +01001139 resolved_method,
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001140 resolved_method_reference,
1141 /*vtable_index=*/ imt_or_vtable_index);
David Brazdildee58d62016-04-07 09:54:26 +00001142 } else {
1143 DCHECK_EQ(invoke_type, kInterface);
Nicolas Geoffray8d34a182020-09-16 09:46:58 +01001144 if (kIsDebugBuild) {
1145 ScopedObjectAccess soa(Thread::Current());
1146 DCHECK(resolved_method->GetDeclaringClass()->IsInterface());
1147 }
Nicolas Geoffrayd5a86952021-01-19 10:35:54 +00001148 MethodLoadKind load_kind = HSharpening::SharpenLoadMethod(
1149 resolved_method,
1150 /* has_method_id= */ true,
1151 /* for_interface_call= */ true,
1152 code_generator_)
Nicolas Geoffray8d34a182020-09-16 09:46:58 +01001153 .method_load_kind;
Vladimir Marko2f40d242020-04-08 12:56:45 +01001154 invoke = new (allocator_) HInvokeInterface(allocator_,
Vladimir Markoca6fff82017-10-03 14:49:14 +01001155 number_of_arguments,
1156 return_type,
1157 dex_pc,
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001158 method_reference,
Vladimir Markoca6fff82017-10-03 14:49:14 +01001159 resolved_method,
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001160 resolved_method_reference,
Nicolas Geoffray8d34a182020-09-16 09:46:58 +01001161 /*imt_index=*/ imt_or_vtable_index,
1162 load_kind);
David Brazdildee58d62016-04-07 09:54:26 +00001163 }
Vladimir Marko5f846072020-04-09 13:20:11 +01001164 return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
David Brazdildee58d62016-04-07 09:54:26 +00001165}
1166
Andra Danciud0f71f22020-09-17 09:00:15 +00001167static bool VarHandleAccessorNeedsReturnTypeCheck(HInvoke* invoke, DataType::Type return_type) {
1168 mirror::VarHandle::AccessModeTemplate access_mode_template =
1169 mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
1170
1171 switch (access_mode_template) {
1172 case mirror::VarHandle::AccessModeTemplate::kGet:
1173 case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate:
1174 case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange:
1175 return return_type == DataType::Type::kReference;
1176 case mirror::VarHandle::AccessModeTemplate::kSet:
1177 case mirror::VarHandle::AccessModeTemplate::kCompareAndSet:
1178 return false;
1179 }
1180}
1181
Ulyana Trafimovich98f01d12021-07-28 14:33:34 +00001182// This function initializes `VarHandleOptimizations`, does a number of static checks and disables
1183// the intrinsic if some of the checks fail. This is necessary for the code generator to work (for
1184// both the baseline and the optimizing compiler).
1185static void DecideVarHandleIntrinsic(HInvoke* invoke) {
1186 switch (invoke->GetIntrinsic()) {
1187 case Intrinsics::kVarHandleCompareAndExchange:
1188 case Intrinsics::kVarHandleCompareAndExchangeAcquire:
1189 case Intrinsics::kVarHandleCompareAndExchangeRelease:
1190 case Intrinsics::kVarHandleCompareAndSet:
1191 case Intrinsics::kVarHandleGet:
1192 case Intrinsics::kVarHandleGetAcquire:
1193 case Intrinsics::kVarHandleGetAndAdd:
1194 case Intrinsics::kVarHandleGetAndAddAcquire:
1195 case Intrinsics::kVarHandleGetAndAddRelease:
1196 case Intrinsics::kVarHandleGetAndBitwiseAnd:
1197 case Intrinsics::kVarHandleGetAndBitwiseAndAcquire:
1198 case Intrinsics::kVarHandleGetAndBitwiseAndRelease:
1199 case Intrinsics::kVarHandleGetAndBitwiseOr:
1200 case Intrinsics::kVarHandleGetAndBitwiseOrAcquire:
1201 case Intrinsics::kVarHandleGetAndBitwiseOrRelease:
1202 case Intrinsics::kVarHandleGetAndBitwiseXor:
1203 case Intrinsics::kVarHandleGetAndBitwiseXorAcquire:
1204 case Intrinsics::kVarHandleGetAndBitwiseXorRelease:
1205 case Intrinsics::kVarHandleGetAndSet:
1206 case Intrinsics::kVarHandleGetAndSetAcquire:
1207 case Intrinsics::kVarHandleGetAndSetRelease:
1208 case Intrinsics::kVarHandleGetOpaque:
1209 case Intrinsics::kVarHandleGetVolatile:
1210 case Intrinsics::kVarHandleSet:
1211 case Intrinsics::kVarHandleSetOpaque:
1212 case Intrinsics::kVarHandleSetRelease:
1213 case Intrinsics::kVarHandleSetVolatile:
1214 case Intrinsics::kVarHandleWeakCompareAndSet:
1215 case Intrinsics::kVarHandleWeakCompareAndSetAcquire:
1216 case Intrinsics::kVarHandleWeakCompareAndSetPlain:
1217 case Intrinsics::kVarHandleWeakCompareAndSetRelease:
1218 break;
1219 default:
1220 return; // Not a VarHandle intrinsic, skip.
1221 }
1222
1223 DCHECK(invoke->IsInvokePolymorphic());
1224 VarHandleOptimizations optimizations(invoke);
1225
1226 // Do only simple static checks here (those for which we have enough information). More complex
1227 // checks should be done in instruction simplifier, which runs after other optimization passes
1228 // that may provide useful information.
1229
1230 size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
1231 if (expected_coordinates_count > 2u) {
1232 optimizations.SetDoNotIntrinsify();
1233 return;
1234 }
1235 if (expected_coordinates_count != 0u) {
1236 // Except for static fields (no coordinates), the first coordinate must be a reference.
1237 // Do not intrinsify if the reference is null as we would always go to slow path anyway.
1238 HInstruction* object = invoke->InputAt(1);
1239 if (object->GetType() != DataType::Type::kReference || object->IsNullConstant()) {
1240 optimizations.SetDoNotIntrinsify();
1241 return;
1242 }
1243 }
1244 if (expected_coordinates_count == 2u) {
1245 // For arrays and views, the second coordinate must be convertible to `int`.
1246 // In this context, `boolean` is not convertible but we have to look at the shorty
1247 // as compiler transformations can give the invoke a valid boolean input.
1248 DataType::Type index_type = GetDataTypeFromShorty(invoke, 2);
1249 if (index_type == DataType::Type::kBool ||
1250 DataType::Kind(index_type) != DataType::Type::kInt32) {
1251 optimizations.SetDoNotIntrinsify();
1252 return;
1253 }
1254 }
1255
1256 uint32_t number_of_arguments = invoke->GetNumberOfArguments();
1257 DataType::Type return_type = invoke->GetType();
1258 mirror::VarHandle::AccessModeTemplate access_mode_template =
1259 mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
1260 switch (access_mode_template) {
1261 case mirror::VarHandle::AccessModeTemplate::kGet:
1262 // The return type should be the same as varType, so it shouldn't be void.
1263 if (return_type == DataType::Type::kVoid) {
1264 optimizations.SetDoNotIntrinsify();
1265 return;
1266 }
1267 break;
1268 case mirror::VarHandle::AccessModeTemplate::kSet:
1269 if (return_type != DataType::Type::kVoid) {
1270 optimizations.SetDoNotIntrinsify();
1271 return;
1272 }
1273 break;
1274 case mirror::VarHandle::AccessModeTemplate::kCompareAndSet: {
1275 if (return_type != DataType::Type::kBool) {
1276 optimizations.SetDoNotIntrinsify();
1277 return;
1278 }
1279 uint32_t expected_value_index = number_of_arguments - 2;
1280 uint32_t new_value_index = number_of_arguments - 1;
1281 DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
1282 DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
1283 if (expected_value_type != new_value_type) {
1284 optimizations.SetDoNotIntrinsify();
1285 return;
1286 }
1287 break;
1288 }
1289 case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange: {
1290 uint32_t expected_value_index = number_of_arguments - 2;
1291 uint32_t new_value_index = number_of_arguments - 1;
1292 DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
1293 DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
1294 if (expected_value_type != new_value_type || return_type != expected_value_type) {
1295 optimizations.SetDoNotIntrinsify();
1296 return;
1297 }
1298 break;
1299 }
1300 case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate: {
1301 DataType::Type value_type = GetDataTypeFromShorty(invoke, number_of_arguments - 1);
1302 if (IsVarHandleGetAndAdd(invoke) &&
1303 (value_type == DataType::Type::kReference || value_type == DataType::Type::kBool)) {
1304 // We should only add numerical types.
1305 optimizations.SetDoNotIntrinsify();
1306 return;
1307 } else if (IsVarHandleGetAndBitwiseOp(invoke) && !DataType::IsIntegralType(value_type)) {
1308 // We can only apply operators to bitwise integral types.
1309 // Note that bitwise VarHandle operations accept a non-integral boolean type and
1310 // perform the appropriate logical operation. However, the result is the same as
1311 // using the bitwise operation on our boolean representation and this fits well
1312 // with DataType::IsIntegralType() treating the compiler type kBool as integral.
1313 optimizations.SetDoNotIntrinsify();
1314 return;
1315 }
1316 if (value_type != return_type) {
1317 optimizations.SetDoNotIntrinsify();
1318 return;
1319 }
1320 break;
1321 }
1322 }
1323}
1324
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001325bool HInstructionBuilder::BuildInvokePolymorphic(uint32_t dex_pc,
Orion Hodsonac141392017-01-13 11:53:47 +00001326 uint32_t method_idx,
Orion Hodson06d10a72018-05-14 08:53:38 +01001327 dex::ProtoIndex proto_idx,
Treehugger Robot2c5827a2018-05-17 22:26:08 +00001328 const InstructionOperands& operands) {
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001329 const char* shorty = dex_file_->GetShorty(proto_idx);
1330 DCHECK_EQ(1 + ArtMethod::NumArgRegisters(shorty), operands.GetNumberOfOperands());
1331 DataType::Type return_type = DataType::FromShorty(shorty[0]);
1332 size_t number_of_arguments = strlen(shorty);
Andra Danciua0130e82020-07-23 12:34:56 +00001333 // We use ResolveMethod which is also used in BuildInvoke in order to
1334 // not duplicate code. As such, we need to provide is_string_constructor
1335 // even if we don't need it afterwards.
1336 InvokeType invoke_type = InvokeType::kPolymorphic;
1337 bool is_string_constructor = false;
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001338 uint16_t imt_or_vtable_index = DexFile::kDexNoIndex16;
1339 MethodReference resolved_method_reference(nullptr, 0u);
Andra Danciua0130e82020-07-23 12:34:56 +00001340 ArtMethod* resolved_method = ResolveMethod(method_idx,
1341 graph_->GetArtMethod(),
1342 *dex_compilation_unit_,
1343 &invoke_type,
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001344 &resolved_method_reference,
1345 &imt_or_vtable_index,
Andra Danciua0130e82020-07-23 12:34:56 +00001346 &is_string_constructor);
Andra Danciuaa358832020-08-25 15:09:43 +00001347
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001348 MethodReference method_reference(&graph_->GetDexFile(), method_idx);
Vladimir Markoca6fff82017-10-03 14:49:14 +01001349 HInvoke* invoke = new (allocator_) HInvokePolymorphic(allocator_,
1350 number_of_arguments,
1351 return_type,
1352 dex_pc,
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001353 method_reference,
Andra Danciu73c31802020-09-01 13:17:05 +00001354 resolved_method,
Nicolas Geoffrayb0f405e2020-09-24 15:10:35 +01001355 resolved_method_reference,
Andra Danciu73c31802020-09-01 13:17:05 +00001356 proto_idx);
Andra Danciu49a19f32020-08-27 12:44:25 +00001357 if (!HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false)) {
1358 return false;
1359 }
1360
Andra Danciud0f71f22020-09-17 09:00:15 +00001361 if (invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvoke &&
1362 invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvokeExact &&
1363 VarHandleAccessorNeedsReturnTypeCheck(invoke, return_type)) {
1364 // Type check is needed because VarHandle intrinsics do not type check the retrieved reference.
Andra Danciuaa358832020-08-25 15:09:43 +00001365 ScopedObjectAccess soa(Thread::Current());
1366 ArtMethod* referrer = graph_->GetArtMethod();
Andra Danciud0f71f22020-09-17 09:00:15 +00001367 dex::TypeIndex return_type_index =
1368 referrer->GetDexFile()->GetProtoId(proto_idx).return_type_idx_;
Andra Danciuaa358832020-08-25 15:09:43 +00001369
Andra Danciud0f71f22020-09-17 09:00:15 +00001370 BuildTypeCheck(/* is_instance_of= */ false, invoke, return_type_index, dex_pc);
Andra Danciu49a19f32020-08-27 12:44:25 +00001371 latest_result_ = current_block_->GetLastInstruction();
Andra Danciuaa358832020-08-25 15:09:43 +00001372 }
1373
Ulyana Trafimovich98f01d12021-07-28 14:33:34 +00001374 DecideVarHandleIntrinsic(invoke);
1375
Andra Danciu49a19f32020-08-27 12:44:25 +00001376 return true;
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001377}
1378
1379
1380bool HInstructionBuilder::BuildInvokeCustom(uint32_t dex_pc,
1381 uint32_t call_site_idx,
1382 const InstructionOperands& operands) {
1383 dex::ProtoIndex proto_idx = dex_file_->GetProtoIndexForCallSite(call_site_idx);
1384 const char* shorty = dex_file_->GetShorty(proto_idx);
1385 DataType::Type return_type = DataType::FromShorty(shorty[0]);
1386 size_t number_of_arguments = strlen(shorty) - 1;
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001387 // HInvokeCustom takes a DexNoNoIndex method reference.
1388 MethodReference method_reference(&graph_->GetDexFile(), dex::kDexNoIndex);
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001389 HInvoke* invoke = new (allocator_) HInvokeCustom(allocator_,
1390 number_of_arguments,
1391 call_site_idx,
1392 return_type,
Nicolas Geoffraye6c0f2a2020-09-07 08:30:52 +01001393 dex_pc,
1394 method_reference);
Andreas Gampe3db70682018-12-26 15:12:03 -08001395 return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
Orion Hodsonac141392017-01-13 11:53:47 +00001396}
1397
Igor Murashkin79d8fa72017-04-18 09:37:23 -07001398HNewInstance* HInstructionBuilder::BuildNewInstance(dex::TypeIndex type_index, uint32_t dex_pc) {
Vladimir Marko3cd50df2016-04-13 19:29:26 +01001399 ScopedObjectAccess soa(Thread::Current());
David Brazdildee58d62016-04-07 09:54:26 +00001400
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00001401 HLoadClass* load_class = BuildLoadClass(type_index, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00001402
David Brazdildee58d62016-04-07 09:54:26 +00001403 HInstruction* cls = load_class;
Nicolas Geoffray5247c082017-01-13 14:17:29 +00001404 Handle<mirror::Class> klass = load_class->GetClass();
1405
Vladimir Marko2f40d242020-04-08 12:56:45 +01001406 if (!IsInitialized(klass.Get())) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01001407 cls = new (allocator_) HClinitCheck(load_class, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00001408 AppendInstruction(cls);
1409 }
1410
Nicolas Geoffray5247c082017-01-13 14:17:29 +00001411 // Only the access check entrypoint handles the finalizable class case. If we
1412 // need access checks, then we haven't resolved the method and the class may
1413 // again be finalizable.
1414 QuickEntrypointEnum entrypoint = kQuickAllocObjectInitialized;
Vladimir Marko270e10a2020-09-24 11:48:47 +01001415 if (load_class->NeedsAccessCheck() ||
1416 klass == nullptr || // Finalizable/instantiable is unknown.
1417 klass->IsFinalizable() ||
Nicolas Geoffray54ed0152020-12-23 17:29:32 +00001418 klass.Get() == klass->GetClass() || // Classes cannot be allocated in code
Vladimir Marko270e10a2020-09-24 11:48:47 +01001419 !klass->IsInstantiable()) {
Nicolas Geoffray5247c082017-01-13 14:17:29 +00001420 entrypoint = kQuickAllocObjectWithChecks;
1421 }
Alex Lightd109e302018-06-27 10:25:41 -07001422 // We will always be able to resolve the string class since it is in the BCP.
1423 if (!klass.IsNull() && klass->IsStringClass()) {
1424 entrypoint = kQuickAllocStringObject;
1425 }
Nicolas Geoffray5247c082017-01-13 14:17:29 +00001426
1427 // Consider classes we haven't resolved as potentially finalizable.
Andreas Gampefa4333d2017-02-14 11:10:34 -08001428 bool finalizable = (klass == nullptr) || klass->IsFinalizable();
Nicolas Geoffray5247c082017-01-13 14:17:29 +00001429
Vladimir Markoca6fff82017-10-03 14:49:14 +01001430 HNewInstance* new_instance = new (allocator_) HNewInstance(
David Brazdildee58d62016-04-07 09:54:26 +00001431 cls,
David Brazdildee58d62016-04-07 09:54:26 +00001432 dex_pc,
1433 type_index,
1434 *dex_compilation_unit_->GetDexFile(),
David Brazdildee58d62016-04-07 09:54:26 +00001435 finalizable,
Igor Murashkin79d8fa72017-04-18 09:37:23 -07001436 entrypoint);
1437 AppendInstruction(new_instance);
1438
1439 return new_instance;
1440}
1441
1442void HInstructionBuilder::BuildConstructorFenceForAllocation(HInstruction* allocation) {
1443 DCHECK(allocation != nullptr &&
George Burgess IVf2072992017-05-23 15:36:41 -07001444 (allocation->IsNewInstance() ||
1445 allocation->IsNewArray())); // corresponding to "new" keyword in JLS.
Igor Murashkin79d8fa72017-04-18 09:37:23 -07001446
1447 if (allocation->IsNewInstance()) {
1448 // STRING SPECIAL HANDLING:
1449 // -------------------------------
1450 // Strings have a real HNewInstance node but they end up always having 0 uses.
1451 // All uses of a String HNewInstance are always transformed to replace their input
1452 // of the HNewInstance with an input of the invoke to StringFactory.
1453 //
1454 // Do not emit an HConstructorFence here since it can inhibit some String new-instance
1455 // optimizations (to pass checker tests that rely on those optimizations).
1456 HNewInstance* new_inst = allocation->AsNewInstance();
1457 HLoadClass* load_class = new_inst->GetLoadClass();
1458
1459 Thread* self = Thread::Current();
1460 ScopedObjectAccess soa(self);
1461 StackHandleScope<1> hs(self);
1462 Handle<mirror::Class> klass = load_class->GetClass();
1463 if (klass != nullptr && klass->IsStringClass()) {
1464 return;
1465 // Note: Do not use allocation->IsStringAlloc which requires
1466 // a valid ReferenceTypeInfo, but that doesn't get made until after reference type
1467 // propagation (and instruction builder is too early).
1468 }
1469 // (In terms of correctness, the StringFactory needs to provide its own
1470 // default initialization barrier, see below.)
1471 }
1472
1473 // JLS 17.4.5 "Happens-before Order" describes:
1474 //
1475 // The default initialization of any object happens-before any other actions (other than
1476 // default-writes) of a program.
1477 //
1478 // In our implementation the default initialization of an object to type T means
1479 // setting all of its initial data (object[0..size)) to 0, and setting the
1480 // object's class header (i.e. object.getClass() == T.class).
1481 //
1482 // In practice this fence ensures that the writes to the object header
1483 // are visible to other threads if this object escapes the current thread.
1484 // (and in theory the 0-initializing, but that happens automatically
1485 // when new memory pages are mapped in by the OS).
1486 HConstructorFence* ctor_fence =
Vladimir Markoca6fff82017-10-03 14:49:14 +01001487 new (allocator_) HConstructorFence(allocation, allocation->GetDexPc(), allocator_);
Igor Murashkin79d8fa72017-04-18 09:37:23 -07001488 AppendInstruction(ctor_fence);
Igor Murashkin6ef45672017-08-08 13:59:55 -07001489 MaybeRecordStat(
1490 compilation_stats_,
1491 MethodCompilationStat::kConstructorFenceGeneratedNew);
David Brazdildee58d62016-04-07 09:54:26 +00001492}
1493
Vladimir Marko2ab1bdd2018-07-12 09:59:56 +01001494static bool IsInBootImage(ObjPtr<mirror::Class> cls, const CompilerOptions& compiler_options)
1495 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko6a67bea2020-01-20 13:05:55 +00001496 if (Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(cls)) {
1497 return true;
1498 }
1499 if (compiler_options.IsBootImage() || compiler_options.IsBootImageExtension()) {
Vladimir Marko2ab1bdd2018-07-12 09:59:56 +01001500 std::string temp;
1501 const char* descriptor = cls->GetDescriptor(&temp);
1502 return compiler_options.IsImageClass(descriptor);
1503 } else {
Vladimir Marko6a67bea2020-01-20 13:05:55 +00001504 return false;
Vladimir Marko2ab1bdd2018-07-12 09:59:56 +01001505 }
1506}
1507
1508static bool IsSubClass(ObjPtr<mirror::Class> to_test, ObjPtr<mirror::Class> super_class)
1509 REQUIRES_SHARED(Locks::mutator_lock_) {
1510 return to_test != nullptr && !to_test->IsInterface() && to_test->IsSubClass(super_class);
1511}
1512
1513static bool HasTrivialClinit(ObjPtr<mirror::Class> klass, PointerSize pointer_size)
1514 REQUIRES_SHARED(Locks::mutator_lock_) {
1515 // Check if the class has encoded fields that trigger bytecode execution.
1516 // (Encoded fields are just a different representation of <clinit>.)
1517 if (klass->NumStaticFields() != 0u) {
1518 DCHECK(klass->GetClassDef() != nullptr);
1519 EncodedStaticFieldValueIterator it(klass->GetDexFile(), *klass->GetClassDef());
1520 for (; it.HasNext(); it.Next()) {
1521 switch (it.GetValueType()) {
1522 case EncodedArrayValueIterator::ValueType::kBoolean:
1523 case EncodedArrayValueIterator::ValueType::kByte:
1524 case EncodedArrayValueIterator::ValueType::kShort:
1525 case EncodedArrayValueIterator::ValueType::kChar:
1526 case EncodedArrayValueIterator::ValueType::kInt:
1527 case EncodedArrayValueIterator::ValueType::kLong:
1528 case EncodedArrayValueIterator::ValueType::kFloat:
1529 case EncodedArrayValueIterator::ValueType::kDouble:
1530 case EncodedArrayValueIterator::ValueType::kNull:
1531 case EncodedArrayValueIterator::ValueType::kString:
1532 // Primitive, null or j.l.String initialization is permitted.
1533 break;
1534 case EncodedArrayValueIterator::ValueType::kType:
1535 // Type initialization can load classes and execute bytecode through a class loader
1536 // which can execute arbitrary bytecode. We do not optimize for known class loaders;
1537 // kType is rarely used (if ever).
1538 return false;
1539 default:
1540 // Other types in the encoded static field list are rejected by the DexFileVerifier.
1541 LOG(FATAL) << "Unexpected type " << it.GetValueType();
1542 UNREACHABLE();
1543 }
1544 }
1545 }
1546 // Check if the class has <clinit> that executes arbitrary code.
1547 // Initialization of static fields of the class itself with constants is allowed.
1548 ArtMethod* clinit = klass->FindClassInitializer(pointer_size);
1549 if (clinit != nullptr) {
1550 const DexFile& dex_file = *clinit->GetDexFile();
1551 CodeItemInstructionAccessor accessor(dex_file, clinit->GetCodeItem());
1552 for (DexInstructionPcPair it : accessor) {
1553 switch (it->Opcode()) {
1554 case Instruction::CONST_4:
1555 case Instruction::CONST_16:
1556 case Instruction::CONST:
1557 case Instruction::CONST_HIGH16:
1558 case Instruction::CONST_WIDE_16:
1559 case Instruction::CONST_WIDE_32:
1560 case Instruction::CONST_WIDE:
1561 case Instruction::CONST_WIDE_HIGH16:
1562 case Instruction::CONST_STRING:
1563 case Instruction::CONST_STRING_JUMBO:
1564 // Primitive, null or j.l.String initialization is permitted.
1565 break;
1566 case Instruction::RETURN_VOID:
Vladimir Marko2ab1bdd2018-07-12 09:59:56 +01001567 break;
1568 case Instruction::SPUT:
1569 case Instruction::SPUT_WIDE:
1570 case Instruction::SPUT_OBJECT:
1571 case Instruction::SPUT_BOOLEAN:
1572 case Instruction::SPUT_BYTE:
1573 case Instruction::SPUT_CHAR:
1574 case Instruction::SPUT_SHORT:
1575 // Only initialization of a static field of the same class is permitted.
1576 if (dex_file.GetFieldId(it->VRegB_21c()).class_idx_ != klass->GetDexTypeIndex()) {
1577 return false;
1578 }
1579 break;
1580 case Instruction::NEW_ARRAY:
1581 // Only primitive arrays are permitted.
1582 if (Primitive::GetType(dex_file.GetTypeDescriptor(dex_file.GetTypeId(
1583 dex::TypeIndex(it->VRegC_22c())))[1]) == Primitive::kPrimNot) {
1584 return false;
1585 }
1586 break;
1587 case Instruction::APUT:
1588 case Instruction::APUT_WIDE:
1589 case Instruction::APUT_BOOLEAN:
1590 case Instruction::APUT_BYTE:
1591 case Instruction::APUT_CHAR:
1592 case Instruction::APUT_SHORT:
1593 case Instruction::FILL_ARRAY_DATA:
1594 case Instruction::NOP:
1595 // Allow initialization of primitive arrays (only constants can be stored).
1596 // Note: We expect NOPs used for fill-array-data-payload but accept all NOPs
1597 // (even unreferenced switch payloads if they make it through the verifier).
1598 break;
1599 default:
1600 return false;
1601 }
1602 }
1603 }
1604 return true;
1605}
1606
1607static bool HasTrivialInitialization(ObjPtr<mirror::Class> cls,
1608 const CompilerOptions& compiler_options)
1609 REQUIRES_SHARED(Locks::mutator_lock_) {
1610 Runtime* runtime = Runtime::Current();
1611 PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
1612
1613 // Check the superclass chain.
1614 for (ObjPtr<mirror::Class> klass = cls; klass != nullptr; klass = klass->GetSuperClass()) {
1615 if (klass->IsInitialized() && IsInBootImage(klass, compiler_options)) {
1616 break; // `klass` and its superclasses are already initialized in the boot image.
1617 }
1618 if (!HasTrivialClinit(klass, pointer_size)) {
1619 return false;
1620 }
1621 }
1622
1623 // Also check interfaces with default methods as they need to be initialized as well.
1624 ObjPtr<mirror::IfTable> iftable = cls->GetIfTable();
1625 DCHECK(iftable != nullptr);
1626 for (int32_t i = 0, count = iftable->Count(); i != count; ++i) {
1627 ObjPtr<mirror::Class> iface = iftable->GetInterface(i);
1628 if (!iface->HasDefaultMethods()) {
1629 continue; // Initializing `cls` does not initialize this interface.
1630 }
1631 if (iface->IsInitialized() && IsInBootImage(iface, compiler_options)) {
1632 continue; // This interface is already initialized in the boot image.
1633 }
1634 if (!HasTrivialClinit(iface, pointer_size)) {
1635 return false;
1636 }
1637 }
1638 return true;
1639}
1640
Vladimir Marko2f40d242020-04-08 12:56:45 +01001641bool HInstructionBuilder::IsInitialized(ObjPtr<mirror::Class> cls) const {
Andreas Gampefa4333d2017-02-14 11:10:34 -08001642 if (cls == nullptr) {
David Brazdildee58d62016-04-07 09:54:26 +00001643 return false;
1644 }
1645
Vladimir Marko51b8aaf2017-06-09 15:17:05 +01001646 // Check if the class will be initialized at runtime.
1647 if (cls->IsInitialized()) {
Vladimir Marko695348f2020-05-19 14:42:02 +01001648 const CompilerOptions& compiler_options = code_generator_->GetCompilerOptions();
1649 if (compiler_options.IsAotCompiler()) {
Nicolas Geoffraya48c3df2019-06-27 13:11:12 +00001650 // Assume loaded only if klass is in the boot image. App classes cannot be assumed
1651 // loaded because we don't even know what class loader will be used to load them.
Vladimir Marko695348f2020-05-19 14:42:02 +01001652 if (IsInBootImage(cls, compiler_options)) {
Nicolas Geoffraya48c3df2019-06-27 13:11:12 +00001653 return true;
1654 }
1655 } else {
Vladimir Marko695348f2020-05-19 14:42:02 +01001656 DCHECK(compiler_options.IsJitCompiler());
Nicolas Geoffraya48c3df2019-06-27 13:11:12 +00001657 if (Runtime::Current()->GetJit()->CanAssumeInitialized(
Vladimir Marko2f40d242020-04-08 12:56:45 +01001658 cls,
Vladimir Marko695348f2020-05-19 14:42:02 +01001659 compiler_options.IsJitCompilerForSharedCode())) {
Nicolas Geoffraya48c3df2019-06-27 13:11:12 +00001660 // For JIT, the class cannot revert to an uninitialized state.
1661 return true;
1662 }
Vladimir Marko51b8aaf2017-06-09 15:17:05 +01001663 }
1664 }
1665
Vladimir Marko7f260d42018-10-30 18:09:55 +00001666 // We can avoid the class initialization check for `cls` in static methods and constructors
1667 // in the very same class; invoking a static method involves a class initialization check
1668 // and so does the instance allocation that must be executed before invoking a constructor.
1669 // Other instance methods of the same class can run on an escaped instance
Vladimir Marko51b8aaf2017-06-09 15:17:05 +01001670 // of an erroneous class. Even a superclass may need to be checked as the subclass
1671 // can be completely initialized while the superclass is initializing and the subclass
1672 // remains initialized when the superclass initializer throws afterwards. b/62478025
1673 // Note: The HClinitCheck+HInvokeStaticOrDirect merging can still apply.
Vladimir Markoa2c211c2018-11-01 09:50:52 +00001674 auto is_static_method_or_constructor_of_cls = [cls](const DexCompilationUnit& compilation_unit)
1675 REQUIRES_SHARED(Locks::mutator_lock_) {
1676 return (compilation_unit.GetAccessFlags() & (kAccStatic | kAccConstructor)) != 0u &&
Vladimir Marko2f40d242020-04-08 12:56:45 +01001677 compilation_unit.GetCompilingClass().Get() == cls;
Vladimir Markoa2c211c2018-11-01 09:50:52 +00001678 };
1679 if (is_static_method_or_constructor_of_cls(*outer_compilation_unit_) ||
1680 // Check also the innermost method. Though excessive copies of ClinitCheck can be
1681 // eliminated by GVN, that happens only after the decision whether to inline the
1682 // graph or not and that may depend on the presence of the ClinitCheck.
1683 // TODO: We should walk over the entire inlined method chain, but we don't pass that
1684 // information to the builder.
1685 is_static_method_or_constructor_of_cls(*dex_compilation_unit_)) {
Vladimir Marko2ab1bdd2018-07-12 09:59:56 +01001686 return true;
1687 }
David Brazdildee58d62016-04-07 09:54:26 +00001688
Vladimir Marko2ab1bdd2018-07-12 09:59:56 +01001689 // Otherwise, we may be able to avoid the check if `cls` is a superclass of a method being
1690 // compiled here (anywhere in the inlining chain) as the `cls` must have started initializing
1691 // before calling any `cls` or subclass methods. Static methods require a clinit check and
1692 // instance methods require an instance which cannot be created before doing a clinit check.
1693 // When a subclass of `cls` starts initializing, it starts initializing its superclass
1694 // chain up to `cls` without running any bytecode, i.e. without any opportunity for circular
1695 // initialization weirdness.
1696 //
1697 // If the initialization of `cls` is trivial (`cls` and its superclasses and superinterfaces
1698 // with default methods initialize only their own static fields using constant values), it must
1699 // complete, either successfully or by throwing and marking `cls` erroneous, without allocating
1700 // any instances of `cls` or subclasses (or any other class) and without calling any methods.
1701 // If it completes by throwing, no instances of `cls` shall be created and no subclass method
1702 // bytecode shall execute (see above), therefore the instruction we're building shall be
1703 // unreachable. By reaching the instruction, we know that `cls` was initialized successfully.
1704 //
1705 // TODO: We should walk over the entire inlined methods chain, but we don't pass that
1706 // information to the builder. (We could also check if we're guaranteed a non-null instance
1707 // of `cls` at this location but that's outside the scope of the instruction builder.)
Vladimir Marko2f40d242020-04-08 12:56:45 +01001708 bool is_subclass = IsSubClass(outer_compilation_unit_->GetCompilingClass().Get(), cls);
Vladimir Markoa2c211c2018-11-01 09:50:52 +00001709 if (dex_compilation_unit_ != outer_compilation_unit_) {
1710 is_subclass = is_subclass ||
Vladimir Marko2f40d242020-04-08 12:56:45 +01001711 IsSubClass(dex_compilation_unit_->GetCompilingClass().Get(), cls);
Vladimir Markoa2c211c2018-11-01 09:50:52 +00001712 }
Vladimir Marko2f40d242020-04-08 12:56:45 +01001713 if (is_subclass && HasTrivialInitialization(cls, code_generator_->GetCompilerOptions())) {
Vladimir Marko2ab1bdd2018-07-12 09:59:56 +01001714 return true;
1715 }
David Brazdildee58d62016-04-07 09:54:26 +00001716
1717 return false;
1718}
1719
1720HClinitCheck* HInstructionBuilder::ProcessClinitCheckForInvoke(
Vladimir Markofca0b492018-07-23 15:30:52 +01001721 uint32_t dex_pc,
1722 ArtMethod* resolved_method,
1723 HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) {
Vladimir Marko2f40d242020-04-08 12:56:45 +01001724 ScopedObjectAccess soa(Thread::Current());
1725 ObjPtr<mirror::Class> klass = resolved_method->GetDeclaringClass();
David Brazdildee58d62016-04-07 09:54:26 +00001726
1727 HClinitCheck* clinit_check = nullptr;
Vladimir Markoa2c211c2018-11-01 09:50:52 +00001728 if (IsInitialized(klass)) {
David Brazdildee58d62016-04-07 09:54:26 +00001729 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00001730 } else {
Vladimir Marko02ca05a2020-05-12 13:58:51 +01001731 Handle<mirror::Class> h_klass = graph_->GetHandleCache()->NewHandle(klass);
Vladimir Marko2f40d242020-04-08 12:56:45 +01001732 HLoadClass* cls = BuildLoadClass(h_klass->GetDexTypeIndex(),
1733 h_klass->GetDexFile(),
1734 h_klass,
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00001735 dex_pc,
Andreas Gampe3db70682018-12-26 15:12:03 -08001736 /* needs_access_check= */ false);
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00001737 if (cls != nullptr) {
1738 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
Vladimir Markoca6fff82017-10-03 14:49:14 +01001739 clinit_check = new (allocator_) HClinitCheck(cls, dex_pc);
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00001740 AppendInstruction(clinit_check);
Vladimir Marko2f40d242020-04-08 12:56:45 +01001741 } else {
1742 // Let the invoke handle this with an implicit class initialization check.
1743 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit;
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00001744 }
David Brazdildee58d62016-04-07 09:54:26 +00001745 }
1746 return clinit_check;
1747}
1748
Vladimir Marko5f846072020-04-09 13:20:11 +01001749bool HInstructionBuilder::SetupInvokeArguments(HInstruction* invoke,
Treehugger Robot2c5827a2018-05-17 22:26:08 +00001750 const InstructionOperands& operands,
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001751 const char* shorty,
Vladimir Marko5f846072020-04-09 13:20:11 +01001752 ReceiverArg receiver_arg) {
1753 // Note: The `invoke` can be an intrinsic replacement, so not necessaritly HInvoke.
1754 // In that case, do not log errors, they shall be reported when we try to build the HInvoke.
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001755 uint32_t shorty_index = 1; // Skip the return type.
Treehugger Robot2c5827a2018-05-17 22:26:08 +00001756 const size_t number_of_operands = operands.GetNumberOfOperands();
Vladimir Marko5f846072020-04-09 13:20:11 +01001757 bool argument_length_error = false;
1758
1759 size_t start_index = 0u;
1760 size_t argument_index = 0u;
1761 if (receiver_arg != ReceiverArg::kNone) {
1762 if (number_of_operands == 0u) {
1763 argument_length_error = true;
1764 } else {
1765 start_index = 1u;
1766 if (receiver_arg != ReceiverArg::kIgnored) {
1767 uint32_t obj_reg = operands.GetOperand(0u);
1768 HInstruction* arg = (receiver_arg == ReceiverArg::kPlainArg)
1769 ? LoadLocal(obj_reg, DataType::Type::kReference)
1770 : LoadNullCheckedLocal(obj_reg, invoke->GetDexPc());
1771 if (receiver_arg != ReceiverArg::kNullCheckedOnly) {
1772 invoke->SetRawInputAt(0u, arg);
1773 argument_index = 1u;
1774 }
1775 }
1776 }
1777 }
1778
1779 for (size_t i = start_index; i < number_of_operands; ++i, ++argument_index) {
1780 // Make sure we don't go over the expected arguments or over the number of
1781 // dex registers given. If the instruction was seen as dead by the verifier,
1782 // it hasn't been properly checked.
1783 if (UNLIKELY(shorty[shorty_index] == 0)) {
1784 argument_length_error = true;
1785 break;
1786 }
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001787 DataType::Type type = DataType::FromShorty(shorty[shorty_index++]);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001788 bool is_wide = (type == DataType::Type::kInt64) || (type == DataType::Type::kFloat64);
Treehugger Robot2c5827a2018-05-17 22:26:08 +00001789 if (is_wide && ((i + 1 == number_of_operands) ||
1790 (operands.GetOperand(i) + 1 != operands.GetOperand(i + 1)))) {
Vladimir Marko5f846072020-04-09 13:20:11 +01001791 if (invoke->IsInvoke()) {
1792 // Longs and doubles should be in pairs, that is, sequential registers. The verifier should
1793 // reject any class where this is violated. However, the verifier only does these checks
1794 // on non trivially dead instructions, so we just bailout the compilation.
1795 VLOG(compiler) << "Did not compile "
1796 << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
1797 << " because of non-sequential dex register pair in wide argument";
1798 MaybeRecordStat(compilation_stats_,
1799 MethodCompilationStat::kNotCompiledMalformedOpcode);
1800 }
David Brazdildee58d62016-04-07 09:54:26 +00001801 return false;
1802 }
Treehugger Robot2c5827a2018-05-17 22:26:08 +00001803 HInstruction* arg = LoadLocal(operands.GetOperand(i), type);
Vladimir Marko5f846072020-04-09 13:20:11 +01001804 DCHECK(invoke->InputAt(argument_index) == nullptr);
1805 invoke->SetRawInputAt(argument_index, arg);
David Brazdildee58d62016-04-07 09:54:26 +00001806 if (is_wide) {
Vladimir Marko5f846072020-04-09 13:20:11 +01001807 ++i;
David Brazdildee58d62016-04-07 09:54:26 +00001808 }
1809 }
1810
Vladimir Marko5f846072020-04-09 13:20:11 +01001811 argument_length_error = argument_length_error || shorty[shorty_index] != 0;
1812 if (argument_length_error) {
1813 if (invoke->IsInvoke()) {
1814 VLOG(compiler) << "Did not compile "
1815 << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
1816 << " because of wrong number of arguments in invoke instruction";
1817 MaybeRecordStat(compilation_stats_,
1818 MethodCompilationStat::kNotCompiledMalformedOpcode);
1819 }
David Brazdildee58d62016-04-07 09:54:26 +00001820 return false;
1821 }
1822
1823 if (invoke->IsInvokeStaticOrDirect() &&
1824 HInvokeStaticOrDirect::NeedsCurrentMethodInput(
Vladimir Marko86c87522020-05-11 16:55:55 +01001825 invoke->AsInvokeStaticOrDirect()->GetDispatchInfo())) {
1826 DCHECK_EQ(argument_index, invoke->AsInvokeStaticOrDirect()->GetCurrentMethodIndex());
Vladimir Marko5f846072020-04-09 13:20:11 +01001827 DCHECK(invoke->InputAt(argument_index) == nullptr);
1828 invoke->SetRawInputAt(argument_index, graph_->GetCurrentMethod());
David Brazdildee58d62016-04-07 09:54:26 +00001829 }
1830
Nicolas Geoffray8d34a182020-09-16 09:46:58 +01001831 if (invoke->IsInvokeInterface() &&
1832 (invoke->AsInvokeInterface()->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive)) {
1833 invoke->SetRawInputAt(invoke->AsInvokeInterface()->GetNumberOfArguments() - 1,
1834 graph_->GetCurrentMethod());
1835 }
1836
David Brazdildee58d62016-04-07 09:54:26 +00001837 return true;
1838}
1839
1840bool HInstructionBuilder::HandleInvoke(HInvoke* invoke,
Treehugger Robot2c5827a2018-05-17 22:26:08 +00001841 const InstructionOperands& operands,
Orion Hodson4c8e12e2018-05-18 08:33:20 +01001842 const char* shorty,
Vladimir Marko5f846072020-04-09 13:20:11 +01001843 bool is_unresolved) {
David Brazdildee58d62016-04-07 09:54:26 +00001844 DCHECK(!invoke->IsInvokeStaticOrDirect() || !invoke->AsInvokeStaticOrDirect()->IsStringInit());
1845
Vladimir Marko5f846072020-04-09 13:20:11 +01001846 ReceiverArg receiver_arg = (invoke->GetInvokeType() == InvokeType::kStatic)
1847 ? ReceiverArg::kNone
1848 : (is_unresolved ? ReceiverArg::kPlainArg : ReceiverArg::kNullCheckedArg);
1849 if (!SetupInvokeArguments(invoke, operands, shorty, receiver_arg)) {
David Brazdildee58d62016-04-07 09:54:26 +00001850 return false;
1851 }
1852
David Brazdildee58d62016-04-07 09:54:26 +00001853 AppendInstruction(invoke);
1854 latest_result_ = invoke;
1855
1856 return true;
1857}
1858
Vladimir Marko5f846072020-04-09 13:20:11 +01001859bool HInstructionBuilder::BuildSimpleIntrinsic(ArtMethod* method,
1860 uint32_t dex_pc,
1861 const InstructionOperands& operands,
1862 const char* shorty) {
1863 Intrinsics intrinsic = static_cast<Intrinsics>(method->GetIntrinsic());
1864 DCHECK_NE(intrinsic, Intrinsics::kNone);
1865 constexpr DataType::Type kInt32 = DataType::Type::kInt32;
1866 constexpr DataType::Type kInt64 = DataType::Type::kInt64;
1867 constexpr DataType::Type kFloat32 = DataType::Type::kFloat32;
1868 constexpr DataType::Type kFloat64 = DataType::Type::kFloat64;
1869 ReceiverArg receiver_arg = method->IsStatic() ? ReceiverArg::kNone : ReceiverArg::kNullCheckedArg;
1870 HInstruction* instruction = nullptr;
1871 switch (intrinsic) {
1872 case Intrinsics::kIntegerRotateRight:
1873 case Intrinsics::kIntegerRotateLeft:
1874 // For rotate left, we negate the distance below.
1875 instruction = new (allocator_) HRor(kInt32, /*value=*/ nullptr, /*distance=*/ nullptr);
1876 break;
1877 case Intrinsics::kLongRotateRight:
1878 case Intrinsics::kLongRotateLeft:
1879 // For rotate left, we negate the distance below.
1880 instruction = new (allocator_) HRor(kInt64, /*value=*/ nullptr, /*distance=*/ nullptr);
1881 break;
1882 case Intrinsics::kIntegerCompare:
1883 instruction = new (allocator_) HCompare(
1884 kInt32, /*first=*/ nullptr, /*second=*/ nullptr, ComparisonBias::kNoBias, dex_pc);
1885 break;
1886 case Intrinsics::kLongCompare:
1887 instruction = new (allocator_) HCompare(
1888 kInt64, /*first=*/ nullptr, /*second=*/ nullptr, ComparisonBias::kNoBias, dex_pc);
1889 break;
1890 case Intrinsics::kIntegerSignum:
1891 instruction = new (allocator_) HCompare(
1892 kInt32, /*first=*/ nullptr, graph_->GetIntConstant(0), ComparisonBias::kNoBias, dex_pc);
1893 break;
1894 case Intrinsics::kLongSignum:
1895 instruction = new (allocator_) HCompare(
1896 kInt64, /*first=*/ nullptr, graph_->GetLongConstant(0), ComparisonBias::kNoBias, dex_pc);
1897 break;
1898 case Intrinsics::kFloatIsNaN:
1899 case Intrinsics::kDoubleIsNaN: {
1900 // IsNaN(x) is the same as x != x.
1901 instruction = new (allocator_) HNotEqual(/*first=*/ nullptr, /*second=*/ nullptr, dex_pc);
1902 instruction->AsCondition()->SetBias(ComparisonBias::kLtBias);
1903 break;
1904 }
1905 case Intrinsics::kStringCharAt:
1906 // We treat String as an array to allow DCE and BCE to seamlessly work on strings.
1907 instruction = new (allocator_) HArrayGet(/*array=*/ nullptr,
1908 /*index=*/ nullptr,
1909 DataType::Type::kUint16,
1910 SideEffects::None(), // Strings are immutable.
1911 dex_pc,
1912 /*is_string_char_at=*/ true);
1913 break;
1914 case Intrinsics::kStringIsEmpty:
1915 case Intrinsics::kStringLength:
1916 // We treat String as an array to allow DCE and BCE to seamlessly work on strings.
1917 // For String.isEmpty(), we add a comparison with 0 below.
1918 instruction =
1919 new (allocator_) HArrayLength(/*array=*/ nullptr, dex_pc, /* is_string_length= */ true);
1920 break;
1921 case Intrinsics::kUnsafeLoadFence:
Sorin Basca2f01e8e2021-06-18 06:44:07 +00001922 case Intrinsics::kJdkUnsafeLoadFence:
Vladimir Marko5f846072020-04-09 13:20:11 +01001923 receiver_arg = ReceiverArg::kNullCheckedOnly;
1924 instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kLoadAny, dex_pc);
1925 break;
1926 case Intrinsics::kUnsafeStoreFence:
Sorin Basca2f01e8e2021-06-18 06:44:07 +00001927 case Intrinsics::kJdkUnsafeStoreFence:
Vladimir Marko5f846072020-04-09 13:20:11 +01001928 receiver_arg = ReceiverArg::kNullCheckedOnly;
1929 instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kAnyStore, dex_pc);
1930 break;
1931 case Intrinsics::kUnsafeFullFence:
Sorin Basca2f01e8e2021-06-18 06:44:07 +00001932 case Intrinsics::kJdkUnsafeFullFence:
Vladimir Marko5f846072020-04-09 13:20:11 +01001933 receiver_arg = ReceiverArg::kNullCheckedOnly;
1934 instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kAnyAny, dex_pc);
1935 break;
1936 case Intrinsics::kVarHandleFullFence:
1937 instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kAnyAny, dex_pc);
1938 break;
1939 case Intrinsics::kVarHandleAcquireFence:
1940 instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kLoadAny, dex_pc);
1941 break;
1942 case Intrinsics::kVarHandleReleaseFence:
1943 instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kAnyStore, dex_pc);
1944 break;
1945 case Intrinsics::kVarHandleLoadLoadFence:
1946 instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kLoadAny, dex_pc);
1947 break;
1948 case Intrinsics::kVarHandleStoreStoreFence:
1949 instruction = new (allocator_) HMemoryBarrier(MemBarrierKind::kStoreStore, dex_pc);
1950 break;
1951 case Intrinsics::kMathMinIntInt:
1952 instruction = new (allocator_) HMin(kInt32, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
1953 break;
1954 case Intrinsics::kMathMinLongLong:
1955 instruction = new (allocator_) HMin(kInt64, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
1956 break;
1957 case Intrinsics::kMathMinFloatFloat:
1958 instruction = new (allocator_) HMin(kFloat32, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
1959 break;
1960 case Intrinsics::kMathMinDoubleDouble:
1961 instruction = new (allocator_) HMin(kFloat64, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
1962 break;
1963 case Intrinsics::kMathMaxIntInt:
1964 instruction = new (allocator_) HMax(kInt32, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
1965 break;
1966 case Intrinsics::kMathMaxLongLong:
1967 instruction = new (allocator_) HMax(kInt64, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
1968 break;
1969 case Intrinsics::kMathMaxFloatFloat:
1970 instruction = new (allocator_) HMax(kFloat32, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
1971 break;
1972 case Intrinsics::kMathMaxDoubleDouble:
1973 instruction = new (allocator_) HMax(kFloat64, /*left=*/ nullptr, /*right=*/ nullptr, dex_pc);
1974 break;
1975 case Intrinsics::kMathAbsInt:
1976 instruction = new (allocator_) HAbs(kInt32, /*input=*/ nullptr, dex_pc);
1977 break;
1978 case Intrinsics::kMathAbsLong:
1979 instruction = new (allocator_) HAbs(kInt64, /*input=*/ nullptr, dex_pc);
1980 break;
1981 case Intrinsics::kMathAbsFloat:
1982 instruction = new (allocator_) HAbs(kFloat32, /*input=*/ nullptr, dex_pc);
1983 break;
1984 case Intrinsics::kMathAbsDouble:
1985 instruction = new (allocator_) HAbs(kFloat64, /*input=*/ nullptr, dex_pc);
1986 break;
1987 default:
1988 // We do not have intermediate representation for other intrinsics.
1989 return false;
1990 }
1991 DCHECK(instruction != nullptr);
1992 if (!SetupInvokeArguments(instruction, operands, shorty, receiver_arg)) {
1993 return false;
1994 }
1995
1996 switch (intrinsic) {
1997 case Intrinsics::kIntegerRotateLeft:
1998 case Intrinsics::kLongRotateLeft: {
1999 // Negate the distance value for rotate left.
2000 DCHECK(instruction->IsRor());
2001 HNeg* neg = new (allocator_) HNeg(kInt32, instruction->InputAt(1u));
2002 AppendInstruction(neg);
2003 instruction->SetRawInputAt(1u, neg);
2004 break;
2005 }
2006 case Intrinsics::kFloatIsNaN:
2007 case Intrinsics::kDoubleIsNaN:
2008 // Set the second input to be the same as first.
2009 DCHECK(instruction->IsNotEqual());
2010 DCHECK(instruction->InputAt(1u) == nullptr);
2011 instruction->SetRawInputAt(1u, instruction->InputAt(0u));
2012 break;
2013 case Intrinsics::kStringCharAt: {
2014 // Add bounds check.
2015 HInstruction* array = instruction->InputAt(0u);
2016 HInstruction* index = instruction->InputAt(1u);
2017 HInstruction* length =
2018 new (allocator_) HArrayLength(array, dex_pc, /*is_string_length=*/ true);
2019 AppendInstruction(length);
2020 HBoundsCheck* bounds_check =
2021 new (allocator_) HBoundsCheck(index, length, dex_pc, /*is_string_char_at=*/ true);
2022 AppendInstruction(bounds_check);
2023 graph_->SetHasBoundsChecks(true);
2024 instruction->SetRawInputAt(1u, bounds_check);
2025 break;
2026 }
2027 case Intrinsics::kStringIsEmpty: {
2028 // Compare the length with 0.
2029 DCHECK(instruction->IsArrayLength());
2030 AppendInstruction(instruction);
2031 HEqual* equal = new (allocator_) HEqual(instruction, graph_->GetIntConstant(0), dex_pc);
2032 instruction = equal;
2033 break;
2034 }
2035 default:
2036 break;
2037 }
2038
2039 AppendInstruction(instruction);
2040 latest_result_ = instruction;
2041
2042 return true;
2043}
2044
David Brazdildee58d62016-04-07 09:54:26 +00002045bool HInstructionBuilder::HandleStringInit(HInvoke* invoke,
Treehugger Robot2c5827a2018-05-17 22:26:08 +00002046 const InstructionOperands& operands,
Orion Hodson4c8e12e2018-05-18 08:33:20 +01002047 const char* shorty) {
David Brazdildee58d62016-04-07 09:54:26 +00002048 DCHECK(invoke->IsInvokeStaticOrDirect());
2049 DCHECK(invoke->AsInvokeStaticOrDirect()->IsStringInit());
2050
Vladimir Marko5f846072020-04-09 13:20:11 +01002051 if (!SetupInvokeArguments(invoke, operands, shorty, ReceiverArg::kIgnored)) {
David Brazdildee58d62016-04-07 09:54:26 +00002052 return false;
2053 }
2054
2055 AppendInstruction(invoke);
2056
2057 // This is a StringFactory call, not an actual String constructor. Its result
2058 // replaces the empty String pre-allocated by NewInstance.
Treehugger Robot2c5827a2018-05-17 22:26:08 +00002059 uint32_t orig_this_reg = operands.GetOperand(0);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002060 HInstruction* arg_this = LoadLocal(orig_this_reg, DataType::Type::kReference);
David Brazdildee58d62016-04-07 09:54:26 +00002061
2062 // Replacing the NewInstance might render it redundant. Keep a list of these
Nicolas Geoffray8a62a4c2018-07-03 09:39:07 +01002063 // to be visited once it is clear whether it has remaining uses.
David Brazdildee58d62016-04-07 09:54:26 +00002064 if (arg_this->IsNewInstance()) {
2065 ssa_builder_->AddUninitializedString(arg_this->AsNewInstance());
Nicolas Geoffray8a62a4c2018-07-03 09:39:07 +01002066 } else {
2067 DCHECK(arg_this->IsPhi());
2068 // We can get a phi as input of a String.<init> if there is a loop between the
2069 // allocation and the String.<init> call. As we don't know which other phis might alias
Nicolas Geoffray0846a8f2018-09-12 15:21:07 +01002070 // with `arg_this`, we keep a record of those invocations so we can later replace
2071 // the allocation with the invocation.
2072 // Add the actual 'this' input so the analysis knows what is the allocation instruction.
2073 // The input will be removed during the analysis.
2074 invoke->AddInput(arg_this);
2075 ssa_builder_->AddUninitializedStringPhi(invoke);
2076 }
2077 // Walk over all vregs and replace any occurrence of `arg_this` with `invoke`.
2078 for (size_t vreg = 0, e = current_locals_->size(); vreg < e; ++vreg) {
2079 if ((*current_locals_)[vreg] == arg_this) {
2080 (*current_locals_)[vreg] = invoke;
2081 }
David Brazdildee58d62016-04-07 09:54:26 +00002082 }
David Brazdildee58d62016-04-07 09:54:26 +00002083 return true;
2084}
2085
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002086static DataType::Type GetFieldAccessType(const DexFile& dex_file, uint16_t field_index) {
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002087 const dex::FieldId& field_id = dex_file.GetFieldId(field_index);
David Brazdildee58d62016-04-07 09:54:26 +00002088 const char* type = dex_file.GetFieldTypeDescriptor(field_id);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002089 return DataType::FromShorty(type[0]);
David Brazdildee58d62016-04-07 09:54:26 +00002090}
2091
2092bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instruction,
2093 uint32_t dex_pc,
Nicolas Geoffray4924ea92021-03-23 08:25:31 +00002094 bool is_put) {
David Brazdildee58d62016-04-07 09:54:26 +00002095 uint32_t source_or_dest_reg = instruction.VRegA_22c();
2096 uint32_t obj_reg = instruction.VRegB_22c();
Nicolas Geoffray4924ea92021-03-23 08:25:31 +00002097 uint16_t field_index = instruction.VRegC_22c();
David Brazdildee58d62016-04-07 09:54:26 +00002098
2099 ScopedObjectAccess soa(Thread::Current());
Andreas Gampe3db70682018-12-26 15:12:03 -08002100 ArtField* resolved_field = ResolveField(field_index, /* is_static= */ false, is_put);
David Brazdildee58d62016-04-07 09:54:26 +00002101
Aart Bik14154132016-06-02 17:53:58 -07002102 // Generate an explicit null check on the reference, unless the field access
2103 // is unresolved. In that case, we rely on the runtime to perform various
2104 // checks first, followed by a null check.
2105 HInstruction* object = (resolved_field == nullptr)
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002106 ? LoadLocal(obj_reg, DataType::Type::kReference)
Aart Bik14154132016-06-02 17:53:58 -07002107 : LoadNullCheckedLocal(obj_reg, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002108
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002109 DataType::Type field_type = GetFieldAccessType(*dex_file_, field_index);
David Brazdildee58d62016-04-07 09:54:26 +00002110 if (is_put) {
2111 HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
2112 HInstruction* field_set = nullptr;
2113 if (resolved_field == nullptr) {
Igor Murashkin1e065a52017-08-09 13:20:34 -07002114 MaybeRecordStat(compilation_stats_,
2115 MethodCompilationStat::kUnresolvedField);
Vladimir Markoca6fff82017-10-03 14:49:14 +01002116 field_set = new (allocator_) HUnresolvedInstanceFieldSet(object,
2117 value,
2118 field_type,
2119 field_index,
2120 dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002121 } else {
2122 uint16_t class_def_index = resolved_field->GetDeclaringClass()->GetDexClassDefIndex();
Vladimir Markoca6fff82017-10-03 14:49:14 +01002123 field_set = new (allocator_) HInstanceFieldSet(object,
2124 value,
2125 resolved_field,
2126 field_type,
2127 resolved_field->GetOffset(),
2128 resolved_field->IsVolatile(),
2129 field_index,
2130 class_def_index,
2131 *dex_file_,
2132 dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002133 }
2134 AppendInstruction(field_set);
2135 } else {
2136 HInstruction* field_get = nullptr;
2137 if (resolved_field == nullptr) {
Igor Murashkin1e065a52017-08-09 13:20:34 -07002138 MaybeRecordStat(compilation_stats_,
2139 MethodCompilationStat::kUnresolvedField);
Vladimir Markoca6fff82017-10-03 14:49:14 +01002140 field_get = new (allocator_) HUnresolvedInstanceFieldGet(object,
2141 field_type,
2142 field_index,
2143 dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002144 } else {
2145 uint16_t class_def_index = resolved_field->GetDeclaringClass()->GetDexClassDefIndex();
Vladimir Markoca6fff82017-10-03 14:49:14 +01002146 field_get = new (allocator_) HInstanceFieldGet(object,
2147 resolved_field,
2148 field_type,
2149 resolved_field->GetOffset(),
2150 resolved_field->IsVolatile(),
2151 field_index,
2152 class_def_index,
2153 *dex_file_,
2154 dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002155 }
2156 AppendInstruction(field_get);
2157 UpdateLocal(source_or_dest_reg, field_get);
2158 }
2159
2160 return true;
2161}
2162
David Brazdildee58d62016-04-07 09:54:26 +00002163void HInstructionBuilder::BuildUnresolvedStaticFieldAccess(const Instruction& instruction,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +00002164 uint32_t dex_pc,
2165 bool is_put,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002166 DataType::Type field_type) {
David Brazdildee58d62016-04-07 09:54:26 +00002167 uint32_t source_or_dest_reg = instruction.VRegA_21c();
2168 uint16_t field_index = instruction.VRegB_21c();
2169
2170 if (is_put) {
2171 HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
2172 AppendInstruction(
Vladimir Markoca6fff82017-10-03 14:49:14 +01002173 new (allocator_) HUnresolvedStaticFieldSet(value, field_type, field_index, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00002174 } else {
Vladimir Markoca6fff82017-10-03 14:49:14 +01002175 AppendInstruction(new (allocator_) HUnresolvedStaticFieldGet(field_type, field_index, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00002176 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
2177 }
2178}
2179
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002180ArtField* HInstructionBuilder::ResolveField(uint16_t field_idx, bool is_static, bool is_put) {
2181 ScopedObjectAccess soa(Thread::Current());
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002182
2183 ClassLinker* class_linker = dex_compilation_unit_->GetClassLinker();
Vladimir Marko8d6768d2017-03-14 10:13:21 +00002184 Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader();
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002185
Nicolas Geoffraycb5f97d2021-01-05 15:30:41 +00002186 ArtField* resolved_field = class_linker->ResolveFieldJLS(field_idx,
2187 dex_compilation_unit_->GetDexCache(),
2188 class_loader);
Nicolas Geoffrayf3688822020-03-25 15:04:03 +00002189 DCHECK_EQ(resolved_field == nullptr, soa.Self()->IsExceptionPending())
2190 << "field="
2191 << ((resolved_field == nullptr) ? "null" : resolved_field->PrettyField())
2192 << ", exception="
2193 << (soa.Self()->IsExceptionPending() ? soa.Self()->GetException()->Dump() : "null");
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002194 if (UNLIKELY(resolved_field == nullptr)) {
Vladimir Markoa2c211c2018-11-01 09:50:52 +00002195 // Clean up any exception left by field resolution.
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002196 soa.Self()->ClearException();
2197 return nullptr;
2198 }
2199
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002200 if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
2201 return nullptr;
2202 }
2203
2204 // Check access.
Vladimir Markoa2c211c2018-11-01 09:50:52 +00002205 Handle<mirror::Class> compiling_class = dex_compilation_unit_->GetCompilingClass();
Andreas Gampefa4333d2017-02-14 11:10:34 -08002206 if (compiling_class == nullptr) {
Vladimir Marko4100e5e2020-08-26 16:44:01 +01002207 // Check if the declaring class or referencing class is accessible.
2208 SamePackageCompare same_package(*dex_compilation_unit_);
2209 ObjPtr<mirror::Class> declaring_class = resolved_field->GetDeclaringClass();
2210 bool declaring_class_accessible = declaring_class->IsPublic() || same_package(declaring_class);
2211 if (!declaring_class_accessible) {
2212 // It is possible to access members from an inaccessible superclass
2213 // by referencing them through an accessible subclass.
2214 ObjPtr<mirror::Class> referenced_class = class_linker->LookupResolvedType(
2215 dex_compilation_unit_->GetDexFile()->GetFieldId(field_idx).class_idx_,
2216 dex_compilation_unit_->GetDexCache().Get(),
2217 class_loader.Get());
2218 DCHECK(referenced_class != nullptr); // Must have been resolved when resolving the field.
2219 if (!referenced_class->IsPublic() && !same_package(referenced_class)) {
2220 return nullptr;
2221 }
2222 }
2223 // Check whether the field itself is accessible.
2224 // Since the referrer is unresolved but the field is resolved, it cannot be
2225 // inside the same class, so a private field is known to be inaccessible.
2226 // And without a resolved referrer, we cannot check for protected member access
2227 // in superlass, so we handle only access to public member or within the package.
2228 if (resolved_field->IsPrivate() ||
2229 (!resolved_field->IsPublic() && !declaring_class_accessible)) {
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002230 return nullptr;
2231 }
2232 } else if (!compiling_class->CanAccessResolvedField(resolved_field->GetDeclaringClass(),
2233 resolved_field,
2234 dex_compilation_unit_->GetDexCache().Get(),
2235 field_idx)) {
2236 return nullptr;
2237 }
2238
2239 if (is_put &&
2240 resolved_field->IsFinal() &&
2241 (compiling_class.Get() != resolved_field->GetDeclaringClass())) {
2242 // Final fields can only be updated within their own class.
2243 // TODO: Only allow it in constructors. b/34966607.
2244 return nullptr;
2245 }
2246
Nicolas Geoffray396198b2020-06-16 12:02:45 +01002247 StackArtFieldHandleScope<1> rhs(soa.Self());
2248 ReflectiveHandle<ArtField> resolved_field_handle(rhs.NewHandle(resolved_field));
2249 if (resolved_field->ResolveType().IsNull()) {
2250 // ArtField::ResolveType() may fail as evidenced with a dexing bug (b/78788577).
2251 soa.Self()->ClearException();
2252 return nullptr; // Failure
2253 }
2254 return resolved_field_handle.Get();
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002255}
2256
Nicolas Geoffraydbb9aef2017-11-23 10:44:11 +00002257void HInstructionBuilder::BuildStaticFieldAccess(const Instruction& instruction,
David Brazdildee58d62016-04-07 09:54:26 +00002258 uint32_t dex_pc,
2259 bool is_put) {
2260 uint32_t source_or_dest_reg = instruction.VRegA_21c();
2261 uint16_t field_index = instruction.VRegB_21c();
2262
2263 ScopedObjectAccess soa(Thread::Current());
Andreas Gampe3db70682018-12-26 15:12:03 -08002264 ArtField* resolved_field = ResolveField(field_index, /* is_static= */ true, is_put);
David Brazdildee58d62016-04-07 09:54:26 +00002265
2266 if (resolved_field == nullptr) {
Igor Murashkin1e065a52017-08-09 13:20:34 -07002267 MaybeRecordStat(compilation_stats_,
2268 MethodCompilationStat::kUnresolvedField);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002269 DataType::Type field_type = GetFieldAccessType(*dex_file_, field_index);
David Brazdildee58d62016-04-07 09:54:26 +00002270 BuildUnresolvedStaticFieldAccess(instruction, dex_pc, is_put, field_type);
Nicolas Geoffraydbb9aef2017-11-23 10:44:11 +00002271 return;
David Brazdildee58d62016-04-07 09:54:26 +00002272 }
2273
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002274 DataType::Type field_type = GetFieldAccessType(*dex_file_, field_index);
David Brazdildee58d62016-04-07 09:54:26 +00002275
Vladimir Marko02ca05a2020-05-12 13:58:51 +01002276 Handle<mirror::Class> klass =
2277 graph_->GetHandleCache()->NewHandle(resolved_field->GetDeclaringClass());
Vladimir Markoa2c211c2018-11-01 09:50:52 +00002278 HLoadClass* constant = BuildLoadClass(klass->GetDexTypeIndex(),
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002279 klass->GetDexFile(),
2280 klass,
2281 dex_pc,
Andreas Gampe3db70682018-12-26 15:12:03 -08002282 /* needs_access_check= */ false);
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002283
2284 if (constant == nullptr) {
2285 // The class cannot be referenced from this compiled code. Generate
2286 // an unresolved access.
Igor Murashkin1e065a52017-08-09 13:20:34 -07002287 MaybeRecordStat(compilation_stats_,
2288 MethodCompilationStat::kUnresolvedFieldNotAFastAccess);
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002289 BuildUnresolvedStaticFieldAccess(instruction, dex_pc, is_put, field_type);
Nicolas Geoffraydbb9aef2017-11-23 10:44:11 +00002290 return;
David Brazdildee58d62016-04-07 09:54:26 +00002291 }
2292
David Brazdildee58d62016-04-07 09:54:26 +00002293 HInstruction* cls = constant;
Vladimir Marko2f40d242020-04-08 12:56:45 +01002294 if (!IsInitialized(klass.Get())) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01002295 cls = new (allocator_) HClinitCheck(constant, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002296 AppendInstruction(cls);
2297 }
2298
2299 uint16_t class_def_index = klass->GetDexClassDefIndex();
2300 if (is_put) {
2301 // We need to keep the class alive before loading the value.
2302 HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
2303 DCHECK_EQ(HPhi::ToPhiType(value->GetType()), HPhi::ToPhiType(field_type));
Vladimir Markoca6fff82017-10-03 14:49:14 +01002304 AppendInstruction(new (allocator_) HStaticFieldSet(cls,
2305 value,
2306 resolved_field,
2307 field_type,
2308 resolved_field->GetOffset(),
2309 resolved_field->IsVolatile(),
2310 field_index,
2311 class_def_index,
2312 *dex_file_,
2313 dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00002314 } else {
Vladimir Markoca6fff82017-10-03 14:49:14 +01002315 AppendInstruction(new (allocator_) HStaticFieldGet(cls,
2316 resolved_field,
2317 field_type,
2318 resolved_field->GetOffset(),
2319 resolved_field->IsVolatile(),
2320 field_index,
2321 class_def_index,
2322 *dex_file_,
2323 dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00002324 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
2325 }
David Brazdildee58d62016-04-07 09:54:26 +00002326}
2327
2328void HInstructionBuilder::BuildCheckedDivRem(uint16_t out_vreg,
Vladimir Markoca6fff82017-10-03 14:49:14 +01002329 uint16_t first_vreg,
2330 int64_t second_vreg_or_constant,
2331 uint32_t dex_pc,
2332 DataType::Type type,
2333 bool second_is_constant,
2334 bool isDiv) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002335 DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64);
David Brazdildee58d62016-04-07 09:54:26 +00002336
2337 HInstruction* first = LoadLocal(first_vreg, type);
2338 HInstruction* second = nullptr;
2339 if (second_is_constant) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002340 if (type == DataType::Type::kInt32) {
David Brazdildee58d62016-04-07 09:54:26 +00002341 second = graph_->GetIntConstant(second_vreg_or_constant, dex_pc);
2342 } else {
2343 second = graph_->GetLongConstant(second_vreg_or_constant, dex_pc);
2344 }
2345 } else {
2346 second = LoadLocal(second_vreg_or_constant, type);
2347 }
2348
2349 if (!second_is_constant
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002350 || (type == DataType::Type::kInt32 && second->AsIntConstant()->GetValue() == 0)
2351 || (type == DataType::Type::kInt64 && second->AsLongConstant()->GetValue() == 0)) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01002352 second = new (allocator_) HDivZeroCheck(second, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002353 AppendInstruction(second);
2354 }
2355
2356 if (isDiv) {
Vladimir Markoca6fff82017-10-03 14:49:14 +01002357 AppendInstruction(new (allocator_) HDiv(type, first, second, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00002358 } else {
Vladimir Markoca6fff82017-10-03 14:49:14 +01002359 AppendInstruction(new (allocator_) HRem(type, first, second, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00002360 }
2361 UpdateLocal(out_vreg, current_block_->GetLastInstruction());
2362}
2363
2364void HInstructionBuilder::BuildArrayAccess(const Instruction& instruction,
2365 uint32_t dex_pc,
2366 bool is_put,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002367 DataType::Type anticipated_type) {
David Brazdildee58d62016-04-07 09:54:26 +00002368 uint8_t source_or_dest_reg = instruction.VRegA_23x();
2369 uint8_t array_reg = instruction.VRegB_23x();
2370 uint8_t index_reg = instruction.VRegC_23x();
2371
David Brazdilc120bbe2016-04-22 16:57:00 +01002372 HInstruction* object = LoadNullCheckedLocal(array_reg, dex_pc);
Vladimir Markoca6fff82017-10-03 14:49:14 +01002373 HInstruction* length = new (allocator_) HArrayLength(object, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002374 AppendInstruction(length);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002375 HInstruction* index = LoadLocal(index_reg, DataType::Type::kInt32);
Vladimir Markoca6fff82017-10-03 14:49:14 +01002376 index = new (allocator_) HBoundsCheck(index, length, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002377 AppendInstruction(index);
2378 if (is_put) {
2379 HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type);
2380 // TODO: Insert a type check node if the type is Object.
Vladimir Markoca6fff82017-10-03 14:49:14 +01002381 HArraySet* aset = new (allocator_) HArraySet(object, index, value, anticipated_type, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002382 ssa_builder_->MaybeAddAmbiguousArraySet(aset);
2383 AppendInstruction(aset);
2384 } else {
Vladimir Markoca6fff82017-10-03 14:49:14 +01002385 HArrayGet* aget = new (allocator_) HArrayGet(object, index, anticipated_type, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002386 ssa_builder_->MaybeAddAmbiguousArrayGet(aget);
2387 AppendInstruction(aget);
2388 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
2389 }
2390 graph_->SetHasBoundsChecks(true);
2391}
2392
Vladimir Markob5461632018-10-15 14:24:21 +01002393HNewArray* HInstructionBuilder::BuildNewArray(uint32_t dex_pc,
2394 dex::TypeIndex type_index,
2395 HInstruction* length) {
2396 HLoadClass* cls = BuildLoadClass(type_index, dex_pc);
2397
2398 const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(type_index));
2399 DCHECK_EQ(descriptor[0], '[');
2400 size_t component_type_shift = Primitive::ComponentSizeShift(Primitive::GetType(descriptor[1]));
2401
2402 HNewArray* new_array = new (allocator_) HNewArray(cls, length, dex_pc, component_type_shift);
2403 AppendInstruction(new_array);
2404 return new_array;
2405}
2406
Igor Murashkin79d8fa72017-04-18 09:37:23 -07002407HNewArray* HInstructionBuilder::BuildFilledNewArray(uint32_t dex_pc,
2408 dex::TypeIndex type_index,
Treehugger Robot2c5827a2018-05-17 22:26:08 +00002409 const InstructionOperands& operands) {
2410 const size_t number_of_operands = operands.GetNumberOfOperands();
2411 HInstruction* length = graph_->GetIntConstant(number_of_operands, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002412
Vladimir Markob5461632018-10-15 14:24:21 +01002413 HNewArray* new_array = BuildNewArray(dex_pc, type_index, length);
David Brazdildee58d62016-04-07 09:54:26 +00002414 const char* descriptor = dex_file_->StringByTypeIdx(type_index);
2415 DCHECK_EQ(descriptor[0], '[') << descriptor;
2416 char primitive = descriptor[1];
2417 DCHECK(primitive == 'I'
2418 || primitive == 'L'
2419 || primitive == '[') << descriptor;
2420 bool is_reference_array = (primitive == 'L') || (primitive == '[');
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002421 DataType::Type type = is_reference_array ? DataType::Type::kReference : DataType::Type::kInt32;
David Brazdildee58d62016-04-07 09:54:26 +00002422
Treehugger Robot2c5827a2018-05-17 22:26:08 +00002423 for (size_t i = 0; i < number_of_operands; ++i) {
2424 HInstruction* value = LoadLocal(operands.GetOperand(i), type);
David Brazdildee58d62016-04-07 09:54:26 +00002425 HInstruction* index = graph_->GetIntConstant(i, dex_pc);
Vladimir Markob5461632018-10-15 14:24:21 +01002426 HArraySet* aset = new (allocator_) HArraySet(new_array, index, value, type, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002427 ssa_builder_->MaybeAddAmbiguousArraySet(aset);
2428 AppendInstruction(aset);
2429 }
Vladimir Markob5461632018-10-15 14:24:21 +01002430 latest_result_ = new_array;
Igor Murashkin79d8fa72017-04-18 09:37:23 -07002431
Vladimir Markob5461632018-10-15 14:24:21 +01002432 return new_array;
David Brazdildee58d62016-04-07 09:54:26 +00002433}
2434
2435template <typename T>
2436void HInstructionBuilder::BuildFillArrayData(HInstruction* object,
2437 const T* data,
2438 uint32_t element_count,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002439 DataType::Type anticipated_type,
David Brazdildee58d62016-04-07 09:54:26 +00002440 uint32_t dex_pc) {
2441 for (uint32_t i = 0; i < element_count; ++i) {
2442 HInstruction* index = graph_->GetIntConstant(i, dex_pc);
2443 HInstruction* value = graph_->GetIntConstant(data[i], dex_pc);
Vladimir Markoca6fff82017-10-03 14:49:14 +01002444 HArraySet* aset = new (allocator_) HArraySet(object, index, value, anticipated_type, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002445 ssa_builder_->MaybeAddAmbiguousArraySet(aset);
2446 AppendInstruction(aset);
2447 }
2448}
2449
2450void HInstructionBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) {
David Brazdilc120bbe2016-04-22 16:57:00 +01002451 HInstruction* array = LoadNullCheckedLocal(instruction.VRegA_31t(), dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002452
2453 int32_t payload_offset = instruction.VRegB_31t() + dex_pc;
2454 const Instruction::ArrayDataPayload* payload =
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002455 reinterpret_cast<const Instruction::ArrayDataPayload*>(
2456 code_item_accessor_.Insns() + payload_offset);
David Brazdildee58d62016-04-07 09:54:26 +00002457 const uint8_t* data = payload->data;
2458 uint32_t element_count = payload->element_count;
2459
Vladimir Markoc69fba22016-09-06 16:49:15 +01002460 if (element_count == 0u) {
2461 // For empty payload we emit only the null check above.
2462 return;
2463 }
2464
Vladimir Markoca6fff82017-10-03 14:49:14 +01002465 HInstruction* length = new (allocator_) HArrayLength(array, dex_pc);
Vladimir Markoc69fba22016-09-06 16:49:15 +01002466 AppendInstruction(length);
2467
David Brazdildee58d62016-04-07 09:54:26 +00002468 // Implementation of this DEX instruction seems to be that the bounds check is
2469 // done before doing any stores.
2470 HInstruction* last_index = graph_->GetIntConstant(payload->element_count - 1, dex_pc);
Vladimir Markoca6fff82017-10-03 14:49:14 +01002471 AppendInstruction(new (allocator_) HBoundsCheck(last_index, length, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00002472
2473 switch (payload->element_width) {
2474 case 1:
David Brazdilc120bbe2016-04-22 16:57:00 +01002475 BuildFillArrayData(array,
David Brazdildee58d62016-04-07 09:54:26 +00002476 reinterpret_cast<const int8_t*>(data),
2477 element_count,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002478 DataType::Type::kInt8,
David Brazdildee58d62016-04-07 09:54:26 +00002479 dex_pc);
2480 break;
2481 case 2:
David Brazdilc120bbe2016-04-22 16:57:00 +01002482 BuildFillArrayData(array,
David Brazdildee58d62016-04-07 09:54:26 +00002483 reinterpret_cast<const int16_t*>(data),
2484 element_count,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002485 DataType::Type::kInt16,
David Brazdildee58d62016-04-07 09:54:26 +00002486 dex_pc);
2487 break;
2488 case 4:
David Brazdilc120bbe2016-04-22 16:57:00 +01002489 BuildFillArrayData(array,
David Brazdildee58d62016-04-07 09:54:26 +00002490 reinterpret_cast<const int32_t*>(data),
2491 element_count,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002492 DataType::Type::kInt32,
David Brazdildee58d62016-04-07 09:54:26 +00002493 dex_pc);
2494 break;
2495 case 8:
David Brazdilc120bbe2016-04-22 16:57:00 +01002496 BuildFillWideArrayData(array,
David Brazdildee58d62016-04-07 09:54:26 +00002497 reinterpret_cast<const int64_t*>(data),
2498 element_count,
2499 dex_pc);
2500 break;
2501 default:
2502 LOG(FATAL) << "Unknown element width for " << payload->element_width;
2503 }
2504 graph_->SetHasBoundsChecks(true);
2505}
2506
2507void HInstructionBuilder::BuildFillWideArrayData(HInstruction* object,
2508 const int64_t* data,
2509 uint32_t element_count,
2510 uint32_t dex_pc) {
2511 for (uint32_t i = 0; i < element_count; ++i) {
2512 HInstruction* index = graph_->GetIntConstant(i, dex_pc);
2513 HInstruction* value = graph_->GetLongConstant(data[i], dex_pc);
Vladimir Markoca6fff82017-10-03 14:49:14 +01002514 HArraySet* aset =
2515 new (allocator_) HArraySet(object, index, value, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002516 ssa_builder_->MaybeAddAmbiguousArraySet(aset);
2517 AppendInstruction(aset);
2518 }
2519}
2520
Vladimir Marko28e012a2017-12-07 11:22:59 +00002521void HInstructionBuilder::BuildLoadString(dex::StringIndex string_index, uint32_t dex_pc) {
2522 HLoadString* load_string =
2523 new (allocator_) HLoadString(graph_->GetCurrentMethod(), string_index, *dex_file_, dex_pc);
2524 HSharpening::ProcessLoadString(load_string,
2525 code_generator_,
Vladimir Marko28e012a2017-12-07 11:22:59 +00002526 *dex_compilation_unit_,
Vladimir Marko02ca05a2020-05-12 13:58:51 +01002527 graph_->GetHandleCache()->GetHandles());
Vladimir Marko28e012a2017-12-07 11:22:59 +00002528 AppendInstruction(load_string);
2529}
2530
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002531HLoadClass* HInstructionBuilder::BuildLoadClass(dex::TypeIndex type_index, uint32_t dex_pc) {
Nicolas Geoffray5247c082017-01-13 14:17:29 +00002532 ScopedObjectAccess soa(Thread::Current());
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002533 const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
Vladimir Marko175e7862018-03-27 09:03:13 +00002534 Handle<mirror::Class> klass = ResolveClass(soa, type_index);
Vladimir Marko270e10a2020-09-24 11:48:47 +01002535 bool needs_access_check = LoadClassNeedsAccessCheck(type_index, klass.Get());
Vladimir Markoa2c211c2018-11-01 09:50:52 +00002536 return BuildLoadClass(type_index, dex_file, klass, dex_pc, needs_access_check);
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002537}
2538
Vladimir Markoa2c211c2018-11-01 09:50:52 +00002539HLoadClass* HInstructionBuilder::BuildLoadClass(dex::TypeIndex type_index,
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002540 const DexFile& dex_file,
2541 Handle<mirror::Class> klass,
2542 uint32_t dex_pc,
2543 bool needs_access_check) {
2544 // Try to find a reference in the compiling dex file.
2545 const DexFile* actual_dex_file = &dex_file;
2546 if (!IsSameDexFile(dex_file, *dex_compilation_unit_->GetDexFile())) {
2547 dex::TypeIndex local_type_index =
2548 klass->FindTypeIndexInOtherDexFile(*dex_compilation_unit_->GetDexFile());
2549 if (local_type_index.IsValid()) {
2550 type_index = local_type_index;
2551 actual_dex_file = dex_compilation_unit_->GetDexFile();
2552 }
2553 }
2554
Vladimir Marko270e10a2020-09-24 11:48:47 +01002555 // We cannot use the referrer's class load kind if we need to do an access check.
2556 // If the `klass` is unresolved, we need access check with the exception of the referrer's
2557 // class, see LoadClassNeedsAccessCheck(), so the `!needs_access_check` check is enough.
2558 // Otherwise, also check if the `klass` is the same as the compiling class, which also
2559 // conveniently rejects the case of unresolved compiling class.
Vladimir Markoa2c211c2018-11-01 09:50:52 +00002560 bool is_referrers_class =
Vladimir Marko270e10a2020-09-24 11:48:47 +01002561 !needs_access_check &&
2562 (klass == nullptr || outer_compilation_unit_->GetCompilingClass().Get() == klass.Get());
2563 // Note: `klass` must be from `graph_->GetHandleCache()`.
Vladimir Markoca6fff82017-10-03 14:49:14 +01002564 HLoadClass* load_class = new (allocator_) HLoadClass(
Nicolas Geoffray5247c082017-01-13 14:17:29 +00002565 graph_->GetCurrentMethod(),
2566 type_index,
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002567 *actual_dex_file,
Nicolas Geoffray5247c082017-01-13 14:17:29 +00002568 klass,
Vladimir Markofca0b492018-07-23 15:30:52 +01002569 is_referrers_class,
Nicolas Geoffray5247c082017-01-13 14:17:29 +00002570 dex_pc,
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002571 needs_access_check);
Nicolas Geoffray5247c082017-01-13 14:17:29 +00002572
Nicolas Geoffrayc4aa82c2017-03-06 14:38:52 +00002573 HLoadClass::LoadKind load_kind = HSharpening::ComputeLoadClassKind(load_class,
2574 code_generator_,
Nicolas Geoffrayc4aa82c2017-03-06 14:38:52 +00002575 *dex_compilation_unit_);
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002576
2577 if (load_kind == HLoadClass::LoadKind::kInvalid) {
2578 // We actually cannot reference this class, we're forced to bail.
2579 return nullptr;
2580 }
Vladimir Marko28e012a2017-12-07 11:22:59 +00002581 // Load kind must be set before inserting the instruction into the graph.
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00002582 load_class->SetLoadKind(load_kind);
Vladimir Marko28e012a2017-12-07 11:22:59 +00002583 AppendInstruction(load_class);
Nicolas Geoffray5247c082017-01-13 14:17:29 +00002584 return load_class;
2585}
2586
Vladimir Marko175e7862018-03-27 09:03:13 +00002587Handle<mirror::Class> HInstructionBuilder::ResolveClass(ScopedObjectAccess& soa,
2588 dex::TypeIndex type_index) {
Vladimir Marko3b506202018-10-31 14:33:58 +00002589 auto it = class_cache_.find(type_index);
2590 if (it != class_cache_.end()) {
2591 return it->second;
2592 }
2593
2594 ObjPtr<mirror::Class> klass = dex_compilation_unit_->GetClassLinker()->ResolveType(
2595 type_index, dex_compilation_unit_->GetDexCache(), dex_compilation_unit_->GetClassLoader());
2596 DCHECK_EQ(klass == nullptr, soa.Self()->IsExceptionPending());
2597 soa.Self()->ClearException(); // Clean up the exception left by type resolution if any.
2598
Vladimir Marko02ca05a2020-05-12 13:58:51 +01002599 Handle<mirror::Class> h_klass = graph_->GetHandleCache()->NewHandle(klass);
Vladimir Marko3b506202018-10-31 14:33:58 +00002600 class_cache_.Put(type_index, h_klass);
2601 return h_klass;
Vladimir Marko175e7862018-03-27 09:03:13 +00002602}
2603
Vladimir Marko270e10a2020-09-24 11:48:47 +01002604bool HInstructionBuilder::LoadClassNeedsAccessCheck(dex::TypeIndex type_index,
2605 ObjPtr<mirror::Class> klass) {
Vladimir Marko175e7862018-03-27 09:03:13 +00002606 if (klass == nullptr) {
Vladimir Marko270e10a2020-09-24 11:48:47 +01002607 // If the class is unresolved, we can avoid access checks only for references to
2608 // the compiling class as determined by checking the descriptor and ClassLoader.
2609 if (outer_compilation_unit_->GetCompilingClass() != nullptr) {
2610 // Compiling class is resolved, so different from the unresolved class.
2611 return true;
2612 }
2613 if (dex_compilation_unit_->GetClassLoader().Get() !=
2614 outer_compilation_unit_->GetClassLoader().Get()) {
2615 // Resolving the same descriptor in a different ClassLoader than the
2616 // defining loader of the compiling class shall either fail to find
2617 // the class definition, or find a different one.
2618 // (Assuming no custom ClassLoader hierarchy with circular delegation.)
2619 return true;
2620 }
2621 // Check if the class is the outer method's class.
2622 // For the same dex file compare type indexes, otherwise descriptors.
2623 const DexFile* outer_dex_file = outer_compilation_unit_->GetDexFile();
2624 const DexFile* inner_dex_file = dex_compilation_unit_->GetDexFile();
2625 const dex::ClassDef& outer_class_def =
2626 outer_dex_file->GetClassDef(outer_compilation_unit_->GetClassDefIndex());
2627 if (IsSameDexFile(*inner_dex_file, *outer_dex_file)) {
2628 if (type_index != outer_class_def.class_idx_) {
2629 return true;
2630 }
2631 } else {
2632 uint32_t outer_utf16_length;
2633 const char* outer_descriptor =
2634 outer_dex_file->StringByTypeIdx(outer_class_def.class_idx_, &outer_utf16_length);
2635 uint32_t target_utf16_length;
2636 const char* target_descriptor =
2637 inner_dex_file->StringByTypeIdx(type_index, &target_utf16_length);
2638 if (outer_utf16_length != target_utf16_length ||
2639 strcmp(outer_descriptor, target_descriptor) != 0) {
2640 return true;
2641 }
2642 }
2643 // For inlined methods we also need to check if the compiling class
2644 // is public or in the same package as the inlined method's class.
2645 if (dex_compilation_unit_ != outer_compilation_unit_ &&
2646 (outer_class_def.access_flags_ & kAccPublic) == 0) {
2647 DCHECK(dex_compilation_unit_->GetCompilingClass() != nullptr);
2648 SamePackageCompare same_package(*outer_compilation_unit_);
2649 if (!same_package(dex_compilation_unit_->GetCompilingClass().Get())) {
2650 return true;
2651 }
2652 }
2653 return false;
Vladimir Marko175e7862018-03-27 09:03:13 +00002654 } else if (klass->IsPublic()) {
2655 return false;
Vladimir Marko0280e5d2020-08-27 17:36:24 +01002656 } else if (dex_compilation_unit_->GetCompilingClass() != nullptr) {
2657 return !dex_compilation_unit_->GetCompilingClass()->CanAccess(klass);
Vladimir Marko175e7862018-03-27 09:03:13 +00002658 } else {
Vladimir Marko0280e5d2020-08-27 17:36:24 +01002659 SamePackageCompare same_package(*dex_compilation_unit_);
2660 return !same_package(klass);
Vladimir Marko175e7862018-03-27 09:03:13 +00002661 }
2662}
2663
Orion Hodson06d10a72018-05-14 08:53:38 +01002664void HInstructionBuilder::BuildLoadMethodHandle(uint16_t method_handle_index, uint32_t dex_pc) {
Orion Hodsondbaa5c72018-05-10 08:22:46 +01002665 const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
Orion Hodson06d10a72018-05-14 08:53:38 +01002666 HLoadMethodHandle* load_method_handle = new (allocator_) HLoadMethodHandle(
2667 graph_->GetCurrentMethod(), method_handle_index, dex_file, dex_pc);
Orion Hodsondbaa5c72018-05-10 08:22:46 +01002668 AppendInstruction(load_method_handle);
2669}
2670
Orion Hodson06d10a72018-05-14 08:53:38 +01002671void HInstructionBuilder::BuildLoadMethodType(dex::ProtoIndex proto_index, uint32_t dex_pc) {
Orion Hodson18259d72018-04-12 11:18:23 +01002672 const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
2673 HLoadMethodType* load_method_type =
Orion Hodson06d10a72018-05-14 08:53:38 +01002674 new (allocator_) HLoadMethodType(graph_->GetCurrentMethod(), proto_index, dex_file, dex_pc);
Orion Hodson18259d72018-04-12 11:18:23 +01002675 AppendInstruction(load_method_type);
2676}
2677
Andra Danciu49a19f32020-08-27 12:44:25 +00002678void HInstructionBuilder::BuildTypeCheck(bool is_instance_of,
2679 HInstruction* object,
Andreas Gampea5b09a62016-11-17 15:21:22 -08002680 dex::TypeIndex type_index,
David Brazdildee58d62016-04-07 09:54:26 +00002681 uint32_t dex_pc) {
Nicolas Geoffray5247c082017-01-13 14:17:29 +00002682 ScopedObjectAccess soa(Thread::Current());
Vladimir Marko175e7862018-03-27 09:03:13 +00002683 const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
2684 Handle<mirror::Class> klass = ResolveClass(soa, type_index);
Vladimir Marko270e10a2020-09-24 11:48:47 +01002685 bool needs_access_check = LoadClassNeedsAccessCheck(type_index, klass.Get());
Vladimir Marko175e7862018-03-27 09:03:13 +00002686 TypeCheckKind check_kind = HSharpening::ComputeTypeCheckKind(
Vladimir Markodc4bcce2018-06-21 16:15:42 +01002687 klass.Get(), code_generator_, needs_access_check);
Vladimir Marko175e7862018-03-27 09:03:13 +00002688
2689 HInstruction* class_or_null = nullptr;
2690 HIntConstant* bitstring_path_to_root = nullptr;
2691 HIntConstant* bitstring_mask = nullptr;
2692 if (check_kind == TypeCheckKind::kBitstringCheck) {
2693 // TODO: Allow using the bitstring check also if we need an access check.
2694 DCHECK(!needs_access_check);
2695 class_or_null = graph_->GetNullConstant(dex_pc);
2696 MutexLock subtype_check_lock(Thread::Current(), *Locks::subtype_check_lock_);
2697 uint32_t path_to_root =
2698 SubtypeCheck<ObjPtr<mirror::Class>>::GetEncodedPathToRootForTarget(klass.Get());
2699 uint32_t mask = SubtypeCheck<ObjPtr<mirror::Class>>::GetEncodedPathToRootMask(klass.Get());
2700 bitstring_path_to_root = graph_->GetIntConstant(static_cast<int32_t>(path_to_root), dex_pc);
2701 bitstring_mask = graph_->GetIntConstant(static_cast<int32_t>(mask), dex_pc);
2702 } else {
Vladimir Markoa2c211c2018-11-01 09:50:52 +00002703 class_or_null = BuildLoadClass(type_index, dex_file, klass, dex_pc, needs_access_check);
Vladimir Marko175e7862018-03-27 09:03:13 +00002704 }
2705 DCHECK(class_or_null != nullptr);
2706
Andra Danciu49a19f32020-08-27 12:44:25 +00002707 if (is_instance_of) {
Vladimir Marko175e7862018-03-27 09:03:13 +00002708 AppendInstruction(new (allocator_) HInstanceOf(object,
2709 class_or_null,
2710 check_kind,
2711 klass,
2712 dex_pc,
2713 allocator_,
2714 bitstring_path_to_root,
2715 bitstring_mask));
David Brazdildee58d62016-04-07 09:54:26 +00002716 } else {
David Brazdildee58d62016-04-07 09:54:26 +00002717 // We emit a CheckCast followed by a BoundType. CheckCast is a statement
2718 // which may throw. If it succeeds BoundType sets the new type of `object`
2719 // for all subsequent uses.
Vladimir Marko175e7862018-03-27 09:03:13 +00002720 AppendInstruction(
2721 new (allocator_) HCheckCast(object,
2722 class_or_null,
2723 check_kind,
2724 klass,
2725 dex_pc,
2726 allocator_,
2727 bitstring_path_to_root,
2728 bitstring_mask));
Vladimir Markoca6fff82017-10-03 14:49:14 +01002729 AppendInstruction(new (allocator_) HBoundType(object, dex_pc));
Andra Danciu49a19f32020-08-27 12:44:25 +00002730 }
2731}
2732
2733void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction,
2734 uint8_t destination,
2735 uint8_t reference,
2736 dex::TypeIndex type_index,
2737 uint32_t dex_pc) {
2738 HInstruction* object = LoadLocal(reference, DataType::Type::kReference);
2739 bool is_instance_of = instruction.Opcode() == Instruction::INSTANCE_OF;
2740
2741 BuildTypeCheck(is_instance_of, object, type_index, dex_pc);
2742
2743 if (is_instance_of) {
2744 UpdateLocal(destination, current_block_->GetLastInstruction());
2745 } else {
2746 DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST);
David Brazdildee58d62016-04-07 09:54:26 +00002747 UpdateLocal(reference, current_block_->GetLastInstruction());
2748 }
2749}
2750
Nicolas Geoffray4924ea92021-03-23 08:25:31 +00002751bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, uint32_t dex_pc) {
David Brazdildee58d62016-04-07 09:54:26 +00002752 switch (instruction.Opcode()) {
2753 case Instruction::CONST_4: {
2754 int32_t register_index = instruction.VRegA();
2755 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n(), dex_pc);
2756 UpdateLocal(register_index, constant);
2757 break;
2758 }
2759
2760 case Instruction::CONST_16: {
2761 int32_t register_index = instruction.VRegA();
2762 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s(), dex_pc);
2763 UpdateLocal(register_index, constant);
2764 break;
2765 }
2766
2767 case Instruction::CONST: {
2768 int32_t register_index = instruction.VRegA();
2769 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i(), dex_pc);
2770 UpdateLocal(register_index, constant);
2771 break;
2772 }
2773
2774 case Instruction::CONST_HIGH16: {
2775 int32_t register_index = instruction.VRegA();
2776 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16, dex_pc);
2777 UpdateLocal(register_index, constant);
2778 break;
2779 }
2780
2781 case Instruction::CONST_WIDE_16: {
2782 int32_t register_index = instruction.VRegA();
2783 // Get 16 bits of constant value, sign extended to 64 bits.
2784 int64_t value = instruction.VRegB_21s();
2785 value <<= 48;
2786 value >>= 48;
2787 HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
2788 UpdateLocal(register_index, constant);
2789 break;
2790 }
2791
2792 case Instruction::CONST_WIDE_32: {
2793 int32_t register_index = instruction.VRegA();
2794 // Get 32 bits of constant value, sign extended to 64 bits.
2795 int64_t value = instruction.VRegB_31i();
2796 value <<= 32;
2797 value >>= 32;
2798 HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
2799 UpdateLocal(register_index, constant);
2800 break;
2801 }
2802
2803 case Instruction::CONST_WIDE: {
2804 int32_t register_index = instruction.VRegA();
2805 HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l(), dex_pc);
2806 UpdateLocal(register_index, constant);
2807 break;
2808 }
2809
2810 case Instruction::CONST_WIDE_HIGH16: {
2811 int32_t register_index = instruction.VRegA();
2812 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
2813 HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
2814 UpdateLocal(register_index, constant);
2815 break;
2816 }
2817
2818 // Note that the SSA building will refine the types.
2819 case Instruction::MOVE:
2820 case Instruction::MOVE_FROM16:
2821 case Instruction::MOVE_16: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002822 HInstruction* value = LoadLocal(instruction.VRegB(), DataType::Type::kInt32);
David Brazdildee58d62016-04-07 09:54:26 +00002823 UpdateLocal(instruction.VRegA(), value);
2824 break;
2825 }
2826
2827 // Note that the SSA building will refine the types.
2828 case Instruction::MOVE_WIDE:
2829 case Instruction::MOVE_WIDE_FROM16:
2830 case Instruction::MOVE_WIDE_16: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002831 HInstruction* value = LoadLocal(instruction.VRegB(), DataType::Type::kInt64);
David Brazdildee58d62016-04-07 09:54:26 +00002832 UpdateLocal(instruction.VRegA(), value);
2833 break;
2834 }
2835
2836 case Instruction::MOVE_OBJECT:
2837 case Instruction::MOVE_OBJECT_16:
2838 case Instruction::MOVE_OBJECT_FROM16: {
Nicolas Geoffray50a9ed02016-09-23 15:40:41 +01002839 // The verifier has no notion of a null type, so a move-object of constant 0
2840 // will lead to the same constant 0 in the destination register. To mimic
2841 // this behavior, we just pretend we haven't seen a type change (int to reference)
2842 // for the 0 constant and phis. We rely on our type propagation to eventually get the
2843 // types correct.
2844 uint32_t reg_number = instruction.VRegB();
2845 HInstruction* value = (*current_locals_)[reg_number];
2846 if (value->IsIntConstant()) {
2847 DCHECK_EQ(value->AsIntConstant()->GetValue(), 0);
2848 } else if (value->IsPhi()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002849 DCHECK(value->GetType() == DataType::Type::kInt32 ||
2850 value->GetType() == DataType::Type::kReference);
Nicolas Geoffray50a9ed02016-09-23 15:40:41 +01002851 } else {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002852 value = LoadLocal(reg_number, DataType::Type::kReference);
Nicolas Geoffray50a9ed02016-09-23 15:40:41 +01002853 }
David Brazdildee58d62016-04-07 09:54:26 +00002854 UpdateLocal(instruction.VRegA(), value);
2855 break;
2856 }
2857
David Brazdildee58d62016-04-07 09:54:26 +00002858 case Instruction::RETURN_VOID: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002859 BuildReturn(instruction, DataType::Type::kVoid, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002860 break;
2861 }
2862
2863#define IF_XX(comparison, cond) \
2864 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_pc); break; \
2865 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_pc); break
2866
2867 IF_XX(HEqual, EQ);
2868 IF_XX(HNotEqual, NE);
2869 IF_XX(HLessThan, LT);
2870 IF_XX(HLessThanOrEqual, LE);
2871 IF_XX(HGreaterThan, GT);
2872 IF_XX(HGreaterThanOrEqual, GE);
2873
2874 case Instruction::GOTO:
2875 case Instruction::GOTO_16:
2876 case Instruction::GOTO_32: {
Vladimir Markoca6fff82017-10-03 14:49:14 +01002877 AppendInstruction(new (allocator_) HGoto(dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00002878 current_block_ = nullptr;
2879 break;
2880 }
2881
2882 case Instruction::RETURN: {
2883 BuildReturn(instruction, return_type_, dex_pc);
2884 break;
2885 }
2886
2887 case Instruction::RETURN_OBJECT: {
2888 BuildReturn(instruction, return_type_, dex_pc);
2889 break;
2890 }
2891
2892 case Instruction::RETURN_WIDE: {
2893 BuildReturn(instruction, return_type_, dex_pc);
2894 break;
2895 }
2896
2897 case Instruction::INVOKE_DIRECT:
2898 case Instruction::INVOKE_INTERFACE:
2899 case Instruction::INVOKE_STATIC:
2900 case Instruction::INVOKE_SUPER:
Nicolas Geoffray4924ea92021-03-23 08:25:31 +00002901 case Instruction::INVOKE_VIRTUAL: {
2902 uint16_t method_idx = instruction.VRegB_35c();
David Brazdildee58d62016-04-07 09:54:26 +00002903 uint32_t args[5];
Treehugger Robot2c5827a2018-05-17 22:26:08 +00002904 uint32_t number_of_vreg_arguments = instruction.GetVarArgs(args);
2905 VarArgsInstructionOperands operands(args, number_of_vreg_arguments);
2906 if (!BuildInvoke(instruction, dex_pc, method_idx, operands)) {
David Brazdildee58d62016-04-07 09:54:26 +00002907 return false;
2908 }
2909 break;
2910 }
2911
2912 case Instruction::INVOKE_DIRECT_RANGE:
2913 case Instruction::INVOKE_INTERFACE_RANGE:
2914 case Instruction::INVOKE_STATIC_RANGE:
2915 case Instruction::INVOKE_SUPER_RANGE:
Nicolas Geoffray4924ea92021-03-23 08:25:31 +00002916 case Instruction::INVOKE_VIRTUAL_RANGE: {
2917 uint16_t method_idx = instruction.VRegB_3rc();
Treehugger Robot2c5827a2018-05-17 22:26:08 +00002918 RangeInstructionOperands operands(instruction.VRegC(), instruction.VRegA_3rc());
2919 if (!BuildInvoke(instruction, dex_pc, method_idx, operands)) {
David Brazdildee58d62016-04-07 09:54:26 +00002920 return false;
2921 }
2922 break;
2923 }
2924
Orion Hodsonac141392017-01-13 11:53:47 +00002925 case Instruction::INVOKE_POLYMORPHIC: {
2926 uint16_t method_idx = instruction.VRegB_45cc();
Orion Hodson06d10a72018-05-14 08:53:38 +01002927 dex::ProtoIndex proto_idx(instruction.VRegH_45cc());
Orion Hodsonac141392017-01-13 11:53:47 +00002928 uint32_t args[5];
Treehugger Robot2c5827a2018-05-17 22:26:08 +00002929 uint32_t number_of_vreg_arguments = instruction.GetVarArgs(args);
2930 VarArgsInstructionOperands operands(args, number_of_vreg_arguments);
Orion Hodson4c8e12e2018-05-18 08:33:20 +01002931 return BuildInvokePolymorphic(dex_pc, method_idx, proto_idx, operands);
Orion Hodsonac141392017-01-13 11:53:47 +00002932 }
2933
2934 case Instruction::INVOKE_POLYMORPHIC_RANGE: {
2935 uint16_t method_idx = instruction.VRegB_4rcc();
Orion Hodson06d10a72018-05-14 08:53:38 +01002936 dex::ProtoIndex proto_idx(instruction.VRegH_4rcc());
Treehugger Robot2c5827a2018-05-17 22:26:08 +00002937 RangeInstructionOperands operands(instruction.VRegC_4rcc(), instruction.VRegA_4rcc());
Orion Hodson4c8e12e2018-05-18 08:33:20 +01002938 return BuildInvokePolymorphic(dex_pc, method_idx, proto_idx, operands);
2939 }
2940
2941 case Instruction::INVOKE_CUSTOM: {
2942 uint16_t call_site_idx = instruction.VRegB_35c();
2943 uint32_t args[5];
2944 uint32_t number_of_vreg_arguments = instruction.GetVarArgs(args);
2945 VarArgsInstructionOperands operands(args, number_of_vreg_arguments);
2946 return BuildInvokeCustom(dex_pc, call_site_idx, operands);
2947 }
2948
2949 case Instruction::INVOKE_CUSTOM_RANGE: {
2950 uint16_t call_site_idx = instruction.VRegB_3rc();
2951 RangeInstructionOperands operands(instruction.VRegC_3rc(), instruction.VRegA_3rc());
2952 return BuildInvokeCustom(dex_pc, call_site_idx, operands);
Orion Hodsonac141392017-01-13 11:53:47 +00002953 }
2954
David Brazdildee58d62016-04-07 09:54:26 +00002955 case Instruction::NEG_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002956 Unop_12x<HNeg>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002957 break;
2958 }
2959
2960 case Instruction::NEG_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002961 Unop_12x<HNeg>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002962 break;
2963 }
2964
2965 case Instruction::NEG_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002966 Unop_12x<HNeg>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002967 break;
2968 }
2969
2970 case Instruction::NEG_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002971 Unop_12x<HNeg>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002972 break;
2973 }
2974
2975 case Instruction::NOT_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002976 Unop_12x<HNot>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002977 break;
2978 }
2979
2980 case Instruction::NOT_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002981 Unop_12x<HNot>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002982 break;
2983 }
2984
2985 case Instruction::INT_TO_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002986 Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002987 break;
2988 }
2989
2990 case Instruction::INT_TO_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002991 Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002992 break;
2993 }
2994
2995 case Instruction::INT_TO_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01002996 Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00002997 break;
2998 }
2999
3000 case Instruction::LONG_TO_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003001 Conversion_12x(instruction, DataType::Type::kInt64, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003002 break;
3003 }
3004
3005 case Instruction::LONG_TO_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003006 Conversion_12x(instruction, DataType::Type::kInt64, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003007 break;
3008 }
3009
3010 case Instruction::LONG_TO_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003011 Conversion_12x(instruction, DataType::Type::kInt64, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003012 break;
3013 }
3014
3015 case Instruction::FLOAT_TO_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003016 Conversion_12x(instruction, DataType::Type::kFloat32, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003017 break;
3018 }
3019
3020 case Instruction::FLOAT_TO_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003021 Conversion_12x(instruction, DataType::Type::kFloat32, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003022 break;
3023 }
3024
3025 case Instruction::FLOAT_TO_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003026 Conversion_12x(instruction, DataType::Type::kFloat32, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003027 break;
3028 }
3029
3030 case Instruction::DOUBLE_TO_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003031 Conversion_12x(instruction, DataType::Type::kFloat64, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003032 break;
3033 }
3034
3035 case Instruction::DOUBLE_TO_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003036 Conversion_12x(instruction, DataType::Type::kFloat64, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003037 break;
3038 }
3039
3040 case Instruction::DOUBLE_TO_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003041 Conversion_12x(instruction, DataType::Type::kFloat64, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003042 break;
3043 }
3044
3045 case Instruction::INT_TO_BYTE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003046 Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kInt8, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003047 break;
3048 }
3049
3050 case Instruction::INT_TO_SHORT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003051 Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kInt16, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003052 break;
3053 }
3054
3055 case Instruction::INT_TO_CHAR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003056 Conversion_12x(instruction, DataType::Type::kInt32, DataType::Type::kUint16, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003057 break;
3058 }
3059
3060 case Instruction::ADD_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003061 Binop_23x<HAdd>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003062 break;
3063 }
3064
3065 case Instruction::ADD_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003066 Binop_23x<HAdd>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003067 break;
3068 }
3069
3070 case Instruction::ADD_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003071 Binop_23x<HAdd>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003072 break;
3073 }
3074
3075 case Instruction::ADD_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003076 Binop_23x<HAdd>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003077 break;
3078 }
3079
3080 case Instruction::SUB_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003081 Binop_23x<HSub>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003082 break;
3083 }
3084
3085 case Instruction::SUB_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003086 Binop_23x<HSub>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003087 break;
3088 }
3089
3090 case Instruction::SUB_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003091 Binop_23x<HSub>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003092 break;
3093 }
3094
3095 case Instruction::SUB_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003096 Binop_23x<HSub>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003097 break;
3098 }
3099
3100 case Instruction::ADD_INT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003101 Binop_12x<HAdd>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003102 break;
3103 }
3104
3105 case Instruction::MUL_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003106 Binop_23x<HMul>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003107 break;
3108 }
3109
3110 case Instruction::MUL_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003111 Binop_23x<HMul>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003112 break;
3113 }
3114
3115 case Instruction::MUL_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003116 Binop_23x<HMul>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003117 break;
3118 }
3119
3120 case Instruction::MUL_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003121 Binop_23x<HMul>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003122 break;
3123 }
3124
3125 case Instruction::DIV_INT: {
3126 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003127 dex_pc, DataType::Type::kInt32, false, true);
David Brazdildee58d62016-04-07 09:54:26 +00003128 break;
3129 }
3130
3131 case Instruction::DIV_LONG: {
3132 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003133 dex_pc, DataType::Type::kInt64, false, true);
David Brazdildee58d62016-04-07 09:54:26 +00003134 break;
3135 }
3136
3137 case Instruction::DIV_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003138 Binop_23x<HDiv>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003139 break;
3140 }
3141
3142 case Instruction::DIV_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003143 Binop_23x<HDiv>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003144 break;
3145 }
3146
3147 case Instruction::REM_INT: {
3148 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003149 dex_pc, DataType::Type::kInt32, false, false);
David Brazdildee58d62016-04-07 09:54:26 +00003150 break;
3151 }
3152
3153 case Instruction::REM_LONG: {
3154 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003155 dex_pc, DataType::Type::kInt64, false, false);
David Brazdildee58d62016-04-07 09:54:26 +00003156 break;
3157 }
3158
3159 case Instruction::REM_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003160 Binop_23x<HRem>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003161 break;
3162 }
3163
3164 case Instruction::REM_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003165 Binop_23x<HRem>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003166 break;
3167 }
3168
3169 case Instruction::AND_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003170 Binop_23x<HAnd>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003171 break;
3172 }
3173
3174 case Instruction::AND_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003175 Binop_23x<HAnd>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003176 break;
3177 }
3178
3179 case Instruction::SHL_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003180 Binop_23x_shift<HShl>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003181 break;
3182 }
3183
3184 case Instruction::SHL_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003185 Binop_23x_shift<HShl>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003186 break;
3187 }
3188
3189 case Instruction::SHR_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003190 Binop_23x_shift<HShr>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003191 break;
3192 }
3193
3194 case Instruction::SHR_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003195 Binop_23x_shift<HShr>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003196 break;
3197 }
3198
3199 case Instruction::USHR_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003200 Binop_23x_shift<HUShr>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003201 break;
3202 }
3203
3204 case Instruction::USHR_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003205 Binop_23x_shift<HUShr>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003206 break;
3207 }
3208
3209 case Instruction::OR_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003210 Binop_23x<HOr>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003211 break;
3212 }
3213
3214 case Instruction::OR_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003215 Binop_23x<HOr>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003216 break;
3217 }
3218
3219 case Instruction::XOR_INT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003220 Binop_23x<HXor>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003221 break;
3222 }
3223
3224 case Instruction::XOR_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003225 Binop_23x<HXor>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003226 break;
3227 }
3228
3229 case Instruction::ADD_LONG_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003230 Binop_12x<HAdd>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003231 break;
3232 }
3233
3234 case Instruction::ADD_DOUBLE_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003235 Binop_12x<HAdd>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003236 break;
3237 }
3238
3239 case Instruction::ADD_FLOAT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003240 Binop_12x<HAdd>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003241 break;
3242 }
3243
3244 case Instruction::SUB_INT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003245 Binop_12x<HSub>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003246 break;
3247 }
3248
3249 case Instruction::SUB_LONG_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003250 Binop_12x<HSub>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003251 break;
3252 }
3253
3254 case Instruction::SUB_FLOAT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003255 Binop_12x<HSub>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003256 break;
3257 }
3258
3259 case Instruction::SUB_DOUBLE_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003260 Binop_12x<HSub>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003261 break;
3262 }
3263
3264 case Instruction::MUL_INT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003265 Binop_12x<HMul>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003266 break;
3267 }
3268
3269 case Instruction::MUL_LONG_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003270 Binop_12x<HMul>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003271 break;
3272 }
3273
3274 case Instruction::MUL_FLOAT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003275 Binop_12x<HMul>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003276 break;
3277 }
3278
3279 case Instruction::MUL_DOUBLE_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003280 Binop_12x<HMul>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003281 break;
3282 }
3283
3284 case Instruction::DIV_INT_2ADDR: {
3285 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003286 dex_pc, DataType::Type::kInt32, false, true);
David Brazdildee58d62016-04-07 09:54:26 +00003287 break;
3288 }
3289
3290 case Instruction::DIV_LONG_2ADDR: {
3291 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003292 dex_pc, DataType::Type::kInt64, false, true);
David Brazdildee58d62016-04-07 09:54:26 +00003293 break;
3294 }
3295
3296 case Instruction::REM_INT_2ADDR: {
3297 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003298 dex_pc, DataType::Type::kInt32, false, false);
David Brazdildee58d62016-04-07 09:54:26 +00003299 break;
3300 }
3301
3302 case Instruction::REM_LONG_2ADDR: {
3303 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003304 dex_pc, DataType::Type::kInt64, false, false);
David Brazdildee58d62016-04-07 09:54:26 +00003305 break;
3306 }
3307
3308 case Instruction::REM_FLOAT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003309 Binop_12x<HRem>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003310 break;
3311 }
3312
3313 case Instruction::REM_DOUBLE_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003314 Binop_12x<HRem>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003315 break;
3316 }
3317
3318 case Instruction::SHL_INT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003319 Binop_12x_shift<HShl>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003320 break;
3321 }
3322
3323 case Instruction::SHL_LONG_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003324 Binop_12x_shift<HShl>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003325 break;
3326 }
3327
3328 case Instruction::SHR_INT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003329 Binop_12x_shift<HShr>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003330 break;
3331 }
3332
3333 case Instruction::SHR_LONG_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003334 Binop_12x_shift<HShr>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003335 break;
3336 }
3337
3338 case Instruction::USHR_INT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003339 Binop_12x_shift<HUShr>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003340 break;
3341 }
3342
3343 case Instruction::USHR_LONG_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003344 Binop_12x_shift<HUShr>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003345 break;
3346 }
3347
3348 case Instruction::DIV_FLOAT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003349 Binop_12x<HDiv>(instruction, DataType::Type::kFloat32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003350 break;
3351 }
3352
3353 case Instruction::DIV_DOUBLE_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003354 Binop_12x<HDiv>(instruction, DataType::Type::kFloat64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003355 break;
3356 }
3357
3358 case Instruction::AND_INT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003359 Binop_12x<HAnd>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003360 break;
3361 }
3362
3363 case Instruction::AND_LONG_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003364 Binop_12x<HAnd>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003365 break;
3366 }
3367
3368 case Instruction::OR_INT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003369 Binop_12x<HOr>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003370 break;
3371 }
3372
3373 case Instruction::OR_LONG_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003374 Binop_12x<HOr>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003375 break;
3376 }
3377
3378 case Instruction::XOR_INT_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003379 Binop_12x<HXor>(instruction, DataType::Type::kInt32, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003380 break;
3381 }
3382
3383 case Instruction::XOR_LONG_2ADDR: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003384 Binop_12x<HXor>(instruction, DataType::Type::kInt64, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003385 break;
3386 }
3387
3388 case Instruction::ADD_INT_LIT16: {
3389 Binop_22s<HAdd>(instruction, false, dex_pc);
3390 break;
3391 }
3392
3393 case Instruction::AND_INT_LIT16: {
3394 Binop_22s<HAnd>(instruction, false, dex_pc);
3395 break;
3396 }
3397
3398 case Instruction::OR_INT_LIT16: {
3399 Binop_22s<HOr>(instruction, false, dex_pc);
3400 break;
3401 }
3402
3403 case Instruction::XOR_INT_LIT16: {
3404 Binop_22s<HXor>(instruction, false, dex_pc);
3405 break;
3406 }
3407
3408 case Instruction::RSUB_INT: {
3409 Binop_22s<HSub>(instruction, true, dex_pc);
3410 break;
3411 }
3412
3413 case Instruction::MUL_INT_LIT16: {
3414 Binop_22s<HMul>(instruction, false, dex_pc);
3415 break;
3416 }
3417
3418 case Instruction::ADD_INT_LIT8: {
3419 Binop_22b<HAdd>(instruction, false, dex_pc);
3420 break;
3421 }
3422
3423 case Instruction::AND_INT_LIT8: {
3424 Binop_22b<HAnd>(instruction, false, dex_pc);
3425 break;
3426 }
3427
3428 case Instruction::OR_INT_LIT8: {
3429 Binop_22b<HOr>(instruction, false, dex_pc);
3430 break;
3431 }
3432
3433 case Instruction::XOR_INT_LIT8: {
3434 Binop_22b<HXor>(instruction, false, dex_pc);
3435 break;
3436 }
3437
3438 case Instruction::RSUB_INT_LIT8: {
3439 Binop_22b<HSub>(instruction, true, dex_pc);
3440 break;
3441 }
3442
3443 case Instruction::MUL_INT_LIT8: {
3444 Binop_22b<HMul>(instruction, false, dex_pc);
3445 break;
3446 }
3447
3448 case Instruction::DIV_INT_LIT16:
3449 case Instruction::DIV_INT_LIT8: {
3450 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003451 dex_pc, DataType::Type::kInt32, true, true);
David Brazdildee58d62016-04-07 09:54:26 +00003452 break;
3453 }
3454
3455 case Instruction::REM_INT_LIT16:
3456 case Instruction::REM_INT_LIT8: {
3457 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003458 dex_pc, DataType::Type::kInt32, true, false);
David Brazdildee58d62016-04-07 09:54:26 +00003459 break;
3460 }
3461
3462 case Instruction::SHL_INT_LIT8: {
3463 Binop_22b<HShl>(instruction, false, dex_pc);
3464 break;
3465 }
3466
3467 case Instruction::SHR_INT_LIT8: {
3468 Binop_22b<HShr>(instruction, false, dex_pc);
3469 break;
3470 }
3471
3472 case Instruction::USHR_INT_LIT8: {
3473 Binop_22b<HUShr>(instruction, false, dex_pc);
3474 break;
3475 }
3476
3477 case Instruction::NEW_INSTANCE: {
Igor Murashkin79d8fa72017-04-18 09:37:23 -07003478 HNewInstance* new_instance =
3479 BuildNewInstance(dex::TypeIndex(instruction.VRegB_21c()), dex_pc);
3480 DCHECK(new_instance != nullptr);
3481
David Brazdildee58d62016-04-07 09:54:26 +00003482 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
Igor Murashkin79d8fa72017-04-18 09:37:23 -07003483 BuildConstructorFenceForAllocation(new_instance);
David Brazdildee58d62016-04-07 09:54:26 +00003484 break;
3485 }
3486
3487 case Instruction::NEW_ARRAY: {
Andreas Gampea5b09a62016-11-17 15:21:22 -08003488 dex::TypeIndex type_index(instruction.VRegC_22c());
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003489 HInstruction* length = LoadLocal(instruction.VRegB_22c(), DataType::Type::kInt32);
Vladimir Markob5461632018-10-15 14:24:21 +01003490 HNewArray* new_array = BuildNewArray(dex_pc, type_index, length);
Igor Murashkin79d8fa72017-04-18 09:37:23 -07003491
David Brazdildee58d62016-04-07 09:54:26 +00003492 UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
Igor Murashkin79d8fa72017-04-18 09:37:23 -07003493 BuildConstructorFenceForAllocation(new_array);
David Brazdildee58d62016-04-07 09:54:26 +00003494 break;
3495 }
3496
3497 case Instruction::FILLED_NEW_ARRAY: {
Andreas Gampea5b09a62016-11-17 15:21:22 -08003498 dex::TypeIndex type_index(instruction.VRegB_35c());
David Brazdildee58d62016-04-07 09:54:26 +00003499 uint32_t args[5];
Treehugger Robot2c5827a2018-05-17 22:26:08 +00003500 uint32_t number_of_vreg_arguments = instruction.GetVarArgs(args);
3501 VarArgsInstructionOperands operands(args, number_of_vreg_arguments);
3502 HNewArray* new_array = BuildFilledNewArray(dex_pc, type_index, operands);
Igor Murashkin79d8fa72017-04-18 09:37:23 -07003503 BuildConstructorFenceForAllocation(new_array);
David Brazdildee58d62016-04-07 09:54:26 +00003504 break;
3505 }
3506
3507 case Instruction::FILLED_NEW_ARRAY_RANGE: {
Andreas Gampea5b09a62016-11-17 15:21:22 -08003508 dex::TypeIndex type_index(instruction.VRegB_3rc());
Treehugger Robot2c5827a2018-05-17 22:26:08 +00003509 RangeInstructionOperands operands(instruction.VRegC_3rc(), instruction.VRegA_3rc());
3510 HNewArray* new_array = BuildFilledNewArray(dex_pc, type_index, operands);
Igor Murashkin79d8fa72017-04-18 09:37:23 -07003511 BuildConstructorFenceForAllocation(new_array);
David Brazdildee58d62016-04-07 09:54:26 +00003512 break;
3513 }
3514
3515 case Instruction::FILL_ARRAY_DATA: {
3516 BuildFillArrayData(instruction, dex_pc);
3517 break;
3518 }
3519
3520 case Instruction::MOVE_RESULT:
3521 case Instruction::MOVE_RESULT_WIDE:
3522 case Instruction::MOVE_RESULT_OBJECT: {
3523 DCHECK(latest_result_ != nullptr);
3524 UpdateLocal(instruction.VRegA(), latest_result_);
3525 latest_result_ = nullptr;
3526 break;
3527 }
3528
3529 case Instruction::CMP_LONG: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003530 Binop_23x_cmp(instruction, DataType::Type::kInt64, ComparisonBias::kNoBias, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003531 break;
3532 }
3533
3534 case Instruction::CMPG_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003535 Binop_23x_cmp(instruction, DataType::Type::kFloat32, ComparisonBias::kGtBias, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003536 break;
3537 }
3538
3539 case Instruction::CMPG_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003540 Binop_23x_cmp(instruction, DataType::Type::kFloat64, ComparisonBias::kGtBias, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003541 break;
3542 }
3543
3544 case Instruction::CMPL_FLOAT: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003545 Binop_23x_cmp(instruction, DataType::Type::kFloat32, ComparisonBias::kLtBias, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003546 break;
3547 }
3548
3549 case Instruction::CMPL_DOUBLE: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003550 Binop_23x_cmp(instruction, DataType::Type::kFloat64, ComparisonBias::kLtBias, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003551 break;
3552 }
3553
3554 case Instruction::NOP:
3555 break;
3556
3557 case Instruction::IGET:
David Brazdildee58d62016-04-07 09:54:26 +00003558 case Instruction::IGET_WIDE:
David Brazdildee58d62016-04-07 09:54:26 +00003559 case Instruction::IGET_OBJECT:
David Brazdildee58d62016-04-07 09:54:26 +00003560 case Instruction::IGET_BOOLEAN:
David Brazdildee58d62016-04-07 09:54:26 +00003561 case Instruction::IGET_BYTE:
David Brazdildee58d62016-04-07 09:54:26 +00003562 case Instruction::IGET_CHAR:
Nicolas Geoffray4924ea92021-03-23 08:25:31 +00003563 case Instruction::IGET_SHORT: {
3564 if (!BuildInstanceFieldAccess(instruction, dex_pc, /* is_put= */ false)) {
David Brazdildee58d62016-04-07 09:54:26 +00003565 return false;
3566 }
3567 break;
3568 }
3569
3570 case Instruction::IPUT:
David Brazdildee58d62016-04-07 09:54:26 +00003571 case Instruction::IPUT_WIDE:
David Brazdildee58d62016-04-07 09:54:26 +00003572 case Instruction::IPUT_OBJECT:
David Brazdildee58d62016-04-07 09:54:26 +00003573 case Instruction::IPUT_BOOLEAN:
David Brazdildee58d62016-04-07 09:54:26 +00003574 case Instruction::IPUT_BYTE:
David Brazdildee58d62016-04-07 09:54:26 +00003575 case Instruction::IPUT_CHAR:
Nicolas Geoffray4924ea92021-03-23 08:25:31 +00003576 case Instruction::IPUT_SHORT: {
3577 if (!BuildInstanceFieldAccess(instruction, dex_pc, /* is_put= */ true)) {
David Brazdildee58d62016-04-07 09:54:26 +00003578 return false;
3579 }
3580 break;
3581 }
3582
3583 case Instruction::SGET:
3584 case Instruction::SGET_WIDE:
3585 case Instruction::SGET_OBJECT:
3586 case Instruction::SGET_BOOLEAN:
3587 case Instruction::SGET_BYTE:
3588 case Instruction::SGET_CHAR:
3589 case Instruction::SGET_SHORT: {
Andreas Gampe3db70682018-12-26 15:12:03 -08003590 BuildStaticFieldAccess(instruction, dex_pc, /* is_put= */ false);
David Brazdildee58d62016-04-07 09:54:26 +00003591 break;
3592 }
3593
3594 case Instruction::SPUT:
3595 case Instruction::SPUT_WIDE:
3596 case Instruction::SPUT_OBJECT:
3597 case Instruction::SPUT_BOOLEAN:
3598 case Instruction::SPUT_BYTE:
3599 case Instruction::SPUT_CHAR:
3600 case Instruction::SPUT_SHORT: {
Andreas Gampe3db70682018-12-26 15:12:03 -08003601 BuildStaticFieldAccess(instruction, dex_pc, /* is_put= */ true);
David Brazdildee58d62016-04-07 09:54:26 +00003602 break;
3603 }
3604
3605#define ARRAY_XX(kind, anticipated_type) \
3606 case Instruction::AGET##kind: { \
3607 BuildArrayAccess(instruction, dex_pc, false, anticipated_type); \
3608 break; \
3609 } \
3610 case Instruction::APUT##kind: { \
3611 BuildArrayAccess(instruction, dex_pc, true, anticipated_type); \
3612 break; \
3613 }
3614
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003615 ARRAY_XX(, DataType::Type::kInt32);
3616 ARRAY_XX(_WIDE, DataType::Type::kInt64);
3617 ARRAY_XX(_OBJECT, DataType::Type::kReference);
3618 ARRAY_XX(_BOOLEAN, DataType::Type::kBool);
3619 ARRAY_XX(_BYTE, DataType::Type::kInt8);
3620 ARRAY_XX(_CHAR, DataType::Type::kUint16);
3621 ARRAY_XX(_SHORT, DataType::Type::kInt16);
David Brazdildee58d62016-04-07 09:54:26 +00003622
3623 case Instruction::ARRAY_LENGTH: {
David Brazdilc120bbe2016-04-22 16:57:00 +01003624 HInstruction* object = LoadNullCheckedLocal(instruction.VRegB_12x(), dex_pc);
Vladimir Markoca6fff82017-10-03 14:49:14 +01003625 AppendInstruction(new (allocator_) HArrayLength(object, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00003626 UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction());
3627 break;
3628 }
3629
3630 case Instruction::CONST_STRING: {
Andreas Gampe8a0128a2016-11-28 07:38:35 -08003631 dex::StringIndex string_index(instruction.VRegB_21c());
Vladimir Marko28e012a2017-12-07 11:22:59 +00003632 BuildLoadString(string_index, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003633 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
3634 break;
3635 }
3636
3637 case Instruction::CONST_STRING_JUMBO: {
Andreas Gampe8a0128a2016-11-28 07:38:35 -08003638 dex::StringIndex string_index(instruction.VRegB_31c());
Vladimir Marko28e012a2017-12-07 11:22:59 +00003639 BuildLoadString(string_index, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003640 UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction());
3641 break;
3642 }
3643
3644 case Instruction::CONST_CLASS: {
Andreas Gampea5b09a62016-11-17 15:21:22 -08003645 dex::TypeIndex type_index(instruction.VRegB_21c());
Nicolas Geoffray83c8e272017-01-31 14:36:37 +00003646 BuildLoadClass(type_index, dex_pc);
David Brazdildee58d62016-04-07 09:54:26 +00003647 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
3648 break;
3649 }
3650
Orion Hodsondbaa5c72018-05-10 08:22:46 +01003651 case Instruction::CONST_METHOD_HANDLE: {
3652 uint16_t method_handle_idx = instruction.VRegB_21c();
3653 BuildLoadMethodHandle(method_handle_idx, dex_pc);
3654 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
3655 break;
3656 }
3657
Orion Hodson18259d72018-04-12 11:18:23 +01003658 case Instruction::CONST_METHOD_TYPE: {
Orion Hodson06d10a72018-05-14 08:53:38 +01003659 dex::ProtoIndex proto_idx(instruction.VRegB_21c());
Orion Hodson18259d72018-04-12 11:18:23 +01003660 BuildLoadMethodType(proto_idx, dex_pc);
3661 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
3662 break;
3663 }
3664
David Brazdildee58d62016-04-07 09:54:26 +00003665 case Instruction::MOVE_EXCEPTION: {
Vladimir Markoca6fff82017-10-03 14:49:14 +01003666 AppendInstruction(new (allocator_) HLoadException(dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00003667 UpdateLocal(instruction.VRegA_11x(), current_block_->GetLastInstruction());
Vladimir Markoca6fff82017-10-03 14:49:14 +01003668 AppendInstruction(new (allocator_) HClearException(dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00003669 break;
3670 }
3671
3672 case Instruction::THROW: {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003673 HInstruction* exception = LoadLocal(instruction.VRegA_11x(), DataType::Type::kReference);
Vladimir Markoca6fff82017-10-03 14:49:14 +01003674 AppendInstruction(new (allocator_) HThrow(exception, dex_pc));
David Brazdildee58d62016-04-07 09:54:26 +00003675 // We finished building this block. Set the current block to null to avoid
3676 // adding dead instructions to it.
3677 current_block_ = nullptr;
3678 break;
3679 }
3680
3681 case Instruction::INSTANCE_OF: {
3682 uint8_t destination = instruction.VRegA_22c();
3683 uint8_t reference = instruction.VRegB_22c();
Andreas Gampea5b09a62016-11-17 15:21:22 -08003684 dex::TypeIndex type_index(instruction.VRegC_22c());
David Brazdildee58d62016-04-07 09:54:26 +00003685 BuildTypeCheck(instruction, destination, reference, type_index, dex_pc);
3686 break;
3687 }
3688
3689 case Instruction::CHECK_CAST: {
3690 uint8_t reference = instruction.VRegA_21c();
Andreas Gampea5b09a62016-11-17 15:21:22 -08003691 dex::TypeIndex type_index(instruction.VRegB_21c());
David Brazdildee58d62016-04-07 09:54:26 +00003692 BuildTypeCheck(instruction, -1, reference, type_index, dex_pc);
3693 break;
3694 }
3695
3696 case Instruction::MONITOR_ENTER: {
Vladimir Markoca6fff82017-10-03 14:49:14 +01003697 AppendInstruction(new (allocator_) HMonitorOperation(
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003698 LoadLocal(instruction.VRegA_11x(), DataType::Type::kReference),
David Brazdildee58d62016-04-07 09:54:26 +00003699 HMonitorOperation::OperationKind::kEnter,
3700 dex_pc));
Artem Serov2808be82018-12-20 19:15:11 +00003701 graph_->SetHasMonitorOperations(true);
David Brazdildee58d62016-04-07 09:54:26 +00003702 break;
3703 }
3704
3705 case Instruction::MONITOR_EXIT: {
Vladimir Markoca6fff82017-10-03 14:49:14 +01003706 AppendInstruction(new (allocator_) HMonitorOperation(
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01003707 LoadLocal(instruction.VRegA_11x(), DataType::Type::kReference),
David Brazdildee58d62016-04-07 09:54:26 +00003708 HMonitorOperation::OperationKind::kExit,
3709 dex_pc));
Artem Serov2808be82018-12-20 19:15:11 +00003710 graph_->SetHasMonitorOperations(true);
David Brazdildee58d62016-04-07 09:54:26 +00003711 break;
3712 }
3713
3714 case Instruction::SPARSE_SWITCH:
3715 case Instruction::PACKED_SWITCH: {
3716 BuildSwitch(instruction, dex_pc);
3717 break;
3718 }
3719
David Srbeckyc5cd5892021-03-23 08:09:15 +00003720 case Instruction::UNUSED_3E ... Instruction::UNUSED_43:
David Srbecky61c62422021-04-27 16:22:48 +01003721 case Instruction::UNUSED_73:
Orion Hodson4c8e12e2018-05-18 08:33:20 +01003722 case Instruction::UNUSED_79:
3723 case Instruction::UNUSED_7A:
David Srbeckyc5cd5892021-03-23 08:09:15 +00003724 case Instruction::UNUSED_E3 ... Instruction::UNUSED_F9: {
David Brazdildee58d62016-04-07 09:54:26 +00003725 VLOG(compiler) << "Did not compile "
David Sehr709b0702016-10-13 09:12:37 -07003726 << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
David Brazdildee58d62016-04-07 09:54:26 +00003727 << " because of unhandled instruction "
3728 << instruction.Name();
Igor Murashkin1e065a52017-08-09 13:20:34 -07003729 MaybeRecordStat(compilation_stats_,
3730 MethodCompilationStat::kNotCompiledUnhandledInstruction);
David Brazdildee58d62016-04-07 09:54:26 +00003731 return false;
Orion Hodson4c8e12e2018-05-18 08:33:20 +01003732 }
David Brazdildee58d62016-04-07 09:54:26 +00003733 }
3734 return true;
3735} // NOLINT(readability/fn_size)
3736
Vladimir Marko8d6768d2017-03-14 10:13:21 +00003737ObjPtr<mirror::Class> HInstructionBuilder::LookupResolvedType(
3738 dex::TypeIndex type_index,
3739 const DexCompilationUnit& compilation_unit) const {
Vladimir Marko666ee3d2017-12-11 18:37:36 +00003740 return compilation_unit.GetClassLinker()->LookupResolvedType(
Vladimir Marko8d6768d2017-03-14 10:13:21 +00003741 type_index, compilation_unit.GetDexCache().Get(), compilation_unit.GetClassLoader().Get());
3742}
3743
3744ObjPtr<mirror::Class> HInstructionBuilder::LookupReferrerClass() const {
3745 // TODO: Cache the result in a Handle<mirror::Class>.
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08003746 const dex::MethodId& method_id =
Vladimir Marko8d6768d2017-03-14 10:13:21 +00003747 dex_compilation_unit_->GetDexFile()->GetMethodId(dex_compilation_unit_->GetDexMethodIndex());
3748 return LookupResolvedType(method_id.class_idx_, *dex_compilation_unit_);
3749}
3750
David Brazdildee58d62016-04-07 09:54:26 +00003751} // namespace art