blob: 0a3f083e100455f3f644afa57c00af2d1a18ae65 [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) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +060049 HInstruction* temp = new (graph_->GetArena()) HTemporary(index_, instruction->GetDexPc());
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.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600164 HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++,
165 Primitive::kPrimNot,
166 true);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100167 entry_block_->AddInstruction(parameter);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100168 HLocal* local = GetLocalAt(locals_index++);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600169 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter, local->GetDexPc()));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100170 number_of_parameters--;
171 }
172
173 uint32_t pos = 1;
174 for (int i = 0; i < number_of_parameters; i++) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600175 HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++,
176 Primitive::GetType(shorty[pos++]),
177 false);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100178 entry_block_->AddInstruction(parameter);
179 HLocal* local = GetLocalAt(locals_index++);
180 // Store the parameter value in the local that the dex code will use
181 // to reference that parameter.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600182 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter, local->GetDexPc()));
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100183 bool is_wide = (parameter->GetType() == Primitive::kPrimLong)
184 || (parameter->GetType() == Primitive::kPrimDouble);
185 if (is_wide) {
186 i++;
187 locals_index++;
188 parameter_index++;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100189 }
190 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100191}
192
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100193template<typename T>
Calin Juravle225ff812014-11-13 16:46:39 +0000194void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc) {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000195 int32_t target_offset = instruction.GetTargetOffset();
David Brazdil852eaff2015-02-02 15:23:05 +0000196 HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset);
197 HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
198 DCHECK(branch_target != nullptr);
199 DCHECK(fallthrough_target != nullptr);
200 PotentiallyAddSuspendCheck(branch_target, dex_pc);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600201 HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
202 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
203 T* comparison = new (arena_) T(first, second, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -0700204 current_block_->AddInstruction(comparison);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600205 HInstruction* ifinst = new (arena_) HIf(comparison, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -0700206 current_block_->AddInstruction(ifinst);
David Brazdil852eaff2015-02-02 15:23:05 +0000207 current_block_->AddSuccessor(branch_target);
208 current_block_->AddSuccessor(fallthrough_target);
Dave Allison20dfc792014-06-16 20:44:29 -0700209 current_block_ = nullptr;
210}
211
212template<typename T>
Calin Juravle225ff812014-11-13 16:46:39 +0000213void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000214 int32_t target_offset = instruction.GetTargetOffset();
David Brazdil852eaff2015-02-02 15:23:05 +0000215 HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset);
216 HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
217 DCHECK(branch_target != nullptr);
218 DCHECK(fallthrough_target != nullptr);
219 PotentiallyAddSuspendCheck(branch_target, dex_pc);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600220 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
221 T* comparison = new (arena_) T(value, graph_->GetIntConstant(0, dex_pc), dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -0700222 current_block_->AddInstruction(comparison);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600223 HInstruction* ifinst = new (arena_) HIf(comparison, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -0700224 current_block_->AddInstruction(ifinst);
David Brazdil852eaff2015-02-02 15:23:05 +0000225 current_block_->AddSuccessor(branch_target);
226 current_block_->AddSuccessor(fallthrough_target);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100227 current_block_ = nullptr;
228}
229
Calin Juravle48c2b032014-12-09 18:11:36 +0000230void HGraphBuilder::MaybeRecordStat(MethodCompilationStat compilation_stat) {
231 if (compilation_stats_ != nullptr) {
232 compilation_stats_->RecordStat(compilation_stat);
233 }
234}
235
David Brazdil1b498722015-03-31 11:37:18 +0100236bool HGraphBuilder::SkipCompilation(const DexFile::CodeItem& code_item,
Calin Juravle48c2b032014-12-09 18:11:36 +0000237 size_t number_of_branches) {
238 const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions();
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000239 CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter();
240 if (compiler_filter == CompilerOptions::kEverything) {
241 return false;
242 }
243
David Brazdil1b498722015-03-31 11:37:18 +0100244 if (compiler_options.IsHugeMethod(code_item.insns_size_in_code_units_)) {
Calin Juravle48c2b032014-12-09 18:11:36 +0000245 VLOG(compiler) << "Skip compilation of huge method "
246 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
David Brazdil1b498722015-03-31 11:37:18 +0100247 << ": " << code_item.insns_size_in_code_units_ << " code units";
Calin Juravle48c2b032014-12-09 18:11:36 +0000248 MaybeRecordStat(MethodCompilationStat::kNotCompiledHugeMethod);
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000249 return true;
250 }
251
252 // If it's large and contains no branches, it's likely to be machine generated initialization.
David Brazdil1b498722015-03-31 11:37:18 +0100253 if (compiler_options.IsLargeMethod(code_item.insns_size_in_code_units_)
254 && (number_of_branches == 0)) {
Calin Juravle48c2b032014-12-09 18:11:36 +0000255 VLOG(compiler) << "Skip compilation of large method with no branch "
256 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
David Brazdil1b498722015-03-31 11:37:18 +0100257 << ": " << code_item.insns_size_in_code_units_ << " code units";
Calin Juravle48c2b032014-12-09 18:11:36 +0000258 MaybeRecordStat(MethodCompilationStat::kNotCompiledLargeMethodNoBranches);
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000259 return true;
260 }
261
262 return false;
263}
264
David Brazdilbff75032015-07-08 17:26:51 +0000265static const DexFile::TryItem* GetTryItem(HBasicBlock* block,
266 const DexFile::CodeItem& code_item,
267 const ArenaBitVector& can_block_throw) {
268 DCHECK(!block->IsSingleTryBoundary());
269
270 // Block does not contain throwing instructions. Even if it is covered by
271 // a TryItem, we will consider it not in a try block.
272 if (!can_block_throw.IsBitSet(block->GetBlockId())) {
273 return nullptr;
274 }
275
276 // Instructions in the block may throw. Find a TryItem covering this block.
277 int32_t try_item_idx = DexFile::FindTryItem(code_item, block->GetDexPc());
David Brazdil6cd788f2015-07-08 16:44:00 +0100278 return (try_item_idx == -1) ? nullptr : DexFile::GetTryItems(code_item, try_item_idx);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000279}
280
281void HGraphBuilder::CreateBlocksForTryCatch(const DexFile::CodeItem& code_item) {
282 if (code_item.tries_size_ == 0) {
283 return;
284 }
285
286 // Create branch targets at the start/end of the TryItem range. These are
287 // places where the program might fall through into/out of the a block and
288 // where TryBoundary instructions will be inserted later. Other edges which
289 // enter/exit the try blocks are a result of branches/switches.
290 for (size_t idx = 0; idx < code_item.tries_size_; ++idx) {
291 const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item, idx);
292 uint32_t dex_pc_start = try_item->start_addr_;
293 uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_;
294 FindOrCreateBlockStartingAt(dex_pc_start);
295 if (dex_pc_end < code_item.insns_size_in_code_units_) {
296 // TODO: Do not create block if the last instruction cannot fall through.
297 FindOrCreateBlockStartingAt(dex_pc_end);
298 } else {
299 // The TryItem spans until the very end of the CodeItem (or beyond if
300 // invalid) and therefore cannot have any code afterwards.
301 }
302 }
303
304 // Create branch targets for exception handlers.
305 const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item, 0);
306 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
307 for (uint32_t idx = 0; idx < handlers_size; ++idx) {
308 CatchHandlerIterator iterator(handlers_ptr);
309 for (; iterator.HasNext(); iterator.Next()) {
310 uint32_t address = iterator.GetHandlerAddress();
311 HBasicBlock* block = FindOrCreateBlockStartingAt(address);
David Brazdilec16f792015-08-19 15:04:01 +0100312 block->SetTryCatchInformation(
313 new (arena_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_));
David Brazdilfc6a86a2015-06-26 10:33:45 +0000314 }
315 handlers_ptr = iterator.EndDataPointer();
316 }
317}
318
David Brazdil56e1acc2015-06-30 15:41:36 +0100319void HGraphBuilder::SplitTryBoundaryEdge(HBasicBlock* predecessor,
320 HBasicBlock* successor,
321 HTryBoundary::BoundaryKind kind,
322 const DexFile::CodeItem& code_item,
323 const DexFile::TryItem& try_item) {
324 // Split the edge with a single TryBoundary instruction.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600325 HTryBoundary* try_boundary = new (arena_) HTryBoundary(kind, successor->GetDexPc());
David Brazdil56e1acc2015-06-30 15:41:36 +0100326 HBasicBlock* try_entry_block = graph_->SplitEdge(predecessor, successor);
327 try_entry_block->AddInstruction(try_boundary);
328
329 // Link the TryBoundary to the handlers of `try_item`.
330 for (CatchHandlerIterator it(code_item, try_item); it.HasNext(); it.Next()) {
331 try_boundary->AddExceptionHandler(FindBlockStartingAt(it.GetHandlerAddress()));
332 }
333}
334
David Brazdilfc6a86a2015-06-26 10:33:45 +0000335void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) {
336 if (code_item.tries_size_ == 0) {
337 return;
338 }
339
David Brazdil72783ff2015-07-09 14:36:05 +0100340 // Bit vector stores information on which blocks contain throwing instructions.
341 // Must be expandable because catch blocks may be split into two.
342 ArenaBitVector can_block_throw(arena_, graph_->GetBlocks().Size(), /* expandable */ true);
David Brazdilbff75032015-07-08 17:26:51 +0000343
344 // Scan blocks and mark those which contain throwing instructions.
David Brazdil72783ff2015-07-09 14:36:05 +0100345 for (size_t block_id = 0, e = graph_->GetBlocks().Size(); block_id < e; ++block_id) {
David Brazdilbff75032015-07-08 17:26:51 +0000346 HBasicBlock* block = graph_->GetBlocks().Get(block_id);
David Brazdil72783ff2015-07-09 14:36:05 +0100347 bool can_throw = false;
David Brazdilbff75032015-07-08 17:26:51 +0000348 for (HInstructionIterator insn(block->GetInstructions()); !insn.Done(); insn.Advance()) {
349 if (insn.Current()->CanThrow()) {
David Brazdil72783ff2015-07-09 14:36:05 +0100350 can_throw = true;
David Brazdilbff75032015-07-08 17:26:51 +0000351 break;
352 }
353 }
David Brazdil72783ff2015-07-09 14:36:05 +0100354
355 if (can_throw) {
356 if (block->IsCatchBlock()) {
357 // Catch blocks are always considered an entry point into the TryItem in
358 // order to avoid splitting exceptional edges. We split the block after
359 // the move-exception (if present) and mark the first part non-throwing.
360 // Later on, a TryBoundary will be inserted between the two blocks.
361 HInstruction* first_insn = block->GetFirstInstruction();
362 if (first_insn->IsLoadException()) {
363 // Catch block starts with a LoadException. Split the block after the
David Brazdilcb1c0552015-08-04 16:22:25 +0100364 // StoreLocal and ClearException which must come after the load.
David Brazdil72783ff2015-07-09 14:36:05 +0100365 DCHECK(first_insn->GetNext()->IsStoreLocal());
David Brazdilcb1c0552015-08-04 16:22:25 +0100366 DCHECK(first_insn->GetNext()->GetNext()->IsClearException());
367 block = block->SplitBefore(first_insn->GetNext()->GetNext()->GetNext());
David Brazdil72783ff2015-07-09 14:36:05 +0100368 } else {
369 // Catch block does not load the exception. Split at the beginning to
370 // create an empty catch block.
371 block = block->SplitBefore(first_insn);
372 }
373 }
374 can_block_throw.SetBit(block->GetBlockId());
375 }
David Brazdilbff75032015-07-08 17:26:51 +0000376 }
377
David Brazdil281a6322015-07-03 10:34:57 +0100378 // Iterate over all blocks, find those covered by some TryItem and:
379 // (a) split edges which enter/exit the try range,
380 // (b) create TryBoundary instructions in the new blocks,
381 // (c) link the new blocks to corresponding exception handlers.
382 // We cannot iterate only over blocks in `branch_targets_` because switch-case
383 // blocks share the same dex_pc.
David Brazdil72783ff2015-07-09 14:36:05 +0100384 for (size_t block_id = 0, e = graph_->GetBlocks().Size(); block_id < e; ++block_id) {
David Brazdil281a6322015-07-03 10:34:57 +0100385 HBasicBlock* try_block = graph_->GetBlocks().Get(block_id);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000386
David Brazdil281a6322015-07-03 10:34:57 +0100387 // TryBoundary blocks are added at the end of the list and not iterated over.
388 DCHECK(!try_block->IsSingleTryBoundary());
David Brazdilfc6a86a2015-06-26 10:33:45 +0000389
David Brazdil281a6322015-07-03 10:34:57 +0100390 // Find the TryItem for this block.
David Brazdilbff75032015-07-08 17:26:51 +0000391 const DexFile::TryItem* try_item = GetTryItem(try_block, code_item, can_block_throw);
392 if (try_item == nullptr) {
David Brazdil281a6322015-07-03 10:34:57 +0100393 continue;
394 }
David Brazdil281a6322015-07-03 10:34:57 +0100395
David Brazdil72783ff2015-07-09 14:36:05 +0100396 // Catch blocks were split earlier and cannot throw.
397 DCHECK(!try_block->IsCatchBlock());
398
399 // Find predecessors which are not covered by the same TryItem range. Such
400 // edges enter the try block and will have a TryBoundary inserted.
Vladimir Marko60584552015-09-03 13:35:12 +0000401 for (size_t i = 0; i < try_block->GetPredecessors().size(); ++i) {
402 HBasicBlock* predecessor = try_block->GetPredecessor(i);
David Brazdil72783ff2015-07-09 14:36:05 +0100403 if (predecessor->IsSingleTryBoundary()) {
404 // The edge was already split because of an exit from a neighbouring
405 // TryItem. We split it again and insert an entry point.
406 if (kIsDebugBuild) {
407 HTryBoundary* last_insn = predecessor->GetLastInstruction()->AsTryBoundary();
408 const DexFile::TryItem* predecessor_try_item =
409 GetTryItem(predecessor->GetSinglePredecessor(), code_item, can_block_throw);
410 DCHECK(!last_insn->IsEntry());
411 DCHECK_EQ(last_insn->GetNormalFlowSuccessor(), try_block);
412 DCHECK(try_block->IsFirstIndexOfPredecessor(predecessor, i));
413 DCHECK_NE(try_item, predecessor_try_item);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000414 }
David Brazdil72783ff2015-07-09 14:36:05 +0100415 } else if (GetTryItem(predecessor, code_item, can_block_throw) != try_item) {
416 // This is an entry point into the TryItem and the edge has not been
417 // split yet. That means that `predecessor` is not in a TryItem, or
418 // it is in a different TryItem and we happened to iterate over this
419 // block first. We split the edge and insert an entry point.
420 } else {
421 // Not an edge on the boundary of the try block.
422 continue;
David Brazdilfc6a86a2015-06-26 10:33:45 +0000423 }
David Brazdil72783ff2015-07-09 14:36:05 +0100424 SplitTryBoundaryEdge(predecessor, try_block, HTryBoundary::kEntry, code_item, *try_item);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000425 }
David Brazdil281a6322015-07-03 10:34:57 +0100426
427 // Find successors which are not covered by the same TryItem range. Such
428 // edges exit the try block and will have a TryBoundary inserted.
Vladimir Marko60584552015-09-03 13:35:12 +0000429 for (HBasicBlock* successor : try_block->GetSuccessors()) {
David Brazdil281a6322015-07-03 10:34:57 +0100430 if (successor->IsCatchBlock()) {
431 // A catch block is always considered an entry point into its TryItem.
432 // We therefore assume this is an exit point, regardless of whether
433 // the catch block is in a different TryItem or not.
434 } else if (successor->IsSingleTryBoundary()) {
435 // The edge was already split because of an entry into a neighbouring
436 // TryItem. We split it again and insert an exit.
437 if (kIsDebugBuild) {
438 HTryBoundary* last_insn = successor->GetLastInstruction()->AsTryBoundary();
David Brazdilbff75032015-07-08 17:26:51 +0000439 const DexFile::TryItem* successor_try_item =
440 GetTryItem(last_insn->GetNormalFlowSuccessor(), code_item, can_block_throw);
David Brazdil281a6322015-07-03 10:34:57 +0100441 DCHECK_EQ(try_block, successor->GetSinglePredecessor());
442 DCHECK(last_insn->IsEntry());
David Brazdilbff75032015-07-08 17:26:51 +0000443 DCHECK_NE(try_item, successor_try_item);
David Brazdil281a6322015-07-03 10:34:57 +0100444 }
David Brazdilbff75032015-07-08 17:26:51 +0000445 } else if (GetTryItem(successor, code_item, can_block_throw) != try_item) {
David Brazdil281a6322015-07-03 10:34:57 +0100446 // This is an exit out of the TryItem and the edge has not been split
447 // yet. That means that either `successor` is not in a TryItem, or it
448 // is in a different TryItem and we happened to iterate over this
449 // block first. We split the edge and insert an exit.
450 HInstruction* last_instruction = try_block->GetLastInstruction();
451 if (last_instruction->IsReturn() || last_instruction->IsReturnVoid()) {
452 DCHECK_EQ(successor, exit_block_);
453 // Control flow exits the try block with a Return(Void). Because
454 // splitting the edge would invalidate the invariant that Return
455 // always jumps to Exit, we move the Return outside the try block.
456 successor = try_block->SplitBefore(last_instruction);
457 }
458 } else {
459 // Not an edge on the boundary of the try block.
460 continue;
461 }
David Brazdilbff75032015-07-08 17:26:51 +0000462 SplitTryBoundaryEdge(try_block, successor, HTryBoundary::kExit, code_item, *try_item);
David Brazdil281a6322015-07-03 10:34:57 +0100463 }
David Brazdilfc6a86a2015-06-26 10:33:45 +0000464 }
465}
466
David Brazdil5e8b1372015-01-23 14:39:08 +0000467bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
468 DCHECK(graph_->GetBlocks().IsEmpty());
469
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000470 const uint16_t* code_ptr = code_item.insns_;
471 const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_;
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +0100472 code_start_ = code_ptr;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000473
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000474 // Setup the graph with the entry block and exit block.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100475 entry_block_ = new (arena_) HBasicBlock(graph_, 0);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000476 graph_->AddBlock(entry_block_);
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100477 exit_block_ = new (arena_) HBasicBlock(graph_, kNoDexPc);
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000478 graph_->SetEntryBlock(entry_block_);
479 graph_->SetExitBlock(exit_block_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000480
David Brazdil77a48ae2015-09-15 12:34:04 +0000481 graph_->SetHasTryCatch(code_item.tries_size_ != 0);
482
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000483 InitializeLocals(code_item.registers_size_);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000484 graph_->SetMaximumNumberOfOutVRegs(code_item.outs_size_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000485
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000486 // Compute the number of dex instructions, blocks, and branches. We will
487 // check these values against limits given to the compiler.
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000488 size_t number_of_branches = 0;
489
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000490 // To avoid splitting blocks, we compute ahead of time the instructions that
491 // start a new block, and create these blocks.
Calin Juravle702d2602015-04-30 19:28:21 +0100492 if (!ComputeBranchTargets(code_ptr, code_end, &number_of_branches)) {
493 MaybeRecordStat(MethodCompilationStat::kNotCompiledBranchOutsideMethodCode);
494 return false;
495 }
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000496
497 // Note that the compiler driver is null when unit testing.
David Brazdil1b498722015-03-31 11:37:18 +0100498 if ((compiler_driver_ != nullptr) && SkipCompilation(code_item, number_of_branches)) {
David Brazdil5e8b1372015-01-23 14:39:08 +0000499 return false;
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000500 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000501
David Brazdilfc6a86a2015-06-26 10:33:45 +0000502 CreateBlocksForTryCatch(code_item);
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000503
Nicolas Geoffray52e832b2014-11-06 15:15:31 +0000504 InitializeParameters(code_item.ins_size_);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100505
Calin Juravle225ff812014-11-13 16:46:39 +0000506 size_t dex_pc = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000507 while (code_ptr < code_end) {
Calin Juravle225ff812014-11-13 16:46:39 +0000508 // Update the current block if dex_pc starts a new block.
509 MaybeUpdateCurrentBlock(dex_pc);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000510 const Instruction& instruction = *Instruction::At(code_ptr);
Calin Juravle48c2b032014-12-09 18:11:36 +0000511 if (!AnalyzeDexInstruction(instruction, dex_pc)) {
David Brazdil5e8b1372015-01-23 14:39:08 +0000512 return false;
Calin Juravle48c2b032014-12-09 18:11:36 +0000513 }
Calin Juravle225ff812014-11-13 16:46:39 +0000514 dex_pc += instruction.SizeInCodeUnits();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000515 code_ptr += instruction.SizeInCodeUnits();
516 }
517
David Brazdilfc6a86a2015-06-26 10:33:45 +0000518 // Add Exit to the exit block.
David Brazdil3e187382015-06-26 09:59:52 +0000519 exit_block_->AddInstruction(new (arena_) HExit());
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000520 // Add the suspend check to the entry block.
521 entry_block_->AddInstruction(new (arena_) HSuspendCheck(0));
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000522 entry_block_->AddInstruction(new (arena_) HGoto());
David Brazdilbff75032015-07-08 17:26:51 +0000523 // Add the exit block at the end.
524 graph_->AddBlock(exit_block_);
David Brazdil5e8b1372015-01-23 14:39:08 +0000525
David Brazdilfc6a86a2015-06-26 10:33:45 +0000526 // Iterate over blocks covered by TryItems and insert TryBoundaries at entry
527 // and exit points. This requires all control-flow instructions and
528 // non-exceptional edges to have been created.
529 InsertTryBoundaryBlocks(code_item);
530
David Brazdil5e8b1372015-01-23 14:39:08 +0000531 return true;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000532}
533
David Brazdilfc6a86a2015-06-26 10:33:45 +0000534void HGraphBuilder::MaybeUpdateCurrentBlock(size_t dex_pc) {
535 HBasicBlock* block = FindBlockStartingAt(dex_pc);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000536 if (block == nullptr) {
537 return;
538 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000539
540 if (current_block_ != nullptr) {
541 // Branching instructions clear current_block, so we know
542 // the last instruction of the current block is not a branching
543 // instruction. We add an unconditional goto to the found block.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600544 current_block_->AddInstruction(new (arena_) HGoto(dex_pc));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000545 current_block_->AddSuccessor(block);
546 }
547 graph_->AddBlock(block);
548 current_block_ = block;
549}
550
Calin Juravle702d2602015-04-30 19:28:21 +0100551bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr,
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000552 const uint16_t* code_end,
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000553 size_t* number_of_branches) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000554 branch_targets_.SetSize(code_end - code_ptr);
555
556 // Create the first block for the dex instructions, single successor of the entry block.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100557 HBasicBlock* block = new (arena_) HBasicBlock(graph_, 0);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000558 branch_targets_.Put(0, block);
559 entry_block_->AddSuccessor(block);
560
561 // Iterate over all instructions and find branching instructions. Create blocks for
562 // the locations these instructions branch to.
Andreas Gamped881df52014-11-24 23:28:39 -0800563 uint32_t dex_pc = 0;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000564 while (code_ptr < code_end) {
565 const Instruction& instruction = *Instruction::At(code_ptr);
566 if (instruction.IsBranch()) {
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000567 (*number_of_branches)++;
Calin Juravle225ff812014-11-13 16:46:39 +0000568 int32_t target = instruction.GetTargetOffset() + dex_pc;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000569 // Create a block for the target instruction.
David Brazdilfc6a86a2015-06-26 10:33:45 +0000570 FindOrCreateBlockStartingAt(target);
571
Calin Juravle225ff812014-11-13 16:46:39 +0000572 dex_pc += instruction.SizeInCodeUnits();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000573 code_ptr += instruction.SizeInCodeUnits();
Calin Juravle702d2602015-04-30 19:28:21 +0100574
David Brazdilfe659462015-06-24 14:23:56 +0100575 if (instruction.CanFlowThrough()) {
576 if (code_ptr >= code_end) {
Calin Juravle702d2602015-04-30 19:28:21 +0100577 // In the normal case we should never hit this but someone can artificially forge a dex
578 // file to fall-through out the method code. In this case we bail out compilation.
579 return false;
David Brazdilfc6a86a2015-06-26 10:33:45 +0000580 } else {
581 FindOrCreateBlockStartingAt(dex_pc);
Calin Juravle702d2602015-04-30 19:28:21 +0100582 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000583 }
Andreas Gampee4d4d322014-12-04 09:09:57 -0800584 } else if (instruction.IsSwitch()) {
585 SwitchTable table(instruction, dex_pc, instruction.Opcode() == Instruction::SPARSE_SWITCH);
Andreas Gamped881df52014-11-24 23:28:39 -0800586
587 uint16_t num_entries = table.GetNumEntries();
588
Andreas Gampee4d4d322014-12-04 09:09:57 -0800589 // In a packed-switch, the entry at index 0 is the starting key. In a sparse-switch, the
590 // entry at index 0 is the first key, and values are after *all* keys.
591 size_t offset = table.GetFirstValueIndex();
592
593 // Use a larger loop counter type to avoid overflow issues.
594 for (size_t i = 0; i < num_entries; ++i) {
Andreas Gamped881df52014-11-24 23:28:39 -0800595 // The target of the case.
Andreas Gampee4d4d322014-12-04 09:09:57 -0800596 uint32_t target = dex_pc + table.GetEntryAt(i + offset);
David Brazdilfc6a86a2015-06-26 10:33:45 +0000597 FindOrCreateBlockStartingAt(target);
Andreas Gamped881df52014-11-24 23:28:39 -0800598
David Brazdil281a6322015-07-03 10:34:57 +0100599 // Create a block for the switch-case logic. The block gets the dex_pc
600 // of the SWITCH instruction because it is part of its semantics.
601 block = new (arena_) HBasicBlock(graph_, dex_pc);
602 branch_targets_.Put(table.GetDexPcForIndex(i), block);
Andreas Gamped881df52014-11-24 23:28:39 -0800603 }
604
605 // Fall-through. Add a block if there is more code afterwards.
606 dex_pc += instruction.SizeInCodeUnits();
607 code_ptr += instruction.SizeInCodeUnits();
Calin Juravle702d2602015-04-30 19:28:21 +0100608 if (code_ptr >= code_end) {
609 // In the normal case we should never hit this but someone can artificially forge a dex
610 // file to fall-through out the method code. In this case we bail out compilation.
611 // (A switch can fall-through so we don't need to check CanFlowThrough().)
612 return false;
David Brazdilfc6a86a2015-06-26 10:33:45 +0000613 } else {
614 FindOrCreateBlockStartingAt(dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -0800615 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000616 } else {
617 code_ptr += instruction.SizeInCodeUnits();
Calin Juravle225ff812014-11-13 16:46:39 +0000618 dex_pc += instruction.SizeInCodeUnits();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000619 }
620 }
Calin Juravle702d2602015-04-30 19:28:21 +0100621 return true;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000622}
623
David Brazdilfc6a86a2015-06-26 10:33:45 +0000624HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t dex_pc) const {
625 DCHECK_GE(dex_pc, 0);
626 DCHECK_LT(static_cast<size_t>(dex_pc), branch_targets_.Size());
627 return branch_targets_.Get(dex_pc);
628}
629
630HBasicBlock* HGraphBuilder::FindOrCreateBlockStartingAt(int32_t dex_pc) {
631 HBasicBlock* block = FindBlockStartingAt(dex_pc);
632 if (block == nullptr) {
633 block = new (arena_) HBasicBlock(graph_, dex_pc);
634 branch_targets_.Put(dex_pc, block);
635 }
636 return block;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000637}
638
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100639template<typename T>
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600640void HGraphBuilder::Unop_12x(const Instruction& instruction,
641 Primitive::Type type,
642 uint32_t dex_pc) {
643 HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc);
644 current_block_->AddInstruction(new (arena_) T(type, first, dex_pc));
645 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Roland Levillain88cb1752014-10-20 16:36:47 +0100646}
647
Roland Levillaindff1f282014-11-05 14:15:05 +0000648void HGraphBuilder::Conversion_12x(const Instruction& instruction,
649 Primitive::Type input_type,
Roland Levillain624279f2014-12-04 11:54:28 +0000650 Primitive::Type result_type,
651 uint32_t dex_pc) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600652 HInstruction* first = LoadLocal(instruction.VRegB(), input_type, dex_pc);
Roland Levillain624279f2014-12-04 11:54:28 +0000653 current_block_->AddInstruction(new (arena_) HTypeConversion(result_type, first, dex_pc));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600654 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100655}
656
657template<typename T>
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000658void HGraphBuilder::Binop_23x(const Instruction& instruction,
659 Primitive::Type type,
660 uint32_t dex_pc) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600661 HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc);
662 HInstruction* second = LoadLocal(instruction.VRegC(), type, dex_pc);
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000663 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600664 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000665}
666
667template<typename T>
Calin Juravle9aec02f2014-11-18 23:06:35 +0000668void HGraphBuilder::Binop_23x_shift(const Instruction& instruction,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600669 Primitive::Type type,
670 uint32_t dex_pc) {
671 HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc);
672 HInstruction* second = LoadLocal(instruction.VRegC(), Primitive::kPrimInt, dex_pc);
673 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
674 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +0000675}
676
Calin Juravleddb7df22014-11-25 20:56:51 +0000677void HGraphBuilder::Binop_23x_cmp(const Instruction& instruction,
678 Primitive::Type type,
Mark Mendellc4701932015-04-10 13:18:51 -0400679 ComparisonBias bias,
Alexey Frunze4dda3372015-06-01 18:31:49 -0700680 uint32_t dex_pc) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600681 HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc);
682 HInstruction* second = LoadLocal(instruction.VRegC(), type, dex_pc);
Alexey Frunze4dda3372015-06-01 18:31:49 -0700683 current_block_->AddInstruction(new (arena_) HCompare(type, first, second, bias, dex_pc));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600684 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +0000685}
686
Calin Juravle9aec02f2014-11-18 23:06:35 +0000687template<typename T>
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600688void HGraphBuilder::Binop_12x_shift(const Instruction& instruction, Primitive::Type type,
689 uint32_t dex_pc) {
690 HInstruction* first = LoadLocal(instruction.VRegA(), type, dex_pc);
691 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
692 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
693 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +0000694}
695
696template<typename T>
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000697void HGraphBuilder::Binop_12x(const Instruction& instruction,
698 Primitive::Type type,
699 uint32_t dex_pc) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600700 HInstruction* first = LoadLocal(instruction.VRegA(), type, dex_pc);
701 HInstruction* second = LoadLocal(instruction.VRegB(), type, dex_pc);
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000702 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600703 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000704}
705
706template<typename T>
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600707void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse, uint32_t dex_pc) {
708 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
709 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s(), dex_pc);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100710 if (reverse) {
711 std::swap(first, second);
712 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600713 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second, dex_pc));
714 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100715}
716
717template<typename T>
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600718void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc) {
719 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
720 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b(), dex_pc);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100721 if (reverse) {
722 std::swap(first, second);
723 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600724 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second, dex_pc));
725 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100726}
727
Calin Juravle0c25d102015-04-20 14:49:09 +0100728static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, const CompilerDriver& driver) {
Calin Juravle27df7582015-04-17 19:12:31 +0100729 Thread* self = Thread::Current();
Calin Juravle0c25d102015-04-20 14:49:09 +0100730 return cu->IsConstructor()
731 && driver.RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex());
Calin Juravle27df7582015-04-17 19:12:31 +0100732}
733
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600734void HGraphBuilder::BuildReturn(const Instruction& instruction,
735 Primitive::Type type,
736 uint32_t dex_pc) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100737 if (type == Primitive::kPrimVoid) {
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100738 if (graph_->ShouldGenerateConstructorBarrier()) {
739 // The compilation unit is null during testing.
740 if (dex_compilation_unit_ != nullptr) {
741 DCHECK(RequiresConstructorBarrier(dex_compilation_unit_, *compiler_driver_))
742 << "Inconsistent use of ShouldGenerateConstructorBarrier. Should not generate a barrier.";
743 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600744 current_block_->AddInstruction(new (arena_) HMemoryBarrier(kStoreStore, dex_pc));
Calin Juravle27df7582015-04-17 19:12:31 +0100745 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600746 current_block_->AddInstruction(new (arena_) HReturnVoid(dex_pc));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100747 } else {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +0600748 HInstruction* value = LoadLocal(instruction.VRegA(), type, dex_pc);
749 current_block_->AddInstruction(new (arena_) HReturn(value, dex_pc));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100750 }
751 current_block_->AddSuccessor(exit_block_);
752 current_block_ = nullptr;
753}
754
Calin Juravle68ad6492015-08-18 17:08:12 +0100755static InvokeType GetInvokeTypeFromOpCode(Instruction::Code opcode) {
756 switch (opcode) {
757 case Instruction::INVOKE_STATIC:
758 case Instruction::INVOKE_STATIC_RANGE:
759 return kStatic;
760 case Instruction::INVOKE_DIRECT:
761 case Instruction::INVOKE_DIRECT_RANGE:
762 return kDirect;
763 case Instruction::INVOKE_VIRTUAL:
764 case Instruction::INVOKE_VIRTUAL_QUICK:
765 case Instruction::INVOKE_VIRTUAL_RANGE:
766 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
767 return kVirtual;
768 case Instruction::INVOKE_INTERFACE:
769 case Instruction::INVOKE_INTERFACE_RANGE:
770 return kInterface;
771 case Instruction::INVOKE_SUPER_RANGE:
772 case Instruction::INVOKE_SUPER:
773 return kSuper;
774 default:
775 LOG(FATAL) << "Unexpected invoke opcode: " << opcode;
776 UNREACHABLE();
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100777 }
Calin Juravle68ad6492015-08-18 17:08:12 +0100778}
779
780bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
781 uint32_t dex_pc,
782 uint32_t method_idx,
783 uint32_t number_of_vreg_arguments,
784 bool is_range,
785 uint32_t* args,
786 uint32_t register_index) {
787 InvokeType original_invoke_type = GetInvokeTypeFromOpCode(instruction.Opcode());
788 InvokeType optimized_invoke_type = original_invoke_type;
789 const char* descriptor = dex_file_->GetMethodShorty(method_idx);
790 Primitive::Type return_type = Primitive::GetType(descriptor[0]);
791
792 // Remove the return type from the 'proto'.
793 size_t number_of_arguments = strlen(descriptor) - 1;
794 if (original_invoke_type != kStatic) { // instance call
795 // One extra argument for 'this'.
796 number_of_arguments++;
797 }
798
799 MethodReference target_method(dex_file_, method_idx);
800 int32_t table_index;
801 uintptr_t direct_code;
802 uintptr_t direct_method;
803
804 if (!compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_,
805 dex_pc,
806 true /* update_stats */,
807 true /* enable_devirtualization */,
808 &optimized_invoke_type,
809 &target_method,
810 &table_index,
811 &direct_code,
812 &direct_method)) {
813 VLOG(compiler) << "Did not compile "
814 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
815 << " because a method call could not be resolved";
816 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedMethod);
817 return false;
818 }
819
820 DCHECK(optimized_invoke_type != kSuper);
821
822 // Special handling for string init.
823 int32_t string_init_offset = 0;
824 bool is_string_init = compiler_driver_->IsStringInit(method_idx, dex_file_,
825 &string_init_offset);
826
827 // Potential class initialization check, in the case of a static method call.
828 HClinitCheck* clinit_check = nullptr;
829 HInvoke* invoke = nullptr;
830
831 if (is_string_init
832 || optimized_invoke_type == kDirect
833 || optimized_invoke_type == kStatic) {
834 // By default, consider that the called method implicitly requires
835 // an initialization check of its declaring method.
836 HInvokeStaticOrDirect::ClinitCheckRequirement clinit_check_requirement
837 = HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit;
838 if (optimized_invoke_type == kStatic && !is_string_init) {
839 clinit_check = ProcessClinitCheckForInvoke(dex_pc, method_idx, &clinit_check_requirement);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100840 }
Calin Juravle68ad6492015-08-18 17:08:12 +0100841
842 // Replace calls to String.<init> with StringFactory.
843 if (is_string_init) {
844 return_type = Primitive::kPrimNot;
845 number_of_arguments--;
846 optimized_invoke_type = kStatic;
847 }
848
849 HInvokeStaticOrDirect::DispatchInfo dispatch_info = ComputeDispatchInfo(is_string_init,
850 string_init_offset,
851 target_method,
852 direct_method,
853 direct_code);
854 invoke = new (arena_) HInvokeStaticOrDirect(arena_,
855 number_of_arguments,
856 return_type,
857 dex_pc,
858 method_idx,
859 target_method,
860 dispatch_info,
861 original_invoke_type,
862 optimized_invoke_type,
863 clinit_check_requirement);
864 } else if (optimized_invoke_type == kVirtual) {
865 invoke = new (arena_) HInvokeVirtual(arena_,
866 number_of_arguments,
867 return_type,
868 dex_pc,
869 method_idx,
870 table_index);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100871 } else {
Calin Juravle68ad6492015-08-18 17:08:12 +0100872 DCHECK_EQ(optimized_invoke_type, kInterface);
873 invoke = new (arena_) HInvokeInterface(arena_,
874 number_of_arguments,
875 return_type,
876 dex_pc,
877 method_idx,
878 table_index);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100879 }
Calin Juravle68ad6492015-08-18 17:08:12 +0100880
Calin Juravle0eedd7e2015-08-20 14:48:00 +0100881 return SetupArgumentsAndAddInvoke(invoke,
882 number_of_vreg_arguments,
883 args,
884 register_index,
885 is_range,
886 descriptor,
Calin Juravle599262c2015-08-20 15:01:27 +0100887 clinit_check);
Calin Juravle68ad6492015-08-18 17:08:12 +0100888}
889
890HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(
891 uint32_t dex_pc,
892 uint32_t method_idx,
893 HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) {
894 ScopedObjectAccess soa(Thread::Current());
895 StackHandleScope<4> hs(soa.Self());
896 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
897 dex_compilation_unit_->GetClassLinker()->FindDexCache(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -0700898 soa.Self(), *dex_compilation_unit_->GetDexFile())));
Calin Juravle68ad6492015-08-18 17:08:12 +0100899 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
900 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
901 ArtMethod* resolved_method = compiler_driver_->ResolveMethod(
902 soa, dex_cache, class_loader, dex_compilation_unit_, method_idx, InvokeType::kStatic);
903
904 DCHECK(resolved_method != nullptr);
905
906 const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
907 Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -0700908 outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file)));
Calin Juravle68ad6492015-08-18 17:08:12 +0100909 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
910
911 // The index at which the method's class is stored in the DexCache's type array.
912 uint32_t storage_index = DexFile::kDexNoIndex;
913 bool is_outer_class = (resolved_method->GetDeclaringClass() == outer_class.Get());
914 if (is_outer_class) {
915 storage_index = outer_class->GetDexTypeIndex();
916 } else if (outer_dex_cache.Get() == dex_cache.Get()) {
917 // Get `storage_index` from IsClassOfStaticMethodAvailableToReferrer.
918 compiler_driver_->IsClassOfStaticMethodAvailableToReferrer(outer_dex_cache.Get(),
919 GetCompilingClass(),
920 resolved_method,
921 method_idx,
922 &storage_index);
923 }
924
925 HClinitCheck* clinit_check = nullptr;
926
927 if (!outer_class->IsInterface()
928 && outer_class->IsSubClass(resolved_method->GetDeclaringClass())) {
929 // If the outer class is the declaring class or a subclass
930 // of the declaring class, no class initialization is needed
931 // before the static method call.
932 // Note that in case of inlining, we do not need to add clinit checks
933 // to calls that satisfy this subclass check with any inlined methods. This
934 // will be detected by the optimization passes.
935 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
936 } else if (storage_index != DexFile::kDexNoIndex) {
937 // If the method's class type index is available, check
938 // whether we should add an explicit class initialization
939 // check for its declaring class before the static method call.
940
941 // TODO: find out why this check is needed.
942 bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
943 *outer_compilation_unit_->GetDexFile(), storage_index);
944 bool is_initialized =
945 resolved_method->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
946
947 if (is_initialized) {
948 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
949 } else {
950 *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
951 HLoadClass* load_class = new (arena_) HLoadClass(
952 graph_->GetCurrentMethod(),
953 storage_index,
954 *dex_compilation_unit_->GetDexFile(),
955 is_outer_class,
956 dex_pc);
957 current_block_->AddInstruction(load_class);
958 clinit_check = new (arena_) HClinitCheck(load_class, dex_pc);
959 current_block_->AddInstruction(clinit_check);
960 }
961 }
962 return clinit_check;
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +0100963}
964
Vladimir Marko58155012015-08-19 12:49:41 +0000965HInvokeStaticOrDirect::DispatchInfo HGraphBuilder::ComputeDispatchInfo(
966 bool is_string_init,
967 int32_t string_init_offset,
968 MethodReference target_method,
969 uintptr_t direct_method,
970 uintptr_t direct_code) {
971 HInvokeStaticOrDirect::MethodLoadKind method_load_kind;
972 HInvokeStaticOrDirect::CodePtrLocation code_ptr_location;
973 uint64_t method_load_data = 0u;
974 uint64_t direct_code_ptr = 0u;
975
976 if (is_string_init) {
977 // TODO: Use direct_method and direct_code for the appropriate StringFactory method.
978 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kStringInit;
979 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
980 method_load_data = string_init_offset;
981 } else if (target_method.dex_file == outer_compilation_unit_->GetDexFile() &&
982 target_method.dex_method_index == outer_compilation_unit_->GetDexMethodIndex()) {
983 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRecursive;
984 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallSelf;
985 } else {
986 if (direct_method != 0u) { // Should we use a direct pointer to the method?
987 if (direct_method != static_cast<uintptr_t>(-1)) { // Is the method pointer known now?
988 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress;
989 method_load_data = direct_method;
990 } else { // The direct pointer will be known at link time.
991 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddressWithFixup;
992 }
993 } else { // Use dex cache.
994 DCHECK(target_method.dex_file == dex_compilation_unit_->GetDexFile());
995 DexCacheArraysLayout layout =
996 compiler_driver_->GetDexCacheArraysLayout(target_method.dex_file);
997 if (layout.Valid()) { // Can we use PC-relative access to the dex cache arrays?
998 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCachePcRelative;
999 method_load_data = layout.MethodOffset(target_method.dex_method_index);
1000 } else { // We must go through the ArtMethod's pointer to resolved methods.
1001 method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDexCacheViaMethod;
1002 }
1003 }
1004 if (direct_code != 0u) { // Should we use a direct pointer to the code?
1005 if (direct_code != static_cast<uintptr_t>(-1)) { // Is the code pointer known now?
1006 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallDirect;
1007 direct_code_ptr = direct_code;
1008 } else if (compiler_driver_->IsImage() ||
1009 target_method.dex_file == dex_compilation_unit_->GetDexFile()) {
1010 // Use PC-relative calls for invokes within a multi-dex oat file.
1011 // TODO: Recognize when the target dex file is within the current oat file for
1012 // app compilation. At the moment we recognize only the boot image as multi-dex.
1013 // NOTE: This will require changing the ARM backend which currently falls
1014 // through from kCallPCRelative to kDirectCodeFixup for different dex files.
1015 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallPCRelative;
1016 } else { // The direct pointer will be known at link time.
1017 // NOTE: This is used for app->boot calls when compiling an app against
1018 // a relocatable but not yet relocated image.
1019 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallDirectWithFixup;
1020 }
1021 } else { // We must use the code pointer from the ArtMethod.
1022 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
1023 }
1024 }
1025
1026 if (graph_->IsDebuggable()) {
1027 // For debuggable apps always use the code pointer from ArtMethod
1028 // so that we don't circumvent instrumentation stubs if installed.
1029 code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
1030 }
1031
1032 return HInvokeStaticOrDirect::DispatchInfo {
1033 method_load_kind, code_ptr_location, method_load_data, direct_code_ptr };
1034}
1035
Calin Juravle0eedd7e2015-08-20 14:48:00 +01001036bool HGraphBuilder::SetupArgumentsAndAddInvoke(HInvoke* invoke,
1037 uint32_t number_of_vreg_arguments,
1038 uint32_t* args,
1039 uint32_t register_index,
1040 bool is_range,
1041 const char* descriptor,
1042 HClinitCheck* clinit_check) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001043 size_t start_index = 0;
Calin Juravle68ad6492015-08-18 17:08:12 +01001044 size_t argument_index = 0;
1045 uint32_t descriptor_index = 1; // Skip the return type.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001046 uint32_t dex_pc = invoke->GetDexPc();
Calin Juravle68ad6492015-08-18 17:08:12 +01001047
1048 bool is_instance_call = invoke->GetOriginalInvokeType() != InvokeType::kStatic;
1049 bool is_string_init = invoke->IsInvokeStaticOrDirect()
1050 && invoke->AsInvokeStaticOrDirect()->IsStringInit();
1051
1052 if (is_string_init) {
1053 start_index = 1;
1054 argument_index = 0;
1055 } else if (is_instance_call) {
1056 Temporaries temps(graph_);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001057 HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot, dex_pc);
Calin Juravle68ad6492015-08-18 17:08:12 +01001058 HNullCheck* null_check = new (arena_) HNullCheck(arg, invoke->GetDexPc());
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +01001059 current_block_->AddInstruction(null_check);
1060 temps.Add(null_check);
1061 invoke->SetArgumentAt(0, null_check);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001062 start_index = 1;
Calin Juravle68ad6492015-08-18 17:08:12 +01001063 argument_index = 1;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001064 }
1065
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001066 for (size_t i = start_index;
1067 // Make sure we don't go over the expected arguments or over the number of
1068 // dex registers given. If the instruction was seen as dead by the verifier,
1069 // it hasn't been properly checked.
Calin Juravle68ad6492015-08-18 17:08:12 +01001070 (i < number_of_vreg_arguments) && (argument_index < invoke->GetNumberOfArguments());
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001071 i++, argument_index++) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001072 Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001073 bool is_wide = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble);
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001074 if (!is_range
1075 && is_wide
1076 && ((i + 1 == number_of_vreg_arguments) || (args[i] + 1 != args[i + 1]))) {
1077 // Longs and doubles should be in pairs, that is, sequential registers. The verifier should
1078 // reject any class where this is violated. However, the verifier only does these checks
1079 // on non trivially dead instructions, so we just bailout the compilation.
1080 VLOG(compiler) << "Did not compile "
1081 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
1082 << " because of non-sequential dex register pair in wide argument";
1083 MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode);
1084 return false;
1085 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001086 HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type, dex_pc);
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001087 invoke->SetArgumentAt(argument_index, arg);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001088 if (is_wide) {
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001089 i++;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001090 }
1091 }
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001092
Calin Juravle68ad6492015-08-18 17:08:12 +01001093 if (argument_index != invoke->GetNumberOfArguments()) {
Nicolas Geoffray2e335252015-06-18 11:11:27 +01001094 VLOG(compiler) << "Did not compile "
1095 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
1096 << " because of wrong number of arguments in invoke instruction";
1097 MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode);
1098 return false;
1099 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001100
Nicolas Geoffray38207af2015-06-01 15:46:22 +01001101 if (invoke->IsInvokeStaticOrDirect()) {
1102 invoke->SetArgumentAt(argument_index, graph_->GetCurrentMethod());
1103 argument_index++;
1104 }
1105
Calin Juravle68ad6492015-08-18 17:08:12 +01001106 if (clinit_check != nullptr) {
Roland Levillain4c0eb422015-04-24 16:43:49 +01001107 // Add the class initialization check as last input of `invoke`.
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01001108 DCHECK(!is_string_init);
Calin Juravle68ad6492015-08-18 17:08:12 +01001109 DCHECK(invoke->IsInvokeStaticOrDirect());
1110 DCHECK(invoke->AsInvokeStaticOrDirect()->GetClinitCheckRequirement()
1111 == HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit);
Roland Levillain3e3d7332015-04-28 11:00:54 +01001112 invoke->SetArgumentAt(argument_index, clinit_check);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01001113 argument_index++;
Roland Levillain4c0eb422015-04-24 16:43:49 +01001114 }
1115
Jeff Hao848f70a2014-01-15 13:49:50 -08001116 // Add move-result for StringFactory method.
1117 if (is_string_init) {
1118 uint32_t orig_this_reg = is_range ? register_index : args[0];
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001119 HInstruction* fake_string = LoadLocal(orig_this_reg, Primitive::kPrimNot, dex_pc);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01001120 invoke->SetArgumentAt(argument_index, fake_string);
Calin Juravle0eedd7e2015-08-20 14:48:00 +01001121 current_block_->AddInstruction(invoke);
Calin Juravle68ad6492015-08-18 17:08:12 +01001122 PotentiallySimplifyFakeString(orig_this_reg, invoke->GetDexPc(), invoke);
Calin Juravle0eedd7e2015-08-20 14:48:00 +01001123 } else {
1124 current_block_->AddInstruction(invoke);
Jeff Hao848f70a2014-01-15 13:49:50 -08001125 }
Calin Juravle0eedd7e2015-08-20 14:48:00 +01001126
1127 latest_result_ = invoke;
1128
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001129 return true;
1130}
1131
Calin Juravle68ad6492015-08-18 17:08:12 +01001132void HGraphBuilder::PotentiallySimplifyFakeString(uint16_t original_dex_register,
1133 uint32_t dex_pc,
1134 HInvoke* actual_string) {
1135 if (!graph_->IsDebuggable()) {
1136 // Notify that we cannot compile with baseline. The dex registers aliasing
1137 // with `original_dex_register` will be handled when we optimize
1138 // (see HInstructionSimplifer::VisitFakeString).
1139 can_use_baseline_for_string_init_ = false;
1140 return;
1141 }
1142 const VerifiedMethod* verified_method =
1143 compiler_driver_->GetVerifiedMethod(dex_file_, dex_compilation_unit_->GetDexMethodIndex());
1144 if (verified_method != nullptr) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001145 UpdateLocal(original_dex_register, actual_string, dex_pc);
Calin Juravle68ad6492015-08-18 17:08:12 +01001146 const SafeMap<uint32_t, std::set<uint32_t>>& string_init_map =
1147 verified_method->GetStringInitPcRegMap();
1148 auto map_it = string_init_map.find(dex_pc);
1149 if (map_it != string_init_map.end()) {
1150 std::set<uint32_t> reg_set = map_it->second;
1151 for (auto set_it = reg_set.begin(); set_it != reg_set.end(); ++set_it) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001152 HInstruction* load_local = LoadLocal(original_dex_register, Primitive::kPrimNot, dex_pc);
1153 UpdateLocal(*set_it, load_local, dex_pc);
Calin Juravle68ad6492015-08-18 17:08:12 +01001154 }
1155 }
1156 } else {
1157 can_use_baseline_for_string_init_ = false;
1158 }
1159}
1160
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001161bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +00001162 uint32_t dex_pc,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001163 bool is_put) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001164 uint32_t source_or_dest_reg = instruction.VRegA_22c();
1165 uint32_t obj_reg = instruction.VRegB_22c();
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001166 uint16_t field_index;
1167 if (instruction.IsQuickened()) {
1168 if (!CanDecodeQuickenedInfo()) {
1169 return false;
1170 }
1171 field_index = LookupQuickenedInfo(dex_pc);
1172 } else {
1173 field_index = instruction.VRegC_22c();
1174 }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001175
1176 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartierc7853442015-03-27 14:35:38 -07001177 ArtField* resolved_field =
1178 compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001179
Mathieu Chartierc7853442015-03-27 14:35:38 -07001180 if (resolved_field == nullptr) {
Calin Juravle48c2b032014-12-09 18:11:36 +00001181 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001182 return false;
1183 }
Calin Juravle52c48962014-12-16 17:02:57 +00001184
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001185 Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001186
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001187 HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot, dex_pc);
Calin Juravle225ff812014-11-13 16:46:39 +00001188 current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_pc));
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001189 if (is_put) {
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001190 Temporaries temps(graph_);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001191 HInstruction* null_check = current_block_->GetLastInstruction();
1192 // We need one temporary for the null check.
1193 temps.Add(null_check);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001194 HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001195 current_block_->AddInstruction(new (arena_) HInstanceFieldSet(
1196 null_check,
1197 value,
Nicolas Geoffray39468442014-09-02 15:17:15 +01001198 field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00001199 resolved_field->GetOffset(),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001200 resolved_field->IsVolatile(),
1201 field_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07001202 *dex_file_,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001203 dex_compilation_unit_->GetDexCache(),
1204 dex_pc));
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001205 } else {
1206 current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
1207 current_block_->GetLastInstruction(),
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001208 field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00001209 resolved_field->GetOffset(),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001210 resolved_field->IsVolatile(),
1211 field_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07001212 *dex_file_,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001213 dex_compilation_unit_->GetDexCache(),
1214 dex_pc));
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001215
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001216 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001217 }
1218 return true;
1219}
1220
Nicolas Geoffray30451742015-06-19 13:32:41 +01001221static mirror::Class* GetClassFrom(CompilerDriver* driver,
1222 const DexCompilationUnit& compilation_unit) {
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001223 ScopedObjectAccess soa(Thread::Current());
1224 StackHandleScope<2> hs(soa.Self());
Nicolas Geoffray30451742015-06-19 13:32:41 +01001225 const DexFile& dex_file = *compilation_unit.GetDexFile();
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001226 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
Nicolas Geoffray30451742015-06-19 13:32:41 +01001227 soa.Decode<mirror::ClassLoader*>(compilation_unit.GetClassLoader())));
1228 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -07001229 compilation_unit.GetClassLinker()->FindDexCache(soa.Self(), dex_file)));
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001230
Nicolas Geoffray30451742015-06-19 13:32:41 +01001231 return driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, &compilation_unit);
1232}
1233
1234mirror::Class* HGraphBuilder::GetOutermostCompilingClass() const {
1235 return GetClassFrom(compiler_driver_, *outer_compilation_unit_);
1236}
1237
1238mirror::Class* HGraphBuilder::GetCompilingClass() const {
1239 return GetClassFrom(compiler_driver_, *dex_compilation_unit_);
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001240}
1241
1242bool HGraphBuilder::IsOutermostCompilingClass(uint16_t type_index) const {
1243 ScopedObjectAccess soa(Thread::Current());
1244 StackHandleScope<4> hs(soa.Self());
1245 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -07001246 dex_compilation_unit_->GetClassLinker()->FindDexCache(
1247 soa.Self(), *dex_compilation_unit_->GetDexFile())));
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001248 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
1249 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
1250 Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass(
1251 soa, dex_cache, class_loader, type_index, dex_compilation_unit_)));
Nicolas Geoffrayafd06412015-06-20 22:44:47 +01001252 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001253
Nicolas Geoffrayafd06412015-06-20 22:44:47 +01001254 return outer_class.Get() == cls.Get();
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001255}
1256
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001257bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +00001258 uint32_t dex_pc,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001259 bool is_put) {
1260 uint32_t source_or_dest_reg = instruction.VRegA_21c();
1261 uint16_t field_index = instruction.VRegB_21c();
1262
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001263 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartierc7853442015-03-27 14:35:38 -07001264 StackHandleScope<4> hs(soa.Self());
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001265 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -07001266 dex_compilation_unit_->GetClassLinker()->FindDexCache(
1267 soa.Self(), *dex_compilation_unit_->GetDexFile())));
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001268 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
1269 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
Mathieu Chartierc7853442015-03-27 14:35:38 -07001270 ArtField* resolved_field = compiler_driver_->ResolveField(
1271 soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001272
Mathieu Chartierc7853442015-03-27 14:35:38 -07001273 if (resolved_field == nullptr) {
Calin Juravle48c2b032014-12-09 18:11:36 +00001274 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001275 return false;
1276 }
1277
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001278 const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
1279 Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
Mathieu Chartier673ed3d2015-08-28 14:56:43 -07001280 outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file)));
Nicolas Geoffray30451742015-06-19 13:32:41 +01001281 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001282
1283 // The index at which the field's class is stored in the DexCache's type array.
1284 uint32_t storage_index;
Nicolas Geoffray30451742015-06-19 13:32:41 +01001285 bool is_outer_class = (outer_class.Get() == resolved_field->GetDeclaringClass());
1286 if (is_outer_class) {
1287 storage_index = outer_class->GetDexTypeIndex();
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001288 } else if (outer_dex_cache.Get() != dex_cache.Get()) {
Roland Levillain4c0eb422015-04-24 16:43:49 +01001289 // The compiler driver cannot currently understand multiple dex caches involved. Just bailout.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001290 return false;
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001291 } else {
1292 std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField(
1293 outer_dex_cache.Get(),
Nicolas Geoffray30451742015-06-19 13:32:41 +01001294 GetCompilingClass(),
Mathieu Chartierc7853442015-03-27 14:35:38 -07001295 resolved_field,
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001296 field_index,
1297 &storage_index);
1298 bool can_easily_access = is_put ? pair.second : pair.first;
1299 if (!can_easily_access) {
1300 return false;
1301 }
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001302 }
1303
1304 // TODO: find out why this check is needed.
1305 bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
Nicolas Geoffray6a816cf2015-03-24 16:17:56 +00001306 *outer_compilation_unit_->GetDexFile(), storage_index);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001307 bool is_initialized = resolved_field->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001308
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001309 HLoadClass* constant = new (arena_) HLoadClass(graph_->GetCurrentMethod(),
1310 storage_index,
1311 *dex_compilation_unit_->GetDexFile(),
Nicolas Geoffray30451742015-06-19 13:32:41 +01001312 is_outer_class,
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001313 dex_pc);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001314 current_block_->AddInstruction(constant);
1315
1316 HInstruction* cls = constant;
Nicolas Geoffray30451742015-06-19 13:32:41 +01001317 if (!is_initialized && !is_outer_class) {
Calin Juravle225ff812014-11-13 16:46:39 +00001318 cls = new (arena_) HClinitCheck(constant, dex_pc);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001319 current_block_->AddInstruction(cls);
1320 }
1321
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001322 Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001323 if (is_put) {
1324 // We need to keep the class alive before loading the value.
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001325 Temporaries temps(graph_);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001326 temps.Add(cls);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001327 HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001328 DCHECK_EQ(value->GetType(), field_type);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001329 current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls,
1330 value,
1331 field_type,
1332 resolved_field->GetOffset(),
1333 resolved_field->IsVolatile(),
1334 field_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07001335 *dex_file_,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001336 dex_cache_,
1337 dex_pc));
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001338 } else {
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001339 current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls,
1340 field_type,
1341 resolved_field->GetOffset(),
1342 resolved_field->IsVolatile(),
1343 field_index,
Mathieu Chartier736b5602015-09-02 14:54:11 -07001344 *dex_file_,
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001345 dex_cache_,
1346 dex_pc));
1347 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001348 }
1349 return true;
1350}
1351
Calin Juravlebacfec32014-11-14 15:54:36 +00001352void HGraphBuilder::BuildCheckedDivRem(uint16_t out_vreg,
1353 uint16_t first_vreg,
1354 int64_t second_vreg_or_constant,
1355 uint32_t dex_pc,
1356 Primitive::Type type,
1357 bool second_is_constant,
1358 bool isDiv) {
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001359 DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
Calin Juravled0d48522014-11-04 16:40:20 +00001360
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001361 HInstruction* first = LoadLocal(first_vreg, type, dex_pc);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001362 HInstruction* second = nullptr;
1363 if (second_is_constant) {
1364 if (type == Primitive::kPrimInt) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001365 second = graph_->GetIntConstant(second_vreg_or_constant, dex_pc);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001366 } else {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001367 second = graph_->GetLongConstant(second_vreg_or_constant, dex_pc);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001368 }
1369 } else {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001370 second = LoadLocal(second_vreg_or_constant, type, dex_pc);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001371 }
1372
1373 if (!second_is_constant
1374 || (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0)
1375 || (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) {
1376 second = new (arena_) HDivZeroCheck(second, dex_pc);
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001377 Temporaries temps(graph_);
Calin Juravled0d48522014-11-04 16:40:20 +00001378 current_block_->AddInstruction(second);
1379 temps.Add(current_block_->GetLastInstruction());
1380 }
1381
Calin Juravlebacfec32014-11-14 15:54:36 +00001382 if (isDiv) {
1383 current_block_->AddInstruction(new (arena_) HDiv(type, first, second, dex_pc));
1384 } else {
1385 current_block_->AddInstruction(new (arena_) HRem(type, first, second, dex_pc));
1386 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001387 UpdateLocal(out_vreg, current_block_->GetLastInstruction(), dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001388}
1389
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001390void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +00001391 uint32_t dex_pc,
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001392 bool is_put,
1393 Primitive::Type anticipated_type) {
1394 uint8_t source_or_dest_reg = instruction.VRegA_23x();
1395 uint8_t array_reg = instruction.VRegB_23x();
1396 uint8_t index_reg = instruction.VRegC_23x();
1397
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001398 // We need one temporary for the null check, one for the index, and one for the length.
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001399 Temporaries temps(graph_);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001400
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001401 HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot, dex_pc);
Calin Juravle225ff812014-11-13 16:46:39 +00001402 object = new (arena_) HNullCheck(object, dex_pc);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001403 current_block_->AddInstruction(object);
1404 temps.Add(object);
1405
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001406 HInstruction* length = new (arena_) HArrayLength(object, dex_pc);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001407 current_block_->AddInstruction(length);
1408 temps.Add(length);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001409 HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt, dex_pc);
Calin Juravle225ff812014-11-13 16:46:39 +00001410 index = new (arena_) HBoundsCheck(index, length, dex_pc);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001411 current_block_->AddInstruction(index);
1412 temps.Add(index);
1413 if (is_put) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001414 HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type, dex_pc);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001415 // TODO: Insert a type check node if the type is Object.
Nicolas Geoffray39468442014-09-02 15:17:15 +01001416 current_block_->AddInstruction(new (arena_) HArraySet(
Calin Juravle225ff812014-11-13 16:46:39 +00001417 object, index, value, anticipated_type, dex_pc));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001418 } else {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001419 current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type, dex_pc));
1420 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001421 }
Mark Mendell1152c922015-04-24 17:06:35 -04001422 graph_->SetHasBoundsChecks(true);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001423}
1424
Calin Juravle225ff812014-11-13 16:46:39 +00001425void HGraphBuilder::BuildFilledNewArray(uint32_t dex_pc,
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001426 uint32_t type_index,
1427 uint32_t number_of_vreg_arguments,
1428 bool is_range,
1429 uint32_t* args,
1430 uint32_t register_index) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001431 HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments, dex_pc);
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001432 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
1433 ? kQuickAllocArrayWithAccessCheck
1434 : kQuickAllocArray;
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01001435 HInstruction* object = new (arena_) HNewArray(length,
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01001436 graph_->GetCurrentMethod(),
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01001437 dex_pc,
1438 type_index,
1439 *dex_compilation_unit_->GetDexFile(),
1440 entrypoint);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001441 current_block_->AddInstruction(object);
1442
1443 const char* descriptor = dex_file_->StringByTypeIdx(type_index);
1444 DCHECK_EQ(descriptor[0], '[') << descriptor;
1445 char primitive = descriptor[1];
1446 DCHECK(primitive == 'I'
1447 || primitive == 'L'
1448 || primitive == '[') << descriptor;
1449 bool is_reference_array = (primitive == 'L') || (primitive == '[');
1450 Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt;
1451
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001452 Temporaries temps(graph_);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001453 temps.Add(object);
1454 for (size_t i = 0; i < number_of_vreg_arguments; ++i) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001455 HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type, dex_pc);
1456 HInstruction* index = graph_->GetIntConstant(i, dex_pc);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001457 current_block_->AddInstruction(
Calin Juravle225ff812014-11-13 16:46:39 +00001458 new (arena_) HArraySet(object, index, value, type, dex_pc));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001459 }
1460 latest_result_ = object;
1461}
1462
1463template <typename T>
1464void HGraphBuilder::BuildFillArrayData(HInstruction* object,
1465 const T* data,
1466 uint32_t element_count,
1467 Primitive::Type anticipated_type,
Calin Juravle225ff812014-11-13 16:46:39 +00001468 uint32_t dex_pc) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001469 for (uint32_t i = 0; i < element_count; ++i) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001470 HInstruction* index = graph_->GetIntConstant(i, dex_pc);
1471 HInstruction* value = graph_->GetIntConstant(data[i], dex_pc);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001472 current_block_->AddInstruction(new (arena_) HArraySet(
Calin Juravle225ff812014-11-13 16:46:39 +00001473 object, index, value, anticipated_type, dex_pc));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001474 }
1475}
1476
Calin Juravle225ff812014-11-13 16:46:39 +00001477void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) {
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001478 Temporaries temps(graph_);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001479 HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot, dex_pc);
Calin Juravle225ff812014-11-13 16:46:39 +00001480 HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001481 current_block_->AddInstruction(null_check);
1482 temps.Add(null_check);
1483
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001484 HInstruction* length = new (arena_) HArrayLength(null_check, dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001485 current_block_->AddInstruction(length);
1486
Calin Juravle225ff812014-11-13 16:46:39 +00001487 int32_t payload_offset = instruction.VRegB_31t() + dex_pc;
Calin Juravled0d48522014-11-04 16:40:20 +00001488 const Instruction::ArrayDataPayload* payload =
1489 reinterpret_cast<const Instruction::ArrayDataPayload*>(code_start_ + payload_offset);
1490 const uint8_t* data = payload->data;
1491 uint32_t element_count = payload->element_count;
1492
1493 // Implementation of this DEX instruction seems to be that the bounds check is
1494 // done before doing any stores.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001495 HInstruction* last_index = graph_->GetIntConstant(payload->element_count - 1, dex_pc);
Calin Juravle225ff812014-11-13 16:46:39 +00001496 current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_pc));
Calin Juravled0d48522014-11-04 16:40:20 +00001497
1498 switch (payload->element_width) {
1499 case 1:
1500 BuildFillArrayData(null_check,
1501 reinterpret_cast<const int8_t*>(data),
1502 element_count,
1503 Primitive::kPrimByte,
Calin Juravle225ff812014-11-13 16:46:39 +00001504 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001505 break;
1506 case 2:
1507 BuildFillArrayData(null_check,
1508 reinterpret_cast<const int16_t*>(data),
1509 element_count,
1510 Primitive::kPrimShort,
Calin Juravle225ff812014-11-13 16:46:39 +00001511 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001512 break;
1513 case 4:
1514 BuildFillArrayData(null_check,
1515 reinterpret_cast<const int32_t*>(data),
1516 element_count,
1517 Primitive::kPrimInt,
Calin Juravle225ff812014-11-13 16:46:39 +00001518 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001519 break;
1520 case 8:
1521 BuildFillWideArrayData(null_check,
1522 reinterpret_cast<const int64_t*>(data),
1523 element_count,
Calin Juravle225ff812014-11-13 16:46:39 +00001524 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001525 break;
1526 default:
1527 LOG(FATAL) << "Unknown element width for " << payload->element_width;
1528 }
Mark Mendell1152c922015-04-24 17:06:35 -04001529 graph_->SetHasBoundsChecks(true);
Calin Juravled0d48522014-11-04 16:40:20 +00001530}
1531
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001532void HGraphBuilder::BuildFillWideArrayData(HInstruction* object,
Nicolas Geoffray8d6ae522014-10-23 18:32:13 +01001533 const int64_t* data,
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001534 uint32_t element_count,
Calin Juravle225ff812014-11-13 16:46:39 +00001535 uint32_t dex_pc) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001536 for (uint32_t i = 0; i < element_count; ++i) {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001537 HInstruction* index = graph_->GetIntConstant(i, dex_pc);
1538 HInstruction* value = graph_->GetLongConstant(data[i], dex_pc);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001539 current_block_->AddInstruction(new (arena_) HArraySet(
Calin Juravle225ff812014-11-13 16:46:39 +00001540 object, index, value, Primitive::kPrimLong, dex_pc));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001541 }
1542}
1543
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001544bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction,
1545 uint8_t destination,
1546 uint8_t reference,
1547 uint16_t type_index,
Calin Juravle225ff812014-11-13 16:46:39 +00001548 uint32_t dex_pc) {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001549 bool type_known_final;
1550 bool type_known_abstract;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001551 // `CanAccessTypeWithoutChecks` will tell whether the method being
1552 // built is trying to access its own class, so that the generated
1553 // code can optimize for this case. However, the optimization does not
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001554 // work for inlining, so we use `IsOutermostCompilingClass` instead.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001555 bool dont_use_is_referrers_class;
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001556 bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
1557 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001558 &type_known_final, &type_known_abstract, &dont_use_is_referrers_class);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001559 if (!can_access) {
Calin Juravle48c2b032014-12-09 18:11:36 +00001560 MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001561 return false;
1562 }
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001563 HInstruction* object = LoadLocal(reference, Primitive::kPrimNot, dex_pc);
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001564 HLoadClass* cls = new (arena_) HLoadClass(
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001565 graph_->GetCurrentMethod(),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01001566 type_index,
1567 *dex_compilation_unit_->GetDexFile(),
1568 IsOutermostCompilingClass(type_index),
1569 dex_pc);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001570 current_block_->AddInstruction(cls);
1571 // The class needs a temporary before being used by the type check.
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001572 Temporaries temps(graph_);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001573 temps.Add(cls);
1574 if (instruction.Opcode() == Instruction::INSTANCE_OF) {
1575 current_block_->AddInstruction(
Calin Juravle225ff812014-11-13 16:46:39 +00001576 new (arena_) HInstanceOf(object, cls, type_known_final, dex_pc));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001577 UpdateLocal(destination, current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001578 } else {
1579 DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST);
1580 current_block_->AddInstruction(
Calin Juravle225ff812014-11-13 16:46:39 +00001581 new (arena_) HCheckCast(object, cls, type_known_final, dex_pc));
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001582 }
1583 return true;
1584}
1585
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001586bool HGraphBuilder::NeedsAccessCheck(uint32_t type_index) const {
1587 return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks(
1588 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index);
1589}
1590
Calin Juravle48c2b032014-12-09 18:11:36 +00001591void HGraphBuilder::BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc) {
David Brazdil2ef645b2015-06-17 18:20:52 +01001592 // Verifier guarantees that the payload for PackedSwitch contains:
1593 // (a) number of entries (may be zero)
1594 // (b) first and lowest switch case value (entry 0, always present)
1595 // (c) list of target pcs (entries 1 <= i <= N)
Andreas Gamped881df52014-11-24 23:28:39 -08001596 SwitchTable table(instruction, dex_pc, false);
1597
1598 // Value to test against.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001599 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -08001600
David Brazdil2ef645b2015-06-17 18:20:52 +01001601 // Retrieve number of entries.
Andreas Gampee4d4d322014-12-04 09:09:57 -08001602 uint16_t num_entries = table.GetNumEntries();
David Brazdil2ef645b2015-06-17 18:20:52 +01001603 if (num_entries == 0) {
1604 return;
1605 }
Andreas Gampee4d4d322014-12-04 09:09:57 -08001606
Andreas Gamped881df52014-11-24 23:28:39 -08001607 // Chained cmp-and-branch, starting from starting_key.
1608 int32_t starting_key = table.GetEntryAt(0);
1609
Andreas Gamped881df52014-11-24 23:28:39 -08001610 for (size_t i = 1; i <= num_entries; i++) {
Andreas Gampee4d4d322014-12-04 09:09:57 -08001611 BuildSwitchCaseHelper(instruction, i, i == num_entries, table, value, starting_key + i - 1,
1612 table.GetEntryAt(i), dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -08001613 }
Andreas Gamped881df52014-11-24 23:28:39 -08001614}
1615
Calin Juravle48c2b032014-12-09 18:11:36 +00001616void HGraphBuilder::BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc) {
David Brazdil2ef645b2015-06-17 18:20:52 +01001617 // Verifier guarantees that the payload for SparseSwitch contains:
1618 // (a) number of entries (may be zero)
1619 // (b) sorted key values (entries 0 <= i < N)
1620 // (c) target pcs corresponding to the switch values (entries N <= i < 2*N)
Andreas Gampee4d4d322014-12-04 09:09:57 -08001621 SwitchTable table(instruction, dex_pc, true);
1622
1623 // Value to test against.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001624 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08001625
1626 uint16_t num_entries = table.GetNumEntries();
Andreas Gampee4d4d322014-12-04 09:09:57 -08001627
1628 for (size_t i = 0; i < num_entries; i++) {
1629 BuildSwitchCaseHelper(instruction, i, i == static_cast<size_t>(num_entries) - 1, table, value,
1630 table.GetEntryAt(i), table.GetEntryAt(i + num_entries), dex_pc);
1631 }
Andreas Gampee4d4d322014-12-04 09:09:57 -08001632}
1633
1634void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t index,
1635 bool is_last_case, const SwitchTable& table,
1636 HInstruction* value, int32_t case_value_int,
1637 int32_t target_offset, uint32_t dex_pc) {
David Brazdil852eaff2015-02-02 15:23:05 +00001638 HBasicBlock* case_target = FindBlockStartingAt(dex_pc + target_offset);
1639 DCHECK(case_target != nullptr);
1640 PotentiallyAddSuspendCheck(case_target, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08001641
1642 // The current case's value.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001643 HInstruction* this_case_value = graph_->GetIntConstant(case_value_int, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08001644
1645 // Compare value and this_case_value.
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001646 HEqual* comparison = new (arena_) HEqual(value, this_case_value, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08001647 current_block_->AddInstruction(comparison);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001648 HInstruction* ifinst = new (arena_) HIf(comparison, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08001649 current_block_->AddInstruction(ifinst);
1650
1651 // Case hit: use the target offset to determine where to go.
Andreas Gampee4d4d322014-12-04 09:09:57 -08001652 current_block_->AddSuccessor(case_target);
1653
1654 // Case miss: go to the next case (or default fall-through).
1655 // When there is a next case, we use the block stored with the table offset representing this
1656 // case (that is where we registered them in ComputeBranchTargets).
1657 // When there is no next case, we use the following instruction.
1658 // TODO: Find a good way to peel the last iteration to avoid conditional, but still have re-use.
1659 if (!is_last_case) {
1660 HBasicBlock* next_case_target = FindBlockStartingAt(table.GetDexPcForIndex(index));
1661 DCHECK(next_case_target != nullptr);
1662 current_block_->AddSuccessor(next_case_target);
1663
1664 // Need to manually add the block, as there is no dex-pc transition for the cases.
1665 graph_->AddBlock(next_case_target);
1666
1667 current_block_ = next_case_target;
1668 } else {
1669 HBasicBlock* default_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
1670 DCHECK(default_target != nullptr);
1671 current_block_->AddSuccessor(default_target);
1672 current_block_ = nullptr;
1673 }
1674}
1675
David Brazdil852eaff2015-02-02 15:23:05 +00001676void HGraphBuilder::PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc) {
1677 int32_t target_offset = target->GetDexPc() - dex_pc;
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001678 if (target_offset <= 0) {
David Brazdil852eaff2015-02-02 15:23:05 +00001679 // DX generates back edges to the first encountered return. We can save
1680 // time of later passes by not adding redundant suspend checks.
David Brazdil2fd6aa52015-02-02 18:58:27 +00001681 HInstruction* last_in_target = target->GetLastInstruction();
1682 if (last_in_target != nullptr &&
1683 (last_in_target->IsReturn() || last_in_target->IsReturnVoid())) {
1684 return;
David Brazdil852eaff2015-02-02 15:23:05 +00001685 }
1686
1687 // Add a suspend check to backward branches which may potentially loop. We
1688 // can remove them after we recognize loops in the graph.
Calin Juravle225ff812014-11-13 16:46:39 +00001689 current_block_->AddInstruction(new (arena_) HSuspendCheck(dex_pc));
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001690 }
1691}
1692
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001693bool HGraphBuilder::CanDecodeQuickenedInfo() const {
1694 return interpreter_metadata_ != nullptr;
1695}
1696
1697uint16_t HGraphBuilder::LookupQuickenedInfo(uint32_t dex_pc) {
1698 DCHECK(interpreter_metadata_ != nullptr);
1699 uint32_t dex_pc_in_map = DecodeUnsignedLeb128(&interpreter_metadata_);
1700 DCHECK_EQ(dex_pc, dex_pc_in_map);
1701 return DecodeUnsignedLeb128(&interpreter_metadata_);
1702}
1703
Calin Juravle225ff812014-11-13 16:46:39 +00001704bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001705 if (current_block_ == nullptr) {
1706 return true; // Dead code
1707 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001708
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001709 switch (instruction.Opcode()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001710 case Instruction::CONST_4: {
1711 int32_t register_index = instruction.VRegA();
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001712 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n(), dex_pc);
1713 UpdateLocal(register_index, constant, dex_pc);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001714 break;
1715 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001716
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001717 case Instruction::CONST_16: {
1718 int32_t register_index = instruction.VRegA();
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001719 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s(), dex_pc);
1720 UpdateLocal(register_index, constant, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001721 break;
1722 }
1723
Dave Allison20dfc792014-06-16 20:44:29 -07001724 case Instruction::CONST: {
1725 int32_t register_index = instruction.VRegA();
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001726 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i(), dex_pc);
1727 UpdateLocal(register_index, constant, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -07001728 break;
1729 }
1730
1731 case Instruction::CONST_HIGH16: {
1732 int32_t register_index = instruction.VRegA();
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001733 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16, dex_pc);
1734 UpdateLocal(register_index, constant, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -07001735 break;
1736 }
1737
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001738 case Instruction::CONST_WIDE_16: {
1739 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -07001740 // Get 16 bits of constant value, sign extended to 64 bits.
1741 int64_t value = instruction.VRegB_21s();
1742 value <<= 48;
1743 value >>= 48;
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001744 HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
1745 UpdateLocal(register_index, constant, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001746 break;
1747 }
1748
1749 case Instruction::CONST_WIDE_32: {
1750 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -07001751 // Get 32 bits of constant value, sign extended to 64 bits.
1752 int64_t value = instruction.VRegB_31i();
1753 value <<= 32;
1754 value >>= 32;
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001755 HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
1756 UpdateLocal(register_index, constant, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001757 break;
1758 }
1759
1760 case Instruction::CONST_WIDE: {
1761 int32_t register_index = instruction.VRegA();
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001762 HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l(), dex_pc);
1763 UpdateLocal(register_index, constant, dex_pc);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001764 break;
1765 }
1766
Dave Allison20dfc792014-06-16 20:44:29 -07001767 case Instruction::CONST_WIDE_HIGH16: {
1768 int32_t register_index = instruction.VRegA();
1769 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001770 HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
1771 UpdateLocal(register_index, constant, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -07001772 break;
1773 }
1774
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00001775 // Note that the SSA building will refine the types.
Dave Allison20dfc792014-06-16 20:44:29 -07001776 case Instruction::MOVE:
1777 case Instruction::MOVE_FROM16:
1778 case Instruction::MOVE_16: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001779 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
1780 UpdateLocal(instruction.VRegA(), value, dex_pc);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001781 break;
1782 }
1783
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00001784 // Note that the SSA building will refine the types.
Dave Allison20dfc792014-06-16 20:44:29 -07001785 case Instruction::MOVE_WIDE:
1786 case Instruction::MOVE_WIDE_FROM16:
1787 case Instruction::MOVE_WIDE_16: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001788 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong, dex_pc);
1789 UpdateLocal(instruction.VRegA(), value, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -07001790 break;
1791 }
1792
1793 case Instruction::MOVE_OBJECT:
1794 case Instruction::MOVE_OBJECT_16:
1795 case Instruction::MOVE_OBJECT_FROM16: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001796 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot, dex_pc);
1797 UpdateLocal(instruction.VRegA(), value, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -07001798 break;
1799 }
1800
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001801 case Instruction::RETURN_VOID_NO_BARRIER:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001802 case Instruction::RETURN_VOID: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001803 BuildReturn(instruction, Primitive::kPrimVoid, dex_pc);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001804 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001805 }
1806
Dave Allison20dfc792014-06-16 20:44:29 -07001807#define IF_XX(comparison, cond) \
Calin Juravle225ff812014-11-13 16:46:39 +00001808 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_pc); break; \
1809 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_pc); break
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001810
Dave Allison20dfc792014-06-16 20:44:29 -07001811 IF_XX(HEqual, EQ);
1812 IF_XX(HNotEqual, NE);
1813 IF_XX(HLessThan, LT);
1814 IF_XX(HLessThanOrEqual, LE);
1815 IF_XX(HGreaterThan, GT);
1816 IF_XX(HGreaterThanOrEqual, GE);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001817
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001818 case Instruction::GOTO:
1819 case Instruction::GOTO_16:
1820 case Instruction::GOTO_32: {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001821 int32_t offset = instruction.GetTargetOffset();
Calin Juravle225ff812014-11-13 16:46:39 +00001822 HBasicBlock* target = FindBlockStartingAt(offset + dex_pc);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001823 DCHECK(target != nullptr);
David Brazdil852eaff2015-02-02 15:23:05 +00001824 PotentiallyAddSuspendCheck(target, dex_pc);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001825 current_block_->AddInstruction(new (arena_) HGoto(dex_pc));
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001826 current_block_->AddSuccessor(target);
1827 current_block_ = nullptr;
1828 break;
1829 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001830
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001831 case Instruction::RETURN: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001832 BuildReturn(instruction, return_type_, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001833 break;
1834 }
1835
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001836 case Instruction::RETURN_OBJECT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001837 BuildReturn(instruction, return_type_, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001838 break;
1839 }
1840
1841 case Instruction::RETURN_WIDE: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001842 BuildReturn(instruction, return_type_, dex_pc);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001843 break;
1844 }
1845
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001846 case Instruction::INVOKE_DIRECT:
Nicolas Geoffray0d8db992014-11-11 14:40:10 +00001847 case Instruction::INVOKE_INTERFACE:
1848 case Instruction::INVOKE_STATIC:
1849 case Instruction::INVOKE_SUPER:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001850 case Instruction::INVOKE_VIRTUAL:
1851 case Instruction::INVOKE_VIRTUAL_QUICK: {
1852 uint16_t method_idx;
1853 if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_QUICK) {
1854 if (!CanDecodeQuickenedInfo()) {
1855 return false;
1856 }
1857 method_idx = LookupQuickenedInfo(dex_pc);
1858 } else {
1859 method_idx = instruction.VRegB_35c();
1860 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001861 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001862 uint32_t args[5];
Ian Rogers29a26482014-05-02 15:27:29 -07001863 instruction.GetVarArgs(args);
Calin Juravle225ff812014-11-13 16:46:39 +00001864 if (!BuildInvoke(instruction, dex_pc, method_idx,
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00001865 number_of_vreg_arguments, false, args, -1)) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001866 return false;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001867 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001868 break;
1869 }
1870
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001871 case Instruction::INVOKE_DIRECT_RANGE:
Nicolas Geoffray0d8db992014-11-11 14:40:10 +00001872 case Instruction::INVOKE_INTERFACE_RANGE:
1873 case Instruction::INVOKE_STATIC_RANGE:
1874 case Instruction::INVOKE_SUPER_RANGE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00001875 case Instruction::INVOKE_VIRTUAL_RANGE:
1876 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
1877 uint16_t method_idx;
1878 if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK) {
1879 if (!CanDecodeQuickenedInfo()) {
1880 return false;
1881 }
1882 method_idx = LookupQuickenedInfo(dex_pc);
1883 } else {
1884 method_idx = instruction.VRegB_3rc();
1885 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001886 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
1887 uint32_t register_index = instruction.VRegC();
Calin Juravle225ff812014-11-13 16:46:39 +00001888 if (!BuildInvoke(instruction, dex_pc, method_idx,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001889 number_of_vreg_arguments, true, nullptr, register_index)) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001890 return false;
1891 }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001892 break;
1893 }
1894
Roland Levillain88cb1752014-10-20 16:36:47 +01001895 case Instruction::NEG_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001896 Unop_12x<HNeg>(instruction, Primitive::kPrimInt, dex_pc);
Roland Levillain88cb1752014-10-20 16:36:47 +01001897 break;
1898 }
1899
Roland Levillain2e07b4f2014-10-23 18:12:09 +01001900 case Instruction::NEG_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001901 Unop_12x<HNeg>(instruction, Primitive::kPrimLong, dex_pc);
Roland Levillain2e07b4f2014-10-23 18:12:09 +01001902 break;
1903 }
1904
Roland Levillain3dbcb382014-10-28 17:30:07 +00001905 case Instruction::NEG_FLOAT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001906 Unop_12x<HNeg>(instruction, Primitive::kPrimFloat, dex_pc);
Roland Levillain3dbcb382014-10-28 17:30:07 +00001907 break;
1908 }
1909
1910 case Instruction::NEG_DOUBLE: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001911 Unop_12x<HNeg>(instruction, Primitive::kPrimDouble, dex_pc);
Roland Levillain3dbcb382014-10-28 17:30:07 +00001912 break;
1913 }
1914
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001915 case Instruction::NOT_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001916 Unop_12x<HNot>(instruction, Primitive::kPrimInt, dex_pc);
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001917 break;
1918 }
1919
Roland Levillain70566432014-10-24 16:20:17 +01001920 case Instruction::NOT_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06001921 Unop_12x<HNot>(instruction, Primitive::kPrimLong, dex_pc);
Roland Levillain70566432014-10-24 16:20:17 +01001922 break;
1923 }
1924
Roland Levillaindff1f282014-11-05 14:15:05 +00001925 case Instruction::INT_TO_LONG: {
Roland Levillain624279f2014-12-04 11:54:28 +00001926 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong, dex_pc);
Roland Levillaindff1f282014-11-05 14:15:05 +00001927 break;
1928 }
1929
Roland Levillaincff13742014-11-17 14:32:17 +00001930 case Instruction::INT_TO_FLOAT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001931 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimFloat, dex_pc);
Roland Levillaincff13742014-11-17 14:32:17 +00001932 break;
1933 }
1934
1935 case Instruction::INT_TO_DOUBLE: {
Roland Levillain624279f2014-12-04 11:54:28 +00001936 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimDouble, dex_pc);
Roland Levillaincff13742014-11-17 14:32:17 +00001937 break;
1938 }
1939
Roland Levillain946e1432014-11-11 17:35:19 +00001940 case Instruction::LONG_TO_INT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001941 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimInt, dex_pc);
Roland Levillain946e1432014-11-11 17:35:19 +00001942 break;
1943 }
1944
Roland Levillain6d0e4832014-11-27 18:31:21 +00001945 case Instruction::LONG_TO_FLOAT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001946 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimFloat, dex_pc);
Roland Levillain6d0e4832014-11-27 18:31:21 +00001947 break;
1948 }
1949
Roland Levillain647b9ed2014-11-27 12:06:00 +00001950 case Instruction::LONG_TO_DOUBLE: {
Roland Levillain624279f2014-12-04 11:54:28 +00001951 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimDouble, dex_pc);
Roland Levillain647b9ed2014-11-27 12:06:00 +00001952 break;
1953 }
1954
Roland Levillain3f8f9362014-12-02 17:45:01 +00001955 case Instruction::FLOAT_TO_INT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001956 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimInt, dex_pc);
1957 break;
1958 }
1959
1960 case Instruction::FLOAT_TO_LONG: {
1961 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimLong, dex_pc);
Roland Levillain3f8f9362014-12-02 17:45:01 +00001962 break;
1963 }
1964
Roland Levillain8964e2b2014-12-04 12:10:50 +00001965 case Instruction::FLOAT_TO_DOUBLE: {
1966 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimDouble, dex_pc);
1967 break;
1968 }
1969
Roland Levillain4c0b61f2014-12-05 12:06:01 +00001970 case Instruction::DOUBLE_TO_INT: {
1971 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimInt, dex_pc);
1972 break;
1973 }
1974
1975 case Instruction::DOUBLE_TO_LONG: {
1976 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimLong, dex_pc);
1977 break;
1978 }
1979
Roland Levillain8964e2b2014-12-04 12:10:50 +00001980 case Instruction::DOUBLE_TO_FLOAT: {
1981 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimFloat, dex_pc);
1982 break;
1983 }
1984
Roland Levillain51d3fc42014-11-13 14:11:42 +00001985 case Instruction::INT_TO_BYTE: {
Roland Levillain624279f2014-12-04 11:54:28 +00001986 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimByte, dex_pc);
Roland Levillain51d3fc42014-11-13 14:11:42 +00001987 break;
1988 }
1989
Roland Levillain01a8d712014-11-14 16:27:39 +00001990 case Instruction::INT_TO_SHORT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001991 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimShort, dex_pc);
Roland Levillain01a8d712014-11-14 16:27:39 +00001992 break;
1993 }
1994
Roland Levillain981e4542014-11-14 11:47:14 +00001995 case Instruction::INT_TO_CHAR: {
Roland Levillain624279f2014-12-04 11:54:28 +00001996 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimChar, dex_pc);
Roland Levillain981e4542014-11-14 11:47:14 +00001997 break;
1998 }
1999
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002000 case Instruction::ADD_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002001 Binop_23x<HAdd>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002002 break;
2003 }
2004
2005 case Instruction::ADD_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002006 Binop_23x<HAdd>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002007 break;
2008 }
2009
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01002010 case Instruction::ADD_DOUBLE: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002011 Binop_23x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01002012 break;
2013 }
2014
2015 case Instruction::ADD_FLOAT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002016 Binop_23x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01002017 break;
2018 }
2019
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002020 case Instruction::SUB_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002021 Binop_23x<HSub>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002022 break;
2023 }
2024
2025 case Instruction::SUB_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002026 Binop_23x<HSub>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002027 break;
2028 }
2029
Calin Juravle096cc022014-10-23 17:01:13 +01002030 case Instruction::SUB_FLOAT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002031 Binop_23x<HSub>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravle096cc022014-10-23 17:01:13 +01002032 break;
2033 }
2034
2035 case Instruction::SUB_DOUBLE: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002036 Binop_23x<HSub>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravle096cc022014-10-23 17:01:13 +01002037 break;
2038 }
2039
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002040 case Instruction::ADD_INT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002041 Binop_12x<HAdd>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002042 break;
2043 }
2044
Calin Juravle34bacdf2014-10-07 20:23:36 +01002045 case Instruction::MUL_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002046 Binop_23x<HMul>(instruction, Primitive::kPrimInt, dex_pc);
Calin Juravle34bacdf2014-10-07 20:23:36 +01002047 break;
2048 }
2049
2050 case Instruction::MUL_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002051 Binop_23x<HMul>(instruction, Primitive::kPrimLong, dex_pc);
Calin Juravle34bacdf2014-10-07 20:23:36 +01002052 break;
2053 }
2054
Calin Juravleb5bfa962014-10-21 18:02:24 +01002055 case Instruction::MUL_FLOAT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002056 Binop_23x<HMul>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravleb5bfa962014-10-21 18:02:24 +01002057 break;
2058 }
2059
2060 case Instruction::MUL_DOUBLE: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002061 Binop_23x<HMul>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravleb5bfa962014-10-21 18:02:24 +01002062 break;
2063 }
2064
Calin Juravled0d48522014-11-04 16:40:20 +00002065 case Instruction::DIV_INT: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002066 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2067 dex_pc, Primitive::kPrimInt, false, true);
Calin Juravled0d48522014-11-04 16:40:20 +00002068 break;
2069 }
2070
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002071 case Instruction::DIV_LONG: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002072 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2073 dex_pc, Primitive::kPrimLong, false, true);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002074 break;
2075 }
2076
Calin Juravle7c4954d2014-10-28 16:57:40 +00002077 case Instruction::DIV_FLOAT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002078 Binop_23x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002079 break;
2080 }
2081
2082 case Instruction::DIV_DOUBLE: {
Calin Juravle225ff812014-11-13 16:46:39 +00002083 Binop_23x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002084 break;
2085 }
2086
Calin Juravlebacfec32014-11-14 15:54:36 +00002087 case Instruction::REM_INT: {
2088 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2089 dex_pc, Primitive::kPrimInt, false, false);
2090 break;
2091 }
2092
2093 case Instruction::REM_LONG: {
2094 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2095 dex_pc, Primitive::kPrimLong, false, false);
2096 break;
2097 }
2098
Calin Juravled2ec87d2014-12-08 14:24:46 +00002099 case Instruction::REM_FLOAT: {
2100 Binop_23x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
2101 break;
2102 }
2103
2104 case Instruction::REM_DOUBLE: {
2105 Binop_23x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
2106 break;
2107 }
2108
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002109 case Instruction::AND_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002110 Binop_23x<HAnd>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002111 break;
2112 }
2113
2114 case Instruction::AND_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002115 Binop_23x<HAnd>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002116 break;
2117 }
2118
Calin Juravle9aec02f2014-11-18 23:06:35 +00002119 case Instruction::SHL_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002120 Binop_23x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002121 break;
2122 }
2123
2124 case Instruction::SHL_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002125 Binop_23x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002126 break;
2127 }
2128
2129 case Instruction::SHR_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002130 Binop_23x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002131 break;
2132 }
2133
2134 case Instruction::SHR_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002135 Binop_23x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002136 break;
2137 }
2138
2139 case Instruction::USHR_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002140 Binop_23x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002141 break;
2142 }
2143
2144 case Instruction::USHR_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002145 Binop_23x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002146 break;
2147 }
2148
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002149 case Instruction::OR_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002150 Binop_23x<HOr>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002151 break;
2152 }
2153
2154 case Instruction::OR_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002155 Binop_23x<HOr>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002156 break;
2157 }
2158
2159 case Instruction::XOR_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002160 Binop_23x<HXor>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002161 break;
2162 }
2163
2164 case Instruction::XOR_LONG: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002165 Binop_23x<HXor>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002166 break;
2167 }
2168
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002169 case Instruction::ADD_LONG_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002170 Binop_12x<HAdd>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002171 break;
2172 }
2173
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01002174 case Instruction::ADD_DOUBLE_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002175 Binop_12x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01002176 break;
2177 }
2178
2179 case Instruction::ADD_FLOAT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002180 Binop_12x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01002181 break;
2182 }
2183
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002184 case Instruction::SUB_INT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002185 Binop_12x<HSub>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002186 break;
2187 }
2188
2189 case Instruction::SUB_LONG_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002190 Binop_12x<HSub>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002191 break;
2192 }
2193
Calin Juravle096cc022014-10-23 17:01:13 +01002194 case Instruction::SUB_FLOAT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002195 Binop_12x<HSub>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravle096cc022014-10-23 17:01:13 +01002196 break;
2197 }
2198
2199 case Instruction::SUB_DOUBLE_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002200 Binop_12x<HSub>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravle096cc022014-10-23 17:01:13 +01002201 break;
2202 }
2203
Calin Juravle34bacdf2014-10-07 20:23:36 +01002204 case Instruction::MUL_INT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002205 Binop_12x<HMul>(instruction, Primitive::kPrimInt, dex_pc);
Calin Juravle34bacdf2014-10-07 20:23:36 +01002206 break;
2207 }
2208
2209 case Instruction::MUL_LONG_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002210 Binop_12x<HMul>(instruction, Primitive::kPrimLong, dex_pc);
Calin Juravle34bacdf2014-10-07 20:23:36 +01002211 break;
2212 }
2213
Calin Juravleb5bfa962014-10-21 18:02:24 +01002214 case Instruction::MUL_FLOAT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002215 Binop_12x<HMul>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravleb5bfa962014-10-21 18:02:24 +01002216 break;
2217 }
2218
2219 case Instruction::MUL_DOUBLE_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002220 Binop_12x<HMul>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravleb5bfa962014-10-21 18:02:24 +01002221 break;
2222 }
2223
Calin Juravle865fc882014-11-06 17:09:03 +00002224 case Instruction::DIV_INT_2ADDR: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002225 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2226 dex_pc, Primitive::kPrimInt, false, true);
Calin Juravle865fc882014-11-06 17:09:03 +00002227 break;
2228 }
2229
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002230 case Instruction::DIV_LONG_2ADDR: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002231 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2232 dex_pc, Primitive::kPrimLong, false, true);
2233 break;
2234 }
2235
2236 case Instruction::REM_INT_2ADDR: {
2237 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2238 dex_pc, Primitive::kPrimInt, false, false);
2239 break;
2240 }
2241
2242 case Instruction::REM_LONG_2ADDR: {
2243 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2244 dex_pc, Primitive::kPrimLong, false, false);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002245 break;
2246 }
2247
Calin Juravled2ec87d2014-12-08 14:24:46 +00002248 case Instruction::REM_FLOAT_2ADDR: {
2249 Binop_12x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
2250 break;
2251 }
2252
2253 case Instruction::REM_DOUBLE_2ADDR: {
2254 Binop_12x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
2255 break;
2256 }
2257
Calin Juravle9aec02f2014-11-18 23:06:35 +00002258 case Instruction::SHL_INT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002259 Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002260 break;
2261 }
2262
2263 case Instruction::SHL_LONG_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002264 Binop_12x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002265 break;
2266 }
2267
2268 case Instruction::SHR_INT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002269 Binop_12x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002270 break;
2271 }
2272
2273 case Instruction::SHR_LONG_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002274 Binop_12x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002275 break;
2276 }
2277
2278 case Instruction::USHR_INT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002279 Binop_12x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002280 break;
2281 }
2282
2283 case Instruction::USHR_LONG_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002284 Binop_12x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002285 break;
2286 }
2287
Calin Juravle7c4954d2014-10-28 16:57:40 +00002288 case Instruction::DIV_FLOAT_2ADDR: {
Calin Juravle225ff812014-11-13 16:46:39 +00002289 Binop_12x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002290 break;
2291 }
2292
2293 case Instruction::DIV_DOUBLE_2ADDR: {
Calin Juravle225ff812014-11-13 16:46:39 +00002294 Binop_12x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002295 break;
2296 }
2297
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002298 case Instruction::AND_INT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002299 Binop_12x<HAnd>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002300 break;
2301 }
2302
2303 case Instruction::AND_LONG_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002304 Binop_12x<HAnd>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002305 break;
2306 }
2307
2308 case Instruction::OR_INT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002309 Binop_12x<HOr>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002310 break;
2311 }
2312
2313 case Instruction::OR_LONG_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002314 Binop_12x<HOr>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002315 break;
2316 }
2317
2318 case Instruction::XOR_INT_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002319 Binop_12x<HXor>(instruction, Primitive::kPrimInt, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002320 break;
2321 }
2322
2323 case Instruction::XOR_LONG_2ADDR: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002324 Binop_12x<HXor>(instruction, Primitive::kPrimLong, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002325 break;
2326 }
2327
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002328 case Instruction::ADD_INT_LIT16: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002329 Binop_22s<HAdd>(instruction, false, dex_pc);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002330 break;
2331 }
2332
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002333 case Instruction::AND_INT_LIT16: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002334 Binop_22s<HAnd>(instruction, false, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002335 break;
2336 }
2337
2338 case Instruction::OR_INT_LIT16: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002339 Binop_22s<HOr>(instruction, false, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002340 break;
2341 }
2342
2343 case Instruction::XOR_INT_LIT16: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002344 Binop_22s<HXor>(instruction, false, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002345 break;
2346 }
2347
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002348 case Instruction::RSUB_INT: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002349 Binop_22s<HSub>(instruction, true, dex_pc);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002350 break;
2351 }
2352
Calin Juravle34bacdf2014-10-07 20:23:36 +01002353 case Instruction::MUL_INT_LIT16: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002354 Binop_22s<HMul>(instruction, false, dex_pc);
Calin Juravle34bacdf2014-10-07 20:23:36 +01002355 break;
2356 }
2357
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002358 case Instruction::ADD_INT_LIT8: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002359 Binop_22b<HAdd>(instruction, false, dex_pc);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002360 break;
2361 }
2362
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002363 case Instruction::AND_INT_LIT8: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002364 Binop_22b<HAnd>(instruction, false, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002365 break;
2366 }
2367
2368 case Instruction::OR_INT_LIT8: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002369 Binop_22b<HOr>(instruction, false, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002370 break;
2371 }
2372
2373 case Instruction::XOR_INT_LIT8: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002374 Binop_22b<HXor>(instruction, false, dex_pc);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002375 break;
2376 }
2377
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002378 case Instruction::RSUB_INT_LIT8: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002379 Binop_22b<HSub>(instruction, true, dex_pc);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002380 break;
2381 }
2382
Calin Juravle34bacdf2014-10-07 20:23:36 +01002383 case Instruction::MUL_INT_LIT8: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002384 Binop_22b<HMul>(instruction, false, dex_pc);
Calin Juravle34bacdf2014-10-07 20:23:36 +01002385 break;
2386 }
2387
Calin Juravled0d48522014-11-04 16:40:20 +00002388 case Instruction::DIV_INT_LIT16:
2389 case Instruction::DIV_INT_LIT8: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002390 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2391 dex_pc, Primitive::kPrimInt, true, true);
2392 break;
2393 }
2394
2395 case Instruction::REM_INT_LIT16:
2396 case Instruction::REM_INT_LIT8: {
2397 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2398 dex_pc, Primitive::kPrimInt, true, false);
Calin Juravled0d48522014-11-04 16:40:20 +00002399 break;
2400 }
2401
Calin Juravle9aec02f2014-11-18 23:06:35 +00002402 case Instruction::SHL_INT_LIT8: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002403 Binop_22b<HShl>(instruction, false, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002404 break;
2405 }
2406
2407 case Instruction::SHR_INT_LIT8: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002408 Binop_22b<HShr>(instruction, false, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002409 break;
2410 }
2411
2412 case Instruction::USHR_INT_LIT8: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002413 Binop_22b<HUShr>(instruction, false, dex_pc);
Calin Juravle9aec02f2014-11-18 23:06:35 +00002414 break;
2415 }
2416
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002417 case Instruction::NEW_INSTANCE: {
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002418 uint16_t type_index = instruction.VRegB_21c();
Jeff Hao848f70a2014-01-15 13:49:50 -08002419 if (compiler_driver_->IsStringTypeIndex(type_index, dex_file_)) {
Jeff Hao848f70a2014-01-15 13:49:50 -08002420 int32_t register_index = instruction.VRegA();
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002421 HFakeString* fake_string = new (arena_) HFakeString(dex_pc);
Nicolas Geoffray2e7cd752015-07-10 11:38:52 +01002422 current_block_->AddInstruction(fake_string);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002423 UpdateLocal(register_index, fake_string, dex_pc);
Jeff Hao848f70a2014-01-15 13:49:50 -08002424 } else {
2425 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
2426 ? kQuickAllocObjectWithAccessCheck
2427 : kQuickAllocObject;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002428
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002429 current_block_->AddInstruction(new (arena_) HNewInstance(
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002430 graph_->GetCurrentMethod(),
2431 dex_pc,
2432 type_index,
2433 *dex_compilation_unit_->GetDexFile(),
2434 entrypoint));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002435 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
Jeff Hao848f70a2014-01-15 13:49:50 -08002436 }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002437 break;
2438 }
2439
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002440 case Instruction::NEW_ARRAY: {
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002441 uint16_t type_index = instruction.VRegC_22c();
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002442 HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt, dex_pc);
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002443 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
2444 ? kQuickAllocArrayWithAccessCheck
2445 : kQuickAllocArray;
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002446 current_block_->AddInstruction(new (arena_) HNewArray(length,
2447 graph_->GetCurrentMethod(),
2448 dex_pc,
2449 type_index,
2450 *dex_compilation_unit_->GetDexFile(),
2451 entrypoint));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002452 UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002453 break;
2454 }
2455
2456 case Instruction::FILLED_NEW_ARRAY: {
2457 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
2458 uint32_t type_index = instruction.VRegB_35c();
2459 uint32_t args[5];
2460 instruction.GetVarArgs(args);
Calin Juravle225ff812014-11-13 16:46:39 +00002461 BuildFilledNewArray(dex_pc, type_index, number_of_vreg_arguments, false, args, 0);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002462 break;
2463 }
2464
2465 case Instruction::FILLED_NEW_ARRAY_RANGE: {
2466 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
2467 uint32_t type_index = instruction.VRegB_3rc();
2468 uint32_t register_index = instruction.VRegC_3rc();
2469 BuildFilledNewArray(
Calin Juravle225ff812014-11-13 16:46:39 +00002470 dex_pc, type_index, number_of_vreg_arguments, true, nullptr, register_index);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002471 break;
2472 }
2473
2474 case Instruction::FILL_ARRAY_DATA: {
Calin Juravle225ff812014-11-13 16:46:39 +00002475 BuildFillArrayData(instruction, dex_pc);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002476 break;
2477 }
2478
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01002479 case Instruction::MOVE_RESULT:
Dave Allison20dfc792014-06-16 20:44:29 -07002480 case Instruction::MOVE_RESULT_WIDE:
David Brazdilfc6a86a2015-06-26 10:33:45 +00002481 case Instruction::MOVE_RESULT_OBJECT: {
Nicolas Geoffray1efcc222015-06-24 12:41:20 +01002482 if (latest_result_ == nullptr) {
2483 // Only dead code can lead to this situation, where the verifier
2484 // does not reject the method.
2485 } else {
David Brazdilfc6a86a2015-06-26 10:33:45 +00002486 // An Invoke/FilledNewArray and its MoveResult could have landed in
2487 // different blocks if there was a try/catch block boundary between
2488 // them. For Invoke, we insert a StoreLocal after the instruction. For
2489 // FilledNewArray, the local needs to be updated after the array was
2490 // filled, otherwise we might overwrite an input vreg.
2491 HStoreLocal* update_local =
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002492 new (arena_) HStoreLocal(GetLocalAt(instruction.VRegA()), latest_result_, dex_pc);
David Brazdilfc6a86a2015-06-26 10:33:45 +00002493 HBasicBlock* block = latest_result_->GetBlock();
2494 if (block == current_block_) {
2495 // MoveResult and the previous instruction are in the same block.
2496 current_block_->AddInstruction(update_local);
2497 } else {
2498 // The two instructions are in different blocks. Insert the MoveResult
2499 // before the final control-flow instruction of the previous block.
2500 DCHECK(block->EndsWithControlFlowInstruction());
2501 DCHECK(current_block_->GetInstructions().IsEmpty());
2502 block->InsertInstructionBefore(update_local, block->GetLastInstruction());
2503 }
Nicolas Geoffray1efcc222015-06-24 12:41:20 +01002504 latest_result_ = nullptr;
2505 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002506 break;
David Brazdilfc6a86a2015-06-26 10:33:45 +00002507 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002508
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002509 case Instruction::CMP_LONG: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002510 Binop_23x_cmp(instruction, Primitive::kPrimLong, ComparisonBias::kNoBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002511 break;
2512 }
2513
2514 case Instruction::CMPG_FLOAT: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002515 Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kGtBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002516 break;
2517 }
2518
2519 case Instruction::CMPG_DOUBLE: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002520 Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kGtBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002521 break;
2522 }
2523
2524 case Instruction::CMPL_FLOAT: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002525 Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kLtBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002526 break;
2527 }
2528
2529 case Instruction::CMPL_DOUBLE: {
Roland Levillain4fa13f62015-07-06 18:11:54 +01002530 Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kLtBias, dex_pc);
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002531 break;
2532 }
2533
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00002534 case Instruction::NOP:
2535 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002536
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002537 case Instruction::IGET:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002538 case Instruction::IGET_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002539 case Instruction::IGET_WIDE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002540 case Instruction::IGET_WIDE_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002541 case Instruction::IGET_OBJECT:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002542 case Instruction::IGET_OBJECT_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002543 case Instruction::IGET_BOOLEAN:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002544 case Instruction::IGET_BOOLEAN_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002545 case Instruction::IGET_BYTE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002546 case Instruction::IGET_BYTE_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002547 case Instruction::IGET_CHAR:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002548 case Instruction::IGET_CHAR_QUICK:
2549 case Instruction::IGET_SHORT:
2550 case Instruction::IGET_SHORT_QUICK: {
Calin Juravle225ff812014-11-13 16:46:39 +00002551 if (!BuildInstanceFieldAccess(instruction, dex_pc, false)) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002552 return false;
2553 }
2554 break;
2555 }
2556
2557 case Instruction::IPUT:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002558 case Instruction::IPUT_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002559 case Instruction::IPUT_WIDE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002560 case Instruction::IPUT_WIDE_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002561 case Instruction::IPUT_OBJECT:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002562 case Instruction::IPUT_OBJECT_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002563 case Instruction::IPUT_BOOLEAN:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002564 case Instruction::IPUT_BOOLEAN_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002565 case Instruction::IPUT_BYTE:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002566 case Instruction::IPUT_BYTE_QUICK:
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002567 case Instruction::IPUT_CHAR:
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +00002568 case Instruction::IPUT_CHAR_QUICK:
2569 case Instruction::IPUT_SHORT:
2570 case Instruction::IPUT_SHORT_QUICK: {
Calin Juravle225ff812014-11-13 16:46:39 +00002571 if (!BuildInstanceFieldAccess(instruction, dex_pc, true)) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002572 return false;
2573 }
2574 break;
2575 }
2576
2577 case Instruction::SGET:
2578 case Instruction::SGET_WIDE:
2579 case Instruction::SGET_OBJECT:
2580 case Instruction::SGET_BOOLEAN:
2581 case Instruction::SGET_BYTE:
2582 case Instruction::SGET_CHAR:
2583 case Instruction::SGET_SHORT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002584 if (!BuildStaticFieldAccess(instruction, dex_pc, false)) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002585 return false;
2586 }
2587 break;
2588 }
2589
2590 case Instruction::SPUT:
2591 case Instruction::SPUT_WIDE:
2592 case Instruction::SPUT_OBJECT:
2593 case Instruction::SPUT_BOOLEAN:
2594 case Instruction::SPUT_BYTE:
2595 case Instruction::SPUT_CHAR:
2596 case Instruction::SPUT_SHORT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002597 if (!BuildStaticFieldAccess(instruction, dex_pc, true)) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002598 return false;
2599 }
2600 break;
2601 }
2602
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002603#define ARRAY_XX(kind, anticipated_type) \
2604 case Instruction::AGET##kind: { \
Calin Juravle225ff812014-11-13 16:46:39 +00002605 BuildArrayAccess(instruction, dex_pc, false, anticipated_type); \
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002606 break; \
2607 } \
2608 case Instruction::APUT##kind: { \
Calin Juravle225ff812014-11-13 16:46:39 +00002609 BuildArrayAccess(instruction, dex_pc, true, anticipated_type); \
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002610 break; \
2611 }
2612
2613 ARRAY_XX(, Primitive::kPrimInt);
2614 ARRAY_XX(_WIDE, Primitive::kPrimLong);
2615 ARRAY_XX(_OBJECT, Primitive::kPrimNot);
2616 ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean);
2617 ARRAY_XX(_BYTE, Primitive::kPrimByte);
2618 ARRAY_XX(_CHAR, Primitive::kPrimChar);
2619 ARRAY_XX(_SHORT, Primitive::kPrimShort);
2620
Nicolas Geoffray39468442014-09-02 15:17:15 +01002621 case Instruction::ARRAY_LENGTH: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002622 HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot, dex_pc);
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002623 // No need for a temporary for the null check, it is the only input of the following
2624 // instruction.
Calin Juravle225ff812014-11-13 16:46:39 +00002625 object = new (arena_) HNullCheck(object, dex_pc);
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002626 current_block_->AddInstruction(object);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002627 current_block_->AddInstruction(new (arena_) HArrayLength(object, dex_pc));
2628 UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffray39468442014-09-02 15:17:15 +01002629 break;
2630 }
2631
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002632 case Instruction::CONST_STRING: {
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01002633 current_block_->AddInstruction(
2634 new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_21c(), dex_pc));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002635 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002636 break;
2637 }
2638
2639 case Instruction::CONST_STRING_JUMBO: {
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01002640 current_block_->AddInstruction(
2641 new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_31c(), dex_pc));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002642 UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002643 break;
2644 }
2645
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002646 case Instruction::CONST_CLASS: {
2647 uint16_t type_index = instruction.VRegB_21c();
2648 bool type_known_final;
2649 bool type_known_abstract;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002650 bool dont_use_is_referrers_class;
2651 // `CanAccessTypeWithoutChecks` will tell whether the method being
2652 // built is trying to access its own class, so that the generated
2653 // code can optimize for this case. However, the optimization does not
Nicolas Geoffray9437b782015-03-25 10:08:51 +00002654 // work for inlining, so we use `IsOutermostCompilingClass` instead.
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002655 bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
2656 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002657 &type_known_final, &type_known_abstract, &dont_use_is_referrers_class);
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002658 if (!can_access) {
Calin Juravle48c2b032014-12-09 18:11:36 +00002659 MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002660 return false;
2661 }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002662 current_block_->AddInstruction(new (arena_) HLoadClass(
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01002663 graph_->GetCurrentMethod(),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002664 type_index,
2665 *dex_compilation_unit_->GetDexFile(),
2666 IsOutermostCompilingClass(type_index),
2667 dex_pc));
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002668 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction(), dex_pc);
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002669 break;
2670 }
2671
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002672 case Instruction::MOVE_EXCEPTION: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002673 current_block_->AddInstruction(new (arena_) HLoadException(dex_pc));
2674 UpdateLocal(instruction.VRegA_11x(), current_block_->GetLastInstruction(), dex_pc);
2675 current_block_->AddInstruction(new (arena_) HClearException(dex_pc));
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002676 break;
2677 }
2678
2679 case Instruction::THROW: {
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002680 HInstruction* exception = LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot, dex_pc);
Calin Juravle225ff812014-11-13 16:46:39 +00002681 current_block_->AddInstruction(new (arena_) HThrow(exception, dex_pc));
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002682 // A throw instruction must branch to the exit block.
2683 current_block_->AddSuccessor(exit_block_);
2684 // We finished building this block. Set the current block to null to avoid
2685 // adding dead instructions to it.
2686 current_block_ = nullptr;
2687 break;
2688 }
2689
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002690 case Instruction::INSTANCE_OF: {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002691 uint8_t destination = instruction.VRegA_22c();
2692 uint8_t reference = instruction.VRegB_22c();
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002693 uint16_t type_index = instruction.VRegC_22c();
Calin Juravle225ff812014-11-13 16:46:39 +00002694 if (!BuildTypeCheck(instruction, destination, reference, type_index, dex_pc)) {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002695 return false;
2696 }
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002697 break;
2698 }
2699
2700 case Instruction::CHECK_CAST: {
2701 uint8_t reference = instruction.VRegA_21c();
2702 uint16_t type_index = instruction.VRegB_21c();
Calin Juravle225ff812014-11-13 16:46:39 +00002703 if (!BuildTypeCheck(instruction, -1, reference, type_index, dex_pc)) {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002704 return false;
2705 }
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002706 break;
2707 }
2708
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002709 case Instruction::MONITOR_ENTER: {
2710 current_block_->AddInstruction(new (arena_) HMonitorOperation(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002711 LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot, dex_pc),
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002712 HMonitorOperation::kEnter,
Calin Juravle225ff812014-11-13 16:46:39 +00002713 dex_pc));
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002714 break;
2715 }
2716
2717 case Instruction::MONITOR_EXIT: {
2718 current_block_->AddInstruction(new (arena_) HMonitorOperation(
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002719 LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot, dex_pc),
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002720 HMonitorOperation::kExit,
Calin Juravle225ff812014-11-13 16:46:39 +00002721 dex_pc));
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002722 break;
2723 }
2724
Andreas Gamped881df52014-11-24 23:28:39 -08002725 case Instruction::PACKED_SWITCH: {
Calin Juravle48c2b032014-12-09 18:11:36 +00002726 BuildPackedSwitch(instruction, dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -08002727 break;
2728 }
2729
Andreas Gampee4d4d322014-12-04 09:09:57 -08002730 case Instruction::SPARSE_SWITCH: {
Calin Juravle48c2b032014-12-09 18:11:36 +00002731 BuildSparseSwitch(instruction, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08002732 break;
2733 }
2734
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002735 default:
Calin Juravle48c2b032014-12-09 18:11:36 +00002736 VLOG(compiler) << "Did not compile "
2737 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
2738 << " because of unhandled instruction "
2739 << instruction.Name();
2740 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnhandledInstruction);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002741 return false;
2742 }
2743 return true;
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00002744} // NOLINT(readability/fn_size)
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002745
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002746HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
2747 return locals_.Get(register_index);
2748}
2749
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002750void HGraphBuilder::UpdateLocal(int register_index,
2751 HInstruction* instruction,
2752 uint32_t dex_pc) const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002753 HLocal* local = GetLocalAt(register_index);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002754 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction, dex_pc));
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002755}
2756
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002757HInstruction* HGraphBuilder::LoadLocal(int register_index,
2758 Primitive::Type type,
2759 uint32_t dex_pc) const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002760 HLocal* local = GetLocalAt(register_index);
Yevgeny Rouban3ecfd652015-09-07 17:57:00 +06002761 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type, dex_pc));
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002762 return current_block_->GetLastInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002763}
2764
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002765} // namespace art