blob: 7fa16bbc0a2d08f5f29716bb3c5474c92da493b9 [file] [log] [blame]
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001/*
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Nicolas Geoffraye5038322014-07-04 09:41:32 +010017#include "builder.h"
18
Mathieu Chartierc7853442015-03-27 14:35:38 -070019#include "art_field-inl.h"
Andreas Gamped881df52014-11-24 23:28:39 -080020#include "base/logging.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010021#include "class_linker.h"
Jeff Hao848f70a2014-01-15 13:49:50 -080022#include "dex/verified_method.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000023#include "dex_file-inl.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000024#include "dex_instruction-inl.h"
Roland Levillain4c0eb422015-04-24 16:43:49 +010025#include "dex/verified_method.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010026#include "driver/compiler_driver-inl.h"
Vladimir Marko20f85592015-03-19 10:07:02 +000027#include "driver/compiler_options.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010028#include "mirror/class_loader.h"
29#include "mirror/dex_cache.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000030#include "nodes.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000031#include "primitive.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010032#include "scoped_thread_state_change.h"
33#include "thread.h"
Vladimir Marko58155012015-08-19 12:49:41 +000034#include "utils/dex_cache_arrays_layout-inl.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000035
36namespace art {
37
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010038/**
39 * Helper class to add HTemporary instructions. This class is used when
40 * converting a DEX instruction to multiple HInstruction, and where those
41 * instructions do not die at the following instruction, but instead spans
42 * multiple instructions.
43 */
44class Temporaries : public ValueObject {
45 public:
Calin Juravlef97f9fb2014-11-11 15:38:19 +000046 explicit Temporaries(HGraph* graph) : graph_(graph), index_(0) {}
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010047
48 void Add(HInstruction* instruction) {
Calin Juravlef97f9fb2014-11-11 15:38:19 +000049 HInstruction* temp = new (graph_->GetArena()) HTemporary(index_);
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010050 instruction->GetBlock()->AddInstruction(temp);
Calin Juravlef97f9fb2014-11-11 15:38:19 +000051
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010052 DCHECK(temp->GetPrevious() == instruction);
Calin Juravlef97f9fb2014-11-11 15:38:19 +000053
54 size_t offset;
55 if (instruction->GetType() == Primitive::kPrimLong
56 || instruction->GetType() == Primitive::kPrimDouble) {
57 offset = 2;
58 } else {
59 offset = 1;
60 }
61 index_ += offset;
62
63 graph_->UpdateTemporariesVRegSlots(index_);
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010064 }
65
66 private:
67 HGraph* const graph_;
68
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010069 // Current index in the temporary stack, updated by `Add`.
70 size_t index_;
71};
72
Andreas Gamped881df52014-11-24 23:28:39 -080073class SwitchTable : public ValueObject {
74 public:
75 SwitchTable(const Instruction& instruction, uint32_t dex_pc, bool sparse)
76 : instruction_(instruction), dex_pc_(dex_pc), sparse_(sparse) {
77 int32_t table_offset = instruction.VRegB_31t();
78 const uint16_t* table = reinterpret_cast<const uint16_t*>(&instruction) + table_offset;
79 if (sparse) {
80 CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
81 } else {
82 CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
83 }
84 num_entries_ = table[1];
85 values_ = reinterpret_cast<const int32_t*>(&table[2]);
86 }
87
88 uint16_t GetNumEntries() const {
89 return num_entries_;
90 }
91
Andreas Gampee4d4d322014-12-04 09:09:57 -080092 void CheckIndex(size_t index) const {
93 if (sparse_) {
94 // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order.
95 DCHECK_LT(index, 2 * static_cast<size_t>(num_entries_));
96 } else {
97 // In a packed table, we have the starting key and num_entries_ values.
98 DCHECK_LT(index, 1 + static_cast<size_t>(num_entries_));
99 }
100 }
101
Andreas Gamped881df52014-11-24 23:28:39 -0800102 int32_t GetEntryAt(size_t index) const {
Andreas Gampee4d4d322014-12-04 09:09:57 -0800103 CheckIndex(index);
Andreas Gamped881df52014-11-24 23:28:39 -0800104 return values_[index];
105 }
106
107 uint32_t GetDexPcForIndex(size_t index) const {
Andreas Gampee4d4d322014-12-04 09:09:57 -0800108 CheckIndex(index);
Andreas Gamped881df52014-11-24 23:28:39 -0800109 return dex_pc_ +
110 (reinterpret_cast<const int16_t*>(values_ + index) -
111 reinterpret_cast<const int16_t*>(&instruction_));
112 }
113
Andreas Gampee4d4d322014-12-04 09:09:57 -0800114 // Index of the first value in the table.
115 size_t GetFirstValueIndex() const {
116 if (sparse_) {
117 // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order.
118 return num_entries_;
119 } else {
120 // In a packed table, we have the starting key and num_entries_ values.
121 return 1;
122 }
123 }
124
Andreas Gamped881df52014-11-24 23:28:39 -0800125 private:
126 const Instruction& instruction_;
127 const uint32_t dex_pc_;
128
129 // Whether this is a sparse-switch table (or a packed-switch one).
130 const bool sparse_;
131
132 // This can't be const as it needs to be computed off of the given instruction, and complicated
133 // expressions in the initializer list seemed very ugly.
134 uint16_t num_entries_;
135
136 const int32_t* values_;
137
138 DISALLOW_COPY_AND_ASSIGN(SwitchTable);
139};
140
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100141void HGraphBuilder::InitializeLocals(uint16_t count) {
142 graph_->SetNumberOfVRegs(count);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000143 locals_.SetSize(count);
144 for (int i = 0; i < count; i++) {
145 HLocal* local = new (arena_) HLocal(i);
146 entry_block_->AddInstruction(local);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000147 locals_.Put(i, local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000148 }
149}
150
Nicolas Geoffray52e832b2014-11-06 15:15:31 +0000151void HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100152 // dex_compilation_unit_ is null only when unit testing.
153 if (dex_compilation_unit_ == nullptr) {
Nicolas Geoffray52e832b2014-11-06 15:15:31 +0000154 return;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100155 }
156
157 graph_->SetNumberOfInVRegs(number_of_parameters);
158 const char* shorty = dex_compilation_unit_->GetShorty();
159 int locals_index = locals_.Size() - number_of_parameters;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100160 int parameter_index = 0;
161
162 if (!dex_compilation_unit_->IsStatic()) {
163 // Add the implicit 'this' argument, not expressed in the signature.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100164 HParameterValue* parameter =
Calin Juravle10e244f2015-01-26 18:54:32 +0000165 new (arena_) HParameterValue(parameter_index++, Primitive::kPrimNot, true);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100166 entry_block_->AddInstruction(parameter);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100167 HLocal* local = GetLocalAt(locals_index++);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100168 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100169 number_of_parameters--;
170 }
171
172 uint32_t pos = 1;
173 for (int i = 0; i < number_of_parameters; i++) {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100174 HParameterValue* parameter =
175 new (arena_) HParameterValue(parameter_index++, Primitive::GetType(shorty[pos++]));
176 entry_block_->AddInstruction(parameter);
177 HLocal* local = GetLocalAt(locals_index++);
178 // Store the parameter value in the local that the dex code will use
179 // to reference that parameter.
180 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
181 bool is_wide = (parameter->GetType() == Primitive::kPrimLong)
182 || (parameter->GetType() == Primitive::kPrimDouble);
183 if (is_wide) {
184 i++;
185 locals_index++;
186 parameter_index++;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100187 }
188 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100189}
190
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100191template<typename T>
Calin Juravle225ff812014-11-13 16:46:39 +0000192void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc) {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000193 int32_t target_offset = instruction.GetTargetOffset();
David Brazdil852eaff2015-02-02 15:23:05 +0000194 HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset);
195 HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
196 DCHECK(branch_target != nullptr);
197 DCHECK(fallthrough_target != nullptr);
198 PotentiallyAddSuspendCheck(branch_target, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100199 HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
200 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Dave Allison20dfc792014-06-16 20:44:29 -0700201 T* comparison = new (arena_) T(first, second);
202 current_block_->AddInstruction(comparison);
203 HInstruction* ifinst = new (arena_) HIf(comparison);
204 current_block_->AddInstruction(ifinst);
David Brazdil852eaff2015-02-02 15:23:05 +0000205 current_block_->AddSuccessor(branch_target);
206 current_block_->AddSuccessor(fallthrough_target);
Dave Allison20dfc792014-06-16 20:44:29 -0700207 current_block_ = nullptr;
208}
209
210template<typename T>
Calin Juravle225ff812014-11-13 16:46:39 +0000211void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000212 int32_t target_offset = instruction.GetTargetOffset();
David Brazdil852eaff2015-02-02 15:23:05 +0000213 HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset);
214 HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
215 DCHECK(branch_target != nullptr);
216 DCHECK(fallthrough_target != nullptr);
217 PotentiallyAddSuspendCheck(branch_target, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -0700218 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000219 T* comparison = new (arena_) T(value, graph_->GetIntConstant(0));
Dave Allison20dfc792014-06-16 20:44:29 -0700220 current_block_->AddInstruction(comparison);
221 HInstruction* ifinst = new (arena_) HIf(comparison);
222 current_block_->AddInstruction(ifinst);
David Brazdil852eaff2015-02-02 15:23:05 +0000223 current_block_->AddSuccessor(branch_target);
224 current_block_->AddSuccessor(fallthrough_target);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100225 current_block_ = nullptr;
226}
227
Calin Juravle48c2b032014-12-09 18:11:36 +0000228void HGraphBuilder::MaybeRecordStat(MethodCompilationStat compilation_stat) {
229 if (compilation_stats_ != nullptr) {
230 compilation_stats_->RecordStat(compilation_stat);
231 }
232}
233
David Brazdil1b498722015-03-31 11:37:18 +0100234bool HGraphBuilder::SkipCompilation(const DexFile::CodeItem& code_item,
Calin Juravle48c2b032014-12-09 18:11:36 +0000235 size_t number_of_branches) {
236 const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions();
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000237 CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter();
238 if (compiler_filter == CompilerOptions::kEverything) {
239 return false;
240 }
241
David Brazdil1b498722015-03-31 11:37:18 +0100242 if (compiler_options.IsHugeMethod(code_item.insns_size_in_code_units_)) {
Calin Juravle48c2b032014-12-09 18:11:36 +0000243 VLOG(compiler) << "Skip compilation of huge method "
244 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
David Brazdil1b498722015-03-31 11:37:18 +0100245 << ": " << code_item.insns_size_in_code_units_ << " code units";
Calin Juravle48c2b032014-12-09 18:11:36 +0000246 MaybeRecordStat(MethodCompilationStat::kNotCompiledHugeMethod);
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000247 return true;
248 }
249
250 // If it's large and contains no branches, it's likely to be machine generated initialization.
David Brazdil1b498722015-03-31 11:37:18 +0100251 if (compiler_options.IsLargeMethod(code_item.insns_size_in_code_units_)
252 && (number_of_branches == 0)) {
Calin Juravle48c2b032014-12-09 18:11:36 +0000253 VLOG(compiler) << "Skip compilation of large method with no branch "
254 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
David Brazdil1b498722015-03-31 11:37:18 +0100255 << ": " << code_item.insns_size_in_code_units_ << " code units";
Calin Juravle48c2b032014-12-09 18:11:36 +0000256 MaybeRecordStat(MethodCompilationStat::kNotCompiledLargeMethodNoBranches);
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000257 return true;
258 }
259
260 return false;
261}
262
David Brazdilbff75032015-07-08 17:26:51 +0000263static const DexFile::TryItem* GetTryItem(HBasicBlock* block,
264 const DexFile::CodeItem& code_item,
265 const ArenaBitVector& can_block_throw) {
266 DCHECK(!block->IsSingleTryBoundary());
267
268 // Block does not contain throwing instructions. Even if it is covered by
269 // a TryItem, we will consider it not in a try block.
270 if (!can_block_throw.IsBitSet(block->GetBlockId())) {
271 return nullptr;
272 }
273
274 // Instructions in the block may throw. Find a TryItem covering this block.
275 int32_t try_item_idx = DexFile::FindTryItem(code_item, block->GetDexPc());
David Brazdil6cd788f2015-07-08 16:44:00 +0100276 return (try_item_idx == -1) ? nullptr : DexFile::GetTryItems(code_item, try_item_idx);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000277}
278
279void HGraphBuilder::CreateBlocksForTryCatch(const DexFile::CodeItem& code_item) {
280 if (code_item.tries_size_ == 0) {
281 return;
282 }
283
284 // Create branch targets at the start/end of the TryItem range. These are
285 // places where the program might fall through into/out of the a block and
286 // where TryBoundary instructions will be inserted later. Other edges which
287 // enter/exit the try blocks are a result of branches/switches.
288 for (size_t idx = 0; idx < code_item.tries_size_; ++idx) {
289 const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item, idx);
290 uint32_t dex_pc_start = try_item->start_addr_;
291 uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_;
292 FindOrCreateBlockStartingAt(dex_pc_start);
293 if (dex_pc_end < code_item.insns_size_in_code_units_) {
294 // TODO: Do not create block if the last instruction cannot fall through.
295 FindOrCreateBlockStartingAt(dex_pc_end);
296 } else {
297 // The TryItem spans until the very end of the CodeItem (or beyond if
298 // invalid) and therefore cannot have any code afterwards.
299 }
300 }
301
302 // Create branch targets for exception handlers.
303 const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item, 0);
304 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
305 for (uint32_t idx = 0; idx < handlers_size; ++idx) {
306 CatchHandlerIterator iterator(handlers_ptr);
307 for (; iterator.HasNext(); iterator.Next()) {
308 uint32_t address = iterator.GetHandlerAddress();
309 HBasicBlock* block = FindOrCreateBlockStartingAt(address);
David Brazdilec16f792015-08-19 15:04:01 +0100310 block->SetTryCatchInformation(
311 new (arena_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_));
David Brazdilfc6a86a2015-06-26 10:33:45 +0000312 }
313 handlers_ptr = iterator.EndDataPointer();
314 }
315}
316
David Brazdil56e1acc2015-06-30 15:41:36 +0100317void HGraphBuilder::SplitTryBoundaryEdge(HBasicBlock* predecessor,
318 HBasicBlock* successor,
319 HTryBoundary::BoundaryKind kind,
320 const DexFile::CodeItem& code_item,
321 const DexFile::TryItem& try_item) {
322 // Split the edge with a single TryBoundary instruction.
323 HTryBoundary* try_boundary = new (arena_) HTryBoundary(kind);
324 HBasicBlock* try_entry_block = graph_->SplitEdge(predecessor, successor);
325 try_entry_block->AddInstruction(try_boundary);
326
327 // Link the TryBoundary to the handlers of `try_item`.
328 for (CatchHandlerIterator it(code_item, try_item); it.HasNext(); it.Next()) {
329 try_boundary->AddExceptionHandler(FindBlockStartingAt(it.GetHandlerAddress()));
330 }
331}
332
David Brazdilfc6a86a2015-06-26 10:33:45 +0000333void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) {
334 if (code_item.tries_size_ == 0) {
335 return;
336 }
337
David Brazdil72783ff2015-07-09 14:36:05 +0100338 // Bit vector stores information on which blocks contain throwing instructions.
339 // Must be expandable because catch blocks may be split into two.
340 ArenaBitVector can_block_throw(arena_, graph_->GetBlocks().Size(), /* expandable */ true);
David Brazdilbff75032015-07-08 17:26:51 +0000341
342 // Scan blocks and mark those which contain throwing instructions.
David Brazdil72783ff2015-07-09 14:36:05 +0100343 for (size_t block_id = 0, e = graph_->GetBlocks().Size(); block_id < e; ++block_id) {
David Brazdilbff75032015-07-08 17:26:51 +0000344 HBasicBlock* block = graph_->GetBlocks().Get(block_id);
David Brazdil72783ff2015-07-09 14:36:05 +0100345 bool can_throw = false;
David Brazdilbff75032015-07-08 17:26:51 +0000346 for (HInstructionIterator insn(block->GetInstructions()); !insn.Done(); insn.Advance()) {
347 if (insn.Current()->CanThrow()) {
David Brazdil72783ff2015-07-09 14:36:05 +0100348 can_throw = true;
David Brazdilbff75032015-07-08 17:26:51 +0000349 break;
350 }
351 }
David Brazdil72783ff2015-07-09 14:36:05 +0100352
353 if (can_throw) {
354 if (block->IsCatchBlock()) {
355 // Catch blocks are always considered an entry point into the TryItem in
356 // order to avoid splitting exceptional edges. We split the block after
357 // the move-exception (if present) and mark the first part non-throwing.
358 // Later on, a TryBoundary will be inserted between the two blocks.
359 HInstruction* first_insn = block->GetFirstInstruction();
360 if (first_insn->IsLoadException()) {
361 // Catch block starts with a LoadException. Split the block after the
David Brazdilcb1c0552015-08-04 16:22:25 +0100362 // StoreLocal and ClearException which must come after the load.
David Brazdil72783ff2015-07-09 14:36:05 +0100363 DCHECK(first_insn->GetNext()->IsStoreLocal());
David Brazdilcb1c0552015-08-04 16:22:25 +0100364 DCHECK(first_insn->GetNext()->GetNext()->IsClearException());
365 block = block->SplitBefore(first_insn->GetNext()->GetNext()->GetNext());
David Brazdil72783ff2015-07-09 14:36:05 +0100366 } else {
367 // Catch block does not load the exception. Split at the beginning to
368 // create an empty catch block.
369 block = block->SplitBefore(first_insn);
370 }
371 }
372 can_block_throw.SetBit(block->GetBlockId());
373 }
David Brazdilbff75032015-07-08 17:26:51 +0000374 }
375
David Brazdil281a6322015-07-03 10:34:57 +0100376 // Iterate over all blocks, find those covered by some TryItem and:
377 // (a) split edges which enter/exit the try range,
378 // (b) create TryBoundary instructions in the new blocks,
379 // (c) link the new blocks to corresponding exception handlers.
380 // We cannot iterate only over blocks in `branch_targets_` because switch-case
381 // blocks share the same dex_pc.
David Brazdil72783ff2015-07-09 14:36:05 +0100382 for (size_t block_id = 0, e = graph_->GetBlocks().Size(); block_id < e; ++block_id) {
David Brazdil281a6322015-07-03 10:34:57 +0100383 HBasicBlock* try_block = graph_->GetBlocks().Get(block_id);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000384
David Brazdil281a6322015-07-03 10:34:57 +0100385 // TryBoundary blocks are added at the end of the list and not iterated over.
386 DCHECK(!try_block->IsSingleTryBoundary());
David Brazdilfc6a86a2015-06-26 10:33:45 +0000387
David Brazdil281a6322015-07-03 10:34:57 +0100388 // Find the TryItem for this block.
David Brazdilbff75032015-07-08 17:26:51 +0000389 const DexFile::TryItem* try_item = GetTryItem(try_block, code_item, can_block_throw);
390 if (try_item == nullptr) {
David Brazdil281a6322015-07-03 10:34:57 +0100391 continue;
392 }
David Brazdil281a6322015-07-03 10:34:57 +0100393
David Brazdil72783ff2015-07-09 14:36:05 +0100394 // Catch blocks were split earlier and cannot throw.
395 DCHECK(!try_block->IsCatchBlock());
396
397 // Find predecessors which are not covered by the same TryItem range. Such
398 // edges enter the try block and will have a TryBoundary inserted.
Vladimir Marko60584552015-09-03 13:35:12 +0000399 for (size_t i = 0; i < try_block->GetPredecessors().size(); ++i) {
400 HBasicBlock* predecessor = try_block->GetPredecessor(i);
David Brazdil72783ff2015-07-09 14:36:05 +0100401 if (predecessor->IsSingleTryBoundary()) {
402 // The edge was already split because of an exit from a neighbouring
403 // TryItem. We split it again and insert an entry point.
404 if (kIsDebugBuild) {
405 HTryBoundary* last_insn = predecessor->GetLastInstruction()->AsTryBoundary();
406 const DexFile::TryItem* predecessor_try_item =
407 GetTryItem(predecessor->GetSinglePredecessor(), code_item, can_block_throw);
408 DCHECK(!last_insn->IsEntry());
409 DCHECK_EQ(last_insn->GetNormalFlowSuccessor(), try_block);
410 DCHECK(try_block->IsFirstIndexOfPredecessor(predecessor, i));
411 DCHECK_NE(try_item, predecessor_try_item);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000412 }
David Brazdil72783ff2015-07-09 14:36:05 +0100413 } else if (GetTryItem(predecessor, code_item, can_block_throw) != try_item) {
414 // This is an entry point into the TryItem and the edge has not been
415 // split yet. That means that `predecessor` is not in a TryItem, or
416 // it is in a different TryItem and we happened to iterate over this
417 // block first. We split the edge and insert an entry point.
418 } else {
419 // Not an edge on the boundary of the try block.
420 continue;
David Brazdilfc6a86a2015-06-26 10:33:45 +0000421 }
David Brazdil72783ff2015-07-09 14:36:05 +0100422 SplitTryBoundaryEdge(predecessor, try_block, HTryBoundary::kEntry, code_item, *try_item);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000423 }
David Brazdil281a6322015-07-03 10:34:57 +0100424
425 // Find successors which are not covered by the same TryItem range. Such
426 // edges exit the try block and will have a TryBoundary inserted.
Vladimir Marko60584552015-09-03 13:35:12 +0000427 for (HBasicBlock* successor : try_block->GetSuccessors()) {
David Brazdil281a6322015-07-03 10:34:57 +0100428 if (successor->IsCatchBlock()) {
429 // A catch block is always considered an entry point into its TryItem.
430 // We therefore assume this is an exit point, regardless of whether
431 // the catch block is in a different TryItem or not.
432 } else if (successor->IsSingleTryBoundary()) {
433 // The edge was already split because of an entry into a neighbouring
434 // TryItem. We split it again and insert an exit.
435 if (kIsDebugBuild) {
436 HTryBoundary* last_insn = successor->GetLastInstruction()->AsTryBoundary();
David Brazdilbff75032015-07-08 17:26:51 +0000437 const DexFile::TryItem* successor_try_item =
438 GetTryItem(last_insn->GetNormalFlowSuccessor(), code_item, can_block_throw);
David Brazdil281a6322015-07-03 10:34:57 +0100439 DCHECK_EQ(try_block, successor->GetSinglePredecessor());
440 DCHECK(last_insn->IsEntry());
David Brazdilbff75032015-07-08 17:26:51 +0000441 DCHECK_NE(try_item, successor_try_item);
David Brazdil281a6322015-07-03 10:34:57 +0100442 }
David Brazdilbff75032015-07-08 17:26:51 +0000443 } else if (GetTryItem(successor, code_item, can_block_throw) != try_item) {
David Brazdil281a6322015-07-03 10:34:57 +0100444 // This is an exit out of the TryItem and the edge has not been split
445 // yet. That means that either `successor` is not in a TryItem, or it
446 // is in a different TryItem and we happened to iterate over this
447 // block first. We split the edge and insert an exit.
448 HInstruction* last_instruction = try_block->GetLastInstruction();
449 if (last_instruction->IsReturn() || last_instruction->IsReturnVoid()) {
450 DCHECK_EQ(successor, exit_block_);
451 // Control flow exits the try block with a Return(Void). Because
452 // splitting the edge would invalidate the invariant that Return
453 // always jumps to Exit, we move the Return outside the try block.
454 successor = try_block->SplitBefore(last_instruction);
455 }
456 } else {
457 // Not an edge on the boundary of the try block.
458 continue;
459 }
David Brazdilbff75032015-07-08 17:26:51 +0000460 SplitTryBoundaryEdge(try_block, successor, HTryBoundary::kExit, code_item, *try_item);
David Brazdil281a6322015-07-03 10:34:57 +0100461 }
David Brazdilfc6a86a2015-06-26 10:33:45 +0000462 }
463}
464
David Brazdil5e8b1372015-01-23 14:39:08 +0000465bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
466 DCHECK(graph_->GetBlocks().IsEmpty());
467
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000468 const uint16_t* code_ptr = code_item.insns_;
469 const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_;
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +0100470 code_start_ = code_ptr;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000471
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000472 // Setup the graph with the entry block and exit block.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100473 entry_block_ = new (arena_) HBasicBlock(graph_, 0);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000474 graph_->AddBlock(entry_block_);
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100475 exit_block_ = new (arena_) HBasicBlock(graph_, kNoDexPc);
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000476 graph_->SetEntryBlock(entry_block_);
477 graph_->SetExitBlock(exit_block_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000478
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000479 InitializeLocals(code_item.registers_size_);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000480 graph_->SetMaximumNumberOfOutVRegs(code_item.outs_size_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000481
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000482 // Compute the number of dex instructions, blocks, and branches. We will
483 // check these values against limits given to the compiler.
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000484 size_t number_of_branches = 0;
485
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000486 // To avoid splitting blocks, we compute ahead of time the instructions that
487 // start a new block, and create these blocks.
Calin Juravle702d2602015-04-30 19:28:21 +0100488 if (!ComputeBranchTargets(code_ptr, code_end, &number_of_branches)) {
489 MaybeRecordStat(MethodCompilationStat::kNotCompiledBranchOutsideMethodCode);
490 return false;
491 }
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000492
493 // Note that the compiler driver is null when unit testing.
David Brazdil1b498722015-03-31 11:37:18 +0100494 if ((compiler_driver_ != nullptr) && SkipCompilation(code_item, number_of_branches)) {
David Brazdil5e8b1372015-01-23 14:39:08 +0000495 return false;
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000496 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000497
David Brazdilfc6a86a2015-06-26 10:33:45 +0000498 CreateBlocksForTryCatch(code_item);
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000499
Nicolas Geoffray52e832b2014-11-06 15:15:31 +0000500 InitializeParameters(code_item.ins_size_);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100501
Calin Juravle225ff812014-11-13 16:46:39 +0000502 size_t dex_pc = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000503 while (code_ptr < code_end) {
Calin Juravle225ff812014-11-13 16:46:39 +0000504 // Update the current block if dex_pc starts a new block.
505 MaybeUpdateCurrentBlock(dex_pc);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000506 const Instruction& instruction = *Instruction::At(code_ptr);
Calin Juravle48c2b032014-12-09 18:11:36 +0000507 if (!AnalyzeDexInstruction(instruction, dex_pc)) {
David Brazdil5e8b1372015-01-23 14:39:08 +0000508 return false;
Calin Juravle48c2b032014-12-09 18:11:36 +0000509 }
Calin Juravle225ff812014-11-13 16:46:39 +0000510 dex_pc += instruction.SizeInCodeUnits();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000511 code_ptr += instruction.SizeInCodeUnits();
512 }
513
David Brazdilfc6a86a2015-06-26 10:33:45 +0000514 // Add Exit to the exit block.
David Brazdil3e187382015-06-26 09:59:52 +0000515 exit_block_->AddInstruction(new (arena_) HExit());
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000516 // Add the suspend check to the entry block.
517 entry_block_->AddInstruction(new (arena_) HSuspendCheck(0));
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000518 entry_block_->AddInstruction(new (arena_) HGoto());
David Brazdilbff75032015-07-08 17:26:51 +0000519 // Add the exit block at the end.
520 graph_->AddBlock(exit_block_);
David Brazdil5e8b1372015-01-23 14:39:08 +0000521
David Brazdilfc6a86a2015-06-26 10:33:45 +0000522 // Iterate over blocks covered by TryItems and insert TryBoundaries at entry
523 // and exit points. This requires all control-flow instructions and
524 // non-exceptional edges to have been created.
525 InsertTryBoundaryBlocks(code_item);
526
David Brazdil5e8b1372015-01-23 14:39:08 +0000527 return true;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000528}
529
David Brazdilfc6a86a2015-06-26 10:33:45 +0000530void HGraphBuilder::MaybeUpdateCurrentBlock(size_t dex_pc) {
531 HBasicBlock* block = FindBlockStartingAt(dex_pc);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000532 if (block == nullptr) {
533 return;
534 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000535
536 if (current_block_ != nullptr) {
537 // Branching instructions clear current_block, so we know
538 // the last instruction of the current block is not a branching
539 // instruction. We add an unconditional goto to the found block.
540 current_block_->AddInstruction(new (arena_) HGoto());
541 current_block_->AddSuccessor(block);
542 }
543 graph_->AddBlock(block);
544 current_block_ = block;
545}
546
Calin Juravle702d2602015-04-30 19:28:21 +0100547bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr,
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000548 const uint16_t* code_end,
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000549 size_t* number_of_branches) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000550 branch_targets_.SetSize(code_end - code_ptr);
551
552 // Create the first block for the dex instructions, single successor of the entry block.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100553 HBasicBlock* block = new (arena_) HBasicBlock(graph_, 0);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000554 branch_targets_.Put(0, block);
555 entry_block_->AddSuccessor(block);
556
557 // Iterate over all instructions and find branching instructions. Create blocks for
558 // the locations these instructions branch to.
Andreas Gamped881df52014-11-24 23:28:39 -0800559 uint32_t dex_pc = 0;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000560 while (code_ptr < code_end) {
561 const Instruction& instruction = *Instruction::At(code_ptr);
562 if (instruction.IsBranch()) {
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000563 (*number_of_branches)++;
Calin Juravle225ff812014-11-13 16:46:39 +0000564 int32_t target = instruction.GetTargetOffset() + dex_pc;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000565 // Create a block for the target instruction.
David Brazdilfc6a86a2015-06-26 10:33:45 +0000566 FindOrCreateBlockStartingAt(target);
567
Calin Juravle225ff812014-11-13 16:46:39 +0000568 dex_pc += instruction.SizeInCodeUnits();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000569 code_ptr += instruction.SizeInCodeUnits();
Calin Juravle702d2602015-04-30 19:28:21 +0100570
David Brazdilfe659462015-06-24 14:23:56 +0100571 if (instruction.CanFlowThrough()) {
572 if (code_ptr >= code_end) {
Calin Juravle702d2602015-04-30 19:28:21 +0100573 // In the normal case we should never hit this but someone can artificially forge a dex
574 // file to fall-through out the method code. In this case we bail out compilation.
575 return false;
David Brazdilfc6a86a2015-06-26 10:33:45 +0000576 } else {
577 FindOrCreateBlockStartingAt(dex_pc);
Calin Juravle702d2602015-04-30 19:28:21 +0100578 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000579 }
Andreas Gampee4d4d322014-12-04 09:09:57 -0800580 } else if (instruction.IsSwitch()) {
581 SwitchTable table(instruction, dex_pc, instruction.Opcode() == Instruction::SPARSE_SWITCH);
Andreas Gamped881df52014-11-24 23:28:39 -0800582
583 uint16_t num_entries = table.GetNumEntries();
584
Andreas Gampee4d4d322014-12-04 09:09:57 -0800585 // In a packed-switch, the entry at index 0 is the starting key. In a sparse-switch, the
586 // entry at index 0 is the first key, and values are after *all* keys.
587 size_t offset = table.GetFirstValueIndex();
588
589 // Use a larger loop counter type to avoid overflow issues.
590 for (size_t i = 0; i < num_entries; ++i) {
Andreas Gamped881df52014-11-24 23:28:39 -0800591 // The target of the case.
Andreas Gampee4d4d322014-12-04 09:09:57 -0800592 uint32_t target = dex_pc + table.GetEntryAt(i + offset);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000593 FindOrCreateBlockStartingAt(target);
Andreas Gamped881df52014-11-24 23:28:39 -0800594
David Brazdil281a6322015-07-03 10:34:57 +0100595 // Create a block for the switch-case logic. The block gets the dex_pc
596 // of the SWITCH instruction because it is part of its semantics.
597 block = new (arena_) HBasicBlock(graph_, dex_pc);
598 branch_targets_.Put(table.GetDexPcForIndex(i), block);
Andreas Gamped881df52014-11-24 23:28:39 -0800599 }
600
601 // Fall-through. Add a block if there is more code afterwards.
602 dex_pc += instruction.SizeInCodeUnits();
603 code_ptr += instruction.SizeInCodeUnits();
Calin Juravle702d2602015-04-30 19:28:21 +0100604 if (code_ptr >= code_end) {
605 // In the normal case we should never hit this but someone can artificially forge a dex
606 // file to fall-through out the method code. In this case we bail out compilation.
607 // (A switch can fall-through so we don't need to check CanFlowThrough().)
608 return false;
David Brazdilfc6a86a2015-06-26 10:33:45 +0000609 } else {
610 FindOrCreateBlockStartingAt(dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -0800611 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000612 } else {
613 code_ptr += instruction.SizeInCodeUnits();
Calin Juravle225ff812014-11-13 16:46:39 +0000614 dex_pc += instruction.SizeInCodeUnits();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000615 }
616 }
Calin Juravle702d2602015-04-30 19:28:21 +0100617 return true;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000618}
619
David Brazdilfc6a86a2015-06-26 10:33:45 +0000620HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t dex_pc) const {
621 DCHECK_GE(dex_pc, 0);
622 DCHECK_LT(static_cast<size_t>(dex_pc), branch_targets_.Size());
623 return branch_targets_.Get(dex_pc);
624}
625
626HBasicBlock* HGraphBuilder::FindOrCreateBlockStartingAt(int32_t dex_pc) {
627 HBasicBlock* block = FindBlockStartingAt(dex_pc);
628 if (block == nullptr) {
629 block = new (arena_) HBasicBlock(graph_, dex_pc);
630 branch_targets_.Put(dex_pc, block);
631 }
632 return block;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000633}
634
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100635template<typename T>
Roland Levillain88cb1752014-10-20 16:36:47 +0100636void HGraphBuilder::Unop_12x(const Instruction& instruction, Primitive::Type type) {
637 HInstruction* first = LoadLocal(instruction.VRegB(), type);
638 current_block_->AddInstruction(new (arena_) T(type, first));
639 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
640}
641
Roland Levillaindff1f282014-11-05 14:15:05 +0000642void HGraphBuilder::Conversion_12x(const Instruction& instruction,
643 Primitive::Type input_type,
Roland Levillain624279f2014-12-04 11:54:28 +0000644 Primitive::Type result_type,
645 uint32_t dex_pc) {
Roland Levillaindff1f282014-11-05 14:15:05 +0000646 HInstruction* first = LoadLocal(instruction.VRegB(), input_type);
Roland Levillain624279f2014-12-04 11:54:28 +0000647 current_block_->AddInstruction(new (arena_) HTypeConversion(result_type, first, dex_pc));
Roland Levillaindff1f282014-11-05 14:15:05 +0000648 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
649}
650
Roland Levillain88cb1752014-10-20 16:36:47 +0100651template<typename T>
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100652void HGraphBuilder::Binop_23x(const Instruction& instruction, Primitive::Type type) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100653 HInstruction* first = LoadLocal(instruction.VRegB(), type);
654 HInstruction* second = LoadLocal(instruction.VRegC(), type);
655 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100656 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
657}
658
659template<typename T>
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000660void HGraphBuilder::Binop_23x(const Instruction& instruction,
661 Primitive::Type type,
662 uint32_t dex_pc) {
663 HInstruction* first = LoadLocal(instruction.VRegB(), type);
664 HInstruction* second = LoadLocal(instruction.VRegC(), type);
665 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
666 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
667}
668
669template<typename T>
Calin Juravle9aec02f2014-11-18 23:06:35 +0000670void HGraphBuilder::Binop_23x_shift(const Instruction& instruction,
671 Primitive::Type type) {
672 HInstruction* first = LoadLocal(instruction.VRegB(), type);
673 HInstruction* second = LoadLocal(instruction.VRegC(), Primitive::kPrimInt);
674 current_block_->AddInstruction(new (arena_) T(type, first, second));
675 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
676}
677
Calin Juravleddb7df22014-11-25 20:56:51 +0000678void HGraphBuilder::Binop_23x_cmp(const Instruction& instruction,
679 Primitive::Type type,
Mark Mendellc4701932015-04-10 13:18:51 -0400680 ComparisonBias bias,
Alexey Frunze4dda3372015-06-01 18:31:49 -0700681 uint32_t dex_pc) {
Calin Juravleddb7df22014-11-25 20:56:51 +0000682 HInstruction* first = LoadLocal(instruction.VRegB(), type);
683 HInstruction* second = LoadLocal(instruction.VRegC(), type);
Alexey Frunze4dda3372015-06-01 18:31:49 -0700684 current_block_->AddInstruction(new (arena_) HCompare(type, first, second, bias, dex_pc));
Calin Juravleddb7df22014-11-25 20:56:51 +0000685 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
686}
687
Calin Juravle9aec02f2014-11-18 23:06:35 +0000688template<typename T>
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100689void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) {
690 HInstruction* first = LoadLocal(instruction.VRegA(), type);
691 HInstruction* second = LoadLocal(instruction.VRegB(), type);
692 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100693 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
694}
695
696template<typename T>
Calin Juravle9aec02f2014-11-18 23:06:35 +0000697void HGraphBuilder::Binop_12x_shift(const Instruction& instruction, Primitive::Type type) {
698 HInstruction* first = LoadLocal(instruction.VRegA(), type);
699 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
700 current_block_->AddInstruction(new (arena_) T(type, first, second));
701 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
702}
703
704template<typename T>
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000705void HGraphBuilder::Binop_12x(const Instruction& instruction,
706 Primitive::Type type,
707 uint32_t dex_pc) {
708 HInstruction* first = LoadLocal(instruction.VRegA(), type);
709 HInstruction* second = LoadLocal(instruction.VRegB(), type);
710 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
711 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
712}
713
714template<typename T>
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100715void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100716 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000717 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100718 if (reverse) {
719 std::swap(first, second);
720 }
721 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
722 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
723}
724
725template<typename T>
726void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100727 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000728 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100729 if (reverse) {
730 std::swap(first, second);
731 }
732 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
733 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
734}
735
Calin Juravle0c25d102015-04-20 14:49:09 +0100736static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, const CompilerDriver& driver) {
Calin Juravle27df7582015-04-17 19:12:31 +0100737 Thread* self = Thread::Current();
Calin Juravle0c25d102015-04-20 14:49:09 +0100738 return cu->IsConstructor()
739 && driver.RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex());
Calin Juravle27df7582015-04-17 19:12:31 +0100740}
741
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100742void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) {
743 if (type == Primitive::kPrimVoid) {
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100744 if (graph_->ShouldGenerateConstructorBarrier()) {
745 // The compilation unit is null during testing.
746 if (dex_compilation_unit_ != nullptr) {
747 DCHECK(RequiresConstructorBarrier(dex_compilation_unit_, *compiler_driver_))
748 << "Inconsistent use of ShouldGenerateConstructorBarrier. Should not generate a barrier.";
749 }
Calin Juravle27df7582015-04-17 19:12:31 +0100750 current_block_->AddInstruction(new (arena_) HMemoryBarrier(kStoreStore));
751 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100752 current_block_->AddInstruction(new (arena_) HReturnVoid());
753 } else {
754 HInstruction* value = LoadLocal(instruction.VRegA(), type);
755 current_block_->AddInstruction(new (arena_) HReturn(value));
756 }
757 current_block_->AddSuccessor(exit_block_);
758 current_block_ = nullptr;
759}
760
Calin Juravle68ad6492015-08-18 17:08:12 +0100761static InvokeType GetInvokeTypeFromOpCode(Instruction::Code opcode) {
762 switch (opcode) {
763 case Instruction::INVOKE_STATIC:
764 case Instruction::INVOKE_STATIC_RANGE:
765 return kStatic;
766 case Instruction::INVOKE_DIRECT:
767 case Instruction::INVOKE_DIRECT_RANGE:
768 return kDirect;
769 case Instruction::INVOKE_VIRTUAL:
770 case Instruction::INVOKE_VIRTUAL_QUICK:
771 case Instruction::INVOKE_VIRTUAL_RANGE:
772 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
773 return kVirtual;
774 case Instruction::INVOKE_INTERFACE:
775 case Instruction::INVOKE_INTERFACE_RANGE:
776 return kInterface;
777 case Instruction::INVOKE_SUPER_RANGE:
778 case Instruction::INVOKE_SUPER:
779 return kSuper;
780 default:
781 LOG(FATAL) << "Unexpected invoke opcode: " << opcode;
782 UNREACHABLE();
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100783 }
Calin Juravle68ad6492015-08-18 17:08:12 +0100784}
785
786bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
787 uint32_t dex_pc,
788 uint32_t method_idx,
789 uint32_t number_of_vreg_arguments,
790 bool is_range,
791 uint32_t* args,
792 uint32_t register_index) {
793 InvokeType original_invoke_type = GetInvokeTypeFromOpCode(instruction.Opcode());
794 InvokeType optimized_invoke_type = original_invoke_type;
795 const char* descriptor = dex_file_->GetMethodShorty(method_idx);
796 Primitive::Type return_type = Primitive::GetType(descriptor[0]);
797
798 // Remove the return type from the 'proto'.
799 size_t number_of_arguments = strlen(descriptor) - 1;
800 if (original_invoke_type != kStatic) { // instance call
801 // One extra argument for 'this'.
802 number_of_arguments++;
803 }
804
805 MethodReference target_method(dex_file_, method_idx);
806 int32_t table_index;
807 uintptr_t direct_code;
808 uintptr_t direct_method;
809
810 if (!compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_,
811 dex_pc,
812 true /* update_stats */,
813 true /* enable_devirtualization */,
814 &optimized_invoke_type,
815 &target_method,
816 &table_index,
817 &direct_code,
818 &direct_method)) {
819 VLOG(compiler) << "Did not compile "
820 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
821 << " because a method call could not be resolved";
822 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedMethod);
823 return false;
824 }
825
826 DCHECK(optimized_invoke_type != kSuper);
827
828 // Special handling for string init.
829 int32_t string_init_offset = 0;
830 bool is_string_init = compiler_driver_->IsStringInit(method_idx, dex_file_,
831 &string_init_offset);
832
833 // Potential class initialization check, in the case of a static method call.
834 HClinitCheck* clinit_check = nullptr;
835 HInvoke* invoke = nullptr;
836
837 if (is_string_init
838 || optimized_invoke_type == kDirect
839 || optimized_invoke_type == kStatic) {
840 // By default, consider that the called method implicitly requires
841 // an initialization check of its declaring method.
842 HInvokeStaticOrDirect::ClinitCheckRequirement clinit_check_requirement
843 = HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit;
844 if (optimized_invoke_type == kStatic && !is_string_init) {
845 clinit_check = ProcessClinitCheckForInvoke(dex_pc, method_idx, &clinit_check_requirement);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100846 }
Calin Juravle68ad6492015-08-18 17:08:12 +0100847
848 // Replace calls to String.<init> with StringFactory.
849 if (is_string_init) {
850 return_type = Primitive::kPrimNot;
851 number_of_arguments--;
852 optimized_invoke_type = kStatic;
853 }
854
855 HInvokeStaticOrDirect::DispatchInfo dispatch_info = ComputeDispatchInfo(is_string_init,
856 string_init_offset,
857 target_method,
858 direct_method,
859 direct_code);
860 invoke = new (arena_) HInvokeStaticOrDirect(arena_,
861 number_of_arguments,
862 return_type,
863 dex_pc,
864 method_idx,
865 target_method,
866 dispatch_info,
867 original_invoke_type,
868 optimized_invoke_type,
869 clinit_check_requirement);
870 } else if (optimized_invoke_type == kVirtual) {
871 invoke = new (arena_) HInvokeVirtual(arena_,
872 number_of_arguments,
873 return_type,
874 dex_pc,
875 method_idx,
876 table_index);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100877 } else {
Calin Juravle68ad6492015-08-18 17:08:12 +0100878 DCHECK_EQ(optimized_invoke_type, kInterface);
879 invoke = new (arena_) HInvokeInterface(arena_,
880 number_of_arguments,
881 return_type,
882 dex_pc,
883 method_idx,
884 table_index);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100885 }
Calin Juravle68ad6492015-08-18 17:08:12 +0100886
Calin Juravle0eedd7e2015-08-20 14:48:00 +0100887 return SetupArgumentsAndAddInvoke(invoke,
888 number_of_vreg_arguments,
889 args,
890 register_index,
891 is_range,
892 descriptor,
Calin Juravle599262c2015-08-20 15:01:27 +0100893 clinit_check);
Calin Juravle68ad6492015-08-18 17:08:12 +0100894}
895
896HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(
897 uint32_t dex_pc,
898 uint32_t method_idx,
899 HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) {
900 ScopedObjectAccess soa(Thread::Current());
901 StackHandleScope<4> hs(soa.Self());
902 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
903 dex_compilation_unit_->GetClassLinker()->FindDexCache(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -0700904 soa.Self(), *dex_compilation_unit_->GetDexFile())));
Calin Juravle68ad6492015-08-18 17:08:12 +0100905 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
906 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
907 ArtMethod* resolved_method = compiler_driver_->ResolveMethod(
908 soa, dex_cache, class_loader, dex_compilation_unit_, method_idx, InvokeType::kStatic);
909
910 DCHECK(resolved_method != nullptr);
911
912 const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
913 Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -0700914 outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file)));
Calin Juravle68ad6492015-08-18 17:08:12 +0100915 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
916
917 // The index at which the method's class is stored in the DexCache's type array.
918 uint32_t storage_index = DexFile::kDexNoIndex;
919 bool is_outer_class = (resolved_method->GetDeclaringClass() == outer_class.Get());
920 if (is_outer_class) {
921 storage_index = outer_class->GetDexTypeIndex();
922 } else if (outer_dex_cache.Get() == dex_cache.Get()) {
923 // Get `storage_index` from IsClassOfStaticMethodAvailableToReferrer.
924 compiler_driver_->IsClassOfStaticMethodAvailableToReferrer(outer_dex_cache.Get(),
925 GetCompilingClass(),
926 resolved_method,
927 method_idx,
928 &storage_index);
929 }
930
931 HClinitCheck* clinit_check = nullptr;
932
933 if (!outer_class->IsInterface()
934 && outer_class->IsSubClass(resolved_method->GetDeclaringClass())) {
935 // If the outer class is the declaring class or a subclass
936 // of the declaring class, no class initialization is needed
937 // before the static method call.
938 // Note that in case of inlining, we do not need to add clinit checks
939 // to calls that satisfy this subclass check with any inlined methods. This
940 // will be detected by the optimization passes.
941 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
942 } else if (storage_index != DexFile::kDexNoIndex) {
943 // If the method's class type index is available, check
944 // whether we should add an explicit class initialization
945 // check for its declaring class before the static method call.
946
947 // TODO: find out why this check is needed.
948 bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
949 *outer_compilation_unit_->GetDexFile(), storage_index);
950 bool is_initialized =
951 resolved_method->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
952
953 if (is_initialized) {
954 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
955 } else {
956 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
957 HLoadClass* load_class = new (arena_) HLoadClass(
958 graph_->GetCurrentMethod(),
959 storage_index,
960 *dex_compilation_unit_->GetDexFile(),
961 is_outer_class,
962 dex_pc);
963 current_block_->AddInstruction(load_class);
964 clinit_check = new (arena_) HClinitCheck(load_class, dex_pc);
965 current_block_->AddInstruction(clinit_check);
966 }
967 }
968 return clinit_check;
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100969}
970
Vladimir Marko58155012015-08-19 12:49:41 +0000971HInvokeStaticOrDirect::DispatchInfo HGraphBuilder::ComputeDispatchInfo(
972 bool is_string_init,
973 int32_t string_init_offset,
974 MethodReference target_method,
975 uintptr_t direct_method,
976 uintptr_t direct_code) {
977 HInvokeStaticOrDirect::MethodLoadKind method_load_kind;
978 HInvokeStaticOrDirect::CodePtrLocation code_ptr_location;
979 uint64_t method_load_data = 0u;
980 uint64_t direct_code_ptr = 0u;
981
982 if (is_string_init) {
983 // TODO: Use direct_method and direct_code for the appropriate StringFactory method.
984 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kStringInit;
985 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
986 method_load_data = string_init_offset;
987 } else if (target_method.dex_file == outer_compilation_unit_->GetDexFile() &&
988 target_method.dex_method_index == outer_compilation_unit_->GetDexMethodIndex()) {
989 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRecursive;
990 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallSelf;
991 } else {
992 if (direct_method != 0u) { // Should we use a direct pointer to the method?
993 if (direct_method != static_cast<uintptr_t>(-1)) { // Is the method pointer known now?
994 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress;
995 method_load_data = direct_method;
996 } else { // The direct pointer will be known at link time.
997 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddressWithFixup;
998 }
999 } else { // Use dex cache.
1000 DCHECK(target_method.dex_file == dex_compilation_unit_->GetDexFile());
1001 DexCacheArraysLayout layout =
1002 compiler_driver_->GetDexCacheArraysLayout(target_method.dex_file);
1003 if (layout.Valid()) { // Can we use PC-relative access to the dex cache arrays?
1004 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative;
1005 method_load_data = layout.MethodOffset(target_method.dex_method_index);
1006 } else { // We must go through the ArtMethod's pointer to resolved methods.
1007 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod;
1008 }
1009 }
1010 if (direct_code != 0u) { // Should we use a direct pointer to the code?
1011 if (direct_code != static_cast<uintptr_t>(-1)) { // Is the code pointer known now?
1012 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallDirect;
1013 direct_code_ptr = direct_code;
1014 } else if (compiler_driver_->IsImage() ||
1015 target_method.dex_file == dex_compilation_unit_->GetDexFile()) {
1016 // Use PC-relative calls for invokes within a multi-dex oat file.
1017 // TODO: Recognize when the target dex file is within the current oat file for
1018 // app compilation. At the moment we recognize only the boot image as multi-dex.
1019 // NOTE: This will require changing the ARM backend which currently falls
1020 // through from kCallPCRelative to kDirectCodeFixup for different dex files.
1021 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallPCRelative;
1022 } else { // The direct pointer will be known at link time.
1023 // NOTE: This is used for app->boot calls when compiling an app against
1024 // a relocatable but not yet relocated image.
1025 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallDirectWithFixup;
1026 }
1027 } else { // We must use the code pointer from the ArtMethod.
1028 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
1029 }
1030 }
1031
1032 if (graph_->IsDebuggable()) {
1033 // For debuggable apps always use the code pointer from ArtMethod
1034 // so that we don't circumvent instrumentation stubs if installed.
1035 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
1036 }
1037
1038 return HInvokeStaticOrDirect::DispatchInfo {
1039 method_load_kind, code_ptr_location, method_load_data, direct_code_ptr };
1040}
1041
Calin Juravle0eedd7e2015-08-20 14:48:00 +01001042bool HGraphBuilder::SetupArgumentsAndAddInvoke(HInvoke* invoke,
1043 uint32_t number_of_vreg_arguments,
1044 uint32_t* args,
1045 uint32_t register_index,
1046 bool is_range,
1047 const char* descriptor,
1048 HClinitCheck* clinit_check) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001049 size_t start_index = 0;
Calin Juravle68ad6492015-08-18 17:08:12 +01001050 size_t argument_index = 0;
1051 uint32_t descriptor_index = 1; // Skip the return type.
1052
1053 bool is_instance_call = invoke->GetOriginalInvokeType() != InvokeType::kStatic;
1054 bool is_string_init = invoke->IsInvokeStaticOrDirect()
1055 && invoke->AsInvokeStaticOrDirect()->IsStringInit();
1056
1057 if (is_string_init) {
1058 start_index = 1;
1059 argument_index = 0;
1060 } else if (is_instance_call) {
1061 Temporaries temps(graph_);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001062 HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot);
Calin Juravle68ad6492015-08-18 17:08:12 +01001063 HNullCheck* null_check = new (arena_) HNullCheck(arg, invoke->GetDexPc());
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +01001064 current_block_->AddInstruction(null_check);
1065 temps.Add(null_check);
1066 invoke->SetArgumentAt(0, null_check);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001067 start_index = 1;
Calin Juravle68ad6492015-08-18 17:08:12 +01001068 argument_index = 1;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001069 }
1070
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001071 for (size_t i = start_index;
1072 // Make sure we don't go over the expected arguments or over the number of
1073 // dex registers given. If the instruction was seen as dead by the verifier,
1074 // it hasn't been properly checked.
Calin Juravle68ad6492015-08-18 17:08:12 +01001075 (i < number_of_vreg_arguments) && (argument_index < invoke->GetNumberOfArguments());
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001076 i++, argument_index++) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001077 Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001078 bool is_wide = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble);
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001079 if (!is_range
1080 && is_wide
1081 && ((i + 1 == number_of_vreg_arguments) || (args[i] + 1 != args[i + 1]))) {
1082 // Longs and doubles should be in pairs, that is, sequential registers. The verifier should
1083 // reject any class where this is violated. However, the verifier only does these checks
1084 // on non trivially dead instructions, so we just bailout the compilation.
1085 VLOG(compiler) << "Did not compile "
1086 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
1087 << " because of non-sequential dex register pair in wide argument";
1088 MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode);
1089 return false;
1090 }
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001091 HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
1092 invoke->SetArgumentAt(argument_index, arg);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001093 if (is_wide) {
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001094 i++;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001095 }
1096 }
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001097
Calin Juravle68ad6492015-08-18 17:08:12 +01001098 if (argument_index != invoke->GetNumberOfArguments()) {
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001099 VLOG(compiler) << "Did not compile "
1100 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
1101 << " because of wrong number of arguments in invoke instruction";
1102 MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode);
1103 return false;
1104 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001105
Nicolas Geoffray38207af2015-06-01 15:46:22 +01001106 if (invoke->IsInvokeStaticOrDirect()) {
1107 invoke->SetArgumentAt(argument_index, graph_->GetCurrentMethod());
1108 argument_index++;
1109 }
1110
Calin Juravle68ad6492015-08-18 17:08:12 +01001111 if (clinit_check != nullptr) {
Roland Levillain4c0eb422015-04-24 16:43:49 +01001112 // Add the class initialization check as last input of `invoke`.
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01001113 DCHECK(!is_string_init);
Calin Juravle68ad6492015-08-18 17:08:12 +01001114 DCHECK(invoke->IsInvokeStaticOrDirect());
1115 DCHECK(invoke->AsInvokeStaticOrDirect()->GetClinitCheckRequirement()
1116 == HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit);
Roland Levillain3e3d7332015-04-28 11:00:54 +01001117 invoke->SetArgumentAt(argument_index, clinit_check);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01001118 argument_index++;
Roland Levillain4c0eb422015-04-24 16:43:49 +01001119 }
1120
Jeff Hao848f70a2014-01-15 13:49:50 -08001121 // Add move-result for StringFactory method.
1122 if (is_string_init) {
1123 uint32_t orig_this_reg = is_range ? register_index : args[0];
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01001124 HInstruction* fake_string = LoadLocal(orig_this_reg, Primitive::kPrimNot);
1125 invoke->SetArgumentAt(argument_index, fake_string);
Calin Juravle0eedd7e2015-08-20 14:48:00 +01001126 current_block_->AddInstruction(invoke);
Calin Juravle68ad6492015-08-18 17:08:12 +01001127 PotentiallySimplifyFakeString(orig_this_reg, invoke->GetDexPc(), invoke);
Calin Juravle0eedd7e2015-08-20 14:48:00 +01001128 } else {
1129 current_block_->AddInstruction(invoke);
Jeff Hao848f70a2014-01-15 13:49:50 -08001130 }
Calin Juravle0eedd7e2015-08-20 14:48:00 +01001131
1132 latest_result_ = invoke;
1133
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001134 return true;
1135}
1136
Calin Juravle68ad6492015-08-18 17:08:12 +01001137void HGraphBuilder::PotentiallySimplifyFakeString(uint16_t original_dex_register,
1138 uint32_t dex_pc,
1139 HInvoke* actual_string) {
1140 if (!graph_->IsDebuggable()) {
1141 // Notify that we cannot compile with baseline. The dex registers aliasing
1142 // with `original_dex_register` will be handled when we optimize
1143 // (see HInstructionSimplifer::VisitFakeString).
1144 can_use_baseline_for_string_init_ = false;
1145 return;
1146 }
1147 const VerifiedMethod* verified_method =
1148 compiler_driver_->GetVerifiedMethod(dex_file_, dex_compilation_unit_->GetDexMethodIndex());
1149 if (verified_method != nullptr) {
1150 UpdateLocal(original_dex_register, actual_string);
1151 const SafeMap<uint32_t, std::set<uint32_t>>& string_init_map =
1152 verified_method->GetStringInitPcRegMap();
1153 auto map_it = string_init_map.find(dex_pc);
1154 if (map_it != string_init_map.end()) {
1155 std::set<uint32_t> reg_set = map_it->second;
1156 for (auto set_it = reg_set.begin(); set_it != reg_set.end(); ++set_it) {
1157 HInstruction* load_local = LoadLocal(original_dex_register, Primitive::kPrimNot);
1158 UpdateLocal(*set_it, load_local);
1159 }
1160 }
1161 } else {
1162 can_use_baseline_for_string_init_ = false;
1163 }
1164}
1165
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001166bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +00001167 uint32_t dex_pc,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001168 bool is_put) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001169 uint32_t source_or_dest_reg = instruction.VRegA_22c();
1170 uint32_t obj_reg = instruction.VRegB_22c();
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001171 uint16_t field_index;
1172 if (instruction.IsQuickened()) {
1173 if (!CanDecodeQuickenedInfo()) {
1174 return false;
1175 }
1176 field_index = LookupQuickenedInfo(dex_pc);
1177 } else {
1178 field_index = instruction.VRegC_22c();
1179 }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001180
1181 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartierc7853442015-03-27 14:35:38 -07001182 ArtField* resolved_field =
1183 compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001184
Mathieu Chartierc7853442015-03-27 14:35:38 -07001185 if (resolved_field == nullptr) {
Calin Juravle48c2b032014-12-09 18:11:36 +00001186 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001187 return false;
1188 }
Calin Juravle52c48962014-12-16 17:02:57 +00001189
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001190 Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001191
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001192 HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot);
Calin Juravle225ff812014-11-13 16:46:39 +00001193 current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_pc));
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001194 if (is_put) {
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001195 Temporaries temps(graph_);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001196 HInstruction* null_check = current_block_->GetLastInstruction();
1197 // We need one temporary for the null check.
1198 temps.Add(null_check);
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001199 HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001200 current_block_->AddInstruction(new (arena_) HInstanceFieldSet(
1201 null_check,
1202 value,
Nicolas Geoffray39468442014-09-02 15:17:15 +01001203 field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00001204 resolved_field->GetOffset(),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001205 resolved_field->IsVolatile(),
1206 field_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07001207 *dex_file_,
1208 dex_compilation_unit_->GetDexCache()));
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001209 } else {
1210 current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
1211 current_block_->GetLastInstruction(),
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001212 field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00001213 resolved_field->GetOffset(),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001214 resolved_field->IsVolatile(),
1215 field_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07001216 *dex_file_,
1217 dex_compilation_unit_->GetDexCache()));
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001218
1219 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
1220 }
1221 return true;
1222}
1223
Nicolas Geoffray30451742015-06-19 13:32:41 +01001224static mirror::Class* GetClassFrom(CompilerDriver* driver,
1225 const DexCompilationUnit& compilation_unit) {
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001226 ScopedObjectAccess soa(Thread::Current());
1227 StackHandleScope<2> hs(soa.Self());
Nicolas Geoffray30451742015-06-19 13:32:41 +01001228 const DexFile& dex_file = *compilation_unit.GetDexFile();
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001229 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
Nicolas Geoffray30451742015-06-19 13:32:41 +01001230 soa.Decode<mirror::ClassLoader*>(compilation_unit.GetClassLoader())));
1231 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -07001232 compilation_unit.GetClassLinker()->FindDexCache(soa.Self(), dex_file)));
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001233
Nicolas Geoffray30451742015-06-19 13:32:41 +01001234 return driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, &compilation_unit);
1235}
1236
1237mirror::Class* HGraphBuilder::GetOutermostCompilingClass() const {
1238 return GetClassFrom(compiler_driver_, *outer_compilation_unit_);
1239}
1240
1241mirror::Class* HGraphBuilder::GetCompilingClass() const {
1242 return GetClassFrom(compiler_driver_, *dex_compilation_unit_);
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001243}
1244
1245bool HGraphBuilder::IsOutermostCompilingClass(uint16_t type_index) const {
1246 ScopedObjectAccess soa(Thread::Current());
1247 StackHandleScope<4> hs(soa.Self());
1248 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -07001249 dex_compilation_unit_->GetClassLinker()->FindDexCache(
1250 soa.Self(), *dex_compilation_unit_->GetDexFile())));
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001251 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
1252 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
1253 Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass(
1254 soa, dex_cache, class_loader, type_index, dex_compilation_unit_)));
Nicolas Geoffrayafd06412015-06-20 22:44:47 +01001255 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001256
Nicolas Geoffrayafd06412015-06-20 22:44:47 +01001257 return outer_class.Get() == cls.Get();
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001258}
1259
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001260bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +00001261 uint32_t dex_pc,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001262 bool is_put) {
1263 uint32_t source_or_dest_reg = instruction.VRegA_21c();
1264 uint16_t field_index = instruction.VRegB_21c();
1265
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001266 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartierc7853442015-03-27 14:35:38 -07001267 StackHandleScope<4> hs(soa.Self());
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001268 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -07001269 dex_compilation_unit_->GetClassLinker()->FindDexCache(
1270 soa.Self(), *dex_compilation_unit_->GetDexFile())));
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001271 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
1272 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
Mathieu Chartierc7853442015-03-27 14:35:38 -07001273 ArtField* resolved_field = compiler_driver_->ResolveField(
1274 soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001275
Mathieu Chartierc7853442015-03-27 14:35:38 -07001276 if (resolved_field == nullptr) {
Calin Juravle48c2b032014-12-09 18:11:36 +00001277 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001278 return false;
1279 }
1280
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001281 const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
1282 Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -07001283 outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file)));
Nicolas Geoffray30451742015-06-19 13:32:41 +01001284 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001285
1286 // The index at which the field's class is stored in the DexCache's type array.
1287 uint32_t storage_index;
Nicolas Geoffray30451742015-06-19 13:32:41 +01001288 bool is_outer_class = (outer_class.Get() == resolved_field->GetDeclaringClass());
1289 if (is_outer_class) {
1290 storage_index = outer_class->GetDexTypeIndex();
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001291 } else if (outer_dex_cache.Get() != dex_cache.Get()) {
Roland Levillain4c0eb422015-04-24 16:43:49 +01001292 // The compiler driver cannot currently understand multiple dex caches involved. Just bailout.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001293 return false;
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001294 } else {
1295 std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField(
1296 outer_dex_cache.Get(),
Nicolas Geoffray30451742015-06-19 13:32:41 +01001297 GetCompilingClass(),
Mathieu Chartierc7853442015-03-27 14:35:38 -07001298 resolved_field,
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001299 field_index,
1300 &storage_index);
1301 bool can_easily_access = is_put ? pair.second : pair.first;
1302 if (!can_easily_access) {
1303 return false;
1304 }
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001305 }
1306
1307 // TODO: find out why this check is needed.
1308 bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
Nicolas Geoffray6a816cf2015-03-24 16:17:56 +00001309 *outer_compilation_unit_->GetDexFile(), storage_index);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001310 bool is_initialized = resolved_field->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001311
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001312 HLoadClass* constant = new (arena_) HLoadClass(graph_->GetCurrentMethod(),
1313 storage_index,
1314 *dex_compilation_unit_->GetDexFile(),
Nicolas Geoffray30451742015-06-19 13:32:41 +01001315 is_outer_class,
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001316 dex_pc);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001317 current_block_->AddInstruction(constant);
1318
1319 HInstruction* cls = constant;
Nicolas Geoffray30451742015-06-19 13:32:41 +01001320 if (!is_initialized && !is_outer_class) {
Calin Juravle225ff812014-11-13 16:46:39 +00001321 cls = new (arena_) HClinitCheck(constant, dex_pc);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001322 current_block_->AddInstruction(cls);
1323 }
1324
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001325 Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001326 if (is_put) {
1327 // We need to keep the class alive before loading the value.
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001328 Temporaries temps(graph_);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001329 temps.Add(cls);
1330 HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
1331 DCHECK_EQ(value->GetType(), field_type);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001332 current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls,
1333 value,
1334 field_type,
1335 resolved_field->GetOffset(),
1336 resolved_field->IsVolatile(),
1337 field_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07001338 *dex_file_,
1339 dex_cache_));
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001340 } else {
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001341 current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls,
1342 field_type,
1343 resolved_field->GetOffset(),
1344 resolved_field->IsVolatile(),
1345 field_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07001346 *dex_file_,
1347 dex_cache_));
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001348 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
1349 }
1350 return true;
1351}
1352
Calin Juravlebacfec32014-11-14 15:54:36 +00001353void HGraphBuilder::BuildCheckedDivRem(uint16_t out_vreg,
1354 uint16_t first_vreg,
1355 int64_t second_vreg_or_constant,
1356 uint32_t dex_pc,
1357 Primitive::Type type,
1358 bool second_is_constant,
1359 bool isDiv) {
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001360 DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
Calin Juravled0d48522014-11-04 16:40:20 +00001361
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001362 HInstruction* first = LoadLocal(first_vreg, type);
1363 HInstruction* second = nullptr;
1364 if (second_is_constant) {
1365 if (type == Primitive::kPrimInt) {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001366 second = graph_->GetIntConstant(second_vreg_or_constant);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001367 } else {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001368 second = graph_->GetLongConstant(second_vreg_or_constant);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001369 }
1370 } else {
1371 second = LoadLocal(second_vreg_or_constant, type);
1372 }
1373
1374 if (!second_is_constant
1375 || (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0)
1376 || (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) {
1377 second = new (arena_) HDivZeroCheck(second, dex_pc);
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001378 Temporaries temps(graph_);
Calin Juravled0d48522014-11-04 16:40:20 +00001379 current_block_->AddInstruction(second);
1380 temps.Add(current_block_->GetLastInstruction());
1381 }
1382
Calin Juravlebacfec32014-11-14 15:54:36 +00001383 if (isDiv) {
1384 current_block_->AddInstruction(new (arena_) HDiv(type, first, second, dex_pc));
1385 } else {
1386 current_block_->AddInstruction(new (arena_) HRem(type, first, second, dex_pc));
1387 }
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001388 UpdateLocal(out_vreg, current_block_->GetLastInstruction());
Calin Juravled0d48522014-11-04 16:40:20 +00001389}
1390
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001391void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +00001392 uint32_t dex_pc,
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001393 bool is_put,
1394 Primitive::Type anticipated_type) {
1395 uint8_t source_or_dest_reg = instruction.VRegA_23x();
1396 uint8_t array_reg = instruction.VRegB_23x();
1397 uint8_t index_reg = instruction.VRegC_23x();
1398
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001399 // We need one temporary for the null check, one for the index, and one for the length.
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001400 Temporaries temps(graph_);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001401
1402 HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot);
Calin Juravle225ff812014-11-13 16:46:39 +00001403 object = new (arena_) HNullCheck(object, dex_pc);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001404 current_block_->AddInstruction(object);
1405 temps.Add(object);
1406
1407 HInstruction* length = new (arena_) HArrayLength(object);
1408 current_block_->AddInstruction(length);
1409 temps.Add(length);
1410 HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt);
Calin Juravle225ff812014-11-13 16:46:39 +00001411 index = new (arena_) HBoundsCheck(index, length, dex_pc);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001412 current_block_->AddInstruction(index);
1413 temps.Add(index);
1414 if (is_put) {
1415 HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type);
1416 // TODO: Insert a type check node if the type is Object.
Nicolas Geoffray39468442014-09-02 15:17:15 +01001417 current_block_->AddInstruction(new (arena_) HArraySet(
Calin Juravle225ff812014-11-13 16:46:39 +00001418 object, index, value, anticipated_type, dex_pc));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001419 } else {
1420 current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type));
1421 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
1422 }
Mark Mendell1152c922015-04-24 17:06:35 -04001423 graph_->SetHasBoundsChecks(true);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001424}
1425
Calin Juravle225ff812014-11-13 16:46:39 +00001426void HGraphBuilder::BuildFilledNewArray(uint32_t dex_pc,
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001427 uint32_t type_index,
1428 uint32_t number_of_vreg_arguments,
1429 bool is_range,
1430 uint32_t* args,
1431 uint32_t register_index) {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001432 HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments);
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001433 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
1434 ? kQuickAllocArrayWithAccessCheck
1435 : kQuickAllocArray;
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01001436 HInstruction* object = new (arena_) HNewArray(length,
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01001437 graph_->GetCurrentMethod(),
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01001438 dex_pc,
1439 type_index,
1440 *dex_compilation_unit_->GetDexFile(),
1441 entrypoint);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001442 current_block_->AddInstruction(object);
1443
1444 const char* descriptor = dex_file_->StringByTypeIdx(type_index);
1445 DCHECK_EQ(descriptor[0], '[') << descriptor;
1446 char primitive = descriptor[1];
1447 DCHECK(primitive == 'I'
1448 || primitive == 'L'
1449 || primitive == '[') << descriptor;
1450 bool is_reference_array = (primitive == 'L') || (primitive == '[');
1451 Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt;
1452
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001453 Temporaries temps(graph_);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001454 temps.Add(object);
1455 for (size_t i = 0; i < number_of_vreg_arguments; ++i) {
1456 HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type);
David Brazdil8d5b8b22015-03-24 10:51:52 +00001457 HInstruction* index = graph_->GetIntConstant(i);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001458 current_block_->AddInstruction(
Calin Juravle225ff812014-11-13 16:46:39 +00001459 new (arena_) HArraySet(object, index, value, type, dex_pc));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001460 }
1461 latest_result_ = object;
1462}
1463
1464template <typename T>
1465void HGraphBuilder::BuildFillArrayData(HInstruction* object,
1466 const T* data,
1467 uint32_t element_count,
1468 Primitive::Type anticipated_type,
Calin Juravle225ff812014-11-13 16:46:39 +00001469 uint32_t dex_pc) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001470 for (uint32_t i = 0; i < element_count; ++i) {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001471 HInstruction* index = graph_->GetIntConstant(i);
1472 HInstruction* value = graph_->GetIntConstant(data[i]);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001473 current_block_->AddInstruction(new (arena_) HArraySet(
Calin Juravle225ff812014-11-13 16:46:39 +00001474 object, index, value, anticipated_type, dex_pc));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001475 }
1476}
1477
Calin Juravle225ff812014-11-13 16:46:39 +00001478void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) {
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001479 Temporaries temps(graph_);
Calin Juravled0d48522014-11-04 16:40:20 +00001480 HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot);
Calin Juravle225ff812014-11-13 16:46:39 +00001481 HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001482 current_block_->AddInstruction(null_check);
1483 temps.Add(null_check);
1484
1485 HInstruction* length = new (arena_) HArrayLength(null_check);
1486 current_block_->AddInstruction(length);
1487
Calin Juravle225ff812014-11-13 16:46:39 +00001488 int32_t payload_offset = instruction.VRegB_31t() + dex_pc;
Calin Juravled0d48522014-11-04 16:40:20 +00001489 const Instruction::ArrayDataPayload* payload =
1490 reinterpret_cast<const Instruction::ArrayDataPayload*>(code_start_ + payload_offset);
1491 const uint8_t* data = payload->data;
1492 uint32_t element_count = payload->element_count;
1493
1494 // Implementation of this DEX instruction seems to be that the bounds check is
1495 // done before doing any stores.
David Brazdil8d5b8b22015-03-24 10:51:52 +00001496 HInstruction* last_index = graph_->GetIntConstant(payload->element_count - 1);
Calin Juravle225ff812014-11-13 16:46:39 +00001497 current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_pc));
Calin Juravled0d48522014-11-04 16:40:20 +00001498
1499 switch (payload->element_width) {
1500 case 1:
1501 BuildFillArrayData(null_check,
1502 reinterpret_cast<const int8_t*>(data),
1503 element_count,
1504 Primitive::kPrimByte,
Calin Juravle225ff812014-11-13 16:46:39 +00001505 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001506 break;
1507 case 2:
1508 BuildFillArrayData(null_check,
1509 reinterpret_cast<const int16_t*>(data),
1510 element_count,
1511 Primitive::kPrimShort,
Calin Juravle225ff812014-11-13 16:46:39 +00001512 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001513 break;
1514 case 4:
1515 BuildFillArrayData(null_check,
1516 reinterpret_cast<const int32_t*>(data),
1517 element_count,
1518 Primitive::kPrimInt,
Calin Juravle225ff812014-11-13 16:46:39 +00001519 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001520 break;
1521 case 8:
1522 BuildFillWideArrayData(null_check,
1523 reinterpret_cast<const int64_t*>(data),
1524 element_count,
Calin Juravle225ff812014-11-13 16:46:39 +00001525 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001526 break;
1527 default:
1528 LOG(FATAL) << "Unknown element width for " << payload->element_width;
1529 }
Mark Mendell1152c922015-04-24 17:06:35 -04001530 graph_->SetHasBoundsChecks(true);
Calin Juravled0d48522014-11-04 16:40:20 +00001531}
1532
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001533void HGraphBuilder::BuildFillWideArrayData(HInstruction* object,
Nicolas Geoffray8d6ae522014-10-23 18:32:13 +01001534 const int64_t* data,
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001535 uint32_t element_count,
Calin Juravle225ff812014-11-13 16:46:39 +00001536 uint32_t dex_pc) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001537 for (uint32_t i = 0; i < element_count; ++i) {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001538 HInstruction* index = graph_->GetIntConstant(i);
1539 HInstruction* value = graph_->GetLongConstant(data[i]);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001540 current_block_->AddInstruction(new (arena_) HArraySet(
Calin Juravle225ff812014-11-13 16:46:39 +00001541 object, index, value, Primitive::kPrimLong, dex_pc));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001542 }
1543}
1544
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001545bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction,
1546 uint8_t destination,
1547 uint8_t reference,
1548 uint16_t type_index,
Calin Juravle225ff812014-11-13 16:46:39 +00001549 uint32_t dex_pc) {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001550 bool type_known_final;
1551 bool type_known_abstract;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001552 // `CanAccessTypeWithoutChecks` will tell whether the method being
1553 // built is trying to access its own class, so that the generated
1554 // code can optimize for this case. However, the optimization does not
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001555 // work for inlining, so we use `IsOutermostCompilingClass` instead.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001556 bool dont_use_is_referrers_class;
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001557 bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
1558 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001559 &type_known_final, &type_known_abstract, &dont_use_is_referrers_class);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001560 if (!can_access) {
Calin Juravle48c2b032014-12-09 18:11:36 +00001561 MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001562 return false;
1563 }
1564 HInstruction* object = LoadLocal(reference, Primitive::kPrimNot);
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001565 HLoadClass* cls = new (arena_) HLoadClass(
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001566 graph_->GetCurrentMethod(),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01001567 type_index,
1568 *dex_compilation_unit_->GetDexFile(),
1569 IsOutermostCompilingClass(type_index),
1570 dex_pc);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001571 current_block_->AddInstruction(cls);
1572 // The class needs a temporary before being used by the type check.
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001573 Temporaries temps(graph_);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001574 temps.Add(cls);
1575 if (instruction.Opcode() == Instruction::INSTANCE_OF) {
1576 current_block_->AddInstruction(
Calin Juravle225ff812014-11-13 16:46:39 +00001577 new (arena_) HInstanceOf(object, cls, type_known_final, dex_pc));
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001578 UpdateLocal(destination, current_block_->GetLastInstruction());
1579 } else {
1580 DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST);
1581 current_block_->AddInstruction(
Calin Juravle225ff812014-11-13 16:46:39 +00001582 new (arena_) HCheckCast(object, cls, type_known_final, dex_pc));
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001583 }
1584 return true;
1585}
1586
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001587bool HGraphBuilder::NeedsAccessCheck(uint32_t type_index) const {
1588 return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks(
1589 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index);
1590}
1591
Calin Juravle48c2b032014-12-09 18:11:36 +00001592void HGraphBuilder::BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc) {
David Brazdil2ef645b2015-06-17 18:20:52 +01001593 // Verifier guarantees that the payload for PackedSwitch contains:
1594 // (a) number of entries (may be zero)
1595 // (b) first and lowest switch case value (entry 0, always present)
1596 // (c) list of target pcs (entries 1 <= i <= N)
Andreas Gamped881df52014-11-24 23:28:39 -08001597 SwitchTable table(instruction, dex_pc, false);
1598
1599 // Value to test against.
1600 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
1601
David Brazdil2ef645b2015-06-17 18:20:52 +01001602 // Retrieve number of entries.
Andreas Gampee4d4d322014-12-04 09:09:57 -08001603 uint16_t num_entries = table.GetNumEntries();
David Brazdil2ef645b2015-06-17 18:20:52 +01001604 if (num_entries == 0) {
1605 return;
1606 }
Andreas Gampee4d4d322014-12-04 09:09:57 -08001607
Andreas Gamped881df52014-11-24 23:28:39 -08001608 // Chained cmp-and-branch, starting from starting_key.
1609 int32_t starting_key = table.GetEntryAt(0);
1610
Andreas Gamped881df52014-11-24 23:28:39 -08001611 for (size_t i = 1; i <= num_entries; i++) {
Andreas Gampee4d4d322014-12-04 09:09:57 -08001612 BuildSwitchCaseHelper(instruction, i, i == num_entries, table, value, starting_key + i - 1,
1613 table.GetEntryAt(i), dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -08001614 }
Andreas Gamped881df52014-11-24 23:28:39 -08001615}
1616
Calin Juravle48c2b032014-12-09 18:11:36 +00001617void HGraphBuilder::BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc) {
David Brazdil2ef645b2015-06-17 18:20:52 +01001618 // Verifier guarantees that the payload for SparseSwitch contains:
1619 // (a) number of entries (may be zero)
1620 // (b) sorted key values (entries 0 <= i < N)
1621 // (c) target pcs corresponding to the switch values (entries N <= i < 2*N)
Andreas Gampee4d4d322014-12-04 09:09:57 -08001622 SwitchTable table(instruction, dex_pc, true);
1623
1624 // Value to test against.
1625 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
1626
1627 uint16_t num_entries = table.GetNumEntries();
Andreas Gampee4d4d322014-12-04 09:09:57 -08001628
1629 for (size_t i = 0; i < num_entries; i++) {
1630 BuildSwitchCaseHelper(instruction, i, i == static_cast<size_t>(num_entries) - 1, table, value,
1631 table.GetEntryAt(i), table.GetEntryAt(i + num_entries), dex_pc);
1632 }
Andreas Gampee4d4d322014-12-04 09:09:57 -08001633}
1634
1635void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t index,
1636 bool is_last_case, const SwitchTable& table,
1637 HInstruction* value, int32_t case_value_int,
1638 int32_t target_offset, uint32_t dex_pc) {
David Brazdil852eaff2015-02-02 15:23:05 +00001639 HBasicBlock* case_target = FindBlockStartingAt(dex_pc + target_offset);
1640 DCHECK(case_target != nullptr);
1641 PotentiallyAddSuspendCheck(case_target, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08001642
1643 // The current case's value.
David Brazdil8d5b8b22015-03-24 10:51:52 +00001644 HInstruction* this_case_value = graph_->GetIntConstant(case_value_int);
Andreas Gampee4d4d322014-12-04 09:09:57 -08001645
1646 // Compare value and this_case_value.
1647 HEqual* comparison = new (arena_) HEqual(value, this_case_value);
1648 current_block_->AddInstruction(comparison);
1649 HInstruction* ifinst = new (arena_) HIf(comparison);
1650 current_block_->AddInstruction(ifinst);
1651
1652 // Case hit: use the target offset to determine where to go.
Andreas Gampee4d4d322014-12-04 09:09:57 -08001653 current_block_->AddSuccessor(case_target);
1654
1655 // Case miss: go to the next case (or default fall-through).
1656 // When there is a next case, we use the block stored with the table offset representing this
1657 // case (that is where we registered them in ComputeBranchTargets).
1658 // When there is no next case, we use the following instruction.
1659 // TODO: Find a good way to peel the last iteration to avoid conditional, but still have re-use.
1660 if (!is_last_case) {
1661 HBasicBlock* next_case_target = FindBlockStartingAt(table.GetDexPcForIndex(index));
1662 DCHECK(next_case_target != nullptr);
1663 current_block_->AddSuccessor(next_case_target);
1664
1665 // Need to manually add the block, as there is no dex-pc transition for the cases.
1666 graph_->AddBlock(next_case_target);
1667
1668 current_block_ = next_case_target;
1669 } else {
1670 HBasicBlock* default_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
1671 DCHECK(default_target != nullptr);
1672 current_block_->AddSuccessor(default_target);
1673 current_block_ = nullptr;
1674 }
1675}
1676
David Brazdil852eaff2015-02-02 15:23:05 +00001677void HGraphBuilder::PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc) {
1678 int32_t target_offset = target->GetDexPc() - dex_pc;
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001679 if (target_offset <= 0) {
David Brazdil852eaff2015-02-02 15:23:05 +00001680 // DX generates back edges to the first encountered return. We can save
1681 // time of later passes by not adding redundant suspend checks.
David Brazdil2fd6aa52015-02-02 18:58:27 +00001682 HInstruction* last_in_target = target->GetLastInstruction();
1683 if (last_in_target != nullptr &&
1684 (last_in_target->IsReturn() || last_in_target->IsReturnVoid())) {
1685 return;
David Brazdil852eaff2015-02-02 15:23:05 +00001686 }
1687
1688 // Add a suspend check to backward branches which may potentially loop. We
1689 // can remove them after we recognize loops in the graph.
Calin Juravle225ff812014-11-13 16:46:39 +00001690 current_block_->AddInstruction(new (arena_) HSuspendCheck(dex_pc));
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001691 }
1692}
1693
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001694bool HGraphBuilder::CanDecodeQuickenedInfo() const {
1695 return interpreter_metadata_ != nullptr;
1696}
1697
1698uint16_t HGraphBuilder::LookupQuickenedInfo(uint32_t dex_pc) {
1699 DCHECK(interpreter_metadata_ != nullptr);
1700 uint32_t dex_pc_in_map = DecodeUnsignedLeb128(&interpreter_metadata_);
1701 DCHECK_EQ(dex_pc, dex_pc_in_map);
1702 return DecodeUnsignedLeb128(&interpreter_metadata_);
1703}
1704
Calin Juravle225ff812014-11-13 16:46:39 +00001705bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001706 if (current_block_ == nullptr) {
1707 return true; // Dead code
1708 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001709
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001710 switch (instruction.Opcode()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001711 case Instruction::CONST_4: {
1712 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001713 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001714 UpdateLocal(register_index, constant);
1715 break;
1716 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001717
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001718 case Instruction::CONST_16: {
1719 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001720 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001721 UpdateLocal(register_index, constant);
1722 break;
1723 }
1724
Dave Allison20dfc792014-06-16 20:44:29 -07001725 case Instruction::CONST: {
1726 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001727 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i());
Dave Allison20dfc792014-06-16 20:44:29 -07001728 UpdateLocal(register_index, constant);
1729 break;
1730 }
1731
1732 case Instruction::CONST_HIGH16: {
1733 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001734 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16);
Dave Allison20dfc792014-06-16 20:44:29 -07001735 UpdateLocal(register_index, constant);
1736 break;
1737 }
1738
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001739 case Instruction::CONST_WIDE_16: {
1740 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -07001741 // Get 16 bits of constant value, sign extended to 64 bits.
1742 int64_t value = instruction.VRegB_21s();
1743 value <<= 48;
1744 value >>= 48;
David Brazdil8d5b8b22015-03-24 10:51:52 +00001745 HLongConstant* constant = graph_->GetLongConstant(value);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001746 UpdateLocal(register_index, constant);
1747 break;
1748 }
1749
1750 case Instruction::CONST_WIDE_32: {
1751 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -07001752 // Get 32 bits of constant value, sign extended to 64 bits.
1753 int64_t value = instruction.VRegB_31i();
1754 value <<= 32;
1755 value >>= 32;
David Brazdil8d5b8b22015-03-24 10:51:52 +00001756 HLongConstant* constant = graph_->GetLongConstant(value);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001757 UpdateLocal(register_index, constant);
1758 break;
1759 }
1760
1761 case Instruction::CONST_WIDE: {
1762 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001763 HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001764 UpdateLocal(register_index, constant);
1765 break;
1766 }
1767
Dave Allison20dfc792014-06-16 20:44:29 -07001768 case Instruction::CONST_WIDE_HIGH16: {
1769 int32_t register_index = instruction.VRegA();
1770 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
David Brazdil8d5b8b22015-03-24 10:51:52 +00001771 HLongConstant* constant = graph_->GetLongConstant(value);
Dave Allison20dfc792014-06-16 20:44:29 -07001772 UpdateLocal(register_index, constant);
1773 break;
1774 }
1775
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00001776 // Note that the SSA building will refine the types.
Dave Allison20dfc792014-06-16 20:44:29 -07001777 case Instruction::MOVE:
1778 case Instruction::MOVE_FROM16:
1779 case Instruction::MOVE_16: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001780 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001781 UpdateLocal(instruction.VRegA(), value);
1782 break;
1783 }
1784
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00001785 // Note that the SSA building will refine the types.
Dave Allison20dfc792014-06-16 20:44:29 -07001786 case Instruction::MOVE_WIDE:
1787 case Instruction::MOVE_WIDE_FROM16:
1788 case Instruction::MOVE_WIDE_16: {
1789 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong);
1790 UpdateLocal(instruction.VRegA(), value);
1791 break;
1792 }
1793
1794 case Instruction::MOVE_OBJECT:
1795 case Instruction::MOVE_OBJECT_16:
1796 case Instruction::MOVE_OBJECT_FROM16: {
1797 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot);
1798 UpdateLocal(instruction.VRegA(), value);
1799 break;
1800 }
1801
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001802 case Instruction::RETURN_VOID_NO_BARRIER:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001803 case Instruction::RETURN_VOID: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001804 BuildReturn(instruction, Primitive::kPrimVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001805 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001806 }
1807
Dave Allison20dfc792014-06-16 20:44:29 -07001808#define IF_XX(comparison, cond) \
Calin Juravle225ff812014-11-13 16:46:39 +00001809 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_pc); break; \
1810 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_pc); break
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001811
Dave Allison20dfc792014-06-16 20:44:29 -07001812 IF_XX(HEqual, EQ);
1813 IF_XX(HNotEqual, NE);
1814 IF_XX(HLessThan, LT);
1815 IF_XX(HLessThanOrEqual, LE);
1816 IF_XX(HGreaterThan, GT);
1817 IF_XX(HGreaterThanOrEqual, GE);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001818
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001819 case Instruction::GOTO:
1820 case Instruction::GOTO_16:
1821 case Instruction::GOTO_32: {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001822 int32_t offset = instruction.GetTargetOffset();
Calin Juravle225ff812014-11-13 16:46:39 +00001823 HBasicBlock* target = FindBlockStartingAt(offset + dex_pc);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001824 DCHECK(target != nullptr);
David Brazdil852eaff2015-02-02 15:23:05 +00001825 PotentiallyAddSuspendCheck(target, dex_pc);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001826 current_block_->AddInstruction(new (arena_) HGoto());
1827 current_block_->AddSuccessor(target);
1828 current_block_ = nullptr;
1829 break;
1830 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001831
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001832 case Instruction::RETURN: {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001833 BuildReturn(instruction, return_type_);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001834 break;
1835 }
1836
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001837 case Instruction::RETURN_OBJECT: {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001838 BuildReturn(instruction, return_type_);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001839 break;
1840 }
1841
1842 case Instruction::RETURN_WIDE: {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001843 BuildReturn(instruction, return_type_);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001844 break;
1845 }
1846
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001847 case Instruction::INVOKE_DIRECT:
Nicolas Geoffray0d8db992014-11-11 14:40:10 +00001848 case Instruction::INVOKE_INTERFACE:
1849 case Instruction::INVOKE_STATIC:
1850 case Instruction::INVOKE_SUPER:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001851 case Instruction::INVOKE_VIRTUAL:
1852 case Instruction::INVOKE_VIRTUAL_QUICK: {
1853 uint16_t method_idx;
1854 if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_QUICK) {
1855 if (!CanDecodeQuickenedInfo()) {
1856 return false;
1857 }
1858 method_idx = LookupQuickenedInfo(dex_pc);
1859 } else {
1860 method_idx = instruction.VRegB_35c();
1861 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001862 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001863 uint32_t args[5];
Ian Rogers29a26482014-05-02 15:27:29 -07001864 instruction.GetVarArgs(args);
Calin Juravle225ff812014-11-13 16:46:39 +00001865 if (!BuildInvoke(instruction, dex_pc, method_idx,
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00001866 number_of_vreg_arguments, false, args, -1)) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001867 return false;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001868 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001869 break;
1870 }
1871
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001872 case Instruction::INVOKE_DIRECT_RANGE:
Nicolas Geoffray0d8db992014-11-11 14:40:10 +00001873 case Instruction::INVOKE_INTERFACE_RANGE:
1874 case Instruction::INVOKE_STATIC_RANGE:
1875 case Instruction::INVOKE_SUPER_RANGE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001876 case Instruction::INVOKE_VIRTUAL_RANGE:
1877 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
1878 uint16_t method_idx;
1879 if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK) {
1880 if (!CanDecodeQuickenedInfo()) {
1881 return false;
1882 }
1883 method_idx = LookupQuickenedInfo(dex_pc);
1884 } else {
1885 method_idx = instruction.VRegB_3rc();
1886 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001887 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
1888 uint32_t register_index = instruction.VRegC();
Calin Juravle225ff812014-11-13 16:46:39 +00001889 if (!BuildInvoke(instruction, dex_pc, method_idx,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001890 number_of_vreg_arguments, true, nullptr, register_index)) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001891 return false;
1892 }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001893 break;
1894 }
1895
Roland Levillain88cb1752014-10-20 16:36:47 +01001896 case Instruction::NEG_INT: {
1897 Unop_12x<HNeg>(instruction, Primitive::kPrimInt);
1898 break;
1899 }
1900
Roland Levillain2e07b4f2014-10-23 18:12:09 +01001901 case Instruction::NEG_LONG: {
1902 Unop_12x<HNeg>(instruction, Primitive::kPrimLong);
1903 break;
1904 }
1905
Roland Levillain3dbcb382014-10-28 17:30:07 +00001906 case Instruction::NEG_FLOAT: {
1907 Unop_12x<HNeg>(instruction, Primitive::kPrimFloat);
1908 break;
1909 }
1910
1911 case Instruction::NEG_DOUBLE: {
1912 Unop_12x<HNeg>(instruction, Primitive::kPrimDouble);
1913 break;
1914 }
1915
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001916 case Instruction::NOT_INT: {
1917 Unop_12x<HNot>(instruction, Primitive::kPrimInt);
1918 break;
1919 }
1920
Roland Levillain70566432014-10-24 16:20:17 +01001921 case Instruction::NOT_LONG: {
1922 Unop_12x<HNot>(instruction, Primitive::kPrimLong);
1923 break;
1924 }
1925
Roland Levillaindff1f282014-11-05 14:15:05 +00001926 case Instruction::INT_TO_LONG: {
Roland Levillain624279f2014-12-04 11:54:28 +00001927 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong, dex_pc);
Roland Levillaindff1f282014-11-05 14:15:05 +00001928 break;
1929 }
1930
Roland Levillaincff13742014-11-17 14:32:17 +00001931 case Instruction::INT_TO_FLOAT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001932 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimFloat, dex_pc);
Roland Levillaincff13742014-11-17 14:32:17 +00001933 break;
1934 }
1935
1936 case Instruction::INT_TO_DOUBLE: {
Roland Levillain624279f2014-12-04 11:54:28 +00001937 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimDouble, dex_pc);
Roland Levillaincff13742014-11-17 14:32:17 +00001938 break;
1939 }
1940
Roland Levillain946e1432014-11-11 17:35:19 +00001941 case Instruction::LONG_TO_INT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001942 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimInt, dex_pc);
Roland Levillain946e1432014-11-11 17:35:19 +00001943 break;
1944 }
1945
Roland Levillain6d0e4832014-11-27 18:31:21 +00001946 case Instruction::LONG_TO_FLOAT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001947 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimFloat, dex_pc);
Roland Levillain6d0e4832014-11-27 18:31:21 +00001948 break;
1949 }
1950
Roland Levillain647b9ed2014-11-27 12:06:00 +00001951 case Instruction::LONG_TO_DOUBLE: {
Roland Levillain624279f2014-12-04 11:54:28 +00001952 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimDouble, dex_pc);
Roland Levillain647b9ed2014-11-27 12:06:00 +00001953 break;
1954 }
1955
Roland Levillain3f8f9362014-12-02 17:45:01 +00001956 case Instruction::FLOAT_TO_INT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001957 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimInt, dex_pc);
1958 break;
1959 }
1960
1961 case Instruction::FLOAT_TO_LONG: {
1962 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimLong, dex_pc);
Roland Levillain3f8f9362014-12-02 17:45:01 +00001963 break;
1964 }
1965
Roland Levillain8964e2b2014-12-04 12:10:50 +00001966 case Instruction::FLOAT_TO_DOUBLE: {
1967 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimDouble, dex_pc);
1968 break;
1969 }
1970
Roland Levillain4c0b61f2014-12-05 12:06:01 +00001971 case Instruction::DOUBLE_TO_INT: {
1972 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimInt, dex_pc);
1973 break;
1974 }
1975
1976 case Instruction::DOUBLE_TO_LONG: {
1977 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimLong, dex_pc);
1978 break;
1979 }
1980
Roland Levillain8964e2b2014-12-04 12:10:50 +00001981 case Instruction::DOUBLE_TO_FLOAT: {
1982 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimFloat, dex_pc);
1983 break;
1984 }
1985
Roland Levillain51d3fc42014-11-13 14:11:42 +00001986 case Instruction::INT_TO_BYTE: {
Roland Levillain624279f2014-12-04 11:54:28 +00001987 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimByte, dex_pc);
Roland Levillain51d3fc42014-11-13 14:11:42 +00001988 break;
1989 }
1990
Roland Levillain01a8d712014-11-14 16:27:39 +00001991 case Instruction::INT_TO_SHORT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001992 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimShort, dex_pc);
Roland Levillain01a8d712014-11-14 16:27:39 +00001993 break;
1994 }
1995
Roland Levillain981e4542014-11-14 11:47:14 +00001996 case Instruction::INT_TO_CHAR: {
Roland Levillain624279f2014-12-04 11:54:28 +00001997 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimChar, dex_pc);
Roland Levillain981e4542014-11-14 11:47:14 +00001998 break;
1999 }
2000
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002001 case Instruction::ADD_INT: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002002 Binop_23x<HAdd>(instruction, Primitive::kPrimInt);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002003 break;
2004 }
2005
2006 case Instruction::ADD_LONG: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002007 Binop_23x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002008 break;
2009 }
2010
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01002011 case Instruction::ADD_DOUBLE: {
2012 Binop_23x<HAdd>(instruction, Primitive::kPrimDouble);
2013 break;
2014 }
2015
2016 case Instruction::ADD_FLOAT: {
2017 Binop_23x<HAdd>(instruction, Primitive::kPrimFloat);
2018 break;
2019 }
2020
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002021 case Instruction::SUB_INT: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002022 Binop_23x<HSub>(instruction, Primitive::kPrimInt);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002023 break;
2024 }
2025
2026 case Instruction::SUB_LONG: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002027 Binop_23x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002028 break;
2029 }
2030
Calin Juravle096cc022014-10-23 17:01:13 +01002031 case Instruction::SUB_FLOAT: {
2032 Binop_23x<HSub>(instruction, Primitive::kPrimFloat);
2033 break;
2034 }
2035
2036 case Instruction::SUB_DOUBLE: {
2037 Binop_23x<HSub>(instruction, Primitive::kPrimDouble);
2038 break;
2039 }
2040
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002041 case Instruction::ADD_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002042 Binop_12x<HAdd>(instruction, Primitive::kPrimInt);
2043 break;
2044 }
2045
Calin Juravle34bacdf2014-10-07 20:23:36 +01002046 case Instruction::MUL_INT: {
2047 Binop_23x<HMul>(instruction, Primitive::kPrimInt);
2048 break;
2049 }
2050
2051 case Instruction::MUL_LONG: {
2052 Binop_23x<HMul>(instruction, Primitive::kPrimLong);
2053 break;
2054 }
2055
Calin Juravleb5bfa962014-10-21 18:02:24 +01002056 case Instruction::MUL_FLOAT: {
2057 Binop_23x<HMul>(instruction, Primitive::kPrimFloat);
2058 break;
2059 }
2060
2061 case Instruction::MUL_DOUBLE: {
2062 Binop_23x<HMul>(instruction, Primitive::kPrimDouble);
2063 break;
2064 }
2065
Calin Juravled0d48522014-11-04 16:40:20 +00002066 case Instruction::DIV_INT: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002067 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2068 dex_pc, Primitive::kPrimInt, false, true);
Calin Juravled0d48522014-11-04 16:40:20 +00002069 break;
2070 }
2071
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002072 case Instruction::DIV_LONG: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002073 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2074 dex_pc, Primitive::kPrimLong, false, true);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002075 break;
2076 }
2077
Calin Juravle7c4954d2014-10-28 16:57:40 +00002078 case Instruction::DIV_FLOAT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002079 Binop_23x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002080 break;
2081 }
2082
2083 case Instruction::DIV_DOUBLE: {
Calin Juravle225ff812014-11-13 16:46:39 +00002084 Binop_23x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002085 break;
2086 }
2087
Calin Juravlebacfec32014-11-14 15:54:36 +00002088 case Instruction::REM_INT: {
2089 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2090 dex_pc, Primitive::kPrimInt, false, false);
2091 break;
2092 }
2093
2094 case Instruction::REM_LONG: {
2095 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2096 dex_pc, Primitive::kPrimLong, false, false);
2097 break;
2098 }
2099
Calin Juravled2ec87d2014-12-08 14:24:46 +00002100 case Instruction::REM_FLOAT: {
2101 Binop_23x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
2102 break;
2103 }
2104
2105 case Instruction::REM_DOUBLE: {
2106 Binop_23x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
2107 break;
2108 }
2109
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002110 case Instruction::AND_INT: {
2111 Binop_23x<HAnd>(instruction, Primitive::kPrimInt);
2112 break;
2113 }
2114
2115 case Instruction::AND_LONG: {
2116 Binop_23x<HAnd>(instruction, Primitive::kPrimLong);
2117 break;
2118 }
2119
Calin Juravle9aec02f2014-11-18 23:06:35 +00002120 case Instruction::SHL_INT: {
2121 Binop_23x_shift<HShl>(instruction, Primitive::kPrimInt);
2122 break;
2123 }
2124
2125 case Instruction::SHL_LONG: {
2126 Binop_23x_shift<HShl>(instruction, Primitive::kPrimLong);
2127 break;
2128 }
2129
2130 case Instruction::SHR_INT: {
2131 Binop_23x_shift<HShr>(instruction, Primitive::kPrimInt);
2132 break;
2133 }
2134
2135 case Instruction::SHR_LONG: {
2136 Binop_23x_shift<HShr>(instruction, Primitive::kPrimLong);
2137 break;
2138 }
2139
2140 case Instruction::USHR_INT: {
2141 Binop_23x_shift<HUShr>(instruction, Primitive::kPrimInt);
2142 break;
2143 }
2144
2145 case Instruction::USHR_LONG: {
2146 Binop_23x_shift<HUShr>(instruction, Primitive::kPrimLong);
2147 break;
2148 }
2149
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002150 case Instruction::OR_INT: {
2151 Binop_23x<HOr>(instruction, Primitive::kPrimInt);
2152 break;
2153 }
2154
2155 case Instruction::OR_LONG: {
2156 Binop_23x<HOr>(instruction, Primitive::kPrimLong);
2157 break;
2158 }
2159
2160 case Instruction::XOR_INT: {
2161 Binop_23x<HXor>(instruction, Primitive::kPrimInt);
2162 break;
2163 }
2164
2165 case Instruction::XOR_LONG: {
2166 Binop_23x<HXor>(instruction, Primitive::kPrimLong);
2167 break;
2168 }
2169
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002170 case Instruction::ADD_LONG_2ADDR: {
2171 Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002172 break;
2173 }
2174
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01002175 case Instruction::ADD_DOUBLE_2ADDR: {
2176 Binop_12x<HAdd>(instruction, Primitive::kPrimDouble);
2177 break;
2178 }
2179
2180 case Instruction::ADD_FLOAT_2ADDR: {
2181 Binop_12x<HAdd>(instruction, Primitive::kPrimFloat);
2182 break;
2183 }
2184
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002185 case Instruction::SUB_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002186 Binop_12x<HSub>(instruction, Primitive::kPrimInt);
2187 break;
2188 }
2189
2190 case Instruction::SUB_LONG_2ADDR: {
2191 Binop_12x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002192 break;
2193 }
2194
Calin Juravle096cc022014-10-23 17:01:13 +01002195 case Instruction::SUB_FLOAT_2ADDR: {
2196 Binop_12x<HSub>(instruction, Primitive::kPrimFloat);
2197 break;
2198 }
2199
2200 case Instruction::SUB_DOUBLE_2ADDR: {
2201 Binop_12x<HSub>(instruction, Primitive::kPrimDouble);
2202 break;
2203 }
2204
Calin Juravle34bacdf2014-10-07 20:23:36 +01002205 case Instruction::MUL_INT_2ADDR: {
2206 Binop_12x<HMul>(instruction, Primitive::kPrimInt);
2207 break;
2208 }
2209
2210 case Instruction::MUL_LONG_2ADDR: {
2211 Binop_12x<HMul>(instruction, Primitive::kPrimLong);
2212 break;
2213 }
2214
Calin Juravleb5bfa962014-10-21 18:02:24 +01002215 case Instruction::MUL_FLOAT_2ADDR: {
2216 Binop_12x<HMul>(instruction, Primitive::kPrimFloat);
2217 break;
2218 }
2219
2220 case Instruction::MUL_DOUBLE_2ADDR: {
2221 Binop_12x<HMul>(instruction, Primitive::kPrimDouble);
2222 break;
2223 }
2224
Calin Juravle865fc882014-11-06 17:09:03 +00002225 case Instruction::DIV_INT_2ADDR: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002226 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2227 dex_pc, Primitive::kPrimInt, false, true);
Calin Juravle865fc882014-11-06 17:09:03 +00002228 break;
2229 }
2230
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002231 case Instruction::DIV_LONG_2ADDR: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002232 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2233 dex_pc, Primitive::kPrimLong, false, true);
2234 break;
2235 }
2236
2237 case Instruction::REM_INT_2ADDR: {
2238 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2239 dex_pc, Primitive::kPrimInt, false, false);
2240 break;
2241 }
2242
2243 case Instruction::REM_LONG_2ADDR: {
2244 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2245 dex_pc, Primitive::kPrimLong, false, false);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002246 break;
2247 }
2248
Calin Juravled2ec87d2014-12-08 14:24:46 +00002249 case Instruction::REM_FLOAT_2ADDR: {
2250 Binop_12x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
2251 break;
2252 }
2253
2254 case Instruction::REM_DOUBLE_2ADDR: {
2255 Binop_12x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
2256 break;
2257 }
2258
Calin Juravle9aec02f2014-11-18 23:06:35 +00002259 case Instruction::SHL_INT_2ADDR: {
2260 Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt);
2261 break;
2262 }
2263
2264 case Instruction::SHL_LONG_2ADDR: {
2265 Binop_12x_shift<HShl>(instruction, Primitive::kPrimLong);
2266 break;
2267 }
2268
2269 case Instruction::SHR_INT_2ADDR: {
2270 Binop_12x_shift<HShr>(instruction, Primitive::kPrimInt);
2271 break;
2272 }
2273
2274 case Instruction::SHR_LONG_2ADDR: {
2275 Binop_12x_shift<HShr>(instruction, Primitive::kPrimLong);
2276 break;
2277 }
2278
2279 case Instruction::USHR_INT_2ADDR: {
2280 Binop_12x_shift<HUShr>(instruction, Primitive::kPrimInt);
2281 break;
2282 }
2283
2284 case Instruction::USHR_LONG_2ADDR: {
2285 Binop_12x_shift<HUShr>(instruction, Primitive::kPrimLong);
2286 break;
2287 }
2288
Calin Juravle7c4954d2014-10-28 16:57:40 +00002289 case Instruction::DIV_FLOAT_2ADDR: {
Calin Juravle225ff812014-11-13 16:46:39 +00002290 Binop_12x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002291 break;
2292 }
2293
2294 case Instruction::DIV_DOUBLE_2ADDR: {
Calin Juravle225ff812014-11-13 16:46:39 +00002295 Binop_12x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002296 break;
2297 }
2298
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002299 case Instruction::AND_INT_2ADDR: {
2300 Binop_12x<HAnd>(instruction, Primitive::kPrimInt);
2301 break;
2302 }
2303
2304 case Instruction::AND_LONG_2ADDR: {
2305 Binop_12x<HAnd>(instruction, Primitive::kPrimLong);
2306 break;
2307 }
2308
2309 case Instruction::OR_INT_2ADDR: {
2310 Binop_12x<HOr>(instruction, Primitive::kPrimInt);
2311 break;
2312 }
2313
2314 case Instruction::OR_LONG_2ADDR: {
2315 Binop_12x<HOr>(instruction, Primitive::kPrimLong);
2316 break;
2317 }
2318
2319 case Instruction::XOR_INT_2ADDR: {
2320 Binop_12x<HXor>(instruction, Primitive::kPrimInt);
2321 break;
2322 }
2323
2324 case Instruction::XOR_LONG_2ADDR: {
2325 Binop_12x<HXor>(instruction, Primitive::kPrimLong);
2326 break;
2327 }
2328
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002329 case Instruction::ADD_INT_LIT16: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002330 Binop_22s<HAdd>(instruction, false);
2331 break;
2332 }
2333
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002334 case Instruction::AND_INT_LIT16: {
2335 Binop_22s<HAnd>(instruction, false);
2336 break;
2337 }
2338
2339 case Instruction::OR_INT_LIT16: {
2340 Binop_22s<HOr>(instruction, false);
2341 break;
2342 }
2343
2344 case Instruction::XOR_INT_LIT16: {
2345 Binop_22s<HXor>(instruction, false);
2346 break;
2347 }
2348
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002349 case Instruction::RSUB_INT: {
2350 Binop_22s<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002351 break;
2352 }
2353
Calin Juravle34bacdf2014-10-07 20:23:36 +01002354 case Instruction::MUL_INT_LIT16: {
2355 Binop_22s<HMul>(instruction, false);
2356 break;
2357 }
2358
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002359 case Instruction::ADD_INT_LIT8: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002360 Binop_22b<HAdd>(instruction, false);
2361 break;
2362 }
2363
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002364 case Instruction::AND_INT_LIT8: {
2365 Binop_22b<HAnd>(instruction, false);
2366 break;
2367 }
2368
2369 case Instruction::OR_INT_LIT8: {
2370 Binop_22b<HOr>(instruction, false);
2371 break;
2372 }
2373
2374 case Instruction::XOR_INT_LIT8: {
2375 Binop_22b<HXor>(instruction, false);
2376 break;
2377 }
2378
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002379 case Instruction::RSUB_INT_LIT8: {
2380 Binop_22b<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002381 break;
2382 }
2383
Calin Juravle34bacdf2014-10-07 20:23:36 +01002384 case Instruction::MUL_INT_LIT8: {
2385 Binop_22b<HMul>(instruction, false);
2386 break;
2387 }
2388
Calin Juravled0d48522014-11-04 16:40:20 +00002389 case Instruction::DIV_INT_LIT16:
2390 case Instruction::DIV_INT_LIT8: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002391 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2392 dex_pc, Primitive::kPrimInt, true, true);
2393 break;
2394 }
2395
2396 case Instruction::REM_INT_LIT16:
2397 case Instruction::REM_INT_LIT8: {
2398 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2399 dex_pc, Primitive::kPrimInt, true, false);
Calin Juravled0d48522014-11-04 16:40:20 +00002400 break;
2401 }
2402
Calin Juravle9aec02f2014-11-18 23:06:35 +00002403 case Instruction::SHL_INT_LIT8: {
2404 Binop_22b<HShl>(instruction, false);
2405 break;
2406 }
2407
2408 case Instruction::SHR_INT_LIT8: {
2409 Binop_22b<HShr>(instruction, false);
2410 break;
2411 }
2412
2413 case Instruction::USHR_INT_LIT8: {
2414 Binop_22b<HUShr>(instruction, false);
2415 break;
2416 }
2417
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002418 case Instruction::NEW_INSTANCE: {
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002419 uint16_t type_index = instruction.VRegB_21c();
Jeff Hao848f70a2014-01-15 13:49:50 -08002420 if (compiler_driver_->IsStringTypeIndex(type_index, dex_file_)) {
Jeff Hao848f70a2014-01-15 13:49:50 -08002421 int32_t register_index = instruction.VRegA();
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01002422 HFakeString* fake_string = new (arena_) HFakeString();
2423 current_block_->AddInstruction(fake_string);
2424 UpdateLocal(register_index, fake_string);
Jeff Hao848f70a2014-01-15 13:49:50 -08002425 } else {
2426 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
2427 ? kQuickAllocObjectWithAccessCheck
2428 : kQuickAllocObject;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002429
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002430 current_block_->AddInstruction(new (arena_) HNewInstance(
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002431 graph_->GetCurrentMethod(),
2432 dex_pc,
2433 type_index,
2434 *dex_compilation_unit_->GetDexFile(),
2435 entrypoint));
Jeff Hao848f70a2014-01-15 13:49:50 -08002436 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
2437 }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002438 break;
2439 }
2440
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002441 case Instruction::NEW_ARRAY: {
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002442 uint16_t type_index = instruction.VRegC_22c();
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002443 HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt);
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002444 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
2445 ? kQuickAllocArrayWithAccessCheck
2446 : kQuickAllocArray;
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002447 current_block_->AddInstruction(new (arena_) HNewArray(length,
2448 graph_->GetCurrentMethod(),
2449 dex_pc,
2450 type_index,
2451 *dex_compilation_unit_->GetDexFile(),
2452 entrypoint));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002453 UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
2454 break;
2455 }
2456
2457 case Instruction::FILLED_NEW_ARRAY: {
2458 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
2459 uint32_t type_index = instruction.VRegB_35c();
2460 uint32_t args[5];
2461 instruction.GetVarArgs(args);
Calin Juravle225ff812014-11-13 16:46:39 +00002462 BuildFilledNewArray(dex_pc, type_index, number_of_vreg_arguments, false, args, 0);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002463 break;
2464 }
2465
2466 case Instruction::FILLED_NEW_ARRAY_RANGE: {
2467 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
2468 uint32_t type_index = instruction.VRegB_3rc();
2469 uint32_t register_index = instruction.VRegC_3rc();
2470 BuildFilledNewArray(
Calin Juravle225ff812014-11-13 16:46:39 +00002471 dex_pc, type_index, number_of_vreg_arguments, true, nullptr, register_index);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002472 break;
2473 }
2474
2475 case Instruction::FILL_ARRAY_DATA: {
Calin Juravle225ff812014-11-13 16:46:39 +00002476 BuildFillArrayData(instruction, dex_pc);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002477 break;
2478 }
2479
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01002480 case Instruction::MOVE_RESULT:
Dave Allison20dfc792014-06-16 20:44:29 -07002481 case Instruction::MOVE_RESULT_WIDE:
David Brazdilfc6a86a2015-06-26 10:33:45 +00002482 case Instruction::MOVE_RESULT_OBJECT: {
Nicolas Geoffray1efcc222015-06-24 12:41:20 +01002483 if (latest_result_ == nullptr) {
2484 // Only dead code can lead to this situation, where the verifier
2485 // does not reject the method.
2486 } else {
David Brazdilfc6a86a2015-06-26 10:33:45 +00002487 // An Invoke/FilledNewArray and its MoveResult could have landed in
2488 // different blocks if there was a try/catch block boundary between
2489 // them. For Invoke, we insert a StoreLocal after the instruction. For
2490 // FilledNewArray, the local needs to be updated after the array was
2491 // filled, otherwise we might overwrite an input vreg.
2492 HStoreLocal* update_local =
2493 new (arena_) HStoreLocal(GetLocalAt(instruction.VRegA()), latest_result_);
2494 HBasicBlock* block = latest_result_->GetBlock();
2495 if (block == current_block_) {
2496 // MoveResult and the previous instruction are in the same block.
2497 current_block_->AddInstruction(update_local);
2498 } else {
2499 // The two instructions are in different blocks. Insert the MoveResult
2500 // before the final control-flow instruction of the previous block.
2501 DCHECK(block->EndsWithControlFlowInstruction());
2502 DCHECK(current_block_->GetInstructions().IsEmpty());
2503 block->InsertInstructionBefore(update_local, block->GetLastInstruction());
2504 }
Nicolas Geoffray1efcc222015-06-24 12:41:20 +01002505 latest_result_ = nullptr;
2506 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002507 break;
David Brazdilfc6a86a2015-06-26 10:33:45 +00002508 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002509
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002510 case Instruction::CMP_LONG: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002511 Binop_23x_cmp(instruction, Primitive::kPrimLong, ComparisonBias::kNoBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002512 break;
2513 }
2514
2515 case Instruction::CMPG_FLOAT: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002516 Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kGtBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002517 break;
2518 }
2519
2520 case Instruction::CMPG_DOUBLE: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002521 Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kGtBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002522 break;
2523 }
2524
2525 case Instruction::CMPL_FLOAT: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002526 Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kLtBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002527 break;
2528 }
2529
2530 case Instruction::CMPL_DOUBLE: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002531 Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kLtBias, dex_pc);
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002532 break;
2533 }
2534
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00002535 case Instruction::NOP:
2536 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002537
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002538 case Instruction::IGET:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002539 case Instruction::IGET_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002540 case Instruction::IGET_WIDE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002541 case Instruction::IGET_WIDE_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002542 case Instruction::IGET_OBJECT:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002543 case Instruction::IGET_OBJECT_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002544 case Instruction::IGET_BOOLEAN:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002545 case Instruction::IGET_BOOLEAN_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002546 case Instruction::IGET_BYTE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002547 case Instruction::IGET_BYTE_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002548 case Instruction::IGET_CHAR:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002549 case Instruction::IGET_CHAR_QUICK:
2550 case Instruction::IGET_SHORT:
2551 case Instruction::IGET_SHORT_QUICK: {
Calin Juravle225ff812014-11-13 16:46:39 +00002552 if (!BuildInstanceFieldAccess(instruction, dex_pc, false)) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002553 return false;
2554 }
2555 break;
2556 }
2557
2558 case Instruction::IPUT:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002559 case Instruction::IPUT_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002560 case Instruction::IPUT_WIDE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002561 case Instruction::IPUT_WIDE_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002562 case Instruction::IPUT_OBJECT:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002563 case Instruction::IPUT_OBJECT_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002564 case Instruction::IPUT_BOOLEAN:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002565 case Instruction::IPUT_BOOLEAN_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002566 case Instruction::IPUT_BYTE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002567 case Instruction::IPUT_BYTE_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002568 case Instruction::IPUT_CHAR:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002569 case Instruction::IPUT_CHAR_QUICK:
2570 case Instruction::IPUT_SHORT:
2571 case Instruction::IPUT_SHORT_QUICK: {
Calin Juravle225ff812014-11-13 16:46:39 +00002572 if (!BuildInstanceFieldAccess(instruction, dex_pc, true)) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002573 return false;
2574 }
2575 break;
2576 }
2577
2578 case Instruction::SGET:
2579 case Instruction::SGET_WIDE:
2580 case Instruction::SGET_OBJECT:
2581 case Instruction::SGET_BOOLEAN:
2582 case Instruction::SGET_BYTE:
2583 case Instruction::SGET_CHAR:
2584 case Instruction::SGET_SHORT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002585 if (!BuildStaticFieldAccess(instruction, dex_pc, false)) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002586 return false;
2587 }
2588 break;
2589 }
2590
2591 case Instruction::SPUT:
2592 case Instruction::SPUT_WIDE:
2593 case Instruction::SPUT_OBJECT:
2594 case Instruction::SPUT_BOOLEAN:
2595 case Instruction::SPUT_BYTE:
2596 case Instruction::SPUT_CHAR:
2597 case Instruction::SPUT_SHORT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002598 if (!BuildStaticFieldAccess(instruction, dex_pc, true)) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002599 return false;
2600 }
2601 break;
2602 }
2603
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002604#define ARRAY_XX(kind, anticipated_type) \
2605 case Instruction::AGET##kind: { \
Calin Juravle225ff812014-11-13 16:46:39 +00002606 BuildArrayAccess(instruction, dex_pc, false, anticipated_type); \
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002607 break; \
2608 } \
2609 case Instruction::APUT##kind: { \
Calin Juravle225ff812014-11-13 16:46:39 +00002610 BuildArrayAccess(instruction, dex_pc, true, anticipated_type); \
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002611 break; \
2612 }
2613
2614 ARRAY_XX(, Primitive::kPrimInt);
2615 ARRAY_XX(_WIDE, Primitive::kPrimLong);
2616 ARRAY_XX(_OBJECT, Primitive::kPrimNot);
2617 ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean);
2618 ARRAY_XX(_BYTE, Primitive::kPrimByte);
2619 ARRAY_XX(_CHAR, Primitive::kPrimChar);
2620 ARRAY_XX(_SHORT, Primitive::kPrimShort);
2621
Nicolas Geoffray39468442014-09-02 15:17:15 +01002622 case Instruction::ARRAY_LENGTH: {
2623 HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot);
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002624 // No need for a temporary for the null check, it is the only input of the following
2625 // instruction.
Calin Juravle225ff812014-11-13 16:46:39 +00002626 object = new (arena_) HNullCheck(object, dex_pc);
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002627 current_block_->AddInstruction(object);
Nicolas Geoffray39468442014-09-02 15:17:15 +01002628 current_block_->AddInstruction(new (arena_) HArrayLength(object));
2629 UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction());
2630 break;
2631 }
2632
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002633 case Instruction::CONST_STRING: {
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01002634 current_block_->AddInstruction(
2635 new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_21c(), dex_pc));
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002636 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
2637 break;
2638 }
2639
2640 case Instruction::CONST_STRING_JUMBO: {
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01002641 current_block_->AddInstruction(
2642 new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_31c(), dex_pc));
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002643 UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction());
2644 break;
2645 }
2646
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002647 case Instruction::CONST_CLASS: {
2648 uint16_t type_index = instruction.VRegB_21c();
2649 bool type_known_final;
2650 bool type_known_abstract;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002651 bool dont_use_is_referrers_class;
2652 // `CanAccessTypeWithoutChecks` will tell whether the method being
2653 // built is trying to access its own class, so that the generated
2654 // code can optimize for this case. However, the optimization does not
Nicolas Geoffray9437b782015-03-25 10:08:51 +00002655 // work for inlining, so we use `IsOutermostCompilingClass` instead.
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002656 bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
2657 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002658 &type_known_final, &type_known_abstract, &dont_use_is_referrers_class);
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002659 if (!can_access) {
Calin Juravle48c2b032014-12-09 18:11:36 +00002660 MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002661 return false;
2662 }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002663 current_block_->AddInstruction(new (arena_) HLoadClass(
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01002664 graph_->GetCurrentMethod(),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002665 type_index,
2666 *dex_compilation_unit_->GetDexFile(),
2667 IsOutermostCompilingClass(type_index),
2668 dex_pc));
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002669 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
2670 break;
2671 }
2672
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002673 case Instruction::MOVE_EXCEPTION: {
2674 current_block_->AddInstruction(new (arena_) HLoadException());
2675 UpdateLocal(instruction.VRegA_11x(), current_block_->GetLastInstruction());
David Brazdilcb1c0552015-08-04 16:22:25 +01002676 current_block_->AddInstruction(new (arena_) HClearException());
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002677 break;
2678 }
2679
2680 case Instruction::THROW: {
2681 HInstruction* exception = LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot);
Calin Juravle225ff812014-11-13 16:46:39 +00002682 current_block_->AddInstruction(new (arena_) HThrow(exception, dex_pc));
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002683 // A throw instruction must branch to the exit block.
2684 current_block_->AddSuccessor(exit_block_);
2685 // We finished building this block. Set the current block to null to avoid
2686 // adding dead instructions to it.
2687 current_block_ = nullptr;
2688 break;
2689 }
2690
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002691 case Instruction::INSTANCE_OF: {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002692 uint8_t destination = instruction.VRegA_22c();
2693 uint8_t reference = instruction.VRegB_22c();
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002694 uint16_t type_index = instruction.VRegC_22c();
Calin Juravle225ff812014-11-13 16:46:39 +00002695 if (!BuildTypeCheck(instruction, destination, reference, type_index, dex_pc)) {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002696 return false;
2697 }
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002698 break;
2699 }
2700
2701 case Instruction::CHECK_CAST: {
2702 uint8_t reference = instruction.VRegA_21c();
2703 uint16_t type_index = instruction.VRegB_21c();
Calin Juravle225ff812014-11-13 16:46:39 +00002704 if (!BuildTypeCheck(instruction, -1, reference, type_index, dex_pc)) {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002705 return false;
2706 }
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002707 break;
2708 }
2709
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002710 case Instruction::MONITOR_ENTER: {
2711 current_block_->AddInstruction(new (arena_) HMonitorOperation(
2712 LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
2713 HMonitorOperation::kEnter,
Calin Juravle225ff812014-11-13 16:46:39 +00002714 dex_pc));
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002715 break;
2716 }
2717
2718 case Instruction::MONITOR_EXIT: {
2719 current_block_->AddInstruction(new (arena_) HMonitorOperation(
2720 LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
2721 HMonitorOperation::kExit,
Calin Juravle225ff812014-11-13 16:46:39 +00002722 dex_pc));
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002723 break;
2724 }
2725
Andreas Gamped881df52014-11-24 23:28:39 -08002726 case Instruction::PACKED_SWITCH: {
Calin Juravle48c2b032014-12-09 18:11:36 +00002727 BuildPackedSwitch(instruction, dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -08002728 break;
2729 }
2730
Andreas Gampee4d4d322014-12-04 09:09:57 -08002731 case Instruction::SPARSE_SWITCH: {
Calin Juravle48c2b032014-12-09 18:11:36 +00002732 BuildSparseSwitch(instruction, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08002733 break;
2734 }
2735
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002736 default:
Calin Juravle48c2b032014-12-09 18:11:36 +00002737 VLOG(compiler) << "Did not compile "
2738 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
2739 << " because of unhandled instruction "
2740 << instruction.Name();
2741 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnhandledInstruction);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002742 return false;
2743 }
2744 return true;
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00002745} // NOLINT(readability/fn_size)
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002746
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002747HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
2748 return locals_.Get(register_index);
2749}
2750
2751void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {
2752 HLocal* local = GetLocalAt(register_index);
2753 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));
2754}
2755
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002756HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002757 HLocal* local = GetLocalAt(register_index);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002758 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type));
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002759 return current_block_->GetLastInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002760}
2761
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002762} // namespace art