blob: 742429cc55bb40c878f9a106538ce44f5c5c69b9 [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"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000034
35namespace art {
36
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010037/**
38 * Helper class to add HTemporary instructions. This class is used when
39 * converting a DEX instruction to multiple HInstruction, and where those
40 * instructions do not die at the following instruction, but instead spans
41 * multiple instructions.
42 */
43class Temporaries : public ValueObject {
44 public:
Calin Juravlef97f9fb2014-11-11 15:38:19 +000045 explicit Temporaries(HGraph* graph) : graph_(graph), index_(0) {}
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010046
47 void Add(HInstruction* instruction) {
Calin Juravlef97f9fb2014-11-11 15:38:19 +000048 HInstruction* temp = new (graph_->GetArena()) HTemporary(index_);
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010049 instruction->GetBlock()->AddInstruction(temp);
Calin Juravlef97f9fb2014-11-11 15:38:19 +000050
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010051 DCHECK(temp->GetPrevious() == instruction);
Calin Juravlef97f9fb2014-11-11 15:38:19 +000052
53 size_t offset;
54 if (instruction->GetType() == Primitive::kPrimLong
55 || instruction->GetType() == Primitive::kPrimDouble) {
56 offset = 2;
57 } else {
58 offset = 1;
59 }
60 index_ += offset;
61
62 graph_->UpdateTemporariesVRegSlots(index_);
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010063 }
64
65 private:
66 HGraph* const graph_;
67
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +010068 // Current index in the temporary stack, updated by `Add`.
69 size_t index_;
70};
71
Andreas Gamped881df52014-11-24 23:28:39 -080072class SwitchTable : public ValueObject {
73 public:
74 SwitchTable(const Instruction& instruction, uint32_t dex_pc, bool sparse)
75 : instruction_(instruction), dex_pc_(dex_pc), sparse_(sparse) {
76 int32_t table_offset = instruction.VRegB_31t();
77 const uint16_t* table = reinterpret_cast<const uint16_t*>(&instruction) + table_offset;
78 if (sparse) {
79 CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
80 } else {
81 CHECK_EQ(table[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
82 }
83 num_entries_ = table[1];
84 values_ = reinterpret_cast<const int32_t*>(&table[2]);
85 }
86
87 uint16_t GetNumEntries() const {
88 return num_entries_;
89 }
90
Andreas Gampee4d4d322014-12-04 09:09:57 -080091 void CheckIndex(size_t index) const {
92 if (sparse_) {
93 // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order.
94 DCHECK_LT(index, 2 * static_cast<size_t>(num_entries_));
95 } else {
96 // In a packed table, we have the starting key and num_entries_ values.
97 DCHECK_LT(index, 1 + static_cast<size_t>(num_entries_));
98 }
99 }
100
Andreas Gamped881df52014-11-24 23:28:39 -0800101 int32_t GetEntryAt(size_t index) const {
Andreas Gampee4d4d322014-12-04 09:09:57 -0800102 CheckIndex(index);
Andreas Gamped881df52014-11-24 23:28:39 -0800103 return values_[index];
104 }
105
106 uint32_t GetDexPcForIndex(size_t index) const {
Andreas Gampee4d4d322014-12-04 09:09:57 -0800107 CheckIndex(index);
Andreas Gamped881df52014-11-24 23:28:39 -0800108 return dex_pc_ +
109 (reinterpret_cast<const int16_t*>(values_ + index) -
110 reinterpret_cast<const int16_t*>(&instruction_));
111 }
112
Andreas Gampee4d4d322014-12-04 09:09:57 -0800113 // Index of the first value in the table.
114 size_t GetFirstValueIndex() const {
115 if (sparse_) {
116 // In a sparse table, we have num_entries_ keys and num_entries_ values, in that order.
117 return num_entries_;
118 } else {
119 // In a packed table, we have the starting key and num_entries_ values.
120 return 1;
121 }
122 }
123
Andreas Gamped881df52014-11-24 23:28:39 -0800124 private:
125 const Instruction& instruction_;
126 const uint32_t dex_pc_;
127
128 // Whether this is a sparse-switch table (or a packed-switch one).
129 const bool sparse_;
130
131 // This can't be const as it needs to be computed off of the given instruction, and complicated
132 // expressions in the initializer list seemed very ugly.
133 uint16_t num_entries_;
134
135 const int32_t* values_;
136
137 DISALLOW_COPY_AND_ASSIGN(SwitchTable);
138};
139
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100140void HGraphBuilder::InitializeLocals(uint16_t count) {
141 graph_->SetNumberOfVRegs(count);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000142 locals_.SetSize(count);
143 for (int i = 0; i < count; i++) {
144 HLocal* local = new (arena_) HLocal(i);
145 entry_block_->AddInstruction(local);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000146 locals_.Put(i, local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000147 }
148}
149
Nicolas Geoffray52e832b2014-11-06 15:15:31 +0000150void HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100151 // dex_compilation_unit_ is null only when unit testing.
152 if (dex_compilation_unit_ == nullptr) {
Nicolas Geoffray52e832b2014-11-06 15:15:31 +0000153 return;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100154 }
155
156 graph_->SetNumberOfInVRegs(number_of_parameters);
157 const char* shorty = dex_compilation_unit_->GetShorty();
158 int locals_index = locals_.Size() - number_of_parameters;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100159 int parameter_index = 0;
160
161 if (!dex_compilation_unit_->IsStatic()) {
162 // Add the implicit 'this' argument, not expressed in the signature.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100163 HParameterValue* parameter =
Calin Juravle10e244f2015-01-26 18:54:32 +0000164 new (arena_) HParameterValue(parameter_index++, Primitive::kPrimNot, true);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100165 entry_block_->AddInstruction(parameter);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100166 HLocal* local = GetLocalAt(locals_index++);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100167 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100168 number_of_parameters--;
169 }
170
171 uint32_t pos = 1;
172 for (int i = 0; i < number_of_parameters; i++) {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100173 HParameterValue* parameter =
174 new (arena_) HParameterValue(parameter_index++, Primitive::GetType(shorty[pos++]));
175 entry_block_->AddInstruction(parameter);
176 HLocal* local = GetLocalAt(locals_index++);
177 // Store the parameter value in the local that the dex code will use
178 // to reference that parameter.
179 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
180 bool is_wide = (parameter->GetType() == Primitive::kPrimLong)
181 || (parameter->GetType() == Primitive::kPrimDouble);
182 if (is_wide) {
183 i++;
184 locals_index++;
185 parameter_index++;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100186 }
187 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100188}
189
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100190template<typename T>
Calin Juravle225ff812014-11-13 16:46:39 +0000191void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc) {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000192 int32_t target_offset = instruction.GetTargetOffset();
David Brazdil852eaff2015-02-02 15:23:05 +0000193 HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset);
194 HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
195 DCHECK(branch_target != nullptr);
196 DCHECK(fallthrough_target != nullptr);
197 PotentiallyAddSuspendCheck(branch_target, dex_pc);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100198 HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
199 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Dave Allison20dfc792014-06-16 20:44:29 -0700200 T* comparison = new (arena_) T(first, second);
201 current_block_->AddInstruction(comparison);
202 HInstruction* ifinst = new (arena_) HIf(comparison);
203 current_block_->AddInstruction(ifinst);
David Brazdil852eaff2015-02-02 15:23:05 +0000204 current_block_->AddSuccessor(branch_target);
205 current_block_->AddSuccessor(fallthrough_target);
Dave Allison20dfc792014-06-16 20:44:29 -0700206 current_block_ = nullptr;
207}
208
209template<typename T>
Calin Juravle225ff812014-11-13 16:46:39 +0000210void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000211 int32_t target_offset = instruction.GetTargetOffset();
David Brazdil852eaff2015-02-02 15:23:05 +0000212 HBasicBlock* branch_target = FindBlockStartingAt(dex_pc + target_offset);
213 HBasicBlock* fallthrough_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
214 DCHECK(branch_target != nullptr);
215 DCHECK(fallthrough_target != nullptr);
216 PotentiallyAddSuspendCheck(branch_target, dex_pc);
Dave Allison20dfc792014-06-16 20:44:29 -0700217 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000218 T* comparison = new (arena_) T(value, graph_->GetIntConstant(0));
Dave Allison20dfc792014-06-16 20:44:29 -0700219 current_block_->AddInstruction(comparison);
220 HInstruction* ifinst = new (arena_) HIf(comparison);
221 current_block_->AddInstruction(ifinst);
David Brazdil852eaff2015-02-02 15:23:05 +0000222 current_block_->AddSuccessor(branch_target);
223 current_block_->AddSuccessor(fallthrough_target);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100224 current_block_ = nullptr;
225}
226
Calin Juravle48c2b032014-12-09 18:11:36 +0000227void HGraphBuilder::MaybeRecordStat(MethodCompilationStat compilation_stat) {
228 if (compilation_stats_ != nullptr) {
229 compilation_stats_->RecordStat(compilation_stat);
230 }
231}
232
David Brazdil1b498722015-03-31 11:37:18 +0100233bool HGraphBuilder::SkipCompilation(const DexFile::CodeItem& code_item,
Calin Juravle48c2b032014-12-09 18:11:36 +0000234 size_t number_of_branches) {
235 const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions();
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000236 CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter();
237 if (compiler_filter == CompilerOptions::kEverything) {
238 return false;
239 }
240
David Brazdil1b498722015-03-31 11:37:18 +0100241 if (compiler_options.IsHugeMethod(code_item.insns_size_in_code_units_)) {
Calin Juravle48c2b032014-12-09 18:11:36 +0000242 VLOG(compiler) << "Skip compilation of huge method "
243 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
David Brazdil1b498722015-03-31 11:37:18 +0100244 << ": " << code_item.insns_size_in_code_units_ << " code units";
Calin Juravle48c2b032014-12-09 18:11:36 +0000245 MaybeRecordStat(MethodCompilationStat::kNotCompiledHugeMethod);
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000246 return true;
247 }
248
249 // If it's large and contains no branches, it's likely to be machine generated initialization.
David Brazdil1b498722015-03-31 11:37:18 +0100250 if (compiler_options.IsLargeMethod(code_item.insns_size_in_code_units_)
251 && (number_of_branches == 0)) {
Calin Juravle48c2b032014-12-09 18:11:36 +0000252 VLOG(compiler) << "Skip compilation of large method with no branch "
253 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
David Brazdil1b498722015-03-31 11:37:18 +0100254 << ": " << code_item.insns_size_in_code_units_ << " code units";
Calin Juravle48c2b032014-12-09 18:11:36 +0000255 MaybeRecordStat(MethodCompilationStat::kNotCompiledLargeMethodNoBranches);
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000256 return true;
257 }
258
259 return false;
260}
261
David Brazdil0b5c7d12015-06-11 11:17:49 +0100262bool HGraphBuilder::IsBlockInPcRange(HBasicBlock* block,
263 uint32_t dex_pc_start,
264 uint32_t dex_pc_end) {
265 uint32_t dex_pc = block->GetDexPc();
266 return block != entry_block_
267 && block != exit_block_
268 && dex_pc >= dex_pc_start
269 && dex_pc < dex_pc_end;
270}
271
272void HGraphBuilder::CreateBlocksForTryCatch(const DexFile::CodeItem& code_item) {
273 if (code_item.tries_size_ == 0) {
274 return;
275 }
276
277 // Create branch targets at the start/end of the TryItem range. These are
278 // places where the program might fall through into/out of the a block and
279 // where TryBoundary instructions will be inserted later. Other edges which
280 // enter/exit the try blocks are a result of branches/switches.
281 for (size_t idx = 0; idx < code_item.tries_size_; ++idx) {
282 const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item, idx);
283 uint32_t dex_pc_start = try_item->start_addr_;
284 uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_;
285 FindOrCreateBlockStartingAt(dex_pc_start);
286 if (dex_pc_end < code_item.insns_size_in_code_units_) {
287 // TODO: Do not create block if the last instruction cannot fall through.
288 FindOrCreateBlockStartingAt(dex_pc_end);
289 } else {
290 // The TryItem spans until the very end of the CodeItem (or beyond if
291 // invalid) and therefore cannot have any code afterwards.
292 }
293 }
294
295 // Create branch targets for exception handlers.
296 const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item, 0);
297 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
298 for (uint32_t idx = 0; idx < handlers_size; ++idx) {
299 CatchHandlerIterator iterator(handlers_ptr);
300 for (; iterator.HasNext(); iterator.Next()) {
301 uint32_t address = iterator.GetHandlerAddress();
302 HBasicBlock* block = FindOrCreateBlockStartingAt(address);
303 block->SetIsCatchBlock();
304 }
305 handlers_ptr = iterator.EndDataPointer();
306 }
307}
308
309void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) {
310 if (code_item.tries_size_ == 0) {
311 return;
312 }
313
314 for (size_t idx = 0; idx < code_item.tries_size_; ++idx) {
315 const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item, idx);
316 uint32_t try_start = try_item->start_addr_;
317 uint32_t try_end = try_start + try_item->insn_count_;
318
319 // Iterate over all blocks in the dex pc range of the TryItem and:
320 // (a) split edges which enter/exit the try range,
321 // (b) create TryBoundary instructions in the new blocks,
322 // (c) link the new blocks to corresponding exception handlers.
323 for (uint32_t inner_pc = try_start; inner_pc < try_end; ++inner_pc) {
324 HBasicBlock* try_block = FindBlockStartingAt(inner_pc);
325 if (try_block == nullptr) {
326 continue;
327 }
328
329 // Find predecessors which are not covered by the same TryItem range. Such
330 // edges enter the try block and will have a TryBoundary inserted.
331 for (size_t i = 0; i < try_block->GetPredecessors().Size(); ++i) {
332 HBasicBlock* predecessor = try_block->GetPredecessors().Get(i);
333 HTryBoundary* try_boundary = nullptr;
334 if (predecessor->IsSingleTryBoundary()) {
335 try_boundary = predecessor->GetLastInstruction()->AsTryBoundary();
336 if (try_boundary->GetNormalFlowSuccessor() == try_block
337 && try_block->IsFirstIndexOfPredecessor(predecessor, i)) {
338 // The edge was already split because of an exit from a neighbouring
339 // TryItem and `predecessor` is the block with a TryBoundary created
340 // between the two original blocks. We do not split the edge again.
341 DCHECK(!IsBlockInPcRange(predecessor->GetSinglePredecessor(), try_start, try_end));
342 DCHECK(try_boundary->IsTryExit());
343 DCHECK(!try_boundary->IsTryEntry());
344 try_boundary->SetIsTryEntry();
345 } else {
346 // This is an edge between a previously created TryBoundary and its
347 // handler. We skip it because it is exceptional flow.
348 DCHECK(try_block->IsCatchBlock());
349 DCHECK(try_boundary->HasExceptionHandler(try_block));
350 continue;
351 }
352 } else if (!IsBlockInPcRange(predecessor, try_start, try_end)) {
353 // This is an entry point into the TryItem and the edge has not been
354 // split yet. That means that either `predecessor` is not in a TryItem,
355 // or it is in a different TryItem and we happened to iterate over
356 // this block first. We split the edge and `predecessor` may add its
357 // own exception handlers later.
358 try_boundary = new (arena_) HTryBoundary(/* is_entry */ true, /* is_exit */ false);
359 HBasicBlock* try_entry_block = graph_->SplitEdge(predecessor, try_block);
360 try_entry_block->AddInstruction(try_boundary);
361 } else {
362 // Not an edge on the boundary of the try block.
363 continue;
364 }
365 DCHECK(try_boundary != nullptr);
366
367 // Link the TryBoundary block to the handlers of this TryItem.
368 for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) {
369 try_boundary->AddExceptionHandler(FindBlockStartingAt(it.GetHandlerAddress()));
370 }
371 }
372
373 // Find successors which are not covered by the same TryItem range. Such
374 // edges exit the try block and will have a TryBoundary inserted.
375 for (size_t i = 0; i < try_block->GetSuccessors().Size(); ++i) {
376 HBasicBlock* successor = try_block->GetSuccessors().Get(i);
377 HTryBoundary* try_boundary = nullptr;
378 if (successor->IsSingleTryBoundary()) {
379 // The edge was already split because of an entry into a neighbouring
380 // TryItem. We do not split the edge again.
381 try_boundary = successor->GetLastInstruction()->AsTryBoundary();
382 DCHECK_EQ(try_block, successor->GetSinglePredecessor());
383 DCHECK(try_boundary->IsTryEntry());
384 DCHECK(!try_boundary->IsTryExit());
385 DCHECK(!IsBlockInPcRange(try_boundary->GetNormalFlowSuccessor(), try_start, try_end));
386 try_boundary->SetIsTryExit();
387 } else if (!IsBlockInPcRange(successor, try_start, try_end)) {
388 // This is an exit out of the TryItem and the edge has not been split
389 // yet. That means that either `successor` is not in a TryItem, or it
390 // is in a different TryItem and we happened to iterate over this
391 // block first. We split the edge and `successor` may add its own
392 // exception handlers later.
393 HInstruction* last_instruction = try_block->GetLastInstruction();
394 if (last_instruction->IsReturn() || last_instruction->IsReturnVoid()) {
395 DCHECK_EQ(successor, exit_block_);
396 // Control flow exits the try block with a Return(Void). Because
397 // splitting the edge would invalidate the invariant that Return
398 // always jumps to Exit, we move the Return outside the try block.
399 HBasicBlock* return_block = try_block->SplitBefore(last_instruction);
400 graph_->AddBlock(return_block);
401 successor = return_block;
402 }
403 try_boundary = new (arena_) HTryBoundary(/* is_entry */ false, /* is_exit */ true);
404 HBasicBlock* try_exit_block = graph_->SplitEdge(try_block, successor);
405 try_exit_block->AddInstruction(try_boundary);
406 } else {
407 // Not an edge on the boundary of the try block.
408 continue;
409 }
410 DCHECK(try_boundary != nullptr);
411
412 // Link the TryBoundary block to the handlers of this TryItem.
413 for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) {
414 try_boundary->AddExceptionHandler(FindBlockStartingAt(it.GetHandlerAddress()));
415 }
416 }
417 }
418 }
419}
420
David Brazdil5e8b1372015-01-23 14:39:08 +0000421bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
422 DCHECK(graph_->GetBlocks().IsEmpty());
423
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000424 const uint16_t* code_ptr = code_item.insns_;
425 const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_;
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +0100426 code_start_ = code_ptr;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000427
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000428 // Setup the graph with the entry block and exit block.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100429 entry_block_ = new (arena_) HBasicBlock(graph_, 0);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000430 graph_->AddBlock(entry_block_);
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100431 exit_block_ = new (arena_) HBasicBlock(graph_, kNoDexPc);
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000432 graph_->SetEntryBlock(entry_block_);
433 graph_->SetExitBlock(exit_block_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000434
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000435 InitializeLocals(code_item.registers_size_);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000436 graph_->SetMaximumNumberOfOutVRegs(code_item.outs_size_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000437
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000438 // Compute the number of dex instructions, blocks, and branches. We will
439 // check these values against limits given to the compiler.
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000440 size_t number_of_branches = 0;
441
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000442 // To avoid splitting blocks, we compute ahead of time the instructions that
443 // start a new block, and create these blocks.
Calin Juravle702d2602015-04-30 19:28:21 +0100444 if (!ComputeBranchTargets(code_ptr, code_end, &number_of_branches)) {
445 MaybeRecordStat(MethodCompilationStat::kNotCompiledBranchOutsideMethodCode);
446 return false;
447 }
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000448
449 // Note that the compiler driver is null when unit testing.
David Brazdil1b498722015-03-31 11:37:18 +0100450 if ((compiler_driver_ != nullptr) && SkipCompilation(code_item, number_of_branches)) {
David Brazdil5e8b1372015-01-23 14:39:08 +0000451 return false;
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000452 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000453
David Brazdil0b5c7d12015-06-11 11:17:49 +0100454 CreateBlocksForTryCatch(code_item);
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000455
Nicolas Geoffray52e832b2014-11-06 15:15:31 +0000456 InitializeParameters(code_item.ins_size_);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100457
Calin Juravle225ff812014-11-13 16:46:39 +0000458 size_t dex_pc = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000459 while (code_ptr < code_end) {
Calin Juravle225ff812014-11-13 16:46:39 +0000460 // Update the current block if dex_pc starts a new block.
461 MaybeUpdateCurrentBlock(dex_pc);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000462 const Instruction& instruction = *Instruction::At(code_ptr);
Calin Juravle48c2b032014-12-09 18:11:36 +0000463 if (!AnalyzeDexInstruction(instruction, dex_pc)) {
David Brazdil5e8b1372015-01-23 14:39:08 +0000464 return false;
Calin Juravle48c2b032014-12-09 18:11:36 +0000465 }
Calin Juravle225ff812014-11-13 16:46:39 +0000466 dex_pc += instruction.SizeInCodeUnits();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000467 code_ptr += instruction.SizeInCodeUnits();
468 }
469
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +0000470 // Add the suspend check to the entry block.
471 entry_block_->AddInstruction(new (arena_) HSuspendCheck(0));
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000472 entry_block_->AddInstruction(new (arena_) HGoto());
David Brazdil0b5c7d12015-06-11 11:17:49 +0100473 // Add Exit to the exit block.
474 exit_block_->AddInstruction(new (arena_) HExit());
David Brazdil5e8b1372015-01-23 14:39:08 +0000475
David Brazdil0b5c7d12015-06-11 11:17:49 +0100476 // Iterate over blocks covered by TryItems and insert TryBoundaries at entry
477 // and exit points. This requires all control-flow instructions and
478 // non-exceptional edges to have been created.
479 InsertTryBoundaryBlocks(code_item);
480
481 // Add the exit block at the end to give it the highest id.
482 graph_->AddBlock(exit_block_);
David Brazdil5e8b1372015-01-23 14:39:08 +0000483 return true;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000484}
485
David Brazdil0b5c7d12015-06-11 11:17:49 +0100486void HGraphBuilder::MaybeUpdateCurrentBlock(size_t dex_pc) {
487 HBasicBlock* block = FindBlockStartingAt(dex_pc);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000488 if (block == nullptr) {
489 return;
490 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000491
492 if (current_block_ != nullptr) {
493 // Branching instructions clear current_block, so we know
494 // the last instruction of the current block is not a branching
495 // instruction. We add an unconditional goto to the found block.
496 current_block_->AddInstruction(new (arena_) HGoto());
497 current_block_->AddSuccessor(block);
498 }
499 graph_->AddBlock(block);
500 current_block_ = block;
501}
502
Calin Juravle702d2602015-04-30 19:28:21 +0100503bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr,
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000504 const uint16_t* code_end,
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000505 size_t* number_of_branches) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000506 branch_targets_.SetSize(code_end - code_ptr);
507
508 // Create the first block for the dex instructions, single successor of the entry block.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100509 HBasicBlock* block = new (arena_) HBasicBlock(graph_, 0);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000510 branch_targets_.Put(0, block);
511 entry_block_->AddSuccessor(block);
512
513 // Iterate over all instructions and find branching instructions. Create blocks for
514 // the locations these instructions branch to.
Andreas Gamped881df52014-11-24 23:28:39 -0800515 uint32_t dex_pc = 0;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000516 while (code_ptr < code_end) {
517 const Instruction& instruction = *Instruction::At(code_ptr);
518 if (instruction.IsBranch()) {
Nicolas Geoffray43a539f2014-12-02 10:19:51 +0000519 (*number_of_branches)++;
Calin Juravle225ff812014-11-13 16:46:39 +0000520 int32_t target = instruction.GetTargetOffset() + dex_pc;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000521 // Create a block for the target instruction.
David Brazdil0b5c7d12015-06-11 11:17:49 +0100522 FindOrCreateBlockStartingAt(target);
523
Calin Juravle225ff812014-11-13 16:46:39 +0000524 dex_pc += instruction.SizeInCodeUnits();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000525 code_ptr += instruction.SizeInCodeUnits();
Calin Juravle702d2602015-04-30 19:28:21 +0100526
David Brazdilfe659462015-06-24 14:23:56 +0100527 if (instruction.CanFlowThrough()) {
528 if (code_ptr >= code_end) {
Calin Juravle702d2602015-04-30 19:28:21 +0100529 // In the normal case we should never hit this but someone can artificially forge a dex
530 // file to fall-through out the method code. In this case we bail out compilation.
531 return false;
David Brazdil0b5c7d12015-06-11 11:17:49 +0100532 } else {
533 FindOrCreateBlockStartingAt(dex_pc);
Calin Juravle702d2602015-04-30 19:28:21 +0100534 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000535 }
Andreas Gampee4d4d322014-12-04 09:09:57 -0800536 } else if (instruction.IsSwitch()) {
537 SwitchTable table(instruction, dex_pc, instruction.Opcode() == Instruction::SPARSE_SWITCH);
Andreas Gamped881df52014-11-24 23:28:39 -0800538
539 uint16_t num_entries = table.GetNumEntries();
540
Andreas Gampee4d4d322014-12-04 09:09:57 -0800541 // In a packed-switch, the entry at index 0 is the starting key. In a sparse-switch, the
542 // entry at index 0 is the first key, and values are after *all* keys.
543 size_t offset = table.GetFirstValueIndex();
544
545 // Use a larger loop counter type to avoid overflow issues.
546 for (size_t i = 0; i < num_entries; ++i) {
Andreas Gamped881df52014-11-24 23:28:39 -0800547 // The target of the case.
Andreas Gampee4d4d322014-12-04 09:09:57 -0800548 uint32_t target = dex_pc + table.GetEntryAt(i + offset);
David Brazdil0b5c7d12015-06-11 11:17:49 +0100549 FindOrCreateBlockStartingAt(target);
Andreas Gamped881df52014-11-24 23:28:39 -0800550
551 // The next case gets its own block.
552 if (i < num_entries) {
553 block = new (arena_) HBasicBlock(graph_, target);
554 branch_targets_.Put(table.GetDexPcForIndex(i), block);
Andreas Gamped881df52014-11-24 23:28:39 -0800555 }
556 }
557
558 // Fall-through. Add a block if there is more code afterwards.
559 dex_pc += instruction.SizeInCodeUnits();
560 code_ptr += instruction.SizeInCodeUnits();
Calin Juravle702d2602015-04-30 19:28:21 +0100561 if (code_ptr >= code_end) {
562 // In the normal case we should never hit this but someone can artificially forge a dex
563 // file to fall-through out the method code. In this case we bail out compilation.
564 // (A switch can fall-through so we don't need to check CanFlowThrough().)
565 return false;
David Brazdil0b5c7d12015-06-11 11:17:49 +0100566 } else {
567 FindOrCreateBlockStartingAt(dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -0800568 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000569 } else {
570 code_ptr += instruction.SizeInCodeUnits();
Calin Juravle225ff812014-11-13 16:46:39 +0000571 dex_pc += instruction.SizeInCodeUnits();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000572 }
573 }
Calin Juravle702d2602015-04-30 19:28:21 +0100574 return true;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000575}
576
David Brazdil0b5c7d12015-06-11 11:17:49 +0100577HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t dex_pc) const {
578 DCHECK_GE(dex_pc, 0);
579 DCHECK_LT(static_cast<size_t>(dex_pc), branch_targets_.Size());
580 return branch_targets_.Get(dex_pc);
581}
582
583HBasicBlock* HGraphBuilder::FindOrCreateBlockStartingAt(int32_t dex_pc) {
584 HBasicBlock* block = FindBlockStartingAt(dex_pc);
585 if (block == nullptr) {
586 block = new (arena_) HBasicBlock(graph_, dex_pc);
587 branch_targets_.Put(dex_pc, block);
588 }
589 return block;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000590}
591
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100592template<typename T>
Roland Levillain88cb1752014-10-20 16:36:47 +0100593void HGraphBuilder::Unop_12x(const Instruction& instruction, Primitive::Type type) {
594 HInstruction* first = LoadLocal(instruction.VRegB(), type);
595 current_block_->AddInstruction(new (arena_) T(type, first));
596 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
597}
598
Roland Levillaindff1f282014-11-05 14:15:05 +0000599void HGraphBuilder::Conversion_12x(const Instruction& instruction,
600 Primitive::Type input_type,
Roland Levillain624279f2014-12-04 11:54:28 +0000601 Primitive::Type result_type,
602 uint32_t dex_pc) {
Roland Levillaindff1f282014-11-05 14:15:05 +0000603 HInstruction* first = LoadLocal(instruction.VRegB(), input_type);
Roland Levillain624279f2014-12-04 11:54:28 +0000604 current_block_->AddInstruction(new (arena_) HTypeConversion(result_type, first, dex_pc));
Roland Levillaindff1f282014-11-05 14:15:05 +0000605 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
606}
607
Roland Levillain88cb1752014-10-20 16:36:47 +0100608template<typename T>
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100609void HGraphBuilder::Binop_23x(const Instruction& instruction, Primitive::Type type) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100610 HInstruction* first = LoadLocal(instruction.VRegB(), type);
611 HInstruction* second = LoadLocal(instruction.VRegC(), type);
612 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100613 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
614}
615
616template<typename T>
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000617void HGraphBuilder::Binop_23x(const Instruction& instruction,
618 Primitive::Type type,
619 uint32_t dex_pc) {
620 HInstruction* first = LoadLocal(instruction.VRegB(), type);
621 HInstruction* second = LoadLocal(instruction.VRegC(), type);
622 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
623 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
624}
625
626template<typename T>
Calin Juravle9aec02f2014-11-18 23:06:35 +0000627void HGraphBuilder::Binop_23x_shift(const Instruction& instruction,
628 Primitive::Type type) {
629 HInstruction* first = LoadLocal(instruction.VRegB(), type);
630 HInstruction* second = LoadLocal(instruction.VRegC(), Primitive::kPrimInt);
631 current_block_->AddInstruction(new (arena_) T(type, first, second));
632 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
633}
634
Calin Juravleddb7df22014-11-25 20:56:51 +0000635void HGraphBuilder::Binop_23x_cmp(const Instruction& instruction,
636 Primitive::Type type,
Alexey Frunze4dda3372015-06-01 18:31:49 -0700637 HCompare::Bias bias,
638 uint32_t dex_pc) {
Calin Juravleddb7df22014-11-25 20:56:51 +0000639 HInstruction* first = LoadLocal(instruction.VRegB(), type);
640 HInstruction* second = LoadLocal(instruction.VRegC(), type);
Alexey Frunze4dda3372015-06-01 18:31:49 -0700641 current_block_->AddInstruction(new (arena_) HCompare(type, first, second, bias, dex_pc));
Calin Juravleddb7df22014-11-25 20:56:51 +0000642 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
643}
644
Calin Juravle9aec02f2014-11-18 23:06:35 +0000645template<typename T>
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100646void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) {
647 HInstruction* first = LoadLocal(instruction.VRegA(), type);
648 HInstruction* second = LoadLocal(instruction.VRegB(), type);
649 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100650 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
651}
652
653template<typename T>
Calin Juravle9aec02f2014-11-18 23:06:35 +0000654void HGraphBuilder::Binop_12x_shift(const Instruction& instruction, Primitive::Type type) {
655 HInstruction* first = LoadLocal(instruction.VRegA(), type);
656 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
657 current_block_->AddInstruction(new (arena_) T(type, first, second));
658 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
659}
660
661template<typename T>
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000662void HGraphBuilder::Binop_12x(const Instruction& instruction,
663 Primitive::Type type,
664 uint32_t dex_pc) {
665 HInstruction* first = LoadLocal(instruction.VRegA(), type);
666 HInstruction* second = LoadLocal(instruction.VRegB(), type);
667 current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
668 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
669}
670
671template<typename T>
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100672void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100673 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000674 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100675 if (reverse) {
676 std::swap(first, second);
677 }
678 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
679 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
680}
681
682template<typename T>
683void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100684 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
David Brazdil8d5b8b22015-03-24 10:51:52 +0000685 HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100686 if (reverse) {
687 std::swap(first, second);
688 }
689 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
690 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
691}
692
Calin Juravle0c25d102015-04-20 14:49:09 +0100693static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, const CompilerDriver& driver) {
Calin Juravle27df7582015-04-17 19:12:31 +0100694 Thread* self = Thread::Current();
Calin Juravle0c25d102015-04-20 14:49:09 +0100695 return cu->IsConstructor()
696 && driver.RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex());
Calin Juravle27df7582015-04-17 19:12:31 +0100697}
698
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100699void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) {
700 if (type == Primitive::kPrimVoid) {
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100701 if (graph_->ShouldGenerateConstructorBarrier()) {
702 // The compilation unit is null during testing.
703 if (dex_compilation_unit_ != nullptr) {
704 DCHECK(RequiresConstructorBarrier(dex_compilation_unit_, *compiler_driver_))
705 << "Inconsistent use of ShouldGenerateConstructorBarrier. Should not generate a barrier.";
706 }
Calin Juravle27df7582015-04-17 19:12:31 +0100707 current_block_->AddInstruction(new (arena_) HMemoryBarrier(kStoreStore));
708 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100709 current_block_->AddInstruction(new (arena_) HReturnVoid());
710 } else {
711 HInstruction* value = LoadLocal(instruction.VRegA(), type);
712 current_block_->AddInstruction(new (arena_) HReturn(value));
713 }
714 current_block_->AddSuccessor(exit_block_);
715 current_block_ = nullptr;
716}
717
718bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +0000719 uint32_t dex_pc,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100720 uint32_t method_idx,
721 uint32_t number_of_vreg_arguments,
722 bool is_range,
723 uint32_t* args,
724 uint32_t register_index) {
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +0100725 Instruction::Code opcode = instruction.Opcode();
726 InvokeType invoke_type;
727 switch (opcode) {
728 case Instruction::INVOKE_STATIC:
729 case Instruction::INVOKE_STATIC_RANGE:
730 invoke_type = kStatic;
731 break;
732 case Instruction::INVOKE_DIRECT:
733 case Instruction::INVOKE_DIRECT_RANGE:
734 invoke_type = kDirect;
735 break;
736 case Instruction::INVOKE_VIRTUAL:
737 case Instruction::INVOKE_VIRTUAL_RANGE:
738 invoke_type = kVirtual;
739 break;
740 case Instruction::INVOKE_INTERFACE:
741 case Instruction::INVOKE_INTERFACE_RANGE:
742 invoke_type = kInterface;
743 break;
744 case Instruction::INVOKE_SUPER_RANGE:
745 case Instruction::INVOKE_SUPER:
746 invoke_type = kSuper;
747 break;
748 default:
749 LOG(FATAL) << "Unexpected invoke op: " << opcode;
750 return false;
751 }
752
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100753 const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
754 const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_id.proto_idx_);
755 const char* descriptor = dex_file_->StringDataByIdx(proto_id.shorty_idx_);
756 Primitive::Type return_type = Primitive::GetType(descriptor[0]);
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +0100757 bool is_instance_call = invoke_type != kStatic;
Nicolas Geoffray2e335252015-06-18 11:11:27 +0100758 // Remove the return type from the 'proto'.
759 size_t number_of_arguments = strlen(descriptor) - 1;
760 if (is_instance_call) {
761 // One extra argument for 'this'.
762 ++number_of_arguments;
763 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100764
Calin Juravlec7c8fe22014-12-02 11:42:34 +0000765 MethodReference target_method(dex_file_, method_idx);
766 uintptr_t direct_code;
767 uintptr_t direct_method;
768 int table_index;
769 InvokeType optimized_invoke_type = invoke_type;
Nicolas Geoffray52839d12014-11-07 17:47:25 +0000770
Calin Juravlec7c8fe22014-12-02 11:42:34 +0000771 if (!compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_pc, true, true,
772 &optimized_invoke_type, &target_method, &table_index,
773 &direct_code, &direct_method)) {
Nicolas Geoffray2e335252015-06-18 11:11:27 +0100774 VLOG(compiler) << "Did not compile "
775 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
Calin Juravle48c2b032014-12-09 18:11:36 +0000776 << " because a method call could not be resolved";
777 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedMethod);
Calin Juravlec7c8fe22014-12-02 11:42:34 +0000778 return false;
779 }
780 DCHECK(optimized_invoke_type != kSuper);
781
Roland Levillain4c0eb422015-04-24 16:43:49 +0100782 // By default, consider that the called method implicitly requires
783 // an initialization check of its declaring method.
784 HInvokeStaticOrDirect::ClinitCheckRequirement clinit_check_requirement =
785 HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit;
786 // Potential class initialization check, in the case of a static method call.
787 HClinitCheck* clinit_check = nullptr;
Jeff Hao848f70a2014-01-15 13:49:50 -0800788 // Replace calls to String.<init> with StringFactory.
789 int32_t string_init_offset = 0;
790 bool is_string_init = compiler_driver_->IsStringInit(method_idx, dex_file_, &string_init_offset);
791 if (is_string_init) {
792 return_type = Primitive::kPrimNot;
793 is_instance_call = false;
794 number_of_arguments--;
795 invoke_type = kStatic;
796 optimized_invoke_type = kStatic;
797 }
Roland Levillain4c0eb422015-04-24 16:43:49 +0100798
Calin Juravlec7c8fe22014-12-02 11:42:34 +0000799 HInvoke* invoke = nullptr;
Roland Levillain4c0eb422015-04-24 16:43:49 +0100800
Calin Juravlec7c8fe22014-12-02 11:42:34 +0000801 if (optimized_invoke_type == kVirtual) {
802 invoke = new (arena_) HInvokeVirtual(
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800803 arena_, number_of_arguments, return_type, dex_pc, method_idx, table_index);
Calin Juravlec7c8fe22014-12-02 11:42:34 +0000804 } else if (optimized_invoke_type == kInterface) {
805 invoke = new (arena_) HInvokeInterface(
806 arena_, number_of_arguments, return_type, dex_pc, method_idx, table_index);
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +0100807 } else {
Calin Juravlec7c8fe22014-12-02 11:42:34 +0000808 DCHECK(optimized_invoke_type == kDirect || optimized_invoke_type == kStatic);
809 // Sharpening to kDirect only works if we compile PIC.
810 DCHECK((optimized_invoke_type == invoke_type) || (optimized_invoke_type != kDirect)
811 || compiler_driver_->GetCompilerOptions().GetCompilePic());
Nicolas Geoffray1cf95282014-12-12 19:22:03 +0000812 bool is_recursive =
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100813 (target_method.dex_method_index == outer_compilation_unit_->GetDexMethodIndex())
814 && (target_method.dex_file == outer_compilation_unit_->GetDexFile());
Roland Levillain4c0eb422015-04-24 16:43:49 +0100815
Jeff Haocad65422015-06-18 21:16:08 -0700816 if (optimized_invoke_type == kStatic && !is_string_init) {
Roland Levillain4c0eb422015-04-24 16:43:49 +0100817 ScopedObjectAccess soa(Thread::Current());
818 StackHandleScope<4> hs(soa.Self());
819 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
820 dex_compilation_unit_->GetClassLinker()->FindDexCache(
821 *dex_compilation_unit_->GetDexFile())));
822 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
823 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700824 ArtMethod* resolved_method = compiler_driver_->ResolveMethod(
825 soa, dex_cache, class_loader, dex_compilation_unit_, method_idx, optimized_invoke_type);
Roland Levillain4c0eb422015-04-24 16:43:49 +0100826
827 if (resolved_method == nullptr) {
828 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedMethod);
829 return false;
830 }
831
832 const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
833 Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
834 outer_compilation_unit_->GetClassLinker()->FindDexCache(outer_dex_file)));
Nicolas Geoffrayafd06412015-06-20 22:44:47 +0100835 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
Roland Levillain4c0eb422015-04-24 16:43:49 +0100836
837 // The index at which the method's class is stored in the DexCache's type array.
838 uint32_t storage_index = DexFile::kDexNoIndex;
Nicolas Geoffrayafd06412015-06-20 22:44:47 +0100839 bool is_outer_class = (resolved_method->GetDeclaringClass() == outer_class.Get());
840 if (is_outer_class) {
841 storage_index = outer_class->GetDexTypeIndex();
Roland Levillain4c0eb422015-04-24 16:43:49 +0100842 } else if (outer_dex_cache.Get() == dex_cache.Get()) {
843 // Get `storage_index` from IsClassOfStaticMethodAvailableToReferrer.
844 compiler_driver_->IsClassOfStaticMethodAvailableToReferrer(outer_dex_cache.Get(),
Nicolas Geoffrayafd06412015-06-20 22:44:47 +0100845 GetCompilingClass(),
Roland Levillain4c0eb422015-04-24 16:43:49 +0100846 resolved_method,
847 method_idx,
848 &storage_index);
849 }
850
Nicolas Geoffrayb783b402015-06-22 11:06:43 +0100851 if (!outer_class->IsInterface()
852 && outer_class->IsSubClass(resolved_method->GetDeclaringClass())) {
Nicolas Geoffrayafd06412015-06-20 22:44:47 +0100853 // If the outer class is the declaring class or a subclass
Roland Levillain5f02c6c2015-04-24 19:14:22 +0100854 // of the declaring class, no class initialization is needed
855 // before the static method call.
Nicolas Geoffrayafd06412015-06-20 22:44:47 +0100856 // Note that in case of inlining, we do not need to add clinit checks
857 // to calls that satisfy this subclass check with any inlined methods. This
858 // will be detected by the optimization passes.
Roland Levillain4c0eb422015-04-24 16:43:49 +0100859 clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
860 } else if (storage_index != DexFile::kDexNoIndex) {
861 // If the method's class type index is available, check
862 // whether we should add an explicit class initialization
863 // check for its declaring class before the static method call.
864
865 // TODO: find out why this check is needed.
866 bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
867 *outer_compilation_unit_->GetDexFile(), storage_index);
868 bool is_initialized =
869 resolved_method->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
870
871 if (is_initialized) {
872 clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
873 } else {
874 clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +0100875 HLoadClass* load_class = new (arena_) HLoadClass(
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100876 graph_->GetCurrentMethod(),
877 storage_index,
878 *dex_compilation_unit_->GetDexFile(),
Nicolas Geoffrayafd06412015-06-20 22:44:47 +0100879 is_outer_class,
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100880 dex_pc);
Roland Levillain4c0eb422015-04-24 16:43:49 +0100881 current_block_->AddInstruction(load_class);
882 clinit_check = new (arena_) HClinitCheck(load_class, dex_pc);
883 current_block_->AddInstruction(clinit_check);
Roland Levillain4c0eb422015-04-24 16:43:49 +0100884 }
885 }
886 }
887
Guillaume "Vermeille" Sanchezae09d2d2015-05-29 10:52:55 +0100888 invoke = new (arena_) HInvokeStaticOrDirect(arena_,
889 number_of_arguments,
890 return_type,
891 dex_pc,
892 target_method.dex_method_index,
893 is_recursive,
894 string_init_offset,
895 invoke_type,
896 optimized_invoke_type,
897 clinit_check_requirement);
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +0100898 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100899
900 size_t start_index = 0;
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000901 Temporaries temps(graph_);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100902 if (is_instance_call) {
903 HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot);
Calin Juravle225ff812014-11-13 16:46:39 +0000904 HNullCheck* null_check = new (arena_) HNullCheck(arg, dex_pc);
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100905 current_block_->AddInstruction(null_check);
906 temps.Add(null_check);
907 invoke->SetArgumentAt(0, null_check);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100908 start_index = 1;
909 }
910
Nicolas Geoffray2e335252015-06-18 11:11:27 +0100911 uint32_t descriptor_index = 1; // Skip the return type.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100912 uint32_t argument_index = start_index;
Jeff Hao848f70a2014-01-15 13:49:50 -0800913 if (is_string_init) {
914 start_index = 1;
915 }
Nicolas Geoffray2e335252015-06-18 11:11:27 +0100916 for (size_t i = start_index;
917 // Make sure we don't go over the expected arguments or over the number of
918 // dex registers given. If the instruction was seen as dead by the verifier,
919 // it hasn't been properly checked.
920 (i < number_of_vreg_arguments) && (argument_index < number_of_arguments);
921 i++, argument_index++) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100922 Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100923 bool is_wide = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble);
Nicolas Geoffray2e335252015-06-18 11:11:27 +0100924 if (!is_range
925 && is_wide
926 && ((i + 1 == number_of_vreg_arguments) || (args[i] + 1 != args[i + 1]))) {
927 // Longs and doubles should be in pairs, that is, sequential registers. The verifier should
928 // reject any class where this is violated. However, the verifier only does these checks
929 // on non trivially dead instructions, so we just bailout the compilation.
930 VLOG(compiler) << "Did not compile "
931 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
932 << " because of non-sequential dex register pair in wide argument";
933 MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode);
934 return false;
935 }
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +0100936 HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
937 invoke->SetArgumentAt(argument_index, arg);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100938 if (is_wide) {
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +0100939 i++;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100940 }
941 }
Nicolas Geoffray2e335252015-06-18 11:11:27 +0100942
943 if (argument_index != number_of_arguments) {
944 VLOG(compiler) << "Did not compile "
945 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
946 << " because of wrong number of arguments in invoke instruction";
947 MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode);
948 return false;
949 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100950
Nicolas Geoffray38207af2015-06-01 15:46:22 +0100951 if (invoke->IsInvokeStaticOrDirect()) {
952 invoke->SetArgumentAt(argument_index, graph_->GetCurrentMethod());
953 argument_index++;
954 }
955
Roland Levillain4c0eb422015-04-24 16:43:49 +0100956 if (clinit_check_requirement == HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit) {
957 // Add the class initialization check as last input of `invoke`.
958 DCHECK(clinit_check != nullptr);
Roland Levillain3e3d7332015-04-28 11:00:54 +0100959 invoke->SetArgumentAt(argument_index, clinit_check);
Roland Levillain4c0eb422015-04-24 16:43:49 +0100960 }
961
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100962 current_block_->AddInstruction(invoke);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +0100963 latest_result_ = invoke;
Jeff Hao848f70a2014-01-15 13:49:50 -0800964
965 // Add move-result for StringFactory method.
966 if (is_string_init) {
967 uint32_t orig_this_reg = is_range ? register_index : args[0];
Nicolas Geoffrayaa919202015-06-21 18:57:02 +0100968 UpdateLocal(orig_this_reg, invoke);
Jeff Hao848f70a2014-01-15 13:49:50 -0800969 const VerifiedMethod* verified_method =
970 compiler_driver_->GetVerifiedMethod(dex_file_, dex_compilation_unit_->GetDexMethodIndex());
971 if (verified_method == nullptr) {
972 LOG(WARNING) << "No verified method for method calling String.<init>: "
973 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_);
974 return false;
975 }
976 const SafeMap<uint32_t, std::set<uint32_t>>& string_init_map =
977 verified_method->GetStringInitPcRegMap();
978 auto map_it = string_init_map.find(dex_pc);
979 if (map_it != string_init_map.end()) {
980 std::set<uint32_t> reg_set = map_it->second;
981 for (auto set_it = reg_set.begin(); set_it != reg_set.end(); ++set_it) {
Nicolas Geoffrayaa919202015-06-21 18:57:02 +0100982 HInstruction* load_local = LoadLocal(orig_this_reg, Primitive::kPrimNot);
983 UpdateLocal(*set_it, load_local);
Jeff Hao848f70a2014-01-15 13:49:50 -0800984 }
985 }
Jeff Hao848f70a2014-01-15 13:49:50 -0800986 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100987 return true;
988}
989
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100990bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +0000991 uint32_t dex_pc,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100992 bool is_put) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100993 uint32_t source_or_dest_reg = instruction.VRegA_22c();
994 uint32_t obj_reg = instruction.VRegB_22c();
995 uint16_t field_index = instruction.VRegC_22c();
996
997 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartierc7853442015-03-27 14:35:38 -0700998 ArtField* resolved_field =
999 compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001000
Mathieu Chartierc7853442015-03-27 14:35:38 -07001001 if (resolved_field == nullptr) {
Calin Juravle48c2b032014-12-09 18:11:36 +00001002 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001003 return false;
1004 }
Calin Juravle52c48962014-12-16 17:02:57 +00001005
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001006 Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001007
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001008 HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot);
Calin Juravle225ff812014-11-13 16:46:39 +00001009 current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_pc));
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001010 if (is_put) {
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001011 Temporaries temps(graph_);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001012 HInstruction* null_check = current_block_->GetLastInstruction();
1013 // We need one temporary for the null check.
1014 temps.Add(null_check);
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001015 HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001016 current_block_->AddInstruction(new (arena_) HInstanceFieldSet(
1017 null_check,
1018 value,
Nicolas Geoffray39468442014-09-02 15:17:15 +01001019 field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00001020 resolved_field->GetOffset(),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001021 resolved_field->IsVolatile(),
1022 field_index,
1023 *dex_file_));
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001024 } else {
1025 current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
1026 current_block_->GetLastInstruction(),
Nicolas Geoffrayabed4d02014-07-14 15:24:11 +01001027 field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00001028 resolved_field->GetOffset(),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001029 resolved_field->IsVolatile(),
1030 field_index,
1031 *dex_file_));
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001032
1033 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
1034 }
1035 return true;
1036}
1037
Nicolas Geoffray30451742015-06-19 13:32:41 +01001038static mirror::Class* GetClassFrom(CompilerDriver* driver,
1039 const DexCompilationUnit& compilation_unit) {
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001040 ScopedObjectAccess soa(Thread::Current());
1041 StackHandleScope<2> hs(soa.Self());
Nicolas Geoffray30451742015-06-19 13:32:41 +01001042 const DexFile& dex_file = *compilation_unit.GetDexFile();
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001043 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
Nicolas Geoffray30451742015-06-19 13:32:41 +01001044 soa.Decode<mirror::ClassLoader*>(compilation_unit.GetClassLoader())));
1045 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
1046 compilation_unit.GetClassLinker()->FindDexCache(dex_file)));
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001047
Nicolas Geoffray30451742015-06-19 13:32:41 +01001048 return driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, &compilation_unit);
1049}
1050
1051mirror::Class* HGraphBuilder::GetOutermostCompilingClass() const {
1052 return GetClassFrom(compiler_driver_, *outer_compilation_unit_);
1053}
1054
1055mirror::Class* HGraphBuilder::GetCompilingClass() const {
1056 return GetClassFrom(compiler_driver_, *dex_compilation_unit_);
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001057}
1058
1059bool HGraphBuilder::IsOutermostCompilingClass(uint16_t type_index) const {
1060 ScopedObjectAccess soa(Thread::Current());
1061 StackHandleScope<4> hs(soa.Self());
1062 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
1063 dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile())));
1064 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
1065 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
1066 Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass(
1067 soa, dex_cache, class_loader, type_index, dex_compilation_unit_)));
Nicolas Geoffrayafd06412015-06-20 22:44:47 +01001068 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001069
Nicolas Geoffrayafd06412015-06-20 22:44:47 +01001070 return outer_class.Get() == cls.Get();
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001071}
1072
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001073bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +00001074 uint32_t dex_pc,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001075 bool is_put) {
1076 uint32_t source_or_dest_reg = instruction.VRegA_21c();
1077 uint16_t field_index = instruction.VRegB_21c();
1078
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001079 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartierc7853442015-03-27 14:35:38 -07001080 StackHandleScope<4> hs(soa.Self());
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001081 Handle<mirror::DexCache> dex_cache(hs.NewHandle(
1082 dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile())));
1083 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
1084 soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
Mathieu Chartierc7853442015-03-27 14:35:38 -07001085 ArtField* resolved_field = compiler_driver_->ResolveField(
1086 soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001087
Mathieu Chartierc7853442015-03-27 14:35:38 -07001088 if (resolved_field == nullptr) {
Calin Juravle48c2b032014-12-09 18:11:36 +00001089 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001090 return false;
1091 }
1092
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001093 const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
1094 Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
1095 outer_compilation_unit_->GetClassLinker()->FindDexCache(outer_dex_file)));
Nicolas Geoffray30451742015-06-19 13:32:41 +01001096 Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001097
1098 // The index at which the field's class is stored in the DexCache's type array.
1099 uint32_t storage_index;
Nicolas Geoffray30451742015-06-19 13:32:41 +01001100 bool is_outer_class = (outer_class.Get() == resolved_field->GetDeclaringClass());
1101 if (is_outer_class) {
1102 storage_index = outer_class->GetDexTypeIndex();
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001103 } else if (outer_dex_cache.Get() != dex_cache.Get()) {
Roland Levillain4c0eb422015-04-24 16:43:49 +01001104 // The compiler driver cannot currently understand multiple dex caches involved. Just bailout.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001105 return false;
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001106 } else {
1107 std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField(
1108 outer_dex_cache.Get(),
Nicolas Geoffray30451742015-06-19 13:32:41 +01001109 GetCompilingClass(),
Mathieu Chartierc7853442015-03-27 14:35:38 -07001110 resolved_field,
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001111 field_index,
1112 &storage_index);
1113 bool can_easily_access = is_put ? pair.second : pair.first;
1114 if (!can_easily_access) {
1115 return false;
1116 }
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001117 }
1118
1119 // TODO: find out why this check is needed.
1120 bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
Nicolas Geoffray6a816cf2015-03-24 16:17:56 +00001121 *outer_compilation_unit_->GetDexFile(), storage_index);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001122 bool is_initialized = resolved_field->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001123
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001124 HLoadClass* constant = new (arena_) HLoadClass(graph_->GetCurrentMethod(),
1125 storage_index,
1126 *dex_compilation_unit_->GetDexFile(),
Nicolas Geoffray30451742015-06-19 13:32:41 +01001127 is_outer_class,
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001128 dex_pc);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001129 current_block_->AddInstruction(constant);
1130
1131 HInstruction* cls = constant;
Nicolas Geoffray30451742015-06-19 13:32:41 +01001132 if (!is_initialized && !is_outer_class) {
Calin Juravle225ff812014-11-13 16:46:39 +00001133 cls = new (arena_) HClinitCheck(constant, dex_pc);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001134 current_block_->AddInstruction(cls);
1135 }
1136
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001137 Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001138 if (is_put) {
1139 // We need to keep the class alive before loading the value.
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001140 Temporaries temps(graph_);
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001141 temps.Add(cls);
1142 HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
1143 DCHECK_EQ(value->GetType(), field_type);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001144 current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls,
1145 value,
1146 field_type,
1147 resolved_field->GetOffset(),
1148 resolved_field->IsVolatile(),
1149 field_index,
1150 *dex_file_));
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001151 } else {
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01001152 current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls,
1153 field_type,
1154 resolved_field->GetOffset(),
1155 resolved_field->IsVolatile(),
1156 field_index,
1157 *dex_file_));
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01001158 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
1159 }
1160 return true;
1161}
1162
Calin Juravlebacfec32014-11-14 15:54:36 +00001163void HGraphBuilder::BuildCheckedDivRem(uint16_t out_vreg,
1164 uint16_t first_vreg,
1165 int64_t second_vreg_or_constant,
1166 uint32_t dex_pc,
1167 Primitive::Type type,
1168 bool second_is_constant,
1169 bool isDiv) {
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001170 DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
Calin Juravled0d48522014-11-04 16:40:20 +00001171
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001172 HInstruction* first = LoadLocal(first_vreg, type);
1173 HInstruction* second = nullptr;
1174 if (second_is_constant) {
1175 if (type == Primitive::kPrimInt) {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001176 second = graph_->GetIntConstant(second_vreg_or_constant);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001177 } else {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001178 second = graph_->GetLongConstant(second_vreg_or_constant);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001179 }
1180 } else {
1181 second = LoadLocal(second_vreg_or_constant, type);
1182 }
1183
1184 if (!second_is_constant
1185 || (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0)
1186 || (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) {
1187 second = new (arena_) HDivZeroCheck(second, dex_pc);
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001188 Temporaries temps(graph_);
Calin Juravled0d48522014-11-04 16:40:20 +00001189 current_block_->AddInstruction(second);
1190 temps.Add(current_block_->GetLastInstruction());
1191 }
1192
Calin Juravlebacfec32014-11-14 15:54:36 +00001193 if (isDiv) {
1194 current_block_->AddInstruction(new (arena_) HDiv(type, first, second, dex_pc));
1195 } else {
1196 current_block_->AddInstruction(new (arena_) HRem(type, first, second, dex_pc));
1197 }
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001198 UpdateLocal(out_vreg, current_block_->GetLastInstruction());
Calin Juravled0d48522014-11-04 16:40:20 +00001199}
1200
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001201void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
Calin Juravle225ff812014-11-13 16:46:39 +00001202 uint32_t dex_pc,
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001203 bool is_put,
1204 Primitive::Type anticipated_type) {
1205 uint8_t source_or_dest_reg = instruction.VRegA_23x();
1206 uint8_t array_reg = instruction.VRegB_23x();
1207 uint8_t index_reg = instruction.VRegC_23x();
1208
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001209 // We need one temporary for the null check, one for the index, and one for the length.
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001210 Temporaries temps(graph_);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001211
1212 HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot);
Calin Juravle225ff812014-11-13 16:46:39 +00001213 object = new (arena_) HNullCheck(object, dex_pc);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001214 current_block_->AddInstruction(object);
1215 temps.Add(object);
1216
1217 HInstruction* length = new (arena_) HArrayLength(object);
1218 current_block_->AddInstruction(length);
1219 temps.Add(length);
1220 HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt);
Calin Juravle225ff812014-11-13 16:46:39 +00001221 index = new (arena_) HBoundsCheck(index, length, dex_pc);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001222 current_block_->AddInstruction(index);
1223 temps.Add(index);
1224 if (is_put) {
1225 HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type);
1226 // TODO: Insert a type check node if the type is Object.
Nicolas Geoffray39468442014-09-02 15:17:15 +01001227 current_block_->AddInstruction(new (arena_) HArraySet(
Calin Juravle225ff812014-11-13 16:46:39 +00001228 object, index, value, anticipated_type, dex_pc));
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001229 } else {
1230 current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type));
1231 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
1232 }
Mark Mendell1152c922015-04-24 17:06:35 -04001233 graph_->SetHasBoundsChecks(true);
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01001234}
1235
Calin Juravle225ff812014-11-13 16:46:39 +00001236void HGraphBuilder::BuildFilledNewArray(uint32_t dex_pc,
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001237 uint32_t type_index,
1238 uint32_t number_of_vreg_arguments,
1239 bool is_range,
1240 uint32_t* args,
1241 uint32_t register_index) {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001242 HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments);
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001243 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
1244 ? kQuickAllocArrayWithAccessCheck
1245 : kQuickAllocArray;
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01001246 HInstruction* object = new (arena_) HNewArray(length,
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01001247 graph_->GetCurrentMethod(),
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01001248 dex_pc,
1249 type_index,
1250 *dex_compilation_unit_->GetDexFile(),
1251 entrypoint);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001252 current_block_->AddInstruction(object);
1253
1254 const char* descriptor = dex_file_->StringByTypeIdx(type_index);
1255 DCHECK_EQ(descriptor[0], '[') << descriptor;
1256 char primitive = descriptor[1];
1257 DCHECK(primitive == 'I'
1258 || primitive == 'L'
1259 || primitive == '[') << descriptor;
1260 bool is_reference_array = (primitive == 'L') || (primitive == '[');
1261 Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt;
1262
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001263 Temporaries temps(graph_);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001264 temps.Add(object);
1265 for (size_t i = 0; i < number_of_vreg_arguments; ++i) {
1266 HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type);
David Brazdil8d5b8b22015-03-24 10:51:52 +00001267 HInstruction* index = graph_->GetIntConstant(i);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001268 current_block_->AddInstruction(
Calin Juravle225ff812014-11-13 16:46:39 +00001269 new (arena_) HArraySet(object, index, value, type, dex_pc));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001270 }
1271 latest_result_ = object;
1272}
1273
1274template <typename T>
1275void HGraphBuilder::BuildFillArrayData(HInstruction* object,
1276 const T* data,
1277 uint32_t element_count,
1278 Primitive::Type anticipated_type,
Calin Juravle225ff812014-11-13 16:46:39 +00001279 uint32_t dex_pc) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001280 for (uint32_t i = 0; i < element_count; ++i) {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001281 HInstruction* index = graph_->GetIntConstant(i);
1282 HInstruction* value = graph_->GetIntConstant(data[i]);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001283 current_block_->AddInstruction(new (arena_) HArraySet(
Calin Juravle225ff812014-11-13 16:46:39 +00001284 object, index, value, anticipated_type, dex_pc));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001285 }
1286}
1287
Calin Juravle225ff812014-11-13 16:46:39 +00001288void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) {
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001289 Temporaries temps(graph_);
Calin Juravled0d48522014-11-04 16:40:20 +00001290 HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot);
Calin Juravle225ff812014-11-13 16:46:39 +00001291 HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001292 current_block_->AddInstruction(null_check);
1293 temps.Add(null_check);
1294
1295 HInstruction* length = new (arena_) HArrayLength(null_check);
1296 current_block_->AddInstruction(length);
1297
Calin Juravle225ff812014-11-13 16:46:39 +00001298 int32_t payload_offset = instruction.VRegB_31t() + dex_pc;
Calin Juravled0d48522014-11-04 16:40:20 +00001299 const Instruction::ArrayDataPayload* payload =
1300 reinterpret_cast<const Instruction::ArrayDataPayload*>(code_start_ + payload_offset);
1301 const uint8_t* data = payload->data;
1302 uint32_t element_count = payload->element_count;
1303
1304 // Implementation of this DEX instruction seems to be that the bounds check is
1305 // done before doing any stores.
David Brazdil8d5b8b22015-03-24 10:51:52 +00001306 HInstruction* last_index = graph_->GetIntConstant(payload->element_count - 1);
Calin Juravle225ff812014-11-13 16:46:39 +00001307 current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_pc));
Calin Juravled0d48522014-11-04 16:40:20 +00001308
1309 switch (payload->element_width) {
1310 case 1:
1311 BuildFillArrayData(null_check,
1312 reinterpret_cast<const int8_t*>(data),
1313 element_count,
1314 Primitive::kPrimByte,
Calin Juravle225ff812014-11-13 16:46:39 +00001315 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001316 break;
1317 case 2:
1318 BuildFillArrayData(null_check,
1319 reinterpret_cast<const int16_t*>(data),
1320 element_count,
1321 Primitive::kPrimShort,
Calin Juravle225ff812014-11-13 16:46:39 +00001322 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001323 break;
1324 case 4:
1325 BuildFillArrayData(null_check,
1326 reinterpret_cast<const int32_t*>(data),
1327 element_count,
1328 Primitive::kPrimInt,
Calin Juravle225ff812014-11-13 16:46:39 +00001329 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001330 break;
1331 case 8:
1332 BuildFillWideArrayData(null_check,
1333 reinterpret_cast<const int64_t*>(data),
1334 element_count,
Calin Juravle225ff812014-11-13 16:46:39 +00001335 dex_pc);
Calin Juravled0d48522014-11-04 16:40:20 +00001336 break;
1337 default:
1338 LOG(FATAL) << "Unknown element width for " << payload->element_width;
1339 }
Mark Mendell1152c922015-04-24 17:06:35 -04001340 graph_->SetHasBoundsChecks(true);
Calin Juravled0d48522014-11-04 16:40:20 +00001341}
1342
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001343void HGraphBuilder::BuildFillWideArrayData(HInstruction* object,
Nicolas Geoffray8d6ae522014-10-23 18:32:13 +01001344 const int64_t* data,
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001345 uint32_t element_count,
Calin Juravle225ff812014-11-13 16:46:39 +00001346 uint32_t dex_pc) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001347 for (uint32_t i = 0; i < element_count; ++i) {
David Brazdil8d5b8b22015-03-24 10:51:52 +00001348 HInstruction* index = graph_->GetIntConstant(i);
1349 HInstruction* value = graph_->GetLongConstant(data[i]);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001350 current_block_->AddInstruction(new (arena_) HArraySet(
Calin Juravle225ff812014-11-13 16:46:39 +00001351 object, index, value, Primitive::kPrimLong, dex_pc));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001352 }
1353}
1354
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001355bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction,
1356 uint8_t destination,
1357 uint8_t reference,
1358 uint16_t type_index,
Calin Juravle225ff812014-11-13 16:46:39 +00001359 uint32_t dex_pc) {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001360 bool type_known_final;
1361 bool type_known_abstract;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001362 // `CanAccessTypeWithoutChecks` will tell whether the method being
1363 // built is trying to access its own class, so that the generated
1364 // code can optimize for this case. However, the optimization does not
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001365 // work for inlining, so we use `IsOutermostCompilingClass` instead.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001366 bool dont_use_is_referrers_class;
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001367 bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
1368 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001369 &type_known_final, &type_known_abstract, &dont_use_is_referrers_class);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001370 if (!can_access) {
Calin Juravle48c2b032014-12-09 18:11:36 +00001371 MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001372 return false;
1373 }
1374 HInstruction* object = LoadLocal(reference, Primitive::kPrimNot);
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001375 HLoadClass* cls = new (arena_) HLoadClass(
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001376 graph_->GetCurrentMethod(),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01001377 type_index,
1378 *dex_compilation_unit_->GetDexFile(),
1379 IsOutermostCompilingClass(type_index),
1380 dex_pc);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001381 current_block_->AddInstruction(cls);
1382 // The class needs a temporary before being used by the type check.
Calin Juravlef97f9fb2014-11-11 15:38:19 +00001383 Temporaries temps(graph_);
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001384 temps.Add(cls);
1385 if (instruction.Opcode() == Instruction::INSTANCE_OF) {
1386 current_block_->AddInstruction(
Calin Juravle225ff812014-11-13 16:46:39 +00001387 new (arena_) HInstanceOf(object, cls, type_known_final, dex_pc));
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001388 UpdateLocal(destination, current_block_->GetLastInstruction());
1389 } else {
1390 DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST);
1391 current_block_->AddInstruction(
Calin Juravle225ff812014-11-13 16:46:39 +00001392 new (arena_) HCheckCast(object, cls, type_known_final, dex_pc));
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00001393 }
1394 return true;
1395}
1396
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001397bool HGraphBuilder::NeedsAccessCheck(uint32_t type_index) const {
1398 return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks(
1399 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index);
1400}
1401
Calin Juravle48c2b032014-12-09 18:11:36 +00001402void HGraphBuilder::BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc) {
David Brazdil2ef645b2015-06-17 18:20:52 +01001403 // Verifier guarantees that the payload for PackedSwitch contains:
1404 // (a) number of entries (may be zero)
1405 // (b) first and lowest switch case value (entry 0, always present)
1406 // (c) list of target pcs (entries 1 <= i <= N)
Andreas Gamped881df52014-11-24 23:28:39 -08001407 SwitchTable table(instruction, dex_pc, false);
1408
1409 // Value to test against.
1410 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
1411
David Brazdil2ef645b2015-06-17 18:20:52 +01001412 // Retrieve number of entries.
Andreas Gampee4d4d322014-12-04 09:09:57 -08001413 uint16_t num_entries = table.GetNumEntries();
David Brazdil2ef645b2015-06-17 18:20:52 +01001414 if (num_entries == 0) {
1415 return;
1416 }
Andreas Gampee4d4d322014-12-04 09:09:57 -08001417
Andreas Gamped881df52014-11-24 23:28:39 -08001418 // Chained cmp-and-branch, starting from starting_key.
1419 int32_t starting_key = table.GetEntryAt(0);
1420
Andreas Gamped881df52014-11-24 23:28:39 -08001421 for (size_t i = 1; i <= num_entries; i++) {
Andreas Gampee4d4d322014-12-04 09:09:57 -08001422 BuildSwitchCaseHelper(instruction, i, i == num_entries, table, value, starting_key + i - 1,
1423 table.GetEntryAt(i), dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -08001424 }
Andreas Gamped881df52014-11-24 23:28:39 -08001425}
1426
Calin Juravle48c2b032014-12-09 18:11:36 +00001427void HGraphBuilder::BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc) {
David Brazdil2ef645b2015-06-17 18:20:52 +01001428 // Verifier guarantees that the payload for SparseSwitch contains:
1429 // (a) number of entries (may be zero)
1430 // (b) sorted key values (entries 0 <= i < N)
1431 // (c) target pcs corresponding to the switch values (entries N <= i < 2*N)
Andreas Gampee4d4d322014-12-04 09:09:57 -08001432 SwitchTable table(instruction, dex_pc, true);
1433
1434 // Value to test against.
1435 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
1436
1437 uint16_t num_entries = table.GetNumEntries();
Andreas Gampee4d4d322014-12-04 09:09:57 -08001438
1439 for (size_t i = 0; i < num_entries; i++) {
1440 BuildSwitchCaseHelper(instruction, i, i == static_cast<size_t>(num_entries) - 1, table, value,
1441 table.GetEntryAt(i), table.GetEntryAt(i + num_entries), dex_pc);
1442 }
Andreas Gampee4d4d322014-12-04 09:09:57 -08001443}
1444
1445void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t index,
1446 bool is_last_case, const SwitchTable& table,
1447 HInstruction* value, int32_t case_value_int,
1448 int32_t target_offset, uint32_t dex_pc) {
David Brazdil852eaff2015-02-02 15:23:05 +00001449 HBasicBlock* case_target = FindBlockStartingAt(dex_pc + target_offset);
1450 DCHECK(case_target != nullptr);
1451 PotentiallyAddSuspendCheck(case_target, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08001452
1453 // The current case's value.
David Brazdil8d5b8b22015-03-24 10:51:52 +00001454 HInstruction* this_case_value = graph_->GetIntConstant(case_value_int);
Andreas Gampee4d4d322014-12-04 09:09:57 -08001455
1456 // Compare value and this_case_value.
1457 HEqual* comparison = new (arena_) HEqual(value, this_case_value);
1458 current_block_->AddInstruction(comparison);
1459 HInstruction* ifinst = new (arena_) HIf(comparison);
1460 current_block_->AddInstruction(ifinst);
1461
1462 // Case hit: use the target offset to determine where to go.
Andreas Gampee4d4d322014-12-04 09:09:57 -08001463 current_block_->AddSuccessor(case_target);
1464
1465 // Case miss: go to the next case (or default fall-through).
1466 // When there is a next case, we use the block stored with the table offset representing this
1467 // case (that is where we registered them in ComputeBranchTargets).
1468 // When there is no next case, we use the following instruction.
1469 // TODO: Find a good way to peel the last iteration to avoid conditional, but still have re-use.
1470 if (!is_last_case) {
1471 HBasicBlock* next_case_target = FindBlockStartingAt(table.GetDexPcForIndex(index));
1472 DCHECK(next_case_target != nullptr);
1473 current_block_->AddSuccessor(next_case_target);
1474
1475 // Need to manually add the block, as there is no dex-pc transition for the cases.
1476 graph_->AddBlock(next_case_target);
1477
1478 current_block_ = next_case_target;
1479 } else {
1480 HBasicBlock* default_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
1481 DCHECK(default_target != nullptr);
1482 current_block_->AddSuccessor(default_target);
1483 current_block_ = nullptr;
1484 }
1485}
1486
David Brazdil852eaff2015-02-02 15:23:05 +00001487void HGraphBuilder::PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc) {
1488 int32_t target_offset = target->GetDexPc() - dex_pc;
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001489 if (target_offset <= 0) {
David Brazdil852eaff2015-02-02 15:23:05 +00001490 // DX generates back edges to the first encountered return. We can save
1491 // time of later passes by not adding redundant suspend checks.
David Brazdil2fd6aa52015-02-02 18:58:27 +00001492 HInstruction* last_in_target = target->GetLastInstruction();
1493 if (last_in_target != nullptr &&
1494 (last_in_target->IsReturn() || last_in_target->IsReturnVoid())) {
1495 return;
David Brazdil852eaff2015-02-02 15:23:05 +00001496 }
1497
1498 // Add a suspend check to backward branches which may potentially loop. We
1499 // can remove them after we recognize loops in the graph.
Calin Juravle225ff812014-11-13 16:46:39 +00001500 current_block_->AddInstruction(new (arena_) HSuspendCheck(dex_pc));
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001501 }
1502}
1503
Calin Juravle225ff812014-11-13 16:46:39 +00001504bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001505 if (current_block_ == nullptr) {
1506 return true; // Dead code
1507 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001508
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001509 switch (instruction.Opcode()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001510 case Instruction::CONST_4: {
1511 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001512 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001513 UpdateLocal(register_index, constant);
1514 break;
1515 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001516
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001517 case Instruction::CONST_16: {
1518 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001519 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s());
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001520 UpdateLocal(register_index, constant);
1521 break;
1522 }
1523
Dave Allison20dfc792014-06-16 20:44:29 -07001524 case Instruction::CONST: {
1525 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001526 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i());
Dave Allison20dfc792014-06-16 20:44:29 -07001527 UpdateLocal(register_index, constant);
1528 break;
1529 }
1530
1531 case Instruction::CONST_HIGH16: {
1532 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001533 HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16);
Dave Allison20dfc792014-06-16 20:44:29 -07001534 UpdateLocal(register_index, constant);
1535 break;
1536 }
1537
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001538 case Instruction::CONST_WIDE_16: {
1539 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -07001540 // Get 16 bits of constant value, sign extended to 64 bits.
1541 int64_t value = instruction.VRegB_21s();
1542 value <<= 48;
1543 value >>= 48;
David Brazdil8d5b8b22015-03-24 10:51:52 +00001544 HLongConstant* constant = graph_->GetLongConstant(value);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001545 UpdateLocal(register_index, constant);
1546 break;
1547 }
1548
1549 case Instruction::CONST_WIDE_32: {
1550 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -07001551 // Get 32 bits of constant value, sign extended to 64 bits.
1552 int64_t value = instruction.VRegB_31i();
1553 value <<= 32;
1554 value >>= 32;
David Brazdil8d5b8b22015-03-24 10:51:52 +00001555 HLongConstant* constant = graph_->GetLongConstant(value);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001556 UpdateLocal(register_index, constant);
1557 break;
1558 }
1559
1560 case Instruction::CONST_WIDE: {
1561 int32_t register_index = instruction.VRegA();
David Brazdil8d5b8b22015-03-24 10:51:52 +00001562 HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001563 UpdateLocal(register_index, constant);
1564 break;
1565 }
1566
Dave Allison20dfc792014-06-16 20:44:29 -07001567 case Instruction::CONST_WIDE_HIGH16: {
1568 int32_t register_index = instruction.VRegA();
1569 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
David Brazdil8d5b8b22015-03-24 10:51:52 +00001570 HLongConstant* constant = graph_->GetLongConstant(value);
Dave Allison20dfc792014-06-16 20:44:29 -07001571 UpdateLocal(register_index, constant);
1572 break;
1573 }
1574
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00001575 // Note that the SSA building will refine the types.
Dave Allison20dfc792014-06-16 20:44:29 -07001576 case Instruction::MOVE:
1577 case Instruction::MOVE_FROM16:
1578 case Instruction::MOVE_16: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001579 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001580 UpdateLocal(instruction.VRegA(), value);
1581 break;
1582 }
1583
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00001584 // Note that the SSA building will refine the types.
Dave Allison20dfc792014-06-16 20:44:29 -07001585 case Instruction::MOVE_WIDE:
1586 case Instruction::MOVE_WIDE_FROM16:
1587 case Instruction::MOVE_WIDE_16: {
1588 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong);
1589 UpdateLocal(instruction.VRegA(), value);
1590 break;
1591 }
1592
1593 case Instruction::MOVE_OBJECT:
1594 case Instruction::MOVE_OBJECT_16:
1595 case Instruction::MOVE_OBJECT_FROM16: {
1596 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot);
1597 UpdateLocal(instruction.VRegA(), value);
1598 break;
1599 }
1600
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001601 case Instruction::RETURN_VOID: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001602 BuildReturn(instruction, Primitive::kPrimVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001603 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001604 }
1605
Dave Allison20dfc792014-06-16 20:44:29 -07001606#define IF_XX(comparison, cond) \
Calin Juravle225ff812014-11-13 16:46:39 +00001607 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_pc); break; \
1608 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_pc); break
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001609
Dave Allison20dfc792014-06-16 20:44:29 -07001610 IF_XX(HEqual, EQ);
1611 IF_XX(HNotEqual, NE);
1612 IF_XX(HLessThan, LT);
1613 IF_XX(HLessThanOrEqual, LE);
1614 IF_XX(HGreaterThan, GT);
1615 IF_XX(HGreaterThanOrEqual, GE);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001616
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001617 case Instruction::GOTO:
1618 case Instruction::GOTO_16:
1619 case Instruction::GOTO_32: {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00001620 int32_t offset = instruction.GetTargetOffset();
Calin Juravle225ff812014-11-13 16:46:39 +00001621 HBasicBlock* target = FindBlockStartingAt(offset + dex_pc);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001622 DCHECK(target != nullptr);
David Brazdil852eaff2015-02-02 15:23:05 +00001623 PotentiallyAddSuspendCheck(target, dex_pc);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001624 current_block_->AddInstruction(new (arena_) HGoto());
1625 current_block_->AddSuccessor(target);
1626 current_block_ = nullptr;
1627 break;
1628 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001629
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001630 case Instruction::RETURN: {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001631 BuildReturn(instruction, return_type_);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001632 break;
1633 }
1634
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001635 case Instruction::RETURN_OBJECT: {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001636 BuildReturn(instruction, return_type_);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001637 break;
1638 }
1639
1640 case Instruction::RETURN_WIDE: {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001641 BuildReturn(instruction, return_type_);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001642 break;
1643 }
1644
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001645 case Instruction::INVOKE_DIRECT:
Nicolas Geoffray0d8db992014-11-11 14:40:10 +00001646 case Instruction::INVOKE_INTERFACE:
1647 case Instruction::INVOKE_STATIC:
1648 case Instruction::INVOKE_SUPER:
1649 case Instruction::INVOKE_VIRTUAL: {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001650 uint32_t method_idx = instruction.VRegB_35c();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001651 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001652 uint32_t args[5];
Ian Rogers29a26482014-05-02 15:27:29 -07001653 instruction.GetVarArgs(args);
Calin Juravle225ff812014-11-13 16:46:39 +00001654 if (!BuildInvoke(instruction, dex_pc, method_idx,
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00001655 number_of_vreg_arguments, false, args, -1)) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001656 return false;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001657 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001658 break;
1659 }
1660
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001661 case Instruction::INVOKE_DIRECT_RANGE:
Nicolas Geoffray0d8db992014-11-11 14:40:10 +00001662 case Instruction::INVOKE_INTERFACE_RANGE:
1663 case Instruction::INVOKE_STATIC_RANGE:
1664 case Instruction::INVOKE_SUPER_RANGE:
1665 case Instruction::INVOKE_VIRTUAL_RANGE: {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001666 uint32_t method_idx = instruction.VRegB_3rc();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001667 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
1668 uint32_t register_index = instruction.VRegC();
Calin Juravle225ff812014-11-13 16:46:39 +00001669 if (!BuildInvoke(instruction, dex_pc, method_idx,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001670 number_of_vreg_arguments, true, nullptr, register_index)) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001671 return false;
1672 }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001673 break;
1674 }
1675
Roland Levillain88cb1752014-10-20 16:36:47 +01001676 case Instruction::NEG_INT: {
1677 Unop_12x<HNeg>(instruction, Primitive::kPrimInt);
1678 break;
1679 }
1680
Roland Levillain2e07b4f2014-10-23 18:12:09 +01001681 case Instruction::NEG_LONG: {
1682 Unop_12x<HNeg>(instruction, Primitive::kPrimLong);
1683 break;
1684 }
1685
Roland Levillain3dbcb382014-10-28 17:30:07 +00001686 case Instruction::NEG_FLOAT: {
1687 Unop_12x<HNeg>(instruction, Primitive::kPrimFloat);
1688 break;
1689 }
1690
1691 case Instruction::NEG_DOUBLE: {
1692 Unop_12x<HNeg>(instruction, Primitive::kPrimDouble);
1693 break;
1694 }
1695
Roland Levillain1cc5f2512014-10-22 18:06:21 +01001696 case Instruction::NOT_INT: {
1697 Unop_12x<HNot>(instruction, Primitive::kPrimInt);
1698 break;
1699 }
1700
Roland Levillain70566432014-10-24 16:20:17 +01001701 case Instruction::NOT_LONG: {
1702 Unop_12x<HNot>(instruction, Primitive::kPrimLong);
1703 break;
1704 }
1705
Roland Levillaindff1f282014-11-05 14:15:05 +00001706 case Instruction::INT_TO_LONG: {
Roland Levillain624279f2014-12-04 11:54:28 +00001707 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong, dex_pc);
Roland Levillaindff1f282014-11-05 14:15:05 +00001708 break;
1709 }
1710
Roland Levillaincff13742014-11-17 14:32:17 +00001711 case Instruction::INT_TO_FLOAT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001712 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimFloat, dex_pc);
Roland Levillaincff13742014-11-17 14:32:17 +00001713 break;
1714 }
1715
1716 case Instruction::INT_TO_DOUBLE: {
Roland Levillain624279f2014-12-04 11:54:28 +00001717 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimDouble, dex_pc);
Roland Levillaincff13742014-11-17 14:32:17 +00001718 break;
1719 }
1720
Roland Levillain946e1432014-11-11 17:35:19 +00001721 case Instruction::LONG_TO_INT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001722 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimInt, dex_pc);
Roland Levillain946e1432014-11-11 17:35:19 +00001723 break;
1724 }
1725
Roland Levillain6d0e4832014-11-27 18:31:21 +00001726 case Instruction::LONG_TO_FLOAT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001727 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimFloat, dex_pc);
Roland Levillain6d0e4832014-11-27 18:31:21 +00001728 break;
1729 }
1730
Roland Levillain647b9ed2014-11-27 12:06:00 +00001731 case Instruction::LONG_TO_DOUBLE: {
Roland Levillain624279f2014-12-04 11:54:28 +00001732 Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimDouble, dex_pc);
Roland Levillain647b9ed2014-11-27 12:06:00 +00001733 break;
1734 }
1735
Roland Levillain3f8f9362014-12-02 17:45:01 +00001736 case Instruction::FLOAT_TO_INT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001737 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimInt, dex_pc);
1738 break;
1739 }
1740
1741 case Instruction::FLOAT_TO_LONG: {
1742 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimLong, dex_pc);
Roland Levillain3f8f9362014-12-02 17:45:01 +00001743 break;
1744 }
1745
Roland Levillain8964e2b2014-12-04 12:10:50 +00001746 case Instruction::FLOAT_TO_DOUBLE: {
1747 Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimDouble, dex_pc);
1748 break;
1749 }
1750
Roland Levillain4c0b61f2014-12-05 12:06:01 +00001751 case Instruction::DOUBLE_TO_INT: {
1752 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimInt, dex_pc);
1753 break;
1754 }
1755
1756 case Instruction::DOUBLE_TO_LONG: {
1757 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimLong, dex_pc);
1758 break;
1759 }
1760
Roland Levillain8964e2b2014-12-04 12:10:50 +00001761 case Instruction::DOUBLE_TO_FLOAT: {
1762 Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimFloat, dex_pc);
1763 break;
1764 }
1765
Roland Levillain51d3fc42014-11-13 14:11:42 +00001766 case Instruction::INT_TO_BYTE: {
Roland Levillain624279f2014-12-04 11:54:28 +00001767 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimByte, dex_pc);
Roland Levillain51d3fc42014-11-13 14:11:42 +00001768 break;
1769 }
1770
Roland Levillain01a8d712014-11-14 16:27:39 +00001771 case Instruction::INT_TO_SHORT: {
Roland Levillain624279f2014-12-04 11:54:28 +00001772 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimShort, dex_pc);
Roland Levillain01a8d712014-11-14 16:27:39 +00001773 break;
1774 }
1775
Roland Levillain981e4542014-11-14 11:47:14 +00001776 case Instruction::INT_TO_CHAR: {
Roland Levillain624279f2014-12-04 11:54:28 +00001777 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimChar, dex_pc);
Roland Levillain981e4542014-11-14 11:47:14 +00001778 break;
1779 }
1780
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001781 case Instruction::ADD_INT: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001782 Binop_23x<HAdd>(instruction, Primitive::kPrimInt);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001783 break;
1784 }
1785
1786 case Instruction::ADD_LONG: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001787 Binop_23x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001788 break;
1789 }
1790
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001791 case Instruction::ADD_DOUBLE: {
1792 Binop_23x<HAdd>(instruction, Primitive::kPrimDouble);
1793 break;
1794 }
1795
1796 case Instruction::ADD_FLOAT: {
1797 Binop_23x<HAdd>(instruction, Primitive::kPrimFloat);
1798 break;
1799 }
1800
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001801 case Instruction::SUB_INT: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001802 Binop_23x<HSub>(instruction, Primitive::kPrimInt);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001803 break;
1804 }
1805
1806 case Instruction::SUB_LONG: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001807 Binop_23x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001808 break;
1809 }
1810
Calin Juravle096cc022014-10-23 17:01:13 +01001811 case Instruction::SUB_FLOAT: {
1812 Binop_23x<HSub>(instruction, Primitive::kPrimFloat);
1813 break;
1814 }
1815
1816 case Instruction::SUB_DOUBLE: {
1817 Binop_23x<HSub>(instruction, Primitive::kPrimDouble);
1818 break;
1819 }
1820
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001821 case Instruction::ADD_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001822 Binop_12x<HAdd>(instruction, Primitive::kPrimInt);
1823 break;
1824 }
1825
Calin Juravle34bacdf2014-10-07 20:23:36 +01001826 case Instruction::MUL_INT: {
1827 Binop_23x<HMul>(instruction, Primitive::kPrimInt);
1828 break;
1829 }
1830
1831 case Instruction::MUL_LONG: {
1832 Binop_23x<HMul>(instruction, Primitive::kPrimLong);
1833 break;
1834 }
1835
Calin Juravleb5bfa962014-10-21 18:02:24 +01001836 case Instruction::MUL_FLOAT: {
1837 Binop_23x<HMul>(instruction, Primitive::kPrimFloat);
1838 break;
1839 }
1840
1841 case Instruction::MUL_DOUBLE: {
1842 Binop_23x<HMul>(instruction, Primitive::kPrimDouble);
1843 break;
1844 }
1845
Calin Juravled0d48522014-11-04 16:40:20 +00001846 case Instruction::DIV_INT: {
Calin Juravlebacfec32014-11-14 15:54:36 +00001847 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1848 dex_pc, Primitive::kPrimInt, false, true);
Calin Juravled0d48522014-11-04 16:40:20 +00001849 break;
1850 }
1851
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001852 case Instruction::DIV_LONG: {
Calin Juravlebacfec32014-11-14 15:54:36 +00001853 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1854 dex_pc, Primitive::kPrimLong, false, true);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001855 break;
1856 }
1857
Calin Juravle7c4954d2014-10-28 16:57:40 +00001858 case Instruction::DIV_FLOAT: {
Calin Juravle225ff812014-11-13 16:46:39 +00001859 Binop_23x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00001860 break;
1861 }
1862
1863 case Instruction::DIV_DOUBLE: {
Calin Juravle225ff812014-11-13 16:46:39 +00001864 Binop_23x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00001865 break;
1866 }
1867
Calin Juravlebacfec32014-11-14 15:54:36 +00001868 case Instruction::REM_INT: {
1869 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1870 dex_pc, Primitive::kPrimInt, false, false);
1871 break;
1872 }
1873
1874 case Instruction::REM_LONG: {
1875 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1876 dex_pc, Primitive::kPrimLong, false, false);
1877 break;
1878 }
1879
Calin Juravled2ec87d2014-12-08 14:24:46 +00001880 case Instruction::REM_FLOAT: {
1881 Binop_23x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
1882 break;
1883 }
1884
1885 case Instruction::REM_DOUBLE: {
1886 Binop_23x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
1887 break;
1888 }
1889
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00001890 case Instruction::AND_INT: {
1891 Binop_23x<HAnd>(instruction, Primitive::kPrimInt);
1892 break;
1893 }
1894
1895 case Instruction::AND_LONG: {
1896 Binop_23x<HAnd>(instruction, Primitive::kPrimLong);
1897 break;
1898 }
1899
Calin Juravle9aec02f2014-11-18 23:06:35 +00001900 case Instruction::SHL_INT: {
1901 Binop_23x_shift<HShl>(instruction, Primitive::kPrimInt);
1902 break;
1903 }
1904
1905 case Instruction::SHL_LONG: {
1906 Binop_23x_shift<HShl>(instruction, Primitive::kPrimLong);
1907 break;
1908 }
1909
1910 case Instruction::SHR_INT: {
1911 Binop_23x_shift<HShr>(instruction, Primitive::kPrimInt);
1912 break;
1913 }
1914
1915 case Instruction::SHR_LONG: {
1916 Binop_23x_shift<HShr>(instruction, Primitive::kPrimLong);
1917 break;
1918 }
1919
1920 case Instruction::USHR_INT: {
1921 Binop_23x_shift<HUShr>(instruction, Primitive::kPrimInt);
1922 break;
1923 }
1924
1925 case Instruction::USHR_LONG: {
1926 Binop_23x_shift<HUShr>(instruction, Primitive::kPrimLong);
1927 break;
1928 }
1929
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00001930 case Instruction::OR_INT: {
1931 Binop_23x<HOr>(instruction, Primitive::kPrimInt);
1932 break;
1933 }
1934
1935 case Instruction::OR_LONG: {
1936 Binop_23x<HOr>(instruction, Primitive::kPrimLong);
1937 break;
1938 }
1939
1940 case Instruction::XOR_INT: {
1941 Binop_23x<HXor>(instruction, Primitive::kPrimInt);
1942 break;
1943 }
1944
1945 case Instruction::XOR_LONG: {
1946 Binop_23x<HXor>(instruction, Primitive::kPrimLong);
1947 break;
1948 }
1949
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001950 case Instruction::ADD_LONG_2ADDR: {
1951 Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001952 break;
1953 }
1954
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +01001955 case Instruction::ADD_DOUBLE_2ADDR: {
1956 Binop_12x<HAdd>(instruction, Primitive::kPrimDouble);
1957 break;
1958 }
1959
1960 case Instruction::ADD_FLOAT_2ADDR: {
1961 Binop_12x<HAdd>(instruction, Primitive::kPrimFloat);
1962 break;
1963 }
1964
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001965 case Instruction::SUB_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001966 Binop_12x<HSub>(instruction, Primitive::kPrimInt);
1967 break;
1968 }
1969
1970 case Instruction::SUB_LONG_2ADDR: {
1971 Binop_12x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001972 break;
1973 }
1974
Calin Juravle096cc022014-10-23 17:01:13 +01001975 case Instruction::SUB_FLOAT_2ADDR: {
1976 Binop_12x<HSub>(instruction, Primitive::kPrimFloat);
1977 break;
1978 }
1979
1980 case Instruction::SUB_DOUBLE_2ADDR: {
1981 Binop_12x<HSub>(instruction, Primitive::kPrimDouble);
1982 break;
1983 }
1984
Calin Juravle34bacdf2014-10-07 20:23:36 +01001985 case Instruction::MUL_INT_2ADDR: {
1986 Binop_12x<HMul>(instruction, Primitive::kPrimInt);
1987 break;
1988 }
1989
1990 case Instruction::MUL_LONG_2ADDR: {
1991 Binop_12x<HMul>(instruction, Primitive::kPrimLong);
1992 break;
1993 }
1994
Calin Juravleb5bfa962014-10-21 18:02:24 +01001995 case Instruction::MUL_FLOAT_2ADDR: {
1996 Binop_12x<HMul>(instruction, Primitive::kPrimFloat);
1997 break;
1998 }
1999
2000 case Instruction::MUL_DOUBLE_2ADDR: {
2001 Binop_12x<HMul>(instruction, Primitive::kPrimDouble);
2002 break;
2003 }
2004
Calin Juravle865fc882014-11-06 17:09:03 +00002005 case Instruction::DIV_INT_2ADDR: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002006 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2007 dex_pc, Primitive::kPrimInt, false, true);
Calin Juravle865fc882014-11-06 17:09:03 +00002008 break;
2009 }
2010
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002011 case Instruction::DIV_LONG_2ADDR: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002012 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2013 dex_pc, Primitive::kPrimLong, false, true);
2014 break;
2015 }
2016
2017 case Instruction::REM_INT_2ADDR: {
2018 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2019 dex_pc, Primitive::kPrimInt, false, false);
2020 break;
2021 }
2022
2023 case Instruction::REM_LONG_2ADDR: {
2024 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
2025 dex_pc, Primitive::kPrimLong, false, false);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002026 break;
2027 }
2028
Calin Juravled2ec87d2014-12-08 14:24:46 +00002029 case Instruction::REM_FLOAT_2ADDR: {
2030 Binop_12x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
2031 break;
2032 }
2033
2034 case Instruction::REM_DOUBLE_2ADDR: {
2035 Binop_12x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
2036 break;
2037 }
2038
Calin Juravle9aec02f2014-11-18 23:06:35 +00002039 case Instruction::SHL_INT_2ADDR: {
2040 Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt);
2041 break;
2042 }
2043
2044 case Instruction::SHL_LONG_2ADDR: {
2045 Binop_12x_shift<HShl>(instruction, Primitive::kPrimLong);
2046 break;
2047 }
2048
2049 case Instruction::SHR_INT_2ADDR: {
2050 Binop_12x_shift<HShr>(instruction, Primitive::kPrimInt);
2051 break;
2052 }
2053
2054 case Instruction::SHR_LONG_2ADDR: {
2055 Binop_12x_shift<HShr>(instruction, Primitive::kPrimLong);
2056 break;
2057 }
2058
2059 case Instruction::USHR_INT_2ADDR: {
2060 Binop_12x_shift<HUShr>(instruction, Primitive::kPrimInt);
2061 break;
2062 }
2063
2064 case Instruction::USHR_LONG_2ADDR: {
2065 Binop_12x_shift<HUShr>(instruction, Primitive::kPrimLong);
2066 break;
2067 }
2068
Calin Juravle7c4954d2014-10-28 16:57:40 +00002069 case Instruction::DIV_FLOAT_2ADDR: {
Calin Juravle225ff812014-11-13 16:46:39 +00002070 Binop_12x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002071 break;
2072 }
2073
2074 case Instruction::DIV_DOUBLE_2ADDR: {
Calin Juravle225ff812014-11-13 16:46:39 +00002075 Binop_12x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
Calin Juravle7c4954d2014-10-28 16:57:40 +00002076 break;
2077 }
2078
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002079 case Instruction::AND_INT_2ADDR: {
2080 Binop_12x<HAnd>(instruction, Primitive::kPrimInt);
2081 break;
2082 }
2083
2084 case Instruction::AND_LONG_2ADDR: {
2085 Binop_12x<HAnd>(instruction, Primitive::kPrimLong);
2086 break;
2087 }
2088
2089 case Instruction::OR_INT_2ADDR: {
2090 Binop_12x<HOr>(instruction, Primitive::kPrimInt);
2091 break;
2092 }
2093
2094 case Instruction::OR_LONG_2ADDR: {
2095 Binop_12x<HOr>(instruction, Primitive::kPrimLong);
2096 break;
2097 }
2098
2099 case Instruction::XOR_INT_2ADDR: {
2100 Binop_12x<HXor>(instruction, Primitive::kPrimInt);
2101 break;
2102 }
2103
2104 case Instruction::XOR_LONG_2ADDR: {
2105 Binop_12x<HXor>(instruction, Primitive::kPrimLong);
2106 break;
2107 }
2108
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002109 case Instruction::ADD_INT_LIT16: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002110 Binop_22s<HAdd>(instruction, false);
2111 break;
2112 }
2113
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002114 case Instruction::AND_INT_LIT16: {
2115 Binop_22s<HAnd>(instruction, false);
2116 break;
2117 }
2118
2119 case Instruction::OR_INT_LIT16: {
2120 Binop_22s<HOr>(instruction, false);
2121 break;
2122 }
2123
2124 case Instruction::XOR_INT_LIT16: {
2125 Binop_22s<HXor>(instruction, false);
2126 break;
2127 }
2128
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002129 case Instruction::RSUB_INT: {
2130 Binop_22s<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002131 break;
2132 }
2133
Calin Juravle34bacdf2014-10-07 20:23:36 +01002134 case Instruction::MUL_INT_LIT16: {
2135 Binop_22s<HMul>(instruction, false);
2136 break;
2137 }
2138
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002139 case Instruction::ADD_INT_LIT8: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002140 Binop_22b<HAdd>(instruction, false);
2141 break;
2142 }
2143
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002144 case Instruction::AND_INT_LIT8: {
2145 Binop_22b<HAnd>(instruction, false);
2146 break;
2147 }
2148
2149 case Instruction::OR_INT_LIT8: {
2150 Binop_22b<HOr>(instruction, false);
2151 break;
2152 }
2153
2154 case Instruction::XOR_INT_LIT8: {
2155 Binop_22b<HXor>(instruction, false);
2156 break;
2157 }
2158
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002159 case Instruction::RSUB_INT_LIT8: {
2160 Binop_22b<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002161 break;
2162 }
2163
Calin Juravle34bacdf2014-10-07 20:23:36 +01002164 case Instruction::MUL_INT_LIT8: {
2165 Binop_22b<HMul>(instruction, false);
2166 break;
2167 }
2168
Calin Juravled0d48522014-11-04 16:40:20 +00002169 case Instruction::DIV_INT_LIT16:
2170 case Instruction::DIV_INT_LIT8: {
Calin Juravlebacfec32014-11-14 15:54:36 +00002171 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2172 dex_pc, Primitive::kPrimInt, true, true);
2173 break;
2174 }
2175
2176 case Instruction::REM_INT_LIT16:
2177 case Instruction::REM_INT_LIT8: {
2178 BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
2179 dex_pc, Primitive::kPrimInt, true, false);
Calin Juravled0d48522014-11-04 16:40:20 +00002180 break;
2181 }
2182
Calin Juravle9aec02f2014-11-18 23:06:35 +00002183 case Instruction::SHL_INT_LIT8: {
2184 Binop_22b<HShl>(instruction, false);
2185 break;
2186 }
2187
2188 case Instruction::SHR_INT_LIT8: {
2189 Binop_22b<HShr>(instruction, false);
2190 break;
2191 }
2192
2193 case Instruction::USHR_INT_LIT8: {
2194 Binop_22b<HUShr>(instruction, false);
2195 break;
2196 }
2197
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002198 case Instruction::NEW_INSTANCE: {
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002199 uint16_t type_index = instruction.VRegB_21c();
Jeff Hao848f70a2014-01-15 13:49:50 -08002200 if (compiler_driver_->IsStringTypeIndex(type_index, dex_file_)) {
2201 // Turn new-instance of string into a const 0.
2202 int32_t register_index = instruction.VRegA();
2203 HNullConstant* constant = graph_->GetNullConstant();
2204 UpdateLocal(register_index, constant);
2205 } else {
2206 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
2207 ? kQuickAllocObjectWithAccessCheck
2208 : kQuickAllocObject;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002209
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002210 current_block_->AddInstruction(new (arena_) HNewInstance(
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002211 graph_->GetCurrentMethod(),
2212 dex_pc,
2213 type_index,
2214 *dex_compilation_unit_->GetDexFile(),
2215 entrypoint));
Jeff Hao848f70a2014-01-15 13:49:50 -08002216 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
2217 }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002218 break;
2219 }
2220
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002221 case Instruction::NEW_ARRAY: {
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002222 uint16_t type_index = instruction.VRegC_22c();
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002223 HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt);
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002224 QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
2225 ? kQuickAllocArrayWithAccessCheck
2226 : kQuickAllocArray;
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002227 current_block_->AddInstruction(new (arena_) HNewArray(length,
2228 graph_->GetCurrentMethod(),
2229 dex_pc,
2230 type_index,
2231 *dex_compilation_unit_->GetDexFile(),
2232 entrypoint));
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002233 UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
2234 break;
2235 }
2236
2237 case Instruction::FILLED_NEW_ARRAY: {
2238 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
2239 uint32_t type_index = instruction.VRegB_35c();
2240 uint32_t args[5];
2241 instruction.GetVarArgs(args);
Calin Juravle225ff812014-11-13 16:46:39 +00002242 BuildFilledNewArray(dex_pc, type_index, number_of_vreg_arguments, false, args, 0);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002243 break;
2244 }
2245
2246 case Instruction::FILLED_NEW_ARRAY_RANGE: {
2247 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
2248 uint32_t type_index = instruction.VRegB_3rc();
2249 uint32_t register_index = instruction.VRegC_3rc();
2250 BuildFilledNewArray(
Calin Juravle225ff812014-11-13 16:46:39 +00002251 dex_pc, type_index, number_of_vreg_arguments, true, nullptr, register_index);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002252 break;
2253 }
2254
2255 case Instruction::FILL_ARRAY_DATA: {
Calin Juravle225ff812014-11-13 16:46:39 +00002256 BuildFillArrayData(instruction, dex_pc);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002257 break;
2258 }
2259
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01002260 case Instruction::MOVE_RESULT:
Dave Allison20dfc792014-06-16 20:44:29 -07002261 case Instruction::MOVE_RESULT_WIDE:
David Brazdil0b5c7d12015-06-11 11:17:49 +01002262 case Instruction::MOVE_RESULT_OBJECT: {
Nicolas Geoffray1efcc222015-06-24 12:41:20 +01002263 if (latest_result_ == nullptr) {
2264 // Only dead code can lead to this situation, where the verifier
2265 // does not reject the method.
2266 } else {
David Brazdil0b5c7d12015-06-11 11:17:49 +01002267 // An Invoke/FilledNewArray and its MoveResult could have landed in
2268 // different blocks if there was a try/catch block boundary between
2269 // them. We need to insert the StoreLocal after the result definition
2270 // but before any potential Temporaries.
2271 HStoreLocal* update_local =
2272 new (arena_) HStoreLocal(GetLocalAt(instruction.VRegA()), latest_result_);
2273 HBasicBlock* block = latest_result_->GetBlock();
2274 if (latest_result_->IsInvoke()) {
2275 block->InsertInstructionAfter(update_local, latest_result_);
2276 } else {
2277 DCHECK(latest_result_->IsNewArray());
2278 DCHECK(latest_result_->GetNext()->IsTemporary());
2279 block->InsertInstructionAfter(update_local, latest_result_->GetNext());
2280 }
Nicolas Geoffray1efcc222015-06-24 12:41:20 +01002281 latest_result_ = nullptr;
2282 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002283 break;
David Brazdil0b5c7d12015-06-11 11:17:49 +01002284 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002285
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002286 case Instruction::CMP_LONG: {
Alexey Frunze4dda3372015-06-01 18:31:49 -07002287 Binop_23x_cmp(instruction, Primitive::kPrimLong, HCompare::kNoBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002288 break;
2289 }
2290
2291 case Instruction::CMPG_FLOAT: {
Alexey Frunze4dda3372015-06-01 18:31:49 -07002292 Binop_23x_cmp(instruction, Primitive::kPrimFloat, HCompare::kGtBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002293 break;
2294 }
2295
2296 case Instruction::CMPG_DOUBLE: {
Alexey Frunze4dda3372015-06-01 18:31:49 -07002297 Binop_23x_cmp(instruction, Primitive::kPrimDouble, HCompare::kGtBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002298 break;
2299 }
2300
2301 case Instruction::CMPL_FLOAT: {
Alexey Frunze4dda3372015-06-01 18:31:49 -07002302 Binop_23x_cmp(instruction, Primitive::kPrimFloat, HCompare::kLtBias, dex_pc);
Calin Juravleddb7df22014-11-25 20:56:51 +00002303 break;
2304 }
2305
2306 case Instruction::CMPL_DOUBLE: {
Alexey Frunze4dda3372015-06-01 18:31:49 -07002307 Binop_23x_cmp(instruction, Primitive::kPrimDouble, HCompare::kLtBias, dex_pc);
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002308 break;
2309 }
2310
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00002311 case Instruction::NOP:
2312 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002313
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002314 case Instruction::IGET:
2315 case Instruction::IGET_WIDE:
2316 case Instruction::IGET_OBJECT:
2317 case Instruction::IGET_BOOLEAN:
2318 case Instruction::IGET_BYTE:
2319 case Instruction::IGET_CHAR:
2320 case Instruction::IGET_SHORT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002321 if (!BuildInstanceFieldAccess(instruction, dex_pc, false)) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002322 return false;
2323 }
2324 break;
2325 }
2326
2327 case Instruction::IPUT:
2328 case Instruction::IPUT_WIDE:
2329 case Instruction::IPUT_OBJECT:
2330 case Instruction::IPUT_BOOLEAN:
2331 case Instruction::IPUT_BYTE:
2332 case Instruction::IPUT_CHAR:
2333 case Instruction::IPUT_SHORT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002334 if (!BuildInstanceFieldAccess(instruction, dex_pc, true)) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002335 return false;
2336 }
2337 break;
2338 }
2339
2340 case Instruction::SGET:
2341 case Instruction::SGET_WIDE:
2342 case Instruction::SGET_OBJECT:
2343 case Instruction::SGET_BOOLEAN:
2344 case Instruction::SGET_BYTE:
2345 case Instruction::SGET_CHAR:
2346 case Instruction::SGET_SHORT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002347 if (!BuildStaticFieldAccess(instruction, dex_pc, false)) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002348 return false;
2349 }
2350 break;
2351 }
2352
2353 case Instruction::SPUT:
2354 case Instruction::SPUT_WIDE:
2355 case Instruction::SPUT_OBJECT:
2356 case Instruction::SPUT_BOOLEAN:
2357 case Instruction::SPUT_BYTE:
2358 case Instruction::SPUT_CHAR:
2359 case Instruction::SPUT_SHORT: {
Calin Juravle225ff812014-11-13 16:46:39 +00002360 if (!BuildStaticFieldAccess(instruction, dex_pc, true)) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002361 return false;
2362 }
2363 break;
2364 }
2365
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002366#define ARRAY_XX(kind, anticipated_type) \
2367 case Instruction::AGET##kind: { \
Calin Juravle225ff812014-11-13 16:46:39 +00002368 BuildArrayAccess(instruction, dex_pc, false, anticipated_type); \
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002369 break; \
2370 } \
2371 case Instruction::APUT##kind: { \
Calin Juravle225ff812014-11-13 16:46:39 +00002372 BuildArrayAccess(instruction, dex_pc, true, anticipated_type); \
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002373 break; \
2374 }
2375
2376 ARRAY_XX(, Primitive::kPrimInt);
2377 ARRAY_XX(_WIDE, Primitive::kPrimLong);
2378 ARRAY_XX(_OBJECT, Primitive::kPrimNot);
2379 ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean);
2380 ARRAY_XX(_BYTE, Primitive::kPrimByte);
2381 ARRAY_XX(_CHAR, Primitive::kPrimChar);
2382 ARRAY_XX(_SHORT, Primitive::kPrimShort);
2383
Nicolas Geoffray39468442014-09-02 15:17:15 +01002384 case Instruction::ARRAY_LENGTH: {
2385 HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot);
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002386 // No need for a temporary for the null check, it is the only input of the following
2387 // instruction.
Calin Juravle225ff812014-11-13 16:46:39 +00002388 object = new (arena_) HNullCheck(object, dex_pc);
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002389 current_block_->AddInstruction(object);
Nicolas Geoffray39468442014-09-02 15:17:15 +01002390 current_block_->AddInstruction(new (arena_) HArrayLength(object));
2391 UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction());
2392 break;
2393 }
2394
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002395 case Instruction::CONST_STRING: {
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01002396 current_block_->AddInstruction(
2397 new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_21c(), dex_pc));
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002398 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
2399 break;
2400 }
2401
2402 case Instruction::CONST_STRING_JUMBO: {
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01002403 current_block_->AddInstruction(
2404 new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_31c(), dex_pc));
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002405 UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction());
2406 break;
2407 }
2408
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002409 case Instruction::CONST_CLASS: {
2410 uint16_t type_index = instruction.VRegB_21c();
2411 bool type_known_final;
2412 bool type_known_abstract;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002413 bool dont_use_is_referrers_class;
2414 // `CanAccessTypeWithoutChecks` will tell whether the method being
2415 // built is trying to access its own class, so that the generated
2416 // code can optimize for this case. However, the optimization does not
Nicolas Geoffray9437b782015-03-25 10:08:51 +00002417 // work for inlining, so we use `IsOutermostCompilingClass` instead.
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002418 bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
2419 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002420 &type_known_final, &type_known_abstract, &dont_use_is_referrers_class);
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002421 if (!can_access) {
Calin Juravle48c2b032014-12-09 18:11:36 +00002422 MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002423 return false;
2424 }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002425 current_block_->AddInstruction(new (arena_) HLoadClass(
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01002426 graph_->GetCurrentMethod(),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002427 type_index,
2428 *dex_compilation_unit_->GetDexFile(),
2429 IsOutermostCompilingClass(type_index),
2430 dex_pc));
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002431 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
2432 break;
2433 }
2434
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002435 case Instruction::MOVE_EXCEPTION: {
2436 current_block_->AddInstruction(new (arena_) HLoadException());
2437 UpdateLocal(instruction.VRegA_11x(), current_block_->GetLastInstruction());
2438 break;
2439 }
2440
2441 case Instruction::THROW: {
2442 HInstruction* exception = LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot);
Calin Juravle225ff812014-11-13 16:46:39 +00002443 current_block_->AddInstruction(new (arena_) HThrow(exception, dex_pc));
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002444 // A throw instruction must branch to the exit block.
2445 current_block_->AddSuccessor(exit_block_);
2446 // We finished building this block. Set the current block to null to avoid
2447 // adding dead instructions to it.
2448 current_block_ = nullptr;
2449 break;
2450 }
2451
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002452 case Instruction::INSTANCE_OF: {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002453 uint8_t destination = instruction.VRegA_22c();
2454 uint8_t reference = instruction.VRegB_22c();
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002455 uint16_t type_index = instruction.VRegC_22c();
Calin Juravle225ff812014-11-13 16:46:39 +00002456 if (!BuildTypeCheck(instruction, destination, reference, type_index, dex_pc)) {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002457 return false;
2458 }
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002459 break;
2460 }
2461
2462 case Instruction::CHECK_CAST: {
2463 uint8_t reference = instruction.VRegA_21c();
2464 uint16_t type_index = instruction.VRegB_21c();
Calin Juravle225ff812014-11-13 16:46:39 +00002465 if (!BuildTypeCheck(instruction, -1, reference, type_index, dex_pc)) {
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002466 return false;
2467 }
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002468 break;
2469 }
2470
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002471 case Instruction::MONITOR_ENTER: {
2472 current_block_->AddInstruction(new (arena_) HMonitorOperation(
2473 LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
2474 HMonitorOperation::kEnter,
Calin Juravle225ff812014-11-13 16:46:39 +00002475 dex_pc));
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002476 break;
2477 }
2478
2479 case Instruction::MONITOR_EXIT: {
2480 current_block_->AddInstruction(new (arena_) HMonitorOperation(
2481 LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
2482 HMonitorOperation::kExit,
Calin Juravle225ff812014-11-13 16:46:39 +00002483 dex_pc));
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002484 break;
2485 }
2486
Andreas Gamped881df52014-11-24 23:28:39 -08002487 case Instruction::PACKED_SWITCH: {
Calin Juravle48c2b032014-12-09 18:11:36 +00002488 BuildPackedSwitch(instruction, dex_pc);
Andreas Gamped881df52014-11-24 23:28:39 -08002489 break;
2490 }
2491
Andreas Gampee4d4d322014-12-04 09:09:57 -08002492 case Instruction::SPARSE_SWITCH: {
Calin Juravle48c2b032014-12-09 18:11:36 +00002493 BuildSparseSwitch(instruction, dex_pc);
Andreas Gampee4d4d322014-12-04 09:09:57 -08002494 break;
2495 }
2496
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002497 default:
Calin Juravle48c2b032014-12-09 18:11:36 +00002498 VLOG(compiler) << "Did not compile "
2499 << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
2500 << " because of unhandled instruction "
2501 << instruction.Name();
2502 MaybeRecordStat(MethodCompilationStat::kNotCompiledUnhandledInstruction);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002503 return false;
2504 }
2505 return true;
Nicolas Geoffraydadf3172014-11-07 16:36:02 +00002506} // NOLINT(readability/fn_size)
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002507
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002508HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
2509 return locals_.Get(register_index);
2510}
2511
2512void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {
2513 HLocal* local = GetLocalAt(register_index);
2514 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));
2515}
2516
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002517HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002518 HLocal* local = GetLocalAt(register_index);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002519 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type));
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002520 return current_block_->GetLastInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002521}
2522
Nicolas Geoffray818f2102014-02-18 16:43:35 +00002523} // namespace art