1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "builder.h"
18 
19 #include "art_field-inl.h"
20 #include "base/logging.h"
21 #include "class_linker.h"
22 #include "dex/verified_method.h"
23 #include "dex_file-inl.h"
24 #include "dex_instruction-inl.h"
25 #include "dex/verified_method.h"
26 #include "driver/compiler_driver-inl.h"
27 #include "driver/compiler_options.h"
28 #include "mirror/class_loader.h"
29 #include "mirror/dex_cache.h"
30 #include "nodes.h"
31 #include "primitive.h"
32 #include "scoped_thread_state_change.h"
33 #include "thread.h"
34 
35 namespace art {
36 
37 /**
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  */
43 class Temporaries : public ValueObject {
44  public:
Temporaries(HGraph * graph)45   explicit Temporaries(HGraph* graph) : graph_(graph), index_(0) {}
46 
Add(HInstruction * instruction)47   void Add(HInstruction* instruction) {
48     HInstruction* temp = new (graph_->GetArena()) HTemporary(index_);
49     instruction->GetBlock()->AddInstruction(temp);
50 
51     DCHECK(temp->GetPrevious() == instruction);
52 
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_);
63   }
64 
65  private:
66   HGraph* const graph_;
67 
68   // Current index in the temporary stack, updated by `Add`.
69   size_t index_;
70 };
71 
72 class SwitchTable : public ValueObject {
73  public:
SwitchTable(const Instruction & instruction,uint32_t dex_pc,bool sparse)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 
GetNumEntries() const87   uint16_t GetNumEntries() const {
88     return num_entries_;
89   }
90 
CheckIndex(size_t index) const91   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 
GetEntryAt(size_t index) const101   int32_t GetEntryAt(size_t index) const {
102     CheckIndex(index);
103     return values_[index];
104   }
105 
GetDexPcForIndex(size_t index) const106   uint32_t GetDexPcForIndex(size_t index) const {
107     CheckIndex(index);
108     return dex_pc_ +
109         (reinterpret_cast<const int16_t*>(values_ + index) -
110          reinterpret_cast<const int16_t*>(&instruction_));
111   }
112 
113   // Index of the first value in the table.
GetFirstValueIndex() const114   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 
124  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 
InitializeLocals(uint16_t count)140 void HGraphBuilder::InitializeLocals(uint16_t count) {
141   graph_->SetNumberOfVRegs(count);
142   locals_.SetSize(count);
143   for (int i = 0; i < count; i++) {
144     HLocal* local = new (arena_) HLocal(i);
145     entry_block_->AddInstruction(local);
146     locals_.Put(i, local);
147   }
148 }
149 
InitializeParameters(uint16_t number_of_parameters)150 void HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) {
151   // dex_compilation_unit_ is null only when unit testing.
152   if (dex_compilation_unit_ == nullptr) {
153     return;
154   }
155 
156   graph_->SetNumberOfInVRegs(number_of_parameters);
157   const char* shorty = dex_compilation_unit_->GetShorty();
158   int locals_index = locals_.Size() - number_of_parameters;
159   int parameter_index = 0;
160 
161   if (!dex_compilation_unit_->IsStatic()) {
162     // Add the implicit 'this' argument, not expressed in the signature.
163     HParameterValue* parameter =
164         new (arena_) HParameterValue(parameter_index++, Primitive::kPrimNot, true);
165     entry_block_->AddInstruction(parameter);
166     HLocal* local = GetLocalAt(locals_index++);
167     entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
168     number_of_parameters--;
169   }
170 
171   uint32_t pos = 1;
172   for (int i = 0; i < number_of_parameters; i++) {
173     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++;
186     }
187   }
188 }
189 
190 template<typename T>
If_22t(const Instruction & instruction,uint32_t dex_pc)191 void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_pc) {
192   int32_t target_offset = instruction.GetTargetOffset();
193   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);
198   HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
199   HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
200   T* comparison = new (arena_) T(first, second);
201   current_block_->AddInstruction(comparison);
202   HInstruction* ifinst = new (arena_) HIf(comparison);
203   current_block_->AddInstruction(ifinst);
204   current_block_->AddSuccessor(branch_target);
205   current_block_->AddSuccessor(fallthrough_target);
206   current_block_ = nullptr;
207 }
208 
209 template<typename T>
If_21t(const Instruction & instruction,uint32_t dex_pc)210 void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) {
211   int32_t target_offset = instruction.GetTargetOffset();
212   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);
217   HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
218   T* comparison = new (arena_) T(value, graph_->GetIntConstant(0));
219   current_block_->AddInstruction(comparison);
220   HInstruction* ifinst = new (arena_) HIf(comparison);
221   current_block_->AddInstruction(ifinst);
222   current_block_->AddSuccessor(branch_target);
223   current_block_->AddSuccessor(fallthrough_target);
224   current_block_ = nullptr;
225 }
226 
MaybeRecordStat(MethodCompilationStat compilation_stat)227 void HGraphBuilder::MaybeRecordStat(MethodCompilationStat compilation_stat) {
228   if (compilation_stats_ != nullptr) {
229     compilation_stats_->RecordStat(compilation_stat);
230   }
231 }
232 
SkipCompilation(const DexFile::CodeItem & code_item,size_t number_of_branches)233 bool HGraphBuilder::SkipCompilation(const DexFile::CodeItem& code_item,
234                                     size_t number_of_branches) {
235   const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions();
236   CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter();
237   if (compiler_filter == CompilerOptions::kEverything) {
238     return false;
239   }
240 
241   if (compiler_options.IsHugeMethod(code_item.insns_size_in_code_units_)) {
242     VLOG(compiler) << "Skip compilation of huge method "
243                    << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
244                    << ": " << code_item.insns_size_in_code_units_ << " code units";
245     MaybeRecordStat(MethodCompilationStat::kNotCompiledHugeMethod);
246     return true;
247   }
248 
249   // If it's large and contains no branches, it's likely to be machine generated initialization.
250   if (compiler_options.IsLargeMethod(code_item.insns_size_in_code_units_)
251       && (number_of_branches == 0)) {
252     VLOG(compiler) << "Skip compilation of large method with no branch "
253                    << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
254                    << ": " << code_item.insns_size_in_code_units_ << " code units";
255     MaybeRecordStat(MethodCompilationStat::kNotCompiledLargeMethodNoBranches);
256     return true;
257   }
258 
259   return false;
260 }
261 
BuildGraph(const DexFile::CodeItem & code_item)262 bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
263   DCHECK(graph_->GetBlocks().IsEmpty());
264 
265   const uint16_t* code_ptr = code_item.insns_;
266   const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_;
267   code_start_ = code_ptr;
268 
269   // Setup the graph with the entry block and exit block.
270   entry_block_ = new (arena_) HBasicBlock(graph_, 0);
271   graph_->AddBlock(entry_block_);
272   exit_block_ = new (arena_) HBasicBlock(graph_, kNoDexPc);
273   graph_->SetEntryBlock(entry_block_);
274   graph_->SetExitBlock(exit_block_);
275 
276   InitializeLocals(code_item.registers_size_);
277   graph_->SetMaximumNumberOfOutVRegs(code_item.outs_size_);
278 
279   // Compute the number of dex instructions, blocks, and branches. We will
280   // check these values against limits given to the compiler.
281   size_t number_of_branches = 0;
282 
283   // To avoid splitting blocks, we compute ahead of time the instructions that
284   // start a new block, and create these blocks.
285   if (!ComputeBranchTargets(code_ptr, code_end, &number_of_branches)) {
286     MaybeRecordStat(MethodCompilationStat::kNotCompiledBranchOutsideMethodCode);
287     return false;
288   }
289 
290   // Note that the compiler driver is null when unit testing.
291   if ((compiler_driver_ != nullptr) && SkipCompilation(code_item, number_of_branches)) {
292     return false;
293   }
294 
295   // Also create blocks for catch handlers.
296   if (code_item.tries_size_ != 0) {
297     const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item, 0);
298     uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
299     for (uint32_t idx = 0; idx < handlers_size; ++idx) {
300       CatchHandlerIterator iterator(handlers_ptr);
301       for (; iterator.HasNext(); iterator.Next()) {
302         uint32_t address = iterator.GetHandlerAddress();
303         HBasicBlock* block = FindBlockStartingAt(address);
304         if (block == nullptr) {
305           block = new (arena_) HBasicBlock(graph_, address);
306           branch_targets_.Put(address, block);
307         }
308         block->SetIsCatchBlock();
309       }
310       handlers_ptr = iterator.EndDataPointer();
311     }
312   }
313 
314   InitializeParameters(code_item.ins_size_);
315 
316   size_t dex_pc = 0;
317   while (code_ptr < code_end) {
318     // Update the current block if dex_pc starts a new block.
319     MaybeUpdateCurrentBlock(dex_pc);
320     const Instruction& instruction = *Instruction::At(code_ptr);
321     if (!AnalyzeDexInstruction(instruction, dex_pc)) {
322       return false;
323     }
324     dex_pc += instruction.SizeInCodeUnits();
325     code_ptr += instruction.SizeInCodeUnits();
326   }
327 
328   // Add the exit block at the end to give it the highest id.
329   graph_->AddBlock(exit_block_);
330   exit_block_->AddInstruction(new (arena_) HExit());
331   // Add the suspend check to the entry block.
332   entry_block_->AddInstruction(new (arena_) HSuspendCheck(0));
333   entry_block_->AddInstruction(new (arena_) HGoto());
334 
335   return true;
336 }
337 
MaybeUpdateCurrentBlock(size_t index)338 void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) {
339   HBasicBlock* block = FindBlockStartingAt(index);
340   if (block == nullptr) {
341     return;
342   }
343 
344   if (current_block_ != nullptr) {
345     // Branching instructions clear current_block, so we know
346     // the last instruction of the current block is not a branching
347     // instruction. We add an unconditional goto to the found block.
348     current_block_->AddInstruction(new (arena_) HGoto());
349     current_block_->AddSuccessor(block);
350   }
351   graph_->AddBlock(block);
352   current_block_ = block;
353 }
354 
ComputeBranchTargets(const uint16_t * code_ptr,const uint16_t * code_end,size_t * number_of_branches)355 bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr,
356                                          const uint16_t* code_end,
357                                          size_t* number_of_branches) {
358   branch_targets_.SetSize(code_end - code_ptr);
359 
360   // Create the first block for the dex instructions, single successor of the entry block.
361   HBasicBlock* block = new (arena_) HBasicBlock(graph_, 0);
362   branch_targets_.Put(0, block);
363   entry_block_->AddSuccessor(block);
364 
365   // Iterate over all instructions and find branching instructions. Create blocks for
366   // the locations these instructions branch to.
367   uint32_t dex_pc = 0;
368   while (code_ptr < code_end) {
369     const Instruction& instruction = *Instruction::At(code_ptr);
370     if (instruction.IsBranch()) {
371       (*number_of_branches)++;
372       int32_t target = instruction.GetTargetOffset() + dex_pc;
373       // Create a block for the target instruction.
374       if (FindBlockStartingAt(target) == nullptr) {
375         block = new (arena_) HBasicBlock(graph_, target);
376         branch_targets_.Put(target, block);
377       }
378       dex_pc += instruction.SizeInCodeUnits();
379       code_ptr += instruction.SizeInCodeUnits();
380 
381       if (code_ptr >= code_end) {
382         if (instruction.CanFlowThrough()) {
383           // In the normal case we should never hit this but someone can artificially forge a dex
384           // file to fall-through out the method code. In this case we bail out compilation.
385           return false;
386         }
387       } else if (FindBlockStartingAt(dex_pc) == nullptr) {
388         block = new (arena_) HBasicBlock(graph_, dex_pc);
389         branch_targets_.Put(dex_pc, block);
390       }
391     } else if (instruction.IsSwitch()) {
392       SwitchTable table(instruction, dex_pc, instruction.Opcode() == Instruction::SPARSE_SWITCH);
393 
394       uint16_t num_entries = table.GetNumEntries();
395 
396       // In a packed-switch, the entry at index 0 is the starting key. In a sparse-switch, the
397       // entry at index 0 is the first key, and values are after *all* keys.
398       size_t offset = table.GetFirstValueIndex();
399 
400       // Use a larger loop counter type to avoid overflow issues.
401       for (size_t i = 0; i < num_entries; ++i) {
402         // The target of the case.
403         uint32_t target = dex_pc + table.GetEntryAt(i + offset);
404         if (FindBlockStartingAt(target) == nullptr) {
405           block = new (arena_) HBasicBlock(graph_, target);
406           branch_targets_.Put(target, block);
407         }
408 
409         // The next case gets its own block.
410         if (i < num_entries) {
411           block = new (arena_) HBasicBlock(graph_, target);
412           branch_targets_.Put(table.GetDexPcForIndex(i), block);
413         }
414       }
415 
416       // Fall-through. Add a block if there is more code afterwards.
417       dex_pc += instruction.SizeInCodeUnits();
418       code_ptr += instruction.SizeInCodeUnits();
419       if (code_ptr >= code_end) {
420         // In the normal case we should never hit this but someone can artificially forge a dex
421         // file to fall-through out the method code. In this case we bail out compilation.
422         // (A switch can fall-through so we don't need to check CanFlowThrough().)
423         return false;
424       } else if (FindBlockStartingAt(dex_pc) == nullptr) {
425         block = new (arena_) HBasicBlock(graph_, dex_pc);
426         branch_targets_.Put(dex_pc, block);
427       }
428     } else {
429       code_ptr += instruction.SizeInCodeUnits();
430       dex_pc += instruction.SizeInCodeUnits();
431     }
432   }
433   return true;
434 }
435 
FindBlockStartingAt(int32_t index) const436 HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const {
437   DCHECK_GE(index, 0);
438   return branch_targets_.Get(index);
439 }
440 
441 template<typename T>
Unop_12x(const Instruction & instruction,Primitive::Type type)442 void HGraphBuilder::Unop_12x(const Instruction& instruction, Primitive::Type type) {
443   HInstruction* first = LoadLocal(instruction.VRegB(), type);
444   current_block_->AddInstruction(new (arena_) T(type, first));
445   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
446 }
447 
Conversion_12x(const Instruction & instruction,Primitive::Type input_type,Primitive::Type result_type,uint32_t dex_pc)448 void HGraphBuilder::Conversion_12x(const Instruction& instruction,
449                                    Primitive::Type input_type,
450                                    Primitive::Type result_type,
451                                    uint32_t dex_pc) {
452   HInstruction* first = LoadLocal(instruction.VRegB(), input_type);
453   current_block_->AddInstruction(new (arena_) HTypeConversion(result_type, first, dex_pc));
454   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
455 }
456 
457 template<typename T>
Binop_23x(const Instruction & instruction,Primitive::Type type)458 void HGraphBuilder::Binop_23x(const Instruction& instruction, Primitive::Type type) {
459   HInstruction* first = LoadLocal(instruction.VRegB(), type);
460   HInstruction* second = LoadLocal(instruction.VRegC(), type);
461   current_block_->AddInstruction(new (arena_) T(type, first, second));
462   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
463 }
464 
465 template<typename T>
Binop_23x(const Instruction & instruction,Primitive::Type type,uint32_t dex_pc)466 void HGraphBuilder::Binop_23x(const Instruction& instruction,
467                               Primitive::Type type,
468                               uint32_t dex_pc) {
469   HInstruction* first = LoadLocal(instruction.VRegB(), type);
470   HInstruction* second = LoadLocal(instruction.VRegC(), type);
471   current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
472   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
473 }
474 
475 template<typename T>
Binop_23x_shift(const Instruction & instruction,Primitive::Type type)476 void HGraphBuilder::Binop_23x_shift(const Instruction& instruction,
477                                     Primitive::Type type) {
478   HInstruction* first = LoadLocal(instruction.VRegB(), type);
479   HInstruction* second = LoadLocal(instruction.VRegC(), Primitive::kPrimInt);
480   current_block_->AddInstruction(new (arena_) T(type, first, second));
481   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
482 }
483 
Binop_23x_cmp(const Instruction & instruction,Primitive::Type type,HCompare::Bias bias,uint32_t dex_pc)484 void HGraphBuilder::Binop_23x_cmp(const Instruction& instruction,
485                                   Primitive::Type type,
486                                   HCompare::Bias bias,
487                                   uint32_t dex_pc) {
488   HInstruction* first = LoadLocal(instruction.VRegB(), type);
489   HInstruction* second = LoadLocal(instruction.VRegC(), type);
490   current_block_->AddInstruction(new (arena_) HCompare(type, first, second, bias, dex_pc));
491   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
492 }
493 
494 template<typename T>
Binop_12x(const Instruction & instruction,Primitive::Type type)495 void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) {
496   HInstruction* first = LoadLocal(instruction.VRegA(), type);
497   HInstruction* second = LoadLocal(instruction.VRegB(), type);
498   current_block_->AddInstruction(new (arena_) T(type, first, second));
499   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
500 }
501 
502 template<typename T>
Binop_12x_shift(const Instruction & instruction,Primitive::Type type)503 void HGraphBuilder::Binop_12x_shift(const Instruction& instruction, Primitive::Type type) {
504   HInstruction* first = LoadLocal(instruction.VRegA(), type);
505   HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
506   current_block_->AddInstruction(new (arena_) T(type, first, second));
507   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
508 }
509 
510 template<typename T>
Binop_12x(const Instruction & instruction,Primitive::Type type,uint32_t dex_pc)511 void HGraphBuilder::Binop_12x(const Instruction& instruction,
512                               Primitive::Type type,
513                               uint32_t dex_pc) {
514   HInstruction* first = LoadLocal(instruction.VRegA(), type);
515   HInstruction* second = LoadLocal(instruction.VRegB(), type);
516   current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
517   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
518 }
519 
520 template<typename T>
Binop_22s(const Instruction & instruction,bool reverse)521 void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
522   HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
523   HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s());
524   if (reverse) {
525     std::swap(first, second);
526   }
527   current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
528   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
529 }
530 
531 template<typename T>
Binop_22b(const Instruction & instruction,bool reverse)532 void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
533   HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
534   HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b());
535   if (reverse) {
536     std::swap(first, second);
537   }
538   current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
539   UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
540 }
541 
RequiresConstructorBarrier(const DexCompilationUnit * cu,const CompilerDriver & driver)542 static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, const CompilerDriver& driver) {
543   // dex compilation unit is null only when unit testing.
544   if (cu == nullptr) {
545     return false;
546   }
547 
548   Thread* self = Thread::Current();
549   return cu->IsConstructor()
550       && driver.RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex());
551 }
552 
BuildReturn(const Instruction & instruction,Primitive::Type type)553 void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) {
554   if (type == Primitive::kPrimVoid) {
555     // Note that we might insert redundant barriers when inlining `super` calls.
556     // TODO: add a data flow analysis to get rid of duplicate barriers.
557     if (RequiresConstructorBarrier(dex_compilation_unit_, *compiler_driver_)) {
558       current_block_->AddInstruction(new (arena_) HMemoryBarrier(kStoreStore));
559     }
560     current_block_->AddInstruction(new (arena_) HReturnVoid());
561   } else {
562     HInstruction* value = LoadLocal(instruction.VRegA(), type);
563     current_block_->AddInstruction(new (arena_) HReturn(value));
564   }
565   current_block_->AddSuccessor(exit_block_);
566   current_block_ = nullptr;
567 }
568 
BuildInvoke(const Instruction & instruction,uint32_t dex_pc,uint32_t method_idx,uint32_t number_of_vreg_arguments,bool is_range,uint32_t * args,uint32_t register_index)569 bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
570                                 uint32_t dex_pc,
571                                 uint32_t method_idx,
572                                 uint32_t number_of_vreg_arguments,
573                                 bool is_range,
574                                 uint32_t* args,
575                                 uint32_t register_index) {
576   Instruction::Code opcode = instruction.Opcode();
577   InvokeType invoke_type;
578   switch (opcode) {
579     case Instruction::INVOKE_STATIC:
580     case Instruction::INVOKE_STATIC_RANGE:
581       invoke_type = kStatic;
582       break;
583     case Instruction::INVOKE_DIRECT:
584     case Instruction::INVOKE_DIRECT_RANGE:
585       invoke_type = kDirect;
586       break;
587     case Instruction::INVOKE_VIRTUAL:
588     case Instruction::INVOKE_VIRTUAL_RANGE:
589       invoke_type = kVirtual;
590       break;
591     case Instruction::INVOKE_INTERFACE:
592     case Instruction::INVOKE_INTERFACE_RANGE:
593       invoke_type = kInterface;
594       break;
595     case Instruction::INVOKE_SUPER_RANGE:
596     case Instruction::INVOKE_SUPER:
597       invoke_type = kSuper;
598       break;
599     default:
600       LOG(FATAL) << "Unexpected invoke op: " << opcode;
601       return false;
602   }
603 
604   const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
605   const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_id.proto_idx_);
606   const char* descriptor = dex_file_->StringDataByIdx(proto_id.shorty_idx_);
607   Primitive::Type return_type = Primitive::GetType(descriptor[0]);
608   bool is_instance_call = invoke_type != kStatic;
609   // Remove the return type from the 'proto'.
610   size_t number_of_arguments = strlen(descriptor) - 1;
611   if (is_instance_call) {
612     // One extra argument for 'this'.
613     ++number_of_arguments;
614   }
615 
616   MethodReference target_method(dex_file_, method_idx);
617   uintptr_t direct_code;
618   uintptr_t direct_method;
619   int table_index;
620   InvokeType optimized_invoke_type = invoke_type;
621 
622   if (!compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_pc, true, true,
623                                            &optimized_invoke_type, &target_method, &table_index,
624                                            &direct_code, &direct_method)) {
625     VLOG(compiler) << "Did not compile "
626                    << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
627                    << " because a method call could not be resolved";
628     MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedMethod);
629     return false;
630   }
631   DCHECK(optimized_invoke_type != kSuper);
632 
633   // By default, consider that the called method implicitly requires
634   // an initialization check of its declaring method.
635   HInvokeStaticOrDirect::ClinitCheckRequirement clinit_check_requirement =
636       HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit;
637   // Potential class initialization check, in the case of a static method call.
638   HClinitCheck* clinit_check = nullptr;
639   // Replace calls to String.<init> with StringFactory.
640   int32_t string_init_offset = 0;
641   bool is_string_init = compiler_driver_->IsStringInit(method_idx, dex_file_, &string_init_offset);
642   if (is_string_init) {
643     return_type = Primitive::kPrimNot;
644     is_instance_call = false;
645     number_of_arguments--;
646     invoke_type = kStatic;
647     optimized_invoke_type = kStatic;
648   }
649 
650   HInvoke* invoke = nullptr;
651 
652   if (optimized_invoke_type == kVirtual) {
653     invoke = new (arena_) HInvokeVirtual(
654         arena_, number_of_arguments, return_type, dex_pc, method_idx, table_index);
655   } else if (optimized_invoke_type == kInterface) {
656     invoke = new (arena_) HInvokeInterface(
657         arena_, number_of_arguments, return_type, dex_pc, method_idx, table_index);
658   } else {
659     DCHECK(optimized_invoke_type == kDirect || optimized_invoke_type == kStatic);
660     // Sharpening to kDirect only works if we compile PIC.
661     DCHECK((optimized_invoke_type == invoke_type) || (optimized_invoke_type != kDirect)
662            || compiler_driver_->GetCompilerOptions().GetCompilePic());
663     bool is_recursive =
664         (target_method.dex_method_index == dex_compilation_unit_->GetDexMethodIndex());
665     DCHECK(!is_recursive || (target_method.dex_file == dex_compilation_unit_->GetDexFile()));
666 
667     if (optimized_invoke_type == kStatic && !is_string_init) {
668       ScopedObjectAccess soa(Thread::Current());
669       StackHandleScope<4> hs(soa.Self());
670       Handle<mirror::DexCache> dex_cache(hs.NewHandle(
671           dex_compilation_unit_->GetClassLinker()->FindDexCache(
672               *dex_compilation_unit_->GetDexFile())));
673       Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
674           soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
675       ArtMethod* resolved_method = compiler_driver_->ResolveMethod(
676           soa, dex_cache, class_loader, dex_compilation_unit_, method_idx, optimized_invoke_type);
677 
678       if (resolved_method == nullptr) {
679         MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedMethod);
680         return false;
681       }
682 
683       const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
684       Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
685           outer_compilation_unit_->GetClassLinker()->FindDexCache(outer_dex_file)));
686       Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
687 
688       // The index at which the method's class is stored in the DexCache's type array.
689       uint32_t storage_index = DexFile::kDexNoIndex;
690       bool is_outer_class = (resolved_method->GetDeclaringClass() == outer_class.Get());
691       if (is_outer_class) {
692         storage_index = outer_class->GetDexTypeIndex();
693       } else if (outer_dex_cache.Get() == dex_cache.Get()) {
694         // Get `storage_index` from IsClassOfStaticMethodAvailableToReferrer.
695         compiler_driver_->IsClassOfStaticMethodAvailableToReferrer(outer_dex_cache.Get(),
696                                                                    GetCompilingClass(),
697                                                                    resolved_method,
698                                                                    method_idx,
699                                                                    &storage_index);
700       }
701 
702       if (!outer_class->IsInterface()
703           && outer_class->IsSubClass(resolved_method->GetDeclaringClass())) {
704         // If the outer class is the declaring class or a subclass
705         // of the declaring class, no class initialization is needed
706         // before the static method call.
707         // Note that in case of inlining, we do not need to add clinit checks
708         // to calls that satisfy this subclass check with any inlined methods. This
709         // will be detected by the optimization passes.
710         clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
711       } else if (storage_index != DexFile::kDexNoIndex) {
712         // If the method's class type index is available, check
713         // whether we should add an explicit class initialization
714         // check for its declaring class before the static method call.
715 
716         // TODO: find out why this check is needed.
717         bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
718             *outer_compilation_unit_->GetDexFile(), storage_index);
719         bool is_initialized =
720             resolved_method->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
721 
722         if (is_initialized) {
723           clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
724         } else {
725           clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
726           HLoadClass* load_class =
727               new (arena_) HLoadClass(storage_index, is_outer_class, dex_pc);
728           current_block_->AddInstruction(load_class);
729           clinit_check = new (arena_) HClinitCheck(load_class, dex_pc);
730           current_block_->AddInstruction(clinit_check);
731         }
732       }
733     }
734 
735     invoke = new (arena_) HInvokeStaticOrDirect(
736         arena_, number_of_arguments, return_type, dex_pc, target_method.dex_method_index,
737         is_recursive, string_init_offset, invoke_type, optimized_invoke_type,
738         clinit_check_requirement);
739   }
740 
741   size_t start_index = 0;
742   Temporaries temps(graph_);
743   if (is_instance_call) {
744     HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot);
745     HNullCheck* null_check = new (arena_) HNullCheck(arg, dex_pc);
746     current_block_->AddInstruction(null_check);
747     temps.Add(null_check);
748     invoke->SetArgumentAt(0, null_check);
749     start_index = 1;
750   }
751 
752   uint32_t descriptor_index = 1;  // Skip the return type.
753   uint32_t argument_index = start_index;
754   if (is_string_init) {
755     start_index = 1;
756   }
757   for (size_t i = start_index;
758        // Make sure we don't go over the expected arguments or over the number of
759        // dex registers given. If the instruction was seen as dead by the verifier,
760        // it hasn't been properly checked.
761        (i < number_of_vreg_arguments) && (argument_index < number_of_arguments);
762        i++, argument_index++) {
763     Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]);
764     bool is_wide = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble);
765     if (!is_range
766         && is_wide
767         && ((i + 1 == number_of_vreg_arguments) || (args[i] + 1 != args[i + 1]))) {
768       // Longs and doubles should be in pairs, that is, sequential registers. The verifier should
769       // reject any class where this is violated. However, the verifier only does these checks
770       // on non trivially dead instructions, so we just bailout the compilation.
771       VLOG(compiler) << "Did not compile "
772                      << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
773                      << " because of non-sequential dex register pair in wide argument";
774       MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode);
775       return false;
776     }
777     HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
778     invoke->SetArgumentAt(argument_index, arg);
779     if (is_wide) {
780       i++;
781     }
782   }
783 
784   if (argument_index != number_of_arguments) {
785     VLOG(compiler) << "Did not compile "
786                    << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
787                    << " because of wrong number of arguments in invoke instruction";
788     MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode);
789     return false;
790   }
791 
792   if (clinit_check_requirement == HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit) {
793     // Add the class initialization check as last input of `invoke`.
794     DCHECK(clinit_check != nullptr);
795     invoke->SetArgumentAt(argument_index, clinit_check);
796   }
797 
798   current_block_->AddInstruction(invoke);
799   latest_result_ = invoke;
800 
801   // Add move-result for StringFactory method.
802   if (is_string_init) {
803     uint32_t orig_this_reg = is_range ? register_index : args[0];
804     UpdateLocal(orig_this_reg, invoke);
805     const VerifiedMethod* verified_method =
806         compiler_driver_->GetVerifiedMethod(dex_file_, dex_compilation_unit_->GetDexMethodIndex());
807     if (verified_method == nullptr) {
808       LOG(WARNING) << "No verified method for method calling String.<init>: "
809                    << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_);
810       return false;
811     }
812     const SafeMap<uint32_t, std::set<uint32_t>>& string_init_map =
813         verified_method->GetStringInitPcRegMap();
814     auto map_it = string_init_map.find(dex_pc);
815     if (map_it != string_init_map.end()) {
816       std::set<uint32_t> reg_set = map_it->second;
817       for (auto set_it = reg_set.begin(); set_it != reg_set.end(); ++set_it) {
818         HInstruction* load_local = LoadLocal(orig_this_reg, Primitive::kPrimNot);
819         UpdateLocal(*set_it, load_local);
820       }
821     }
822   }
823   return true;
824 }
825 
BuildInstanceFieldAccess(const Instruction & instruction,uint32_t dex_pc,bool is_put)826 bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction,
827                                              uint32_t dex_pc,
828                                              bool is_put) {
829   uint32_t source_or_dest_reg = instruction.VRegA_22c();
830   uint32_t obj_reg = instruction.VRegB_22c();
831   uint16_t field_index = instruction.VRegC_22c();
832 
833   ScopedObjectAccess soa(Thread::Current());
834   ArtField* resolved_field =
835       compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa);
836 
837   if (resolved_field == nullptr) {
838     MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
839     return false;
840   }
841 
842   Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
843 
844   HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot);
845   current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_pc));
846   if (is_put) {
847     Temporaries temps(graph_);
848     HInstruction* null_check = current_block_->GetLastInstruction();
849     // We need one temporary for the null check.
850     temps.Add(null_check);
851     HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
852     current_block_->AddInstruction(new (arena_) HInstanceFieldSet(
853         null_check,
854         value,
855         field_type,
856         resolved_field->GetOffset(),
857         resolved_field->IsVolatile()));
858   } else {
859     current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
860         current_block_->GetLastInstruction(),
861         field_type,
862         resolved_field->GetOffset(),
863         resolved_field->IsVolatile()));
864 
865     UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
866   }
867   return true;
868 }
869 
GetClassFrom(CompilerDriver * driver,const DexCompilationUnit & compilation_unit)870 static mirror::Class* GetClassFrom(CompilerDriver* driver,
871                                    const DexCompilationUnit& compilation_unit) {
872   ScopedObjectAccess soa(Thread::Current());
873   StackHandleScope<2> hs(soa.Self());
874   const DexFile& dex_file = *compilation_unit.GetDexFile();
875   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
876       soa.Decode<mirror::ClassLoader*>(compilation_unit.GetClassLoader())));
877   Handle<mirror::DexCache> dex_cache(hs.NewHandle(
878       compilation_unit.GetClassLinker()->FindDexCache(dex_file)));
879 
880   return driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, &compilation_unit);
881 }
882 
GetOutermostCompilingClass() const883 mirror::Class* HGraphBuilder::GetOutermostCompilingClass() const {
884   return GetClassFrom(compiler_driver_, *outer_compilation_unit_);
885 }
886 
GetCompilingClass() const887 mirror::Class* HGraphBuilder::GetCompilingClass() const {
888   return GetClassFrom(compiler_driver_, *dex_compilation_unit_);
889 }
890 
IsOutermostCompilingClass(uint16_t type_index) const891 bool HGraphBuilder::IsOutermostCompilingClass(uint16_t type_index) const {
892   ScopedObjectAccess soa(Thread::Current());
893   StackHandleScope<4> hs(soa.Self());
894   Handle<mirror::DexCache> dex_cache(hs.NewHandle(
895       dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile())));
896   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
897       soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
898   Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass(
899       soa, dex_cache, class_loader, type_index, dex_compilation_unit_)));
900   Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
901 
902   return outer_class.Get() == cls.Get();
903 }
904 
BuildStaticFieldAccess(const Instruction & instruction,uint32_t dex_pc,bool is_put)905 bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
906                                            uint32_t dex_pc,
907                                            bool is_put) {
908   uint32_t source_or_dest_reg = instruction.VRegA_21c();
909   uint16_t field_index = instruction.VRegB_21c();
910 
911   ScopedObjectAccess soa(Thread::Current());
912   StackHandleScope<4> hs(soa.Self());
913   Handle<mirror::DexCache> dex_cache(hs.NewHandle(
914       dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile())));
915   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
916       soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
917   ArtField* resolved_field = compiler_driver_->ResolveField(
918       soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true);
919 
920   if (resolved_field == nullptr) {
921     MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
922     return false;
923   }
924 
925   const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
926   Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
927       outer_compilation_unit_->GetClassLinker()->FindDexCache(outer_dex_file)));
928   Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
929 
930   // The index at which the field's class is stored in the DexCache's type array.
931   uint32_t storage_index;
932   bool is_outer_class = (outer_class.Get() == resolved_field->GetDeclaringClass());
933   if (is_outer_class) {
934     storage_index = outer_class->GetDexTypeIndex();
935   } else if (outer_dex_cache.Get() != dex_cache.Get()) {
936     // The compiler driver cannot currently understand multiple dex caches involved. Just bailout.
937     return false;
938   } else {
939     std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField(
940         outer_dex_cache.Get(),
941         GetCompilingClass(),
942         resolved_field,
943         field_index,
944         &storage_index);
945     bool can_easily_access = is_put ? pair.second : pair.first;
946     if (!can_easily_access) {
947       return false;
948     }
949   }
950 
951   // TODO: find out why this check is needed.
952   bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache(
953       *outer_compilation_unit_->GetDexFile(), storage_index);
954   bool is_initialized = resolved_field->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
955 
956   HLoadClass* constant = new (arena_) HLoadClass(storage_index, is_outer_class, dex_pc);
957   current_block_->AddInstruction(constant);
958 
959   HInstruction* cls = constant;
960   if (!is_initialized && !is_outer_class) {
961     cls = new (arena_) HClinitCheck(constant, dex_pc);
962     current_block_->AddInstruction(cls);
963   }
964 
965   Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
966   if (is_put) {
967     // We need to keep the class alive before loading the value.
968     Temporaries temps(graph_);
969     temps.Add(cls);
970     HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
971     DCHECK_EQ(value->GetType(), field_type);
972     current_block_->AddInstruction(
973         new (arena_) HStaticFieldSet(cls, value, field_type, resolved_field->GetOffset(),
974             resolved_field->IsVolatile()));
975   } else {
976     current_block_->AddInstruction(
977         new (arena_) HStaticFieldGet(cls, field_type, resolved_field->GetOffset(),
978             resolved_field->IsVolatile()));
979     UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
980   }
981   return true;
982 }
983 
BuildCheckedDivRem(uint16_t out_vreg,uint16_t first_vreg,int64_t second_vreg_or_constant,uint32_t dex_pc,Primitive::Type type,bool second_is_constant,bool isDiv)984 void HGraphBuilder::BuildCheckedDivRem(uint16_t out_vreg,
985                                        uint16_t first_vreg,
986                                        int64_t second_vreg_or_constant,
987                                        uint32_t dex_pc,
988                                        Primitive::Type type,
989                                        bool second_is_constant,
990                                        bool isDiv) {
991   DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
992 
993   HInstruction* first = LoadLocal(first_vreg, type);
994   HInstruction* second = nullptr;
995   if (second_is_constant) {
996     if (type == Primitive::kPrimInt) {
997       second = graph_->GetIntConstant(second_vreg_or_constant);
998     } else {
999       second = graph_->GetLongConstant(second_vreg_or_constant);
1000     }
1001   } else {
1002     second = LoadLocal(second_vreg_or_constant, type);
1003   }
1004 
1005   if (!second_is_constant
1006       || (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0)
1007       || (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) {
1008     second = new (arena_) HDivZeroCheck(second, dex_pc);
1009     Temporaries temps(graph_);
1010     current_block_->AddInstruction(second);
1011     temps.Add(current_block_->GetLastInstruction());
1012   }
1013 
1014   if (isDiv) {
1015     current_block_->AddInstruction(new (arena_) HDiv(type, first, second, dex_pc));
1016   } else {
1017     current_block_->AddInstruction(new (arena_) HRem(type, first, second, dex_pc));
1018   }
1019   UpdateLocal(out_vreg, current_block_->GetLastInstruction());
1020 }
1021 
BuildArrayAccess(const Instruction & instruction,uint32_t dex_pc,bool is_put,Primitive::Type anticipated_type)1022 void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
1023                                      uint32_t dex_pc,
1024                                      bool is_put,
1025                                      Primitive::Type anticipated_type) {
1026   uint8_t source_or_dest_reg = instruction.VRegA_23x();
1027   uint8_t array_reg = instruction.VRegB_23x();
1028   uint8_t index_reg = instruction.VRegC_23x();
1029 
1030   // We need one temporary for the null check, one for the index, and one for the length.
1031   Temporaries temps(graph_);
1032 
1033   HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot);
1034   object = new (arena_) HNullCheck(object, dex_pc);
1035   current_block_->AddInstruction(object);
1036   temps.Add(object);
1037 
1038   HInstruction* length = new (arena_) HArrayLength(object);
1039   current_block_->AddInstruction(length);
1040   temps.Add(length);
1041   HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt);
1042   index = new (arena_) HBoundsCheck(index, length, dex_pc);
1043   current_block_->AddInstruction(index);
1044   temps.Add(index);
1045   if (is_put) {
1046     HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type);
1047     // TODO: Insert a type check node if the type is Object.
1048     current_block_->AddInstruction(new (arena_) HArraySet(
1049         object, index, value, anticipated_type, dex_pc));
1050   } else {
1051     current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type));
1052     UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
1053   }
1054   graph_->SetHasBoundsChecks(true);
1055 }
1056 
BuildFilledNewArray(uint32_t dex_pc,uint32_t type_index,uint32_t number_of_vreg_arguments,bool is_range,uint32_t * args,uint32_t register_index)1057 void HGraphBuilder::BuildFilledNewArray(uint32_t dex_pc,
1058                                         uint32_t type_index,
1059                                         uint32_t number_of_vreg_arguments,
1060                                         bool is_range,
1061                                         uint32_t* args,
1062                                         uint32_t register_index) {
1063   HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments);
1064   QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
1065       ? kQuickAllocArrayWithAccessCheck
1066       : kQuickAllocArray;
1067   HInstruction* object = new (arena_) HNewArray(length, dex_pc, type_index, entrypoint);
1068   current_block_->AddInstruction(object);
1069 
1070   const char* descriptor = dex_file_->StringByTypeIdx(type_index);
1071   DCHECK_EQ(descriptor[0], '[') << descriptor;
1072   char primitive = descriptor[1];
1073   DCHECK(primitive == 'I'
1074       || primitive == 'L'
1075       || primitive == '[') << descriptor;
1076   bool is_reference_array = (primitive == 'L') || (primitive == '[');
1077   Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt;
1078 
1079   Temporaries temps(graph_);
1080   temps.Add(object);
1081   for (size_t i = 0; i < number_of_vreg_arguments; ++i) {
1082     HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type);
1083     HInstruction* index = graph_->GetIntConstant(i);
1084     current_block_->AddInstruction(
1085         new (arena_) HArraySet(object, index, value, type, dex_pc));
1086   }
1087   latest_result_ = object;
1088 }
1089 
1090 template <typename T>
BuildFillArrayData(HInstruction * object,const T * data,uint32_t element_count,Primitive::Type anticipated_type,uint32_t dex_pc)1091 void HGraphBuilder::BuildFillArrayData(HInstruction* object,
1092                                        const T* data,
1093                                        uint32_t element_count,
1094                                        Primitive::Type anticipated_type,
1095                                        uint32_t dex_pc) {
1096   for (uint32_t i = 0; i < element_count; ++i) {
1097     HInstruction* index = graph_->GetIntConstant(i);
1098     HInstruction* value = graph_->GetIntConstant(data[i]);
1099     current_block_->AddInstruction(new (arena_) HArraySet(
1100       object, index, value, anticipated_type, dex_pc));
1101   }
1102 }
1103 
BuildFillArrayData(const Instruction & instruction,uint32_t dex_pc)1104 void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) {
1105   Temporaries temps(graph_);
1106   HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot);
1107   HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc);
1108   current_block_->AddInstruction(null_check);
1109   temps.Add(null_check);
1110 
1111   HInstruction* length = new (arena_) HArrayLength(null_check);
1112   current_block_->AddInstruction(length);
1113 
1114   int32_t payload_offset = instruction.VRegB_31t() + dex_pc;
1115   const Instruction::ArrayDataPayload* payload =
1116       reinterpret_cast<const Instruction::ArrayDataPayload*>(code_start_ + payload_offset);
1117   const uint8_t* data = payload->data;
1118   uint32_t element_count = payload->element_count;
1119 
1120   // Implementation of this DEX instruction seems to be that the bounds check is
1121   // done before doing any stores.
1122   HInstruction* last_index = graph_->GetIntConstant(payload->element_count - 1);
1123   current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_pc));
1124 
1125   switch (payload->element_width) {
1126     case 1:
1127       BuildFillArrayData(null_check,
1128                          reinterpret_cast<const int8_t*>(data),
1129                          element_count,
1130                          Primitive::kPrimByte,
1131                          dex_pc);
1132       break;
1133     case 2:
1134       BuildFillArrayData(null_check,
1135                          reinterpret_cast<const int16_t*>(data),
1136                          element_count,
1137                          Primitive::kPrimShort,
1138                          dex_pc);
1139       break;
1140     case 4:
1141       BuildFillArrayData(null_check,
1142                          reinterpret_cast<const int32_t*>(data),
1143                          element_count,
1144                          Primitive::kPrimInt,
1145                          dex_pc);
1146       break;
1147     case 8:
1148       BuildFillWideArrayData(null_check,
1149                              reinterpret_cast<const int64_t*>(data),
1150                              element_count,
1151                              dex_pc);
1152       break;
1153     default:
1154       LOG(FATAL) << "Unknown element width for " << payload->element_width;
1155   }
1156   graph_->SetHasBoundsChecks(true);
1157 }
1158 
BuildFillWideArrayData(HInstruction * object,const int64_t * data,uint32_t element_count,uint32_t dex_pc)1159 void HGraphBuilder::BuildFillWideArrayData(HInstruction* object,
1160                                            const int64_t* data,
1161                                            uint32_t element_count,
1162                                            uint32_t dex_pc) {
1163   for (uint32_t i = 0; i < element_count; ++i) {
1164     HInstruction* index = graph_->GetIntConstant(i);
1165     HInstruction* value = graph_->GetLongConstant(data[i]);
1166     current_block_->AddInstruction(new (arena_) HArraySet(
1167       object, index, value, Primitive::kPrimLong, dex_pc));
1168   }
1169 }
1170 
BuildTypeCheck(const Instruction & instruction,uint8_t destination,uint8_t reference,uint16_t type_index,uint32_t dex_pc)1171 bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction,
1172                                    uint8_t destination,
1173                                    uint8_t reference,
1174                                    uint16_t type_index,
1175                                    uint32_t dex_pc) {
1176   bool type_known_final;
1177   bool type_known_abstract;
1178   // `CanAccessTypeWithoutChecks` will tell whether the method being
1179   // built is trying to access its own class, so that the generated
1180   // code can optimize for this case. However, the optimization does not
1181   // work for inlining, so we use `IsOutermostCompilingClass` instead.
1182   bool dont_use_is_referrers_class;
1183   bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
1184       dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
1185       &type_known_final, &type_known_abstract, &dont_use_is_referrers_class);
1186   if (!can_access) {
1187     MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
1188     return false;
1189   }
1190   HInstruction* object = LoadLocal(reference, Primitive::kPrimNot);
1191   HLoadClass* cls = new (arena_) HLoadClass(
1192       type_index, IsOutermostCompilingClass(type_index), dex_pc);
1193   current_block_->AddInstruction(cls);
1194   // The class needs a temporary before being used by the type check.
1195   Temporaries temps(graph_);
1196   temps.Add(cls);
1197   if (instruction.Opcode() == Instruction::INSTANCE_OF) {
1198     current_block_->AddInstruction(
1199         new (arena_) HInstanceOf(object, cls, type_known_final, dex_pc));
1200     UpdateLocal(destination, current_block_->GetLastInstruction());
1201   } else {
1202     DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST);
1203     current_block_->AddInstruction(
1204         new (arena_) HCheckCast(object, cls, type_known_final, dex_pc));
1205   }
1206   return true;
1207 }
1208 
NeedsAccessCheck(uint32_t type_index) const1209 bool HGraphBuilder::NeedsAccessCheck(uint32_t type_index) const {
1210   return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks(
1211       dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index);
1212 }
1213 
BuildPackedSwitch(const Instruction & instruction,uint32_t dex_pc)1214 void HGraphBuilder::BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc) {
1215   // Verifier guarantees that the payload for PackedSwitch contains:
1216   //   (a) number of entries (may be zero)
1217   //   (b) first and lowest switch case value (entry 0, always present)
1218   //   (c) list of target pcs (entries 1 <= i <= N)
1219   SwitchTable table(instruction, dex_pc, false);
1220 
1221   // Value to test against.
1222   HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
1223 
1224   // Retrieve number of entries.
1225   uint16_t num_entries = table.GetNumEntries();
1226   if (num_entries == 0) {
1227     return;
1228   }
1229 
1230   // Chained cmp-and-branch, starting from starting_key.
1231   int32_t starting_key = table.GetEntryAt(0);
1232 
1233   for (size_t i = 1; i <= num_entries; i++) {
1234     BuildSwitchCaseHelper(instruction, i, i == num_entries, table, value, starting_key + i - 1,
1235                           table.GetEntryAt(i), dex_pc);
1236   }
1237 }
1238 
BuildSparseSwitch(const Instruction & instruction,uint32_t dex_pc)1239 void HGraphBuilder::BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc) {
1240   // Verifier guarantees that the payload for SparseSwitch contains:
1241   //   (a) number of entries (may be zero)
1242   //   (b) sorted key values (entries 0 <= i < N)
1243   //   (c) target pcs corresponding to the switch values (entries N <= i < 2*N)
1244   SwitchTable table(instruction, dex_pc, true);
1245 
1246   // Value to test against.
1247   HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
1248 
1249   uint16_t num_entries = table.GetNumEntries();
1250 
1251   for (size_t i = 0; i < num_entries; i++) {
1252     BuildSwitchCaseHelper(instruction, i, i == static_cast<size_t>(num_entries) - 1, table, value,
1253                           table.GetEntryAt(i), table.GetEntryAt(i + num_entries), dex_pc);
1254   }
1255 }
1256 
BuildSwitchCaseHelper(const Instruction & instruction,size_t index,bool is_last_case,const SwitchTable & table,HInstruction * value,int32_t case_value_int,int32_t target_offset,uint32_t dex_pc)1257 void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t index,
1258                                           bool is_last_case, const SwitchTable& table,
1259                                           HInstruction* value, int32_t case_value_int,
1260                                           int32_t target_offset, uint32_t dex_pc) {
1261   HBasicBlock* case_target = FindBlockStartingAt(dex_pc + target_offset);
1262   DCHECK(case_target != nullptr);
1263   PotentiallyAddSuspendCheck(case_target, dex_pc);
1264 
1265   // The current case's value.
1266   HInstruction* this_case_value = graph_->GetIntConstant(case_value_int);
1267 
1268   // Compare value and this_case_value.
1269   HEqual* comparison = new (arena_) HEqual(value, this_case_value);
1270   current_block_->AddInstruction(comparison);
1271   HInstruction* ifinst = new (arena_) HIf(comparison);
1272   current_block_->AddInstruction(ifinst);
1273 
1274   // Case hit: use the target offset to determine where to go.
1275   current_block_->AddSuccessor(case_target);
1276 
1277   // Case miss: go to the next case (or default fall-through).
1278   // When there is a next case, we use the block stored with the table offset representing this
1279   // case (that is where we registered them in ComputeBranchTargets).
1280   // When there is no next case, we use the following instruction.
1281   // TODO: Find a good way to peel the last iteration to avoid conditional, but still have re-use.
1282   if (!is_last_case) {
1283     HBasicBlock* next_case_target = FindBlockStartingAt(table.GetDexPcForIndex(index));
1284     DCHECK(next_case_target != nullptr);
1285     current_block_->AddSuccessor(next_case_target);
1286 
1287     // Need to manually add the block, as there is no dex-pc transition for the cases.
1288     graph_->AddBlock(next_case_target);
1289 
1290     current_block_ = next_case_target;
1291   } else {
1292     HBasicBlock* default_target = FindBlockStartingAt(dex_pc + instruction.SizeInCodeUnits());
1293     DCHECK(default_target != nullptr);
1294     current_block_->AddSuccessor(default_target);
1295     current_block_ = nullptr;
1296   }
1297 }
1298 
PotentiallyAddSuspendCheck(HBasicBlock * target,uint32_t dex_pc)1299 void HGraphBuilder::PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc) {
1300   int32_t target_offset = target->GetDexPc() - dex_pc;
1301   if (target_offset <= 0) {
1302     // DX generates back edges to the first encountered return. We can save
1303     // time of later passes by not adding redundant suspend checks.
1304     HInstruction* last_in_target = target->GetLastInstruction();
1305     if (last_in_target != nullptr &&
1306         (last_in_target->IsReturn() || last_in_target->IsReturnVoid())) {
1307       return;
1308     }
1309 
1310     // Add a suspend check to backward branches which may potentially loop. We
1311     // can remove them after we recognize loops in the graph.
1312     current_block_->AddInstruction(new (arena_) HSuspendCheck(dex_pc));
1313   }
1314 }
1315 
AnalyzeDexInstruction(const Instruction & instruction,uint32_t dex_pc)1316 bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc) {
1317   if (current_block_ == nullptr) {
1318     return true;  // Dead code
1319   }
1320 
1321   switch (instruction.Opcode()) {
1322     case Instruction::CONST_4: {
1323       int32_t register_index = instruction.VRegA();
1324       HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n());
1325       UpdateLocal(register_index, constant);
1326       break;
1327     }
1328 
1329     case Instruction::CONST_16: {
1330       int32_t register_index = instruction.VRegA();
1331       HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s());
1332       UpdateLocal(register_index, constant);
1333       break;
1334     }
1335 
1336     case Instruction::CONST: {
1337       int32_t register_index = instruction.VRegA();
1338       HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i());
1339       UpdateLocal(register_index, constant);
1340       break;
1341     }
1342 
1343     case Instruction::CONST_HIGH16: {
1344       int32_t register_index = instruction.VRegA();
1345       HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16);
1346       UpdateLocal(register_index, constant);
1347       break;
1348     }
1349 
1350     case Instruction::CONST_WIDE_16: {
1351       int32_t register_index = instruction.VRegA();
1352       // Get 16 bits of constant value, sign extended to 64 bits.
1353       int64_t value = instruction.VRegB_21s();
1354       value <<= 48;
1355       value >>= 48;
1356       HLongConstant* constant = graph_->GetLongConstant(value);
1357       UpdateLocal(register_index, constant);
1358       break;
1359     }
1360 
1361     case Instruction::CONST_WIDE_32: {
1362       int32_t register_index = instruction.VRegA();
1363       // Get 32 bits of constant value, sign extended to 64 bits.
1364       int64_t value = instruction.VRegB_31i();
1365       value <<= 32;
1366       value >>= 32;
1367       HLongConstant* constant = graph_->GetLongConstant(value);
1368       UpdateLocal(register_index, constant);
1369       break;
1370     }
1371 
1372     case Instruction::CONST_WIDE: {
1373       int32_t register_index = instruction.VRegA();
1374       HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l());
1375       UpdateLocal(register_index, constant);
1376       break;
1377     }
1378 
1379     case Instruction::CONST_WIDE_HIGH16: {
1380       int32_t register_index = instruction.VRegA();
1381       int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
1382       HLongConstant* constant = graph_->GetLongConstant(value);
1383       UpdateLocal(register_index, constant);
1384       break;
1385     }
1386 
1387     // Note that the SSA building will refine the types.
1388     case Instruction::MOVE:
1389     case Instruction::MOVE_FROM16:
1390     case Instruction::MOVE_16: {
1391       HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
1392       UpdateLocal(instruction.VRegA(), value);
1393       break;
1394     }
1395 
1396     // Note that the SSA building will refine the types.
1397     case Instruction::MOVE_WIDE:
1398     case Instruction::MOVE_WIDE_FROM16:
1399     case Instruction::MOVE_WIDE_16: {
1400       HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong);
1401       UpdateLocal(instruction.VRegA(), value);
1402       break;
1403     }
1404 
1405     case Instruction::MOVE_OBJECT:
1406     case Instruction::MOVE_OBJECT_16:
1407     case Instruction::MOVE_OBJECT_FROM16: {
1408       HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot);
1409       UpdateLocal(instruction.VRegA(), value);
1410       break;
1411     }
1412 
1413     case Instruction::RETURN_VOID: {
1414       BuildReturn(instruction, Primitive::kPrimVoid);
1415       break;
1416     }
1417 
1418 #define IF_XX(comparison, cond) \
1419     case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_pc); break; \
1420     case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_pc); break
1421 
1422     IF_XX(HEqual, EQ);
1423     IF_XX(HNotEqual, NE);
1424     IF_XX(HLessThan, LT);
1425     IF_XX(HLessThanOrEqual, LE);
1426     IF_XX(HGreaterThan, GT);
1427     IF_XX(HGreaterThanOrEqual, GE);
1428 
1429     case Instruction::GOTO:
1430     case Instruction::GOTO_16:
1431     case Instruction::GOTO_32: {
1432       int32_t offset = instruction.GetTargetOffset();
1433       HBasicBlock* target = FindBlockStartingAt(offset + dex_pc);
1434       DCHECK(target != nullptr);
1435       PotentiallyAddSuspendCheck(target, dex_pc);
1436       current_block_->AddInstruction(new (arena_) HGoto());
1437       current_block_->AddSuccessor(target);
1438       current_block_ = nullptr;
1439       break;
1440     }
1441 
1442     case Instruction::RETURN: {
1443       BuildReturn(instruction, return_type_);
1444       break;
1445     }
1446 
1447     case Instruction::RETURN_OBJECT: {
1448       BuildReturn(instruction, return_type_);
1449       break;
1450     }
1451 
1452     case Instruction::RETURN_WIDE: {
1453       BuildReturn(instruction, return_type_);
1454       break;
1455     }
1456 
1457     case Instruction::INVOKE_DIRECT:
1458     case Instruction::INVOKE_INTERFACE:
1459     case Instruction::INVOKE_STATIC:
1460     case Instruction::INVOKE_SUPER:
1461     case Instruction::INVOKE_VIRTUAL: {
1462       uint32_t method_idx = instruction.VRegB_35c();
1463       uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
1464       uint32_t args[5];
1465       instruction.GetVarArgs(args);
1466       if (!BuildInvoke(instruction, dex_pc, method_idx,
1467                        number_of_vreg_arguments, false, args, -1)) {
1468         return false;
1469       }
1470       break;
1471     }
1472 
1473     case Instruction::INVOKE_DIRECT_RANGE:
1474     case Instruction::INVOKE_INTERFACE_RANGE:
1475     case Instruction::INVOKE_STATIC_RANGE:
1476     case Instruction::INVOKE_SUPER_RANGE:
1477     case Instruction::INVOKE_VIRTUAL_RANGE: {
1478       uint32_t method_idx = instruction.VRegB_3rc();
1479       uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
1480       uint32_t register_index = instruction.VRegC();
1481       if (!BuildInvoke(instruction, dex_pc, method_idx,
1482                        number_of_vreg_arguments, true, nullptr, register_index)) {
1483         return false;
1484       }
1485       break;
1486     }
1487 
1488     case Instruction::NEG_INT: {
1489       Unop_12x<HNeg>(instruction, Primitive::kPrimInt);
1490       break;
1491     }
1492 
1493     case Instruction::NEG_LONG: {
1494       Unop_12x<HNeg>(instruction, Primitive::kPrimLong);
1495       break;
1496     }
1497 
1498     case Instruction::NEG_FLOAT: {
1499       Unop_12x<HNeg>(instruction, Primitive::kPrimFloat);
1500       break;
1501     }
1502 
1503     case Instruction::NEG_DOUBLE: {
1504       Unop_12x<HNeg>(instruction, Primitive::kPrimDouble);
1505       break;
1506     }
1507 
1508     case Instruction::NOT_INT: {
1509       Unop_12x<HNot>(instruction, Primitive::kPrimInt);
1510       break;
1511     }
1512 
1513     case Instruction::NOT_LONG: {
1514       Unop_12x<HNot>(instruction, Primitive::kPrimLong);
1515       break;
1516     }
1517 
1518     case Instruction::INT_TO_LONG: {
1519       Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong, dex_pc);
1520       break;
1521     }
1522 
1523     case Instruction::INT_TO_FLOAT: {
1524       Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimFloat, dex_pc);
1525       break;
1526     }
1527 
1528     case Instruction::INT_TO_DOUBLE: {
1529       Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimDouble, dex_pc);
1530       break;
1531     }
1532 
1533     case Instruction::LONG_TO_INT: {
1534       Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimInt, dex_pc);
1535       break;
1536     }
1537 
1538     case Instruction::LONG_TO_FLOAT: {
1539       Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimFloat, dex_pc);
1540       break;
1541     }
1542 
1543     case Instruction::LONG_TO_DOUBLE: {
1544       Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimDouble, dex_pc);
1545       break;
1546     }
1547 
1548     case Instruction::FLOAT_TO_INT: {
1549       Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimInt, dex_pc);
1550       break;
1551     }
1552 
1553     case Instruction::FLOAT_TO_LONG: {
1554       Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimLong, dex_pc);
1555       break;
1556     }
1557 
1558     case Instruction::FLOAT_TO_DOUBLE: {
1559       Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimDouble, dex_pc);
1560       break;
1561     }
1562 
1563     case Instruction::DOUBLE_TO_INT: {
1564       Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimInt, dex_pc);
1565       break;
1566     }
1567 
1568     case Instruction::DOUBLE_TO_LONG: {
1569       Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimLong, dex_pc);
1570       break;
1571     }
1572 
1573     case Instruction::DOUBLE_TO_FLOAT: {
1574       Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimFloat, dex_pc);
1575       break;
1576     }
1577 
1578     case Instruction::INT_TO_BYTE: {
1579       Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimByte, dex_pc);
1580       break;
1581     }
1582 
1583     case Instruction::INT_TO_SHORT: {
1584       Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimShort, dex_pc);
1585       break;
1586     }
1587 
1588     case Instruction::INT_TO_CHAR: {
1589       Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimChar, dex_pc);
1590       break;
1591     }
1592 
1593     case Instruction::ADD_INT: {
1594       Binop_23x<HAdd>(instruction, Primitive::kPrimInt);
1595       break;
1596     }
1597 
1598     case Instruction::ADD_LONG: {
1599       Binop_23x<HAdd>(instruction, Primitive::kPrimLong);
1600       break;
1601     }
1602 
1603     case Instruction::ADD_DOUBLE: {
1604       Binop_23x<HAdd>(instruction, Primitive::kPrimDouble);
1605       break;
1606     }
1607 
1608     case Instruction::ADD_FLOAT: {
1609       Binop_23x<HAdd>(instruction, Primitive::kPrimFloat);
1610       break;
1611     }
1612 
1613     case Instruction::SUB_INT: {
1614       Binop_23x<HSub>(instruction, Primitive::kPrimInt);
1615       break;
1616     }
1617 
1618     case Instruction::SUB_LONG: {
1619       Binop_23x<HSub>(instruction, Primitive::kPrimLong);
1620       break;
1621     }
1622 
1623     case Instruction::SUB_FLOAT: {
1624       Binop_23x<HSub>(instruction, Primitive::kPrimFloat);
1625       break;
1626     }
1627 
1628     case Instruction::SUB_DOUBLE: {
1629       Binop_23x<HSub>(instruction, Primitive::kPrimDouble);
1630       break;
1631     }
1632 
1633     case Instruction::ADD_INT_2ADDR: {
1634       Binop_12x<HAdd>(instruction, Primitive::kPrimInt);
1635       break;
1636     }
1637 
1638     case Instruction::MUL_INT: {
1639       Binop_23x<HMul>(instruction, Primitive::kPrimInt);
1640       break;
1641     }
1642 
1643     case Instruction::MUL_LONG: {
1644       Binop_23x<HMul>(instruction, Primitive::kPrimLong);
1645       break;
1646     }
1647 
1648     case Instruction::MUL_FLOAT: {
1649       Binop_23x<HMul>(instruction, Primitive::kPrimFloat);
1650       break;
1651     }
1652 
1653     case Instruction::MUL_DOUBLE: {
1654       Binop_23x<HMul>(instruction, Primitive::kPrimDouble);
1655       break;
1656     }
1657 
1658     case Instruction::DIV_INT: {
1659       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1660                          dex_pc, Primitive::kPrimInt, false, true);
1661       break;
1662     }
1663 
1664     case Instruction::DIV_LONG: {
1665       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1666                          dex_pc, Primitive::kPrimLong, false, true);
1667       break;
1668     }
1669 
1670     case Instruction::DIV_FLOAT: {
1671       Binop_23x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
1672       break;
1673     }
1674 
1675     case Instruction::DIV_DOUBLE: {
1676       Binop_23x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
1677       break;
1678     }
1679 
1680     case Instruction::REM_INT: {
1681       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1682                          dex_pc, Primitive::kPrimInt, false, false);
1683       break;
1684     }
1685 
1686     case Instruction::REM_LONG: {
1687       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1688                          dex_pc, Primitive::kPrimLong, false, false);
1689       break;
1690     }
1691 
1692     case Instruction::REM_FLOAT: {
1693       Binop_23x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
1694       break;
1695     }
1696 
1697     case Instruction::REM_DOUBLE: {
1698       Binop_23x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
1699       break;
1700     }
1701 
1702     case Instruction::AND_INT: {
1703       Binop_23x<HAnd>(instruction, Primitive::kPrimInt);
1704       break;
1705     }
1706 
1707     case Instruction::AND_LONG: {
1708       Binop_23x<HAnd>(instruction, Primitive::kPrimLong);
1709       break;
1710     }
1711 
1712     case Instruction::SHL_INT: {
1713       Binop_23x_shift<HShl>(instruction, Primitive::kPrimInt);
1714       break;
1715     }
1716 
1717     case Instruction::SHL_LONG: {
1718       Binop_23x_shift<HShl>(instruction, Primitive::kPrimLong);
1719       break;
1720     }
1721 
1722     case Instruction::SHR_INT: {
1723       Binop_23x_shift<HShr>(instruction, Primitive::kPrimInt);
1724       break;
1725     }
1726 
1727     case Instruction::SHR_LONG: {
1728       Binop_23x_shift<HShr>(instruction, Primitive::kPrimLong);
1729       break;
1730     }
1731 
1732     case Instruction::USHR_INT: {
1733       Binop_23x_shift<HUShr>(instruction, Primitive::kPrimInt);
1734       break;
1735     }
1736 
1737     case Instruction::USHR_LONG: {
1738       Binop_23x_shift<HUShr>(instruction, Primitive::kPrimLong);
1739       break;
1740     }
1741 
1742     case Instruction::OR_INT: {
1743       Binop_23x<HOr>(instruction, Primitive::kPrimInt);
1744       break;
1745     }
1746 
1747     case Instruction::OR_LONG: {
1748       Binop_23x<HOr>(instruction, Primitive::kPrimLong);
1749       break;
1750     }
1751 
1752     case Instruction::XOR_INT: {
1753       Binop_23x<HXor>(instruction, Primitive::kPrimInt);
1754       break;
1755     }
1756 
1757     case Instruction::XOR_LONG: {
1758       Binop_23x<HXor>(instruction, Primitive::kPrimLong);
1759       break;
1760     }
1761 
1762     case Instruction::ADD_LONG_2ADDR: {
1763       Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
1764       break;
1765     }
1766 
1767     case Instruction::ADD_DOUBLE_2ADDR: {
1768       Binop_12x<HAdd>(instruction, Primitive::kPrimDouble);
1769       break;
1770     }
1771 
1772     case Instruction::ADD_FLOAT_2ADDR: {
1773       Binop_12x<HAdd>(instruction, Primitive::kPrimFloat);
1774       break;
1775     }
1776 
1777     case Instruction::SUB_INT_2ADDR: {
1778       Binop_12x<HSub>(instruction, Primitive::kPrimInt);
1779       break;
1780     }
1781 
1782     case Instruction::SUB_LONG_2ADDR: {
1783       Binop_12x<HSub>(instruction, Primitive::kPrimLong);
1784       break;
1785     }
1786 
1787     case Instruction::SUB_FLOAT_2ADDR: {
1788       Binop_12x<HSub>(instruction, Primitive::kPrimFloat);
1789       break;
1790     }
1791 
1792     case Instruction::SUB_DOUBLE_2ADDR: {
1793       Binop_12x<HSub>(instruction, Primitive::kPrimDouble);
1794       break;
1795     }
1796 
1797     case Instruction::MUL_INT_2ADDR: {
1798       Binop_12x<HMul>(instruction, Primitive::kPrimInt);
1799       break;
1800     }
1801 
1802     case Instruction::MUL_LONG_2ADDR: {
1803       Binop_12x<HMul>(instruction, Primitive::kPrimLong);
1804       break;
1805     }
1806 
1807     case Instruction::MUL_FLOAT_2ADDR: {
1808       Binop_12x<HMul>(instruction, Primitive::kPrimFloat);
1809       break;
1810     }
1811 
1812     case Instruction::MUL_DOUBLE_2ADDR: {
1813       Binop_12x<HMul>(instruction, Primitive::kPrimDouble);
1814       break;
1815     }
1816 
1817     case Instruction::DIV_INT_2ADDR: {
1818       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
1819                          dex_pc, Primitive::kPrimInt, false, true);
1820       break;
1821     }
1822 
1823     case Instruction::DIV_LONG_2ADDR: {
1824       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
1825                          dex_pc, Primitive::kPrimLong, false, true);
1826       break;
1827     }
1828 
1829     case Instruction::REM_INT_2ADDR: {
1830       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
1831                          dex_pc, Primitive::kPrimInt, false, false);
1832       break;
1833     }
1834 
1835     case Instruction::REM_LONG_2ADDR: {
1836       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
1837                          dex_pc, Primitive::kPrimLong, false, false);
1838       break;
1839     }
1840 
1841     case Instruction::REM_FLOAT_2ADDR: {
1842       Binop_12x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
1843       break;
1844     }
1845 
1846     case Instruction::REM_DOUBLE_2ADDR: {
1847       Binop_12x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
1848       break;
1849     }
1850 
1851     case Instruction::SHL_INT_2ADDR: {
1852       Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt);
1853       break;
1854     }
1855 
1856     case Instruction::SHL_LONG_2ADDR: {
1857       Binop_12x_shift<HShl>(instruction, Primitive::kPrimLong);
1858       break;
1859     }
1860 
1861     case Instruction::SHR_INT_2ADDR: {
1862       Binop_12x_shift<HShr>(instruction, Primitive::kPrimInt);
1863       break;
1864     }
1865 
1866     case Instruction::SHR_LONG_2ADDR: {
1867       Binop_12x_shift<HShr>(instruction, Primitive::kPrimLong);
1868       break;
1869     }
1870 
1871     case Instruction::USHR_INT_2ADDR: {
1872       Binop_12x_shift<HUShr>(instruction, Primitive::kPrimInt);
1873       break;
1874     }
1875 
1876     case Instruction::USHR_LONG_2ADDR: {
1877       Binop_12x_shift<HUShr>(instruction, Primitive::kPrimLong);
1878       break;
1879     }
1880 
1881     case Instruction::DIV_FLOAT_2ADDR: {
1882       Binop_12x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
1883       break;
1884     }
1885 
1886     case Instruction::DIV_DOUBLE_2ADDR: {
1887       Binop_12x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
1888       break;
1889     }
1890 
1891     case Instruction::AND_INT_2ADDR: {
1892       Binop_12x<HAnd>(instruction, Primitive::kPrimInt);
1893       break;
1894     }
1895 
1896     case Instruction::AND_LONG_2ADDR: {
1897       Binop_12x<HAnd>(instruction, Primitive::kPrimLong);
1898       break;
1899     }
1900 
1901     case Instruction::OR_INT_2ADDR: {
1902       Binop_12x<HOr>(instruction, Primitive::kPrimInt);
1903       break;
1904     }
1905 
1906     case Instruction::OR_LONG_2ADDR: {
1907       Binop_12x<HOr>(instruction, Primitive::kPrimLong);
1908       break;
1909     }
1910 
1911     case Instruction::XOR_INT_2ADDR: {
1912       Binop_12x<HXor>(instruction, Primitive::kPrimInt);
1913       break;
1914     }
1915 
1916     case Instruction::XOR_LONG_2ADDR: {
1917       Binop_12x<HXor>(instruction, Primitive::kPrimLong);
1918       break;
1919     }
1920 
1921     case Instruction::ADD_INT_LIT16: {
1922       Binop_22s<HAdd>(instruction, false);
1923       break;
1924     }
1925 
1926     case Instruction::AND_INT_LIT16: {
1927       Binop_22s<HAnd>(instruction, false);
1928       break;
1929     }
1930 
1931     case Instruction::OR_INT_LIT16: {
1932       Binop_22s<HOr>(instruction, false);
1933       break;
1934     }
1935 
1936     case Instruction::XOR_INT_LIT16: {
1937       Binop_22s<HXor>(instruction, false);
1938       break;
1939     }
1940 
1941     case Instruction::RSUB_INT: {
1942       Binop_22s<HSub>(instruction, true);
1943       break;
1944     }
1945 
1946     case Instruction::MUL_INT_LIT16: {
1947       Binop_22s<HMul>(instruction, false);
1948       break;
1949     }
1950 
1951     case Instruction::ADD_INT_LIT8: {
1952       Binop_22b<HAdd>(instruction, false);
1953       break;
1954     }
1955 
1956     case Instruction::AND_INT_LIT8: {
1957       Binop_22b<HAnd>(instruction, false);
1958       break;
1959     }
1960 
1961     case Instruction::OR_INT_LIT8: {
1962       Binop_22b<HOr>(instruction, false);
1963       break;
1964     }
1965 
1966     case Instruction::XOR_INT_LIT8: {
1967       Binop_22b<HXor>(instruction, false);
1968       break;
1969     }
1970 
1971     case Instruction::RSUB_INT_LIT8: {
1972       Binop_22b<HSub>(instruction, true);
1973       break;
1974     }
1975 
1976     case Instruction::MUL_INT_LIT8: {
1977       Binop_22b<HMul>(instruction, false);
1978       break;
1979     }
1980 
1981     case Instruction::DIV_INT_LIT16:
1982     case Instruction::DIV_INT_LIT8: {
1983       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1984                          dex_pc, Primitive::kPrimInt, true, true);
1985       break;
1986     }
1987 
1988     case Instruction::REM_INT_LIT16:
1989     case Instruction::REM_INT_LIT8: {
1990       BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
1991                          dex_pc, Primitive::kPrimInt, true, false);
1992       break;
1993     }
1994 
1995     case Instruction::SHL_INT_LIT8: {
1996       Binop_22b<HShl>(instruction, false);
1997       break;
1998     }
1999 
2000     case Instruction::SHR_INT_LIT8: {
2001       Binop_22b<HShr>(instruction, false);
2002       break;
2003     }
2004 
2005     case Instruction::USHR_INT_LIT8: {
2006       Binop_22b<HUShr>(instruction, false);
2007       break;
2008     }
2009 
2010     case Instruction::NEW_INSTANCE: {
2011       uint16_t type_index = instruction.VRegB_21c();
2012       if (compiler_driver_->IsStringTypeIndex(type_index, dex_file_)) {
2013         // Turn new-instance of string into a const 0.
2014         int32_t register_index = instruction.VRegA();
2015         HNullConstant* constant = graph_->GetNullConstant();
2016         UpdateLocal(register_index, constant);
2017       } else {
2018         QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
2019             ? kQuickAllocObjectWithAccessCheck
2020             : kQuickAllocObject;
2021 
2022         current_block_->AddInstruction(new (arena_) HNewInstance(dex_pc, type_index, entrypoint));
2023         UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
2024       }
2025       break;
2026     }
2027 
2028     case Instruction::NEW_ARRAY: {
2029       uint16_t type_index = instruction.VRegC_22c();
2030       HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt);
2031       QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
2032           ? kQuickAllocArrayWithAccessCheck
2033           : kQuickAllocArray;
2034       current_block_->AddInstruction(
2035           new (arena_) HNewArray(length, dex_pc, type_index, entrypoint));
2036       UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
2037       break;
2038     }
2039 
2040     case Instruction::FILLED_NEW_ARRAY: {
2041       uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
2042       uint32_t type_index = instruction.VRegB_35c();
2043       uint32_t args[5];
2044       instruction.GetVarArgs(args);
2045       BuildFilledNewArray(dex_pc, type_index, number_of_vreg_arguments, false, args, 0);
2046       break;
2047     }
2048 
2049     case Instruction::FILLED_NEW_ARRAY_RANGE: {
2050       uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
2051       uint32_t type_index = instruction.VRegB_3rc();
2052       uint32_t register_index = instruction.VRegC_3rc();
2053       BuildFilledNewArray(
2054           dex_pc, type_index, number_of_vreg_arguments, true, nullptr, register_index);
2055       break;
2056     }
2057 
2058     case Instruction::FILL_ARRAY_DATA: {
2059       BuildFillArrayData(instruction, dex_pc);
2060       break;
2061     }
2062 
2063     case Instruction::MOVE_RESULT:
2064     case Instruction::MOVE_RESULT_WIDE:
2065     case Instruction::MOVE_RESULT_OBJECT:
2066       if (latest_result_ == nullptr) {
2067         // Only dead code can lead to this situation, where the verifier
2068         // does not reject the method.
2069       } else {
2070         UpdateLocal(instruction.VRegA(), latest_result_);
2071         latest_result_ = nullptr;
2072       }
2073       break;
2074 
2075     case Instruction::CMP_LONG: {
2076       Binop_23x_cmp(instruction, Primitive::kPrimLong, HCompare::kNoBias, dex_pc);
2077       break;
2078     }
2079 
2080     case Instruction::CMPG_FLOAT: {
2081       Binop_23x_cmp(instruction, Primitive::kPrimFloat, HCompare::kGtBias, dex_pc);
2082       break;
2083     }
2084 
2085     case Instruction::CMPG_DOUBLE: {
2086       Binop_23x_cmp(instruction, Primitive::kPrimDouble, HCompare::kGtBias, dex_pc);
2087       break;
2088     }
2089 
2090     case Instruction::CMPL_FLOAT: {
2091       Binop_23x_cmp(instruction, Primitive::kPrimFloat, HCompare::kLtBias, dex_pc);
2092       break;
2093     }
2094 
2095     case Instruction::CMPL_DOUBLE: {
2096       Binop_23x_cmp(instruction, Primitive::kPrimDouble, HCompare::kLtBias, dex_pc);
2097       break;
2098     }
2099 
2100     case Instruction::NOP:
2101       break;
2102 
2103     case Instruction::IGET:
2104     case Instruction::IGET_WIDE:
2105     case Instruction::IGET_OBJECT:
2106     case Instruction::IGET_BOOLEAN:
2107     case Instruction::IGET_BYTE:
2108     case Instruction::IGET_CHAR:
2109     case Instruction::IGET_SHORT: {
2110       if (!BuildInstanceFieldAccess(instruction, dex_pc, false)) {
2111         return false;
2112       }
2113       break;
2114     }
2115 
2116     case Instruction::IPUT:
2117     case Instruction::IPUT_WIDE:
2118     case Instruction::IPUT_OBJECT:
2119     case Instruction::IPUT_BOOLEAN:
2120     case Instruction::IPUT_BYTE:
2121     case Instruction::IPUT_CHAR:
2122     case Instruction::IPUT_SHORT: {
2123       if (!BuildInstanceFieldAccess(instruction, dex_pc, true)) {
2124         return false;
2125       }
2126       break;
2127     }
2128 
2129     case Instruction::SGET:
2130     case Instruction::SGET_WIDE:
2131     case Instruction::SGET_OBJECT:
2132     case Instruction::SGET_BOOLEAN:
2133     case Instruction::SGET_BYTE:
2134     case Instruction::SGET_CHAR:
2135     case Instruction::SGET_SHORT: {
2136       if (!BuildStaticFieldAccess(instruction, dex_pc, false)) {
2137         return false;
2138       }
2139       break;
2140     }
2141 
2142     case Instruction::SPUT:
2143     case Instruction::SPUT_WIDE:
2144     case Instruction::SPUT_OBJECT:
2145     case Instruction::SPUT_BOOLEAN:
2146     case Instruction::SPUT_BYTE:
2147     case Instruction::SPUT_CHAR:
2148     case Instruction::SPUT_SHORT: {
2149       if (!BuildStaticFieldAccess(instruction, dex_pc, true)) {
2150         return false;
2151       }
2152       break;
2153     }
2154 
2155 #define ARRAY_XX(kind, anticipated_type)                                          \
2156     case Instruction::AGET##kind: {                                               \
2157       BuildArrayAccess(instruction, dex_pc, false, anticipated_type);         \
2158       break;                                                                      \
2159     }                                                                             \
2160     case Instruction::APUT##kind: {                                               \
2161       BuildArrayAccess(instruction, dex_pc, true, anticipated_type);          \
2162       break;                                                                      \
2163     }
2164 
2165     ARRAY_XX(, Primitive::kPrimInt);
2166     ARRAY_XX(_WIDE, Primitive::kPrimLong);
2167     ARRAY_XX(_OBJECT, Primitive::kPrimNot);
2168     ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean);
2169     ARRAY_XX(_BYTE, Primitive::kPrimByte);
2170     ARRAY_XX(_CHAR, Primitive::kPrimChar);
2171     ARRAY_XX(_SHORT, Primitive::kPrimShort);
2172 
2173     case Instruction::ARRAY_LENGTH: {
2174       HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot);
2175       // No need for a temporary for the null check, it is the only input of the following
2176       // instruction.
2177       object = new (arena_) HNullCheck(object, dex_pc);
2178       current_block_->AddInstruction(object);
2179       current_block_->AddInstruction(new (arena_) HArrayLength(object));
2180       UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction());
2181       break;
2182     }
2183 
2184     case Instruction::CONST_STRING: {
2185       current_block_->AddInstruction(new (arena_) HLoadString(instruction.VRegB_21c(), dex_pc));
2186       UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
2187       break;
2188     }
2189 
2190     case Instruction::CONST_STRING_JUMBO: {
2191       current_block_->AddInstruction(new (arena_) HLoadString(instruction.VRegB_31c(), dex_pc));
2192       UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction());
2193       break;
2194     }
2195 
2196     case Instruction::CONST_CLASS: {
2197       uint16_t type_index = instruction.VRegB_21c();
2198       bool type_known_final;
2199       bool type_known_abstract;
2200       bool dont_use_is_referrers_class;
2201       // `CanAccessTypeWithoutChecks` will tell whether the method being
2202       // built is trying to access its own class, so that the generated
2203       // code can optimize for this case. However, the optimization does not
2204       // work for inlining, so we use `IsOutermostCompilingClass` instead.
2205       bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
2206           dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
2207           &type_known_final, &type_known_abstract, &dont_use_is_referrers_class);
2208       if (!can_access) {
2209         MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
2210         return false;
2211       }
2212       current_block_->AddInstruction(
2213           new (arena_) HLoadClass(type_index, IsOutermostCompilingClass(type_index), dex_pc));
2214       UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
2215       break;
2216     }
2217 
2218     case Instruction::MOVE_EXCEPTION: {
2219       current_block_->AddInstruction(new (arena_) HLoadException());
2220       UpdateLocal(instruction.VRegA_11x(), current_block_->GetLastInstruction());
2221       break;
2222     }
2223 
2224     case Instruction::THROW: {
2225       HInstruction* exception = LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot);
2226       current_block_->AddInstruction(new (arena_) HThrow(exception, dex_pc));
2227       // A throw instruction must branch to the exit block.
2228       current_block_->AddSuccessor(exit_block_);
2229       // We finished building this block. Set the current block to null to avoid
2230       // adding dead instructions to it.
2231       current_block_ = nullptr;
2232       break;
2233     }
2234 
2235     case Instruction::INSTANCE_OF: {
2236       uint8_t destination = instruction.VRegA_22c();
2237       uint8_t reference = instruction.VRegB_22c();
2238       uint16_t type_index = instruction.VRegC_22c();
2239       if (!BuildTypeCheck(instruction, destination, reference, type_index, dex_pc)) {
2240         return false;
2241       }
2242       break;
2243     }
2244 
2245     case Instruction::CHECK_CAST: {
2246       uint8_t reference = instruction.VRegA_21c();
2247       uint16_t type_index = instruction.VRegB_21c();
2248       if (!BuildTypeCheck(instruction, -1, reference, type_index, dex_pc)) {
2249         return false;
2250       }
2251       break;
2252     }
2253 
2254     case Instruction::MONITOR_ENTER: {
2255       current_block_->AddInstruction(new (arena_) HMonitorOperation(
2256           LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
2257           HMonitorOperation::kEnter,
2258           dex_pc));
2259       break;
2260     }
2261 
2262     case Instruction::MONITOR_EXIT: {
2263       current_block_->AddInstruction(new (arena_) HMonitorOperation(
2264           LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
2265           HMonitorOperation::kExit,
2266           dex_pc));
2267       break;
2268     }
2269 
2270     case Instruction::PACKED_SWITCH: {
2271       BuildPackedSwitch(instruction, dex_pc);
2272       break;
2273     }
2274 
2275     case Instruction::SPARSE_SWITCH: {
2276       BuildSparseSwitch(instruction, dex_pc);
2277       break;
2278     }
2279 
2280     default:
2281       VLOG(compiler) << "Did not compile "
2282                      << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
2283                      << " because of unhandled instruction "
2284                      << instruction.Name();
2285       MaybeRecordStat(MethodCompilationStat::kNotCompiledUnhandledInstruction);
2286       return false;
2287   }
2288   return true;
2289 }  // NOLINT(readability/fn_size)
2290 
GetLocalAt(int register_index) const2291 HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
2292   return locals_.Get(register_index);
2293 }
2294 
UpdateLocal(int register_index,HInstruction * instruction) const2295 void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {
2296   HLocal* local = GetLocalAt(register_index);
2297   current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));
2298 }
2299 
LoadLocal(int register_index,Primitive::Type type) const2300 HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const {
2301   HLocal* local = GetLocalAt(register_index);
2302   current_block_->AddInstruction(new (arena_) HLoadLocal(local, type));
2303   return current_block_->GetLastInstruction();
2304 }
2305 
2306 }  // namespace art
2307