builder.cc revision 3dbcb38a8b2237b0da290ae35dc0caab3cb47b3d
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 "class_linker.h"
20#include "dex_file.h"
21#include "dex_file-inl.h"
22#include "dex_instruction.h"
23#include "dex_instruction-inl.h"
24#include "driver/compiler_driver-inl.h"
25#include "mirror/art_field.h"
26#include "mirror/art_field-inl.h"
27#include "mirror/class_loader.h"
28#include "mirror/dex_cache.h"
29#include "nodes.h"
30#include "primitive.h"
31#include "scoped_thread_state_change.h"
32#include "thread.h"
33
34namespace art {
35
36/**
37 * Helper class to add HTemporary instructions. This class is used when
38 * converting a DEX instruction to multiple HInstruction, and where those
39 * instructions do not die at the following instruction, but instead spans
40 * multiple instructions.
41 */
42class Temporaries : public ValueObject {
43 public:
44  Temporaries(HGraph* graph, size_t count) : graph_(graph), count_(count), index_(0) {
45    graph_->UpdateNumberOfTemporaries(count_);
46  }
47
48  void Add(HInstruction* instruction) {
49    // We currently only support vreg size temps.
50    DCHECK(instruction->GetType() != Primitive::kPrimLong
51           && instruction->GetType() != Primitive::kPrimDouble);
52    HInstruction* temp = new (graph_->GetArena()) HTemporary(index_++);
53    instruction->GetBlock()->AddInstruction(temp);
54    DCHECK(temp->GetPrevious() == instruction);
55  }
56
57 private:
58  HGraph* const graph_;
59
60  // The total number of temporaries that will be used.
61  const size_t count_;
62
63  // Current index in the temporary stack, updated by `Add`.
64  size_t index_;
65};
66
67static bool IsTypeSupported(Primitive::Type type) {
68  return type != Primitive::kPrimFloat && type != Primitive::kPrimDouble;
69}
70
71void HGraphBuilder::InitializeLocals(uint16_t count) {
72  graph_->SetNumberOfVRegs(count);
73  locals_.SetSize(count);
74  for (int i = 0; i < count; i++) {
75    HLocal* local = new (arena_) HLocal(i);
76    entry_block_->AddInstruction(local);
77    locals_.Put(i, local);
78  }
79}
80
81bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) {
82  // dex_compilation_unit_ is null only when unit testing.
83  if (dex_compilation_unit_ == nullptr) {
84    return true;
85  }
86
87  graph_->SetNumberOfInVRegs(number_of_parameters);
88  const char* shorty = dex_compilation_unit_->GetShorty();
89  int locals_index = locals_.Size() - number_of_parameters;
90  int parameter_index = 0;
91
92  if (!dex_compilation_unit_->IsStatic()) {
93    // Add the implicit 'this' argument, not expressed in the signature.
94    HParameterValue* parameter =
95        new (arena_) HParameterValue(parameter_index++, Primitive::kPrimNot);
96    entry_block_->AddInstruction(parameter);
97    HLocal* local = GetLocalAt(locals_index++);
98    entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
99    number_of_parameters--;
100  }
101
102  uint32_t pos = 1;
103  for (int i = 0; i < number_of_parameters; i++) {
104    HParameterValue* parameter =
105        new (arena_) HParameterValue(parameter_index++, Primitive::GetType(shorty[pos++]));
106    entry_block_->AddInstruction(parameter);
107    HLocal* local = GetLocalAt(locals_index++);
108    // Store the parameter value in the local that the dex code will use
109    // to reference that parameter.
110    entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
111    bool is_wide = (parameter->GetType() == Primitive::kPrimLong)
112        || (parameter->GetType() == Primitive::kPrimDouble);
113    if (is_wide) {
114      i++;
115      locals_index++;
116      parameter_index++;
117    }
118  }
119  return true;
120}
121
122static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) {
123  if (code_item.tries_size_ > 0) {
124    return false;
125  }
126  return true;
127}
128
129template<typename T>
130void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_offset) {
131  int32_t target_offset = instruction.GetTargetOffset();
132  PotentiallyAddSuspendCheck(target_offset, dex_offset);
133  HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
134  HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
135  T* comparison = new (arena_) T(first, second);
136  current_block_->AddInstruction(comparison);
137  HInstruction* ifinst = new (arena_) HIf(comparison);
138  current_block_->AddInstruction(ifinst);
139  HBasicBlock* target = FindBlockStartingAt(dex_offset + target_offset);
140  DCHECK(target != nullptr);
141  current_block_->AddSuccessor(target);
142  target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits());
143  DCHECK(target != nullptr);
144  current_block_->AddSuccessor(target);
145  current_block_ = nullptr;
146}
147
148template<typename T>
149void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_offset) {
150  int32_t target_offset = instruction.GetTargetOffset();
151  PotentiallyAddSuspendCheck(target_offset, dex_offset);
152  HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
153  T* comparison = new (arena_) T(value, GetIntConstant(0));
154  current_block_->AddInstruction(comparison);
155  HInstruction* ifinst = new (arena_) HIf(comparison);
156  current_block_->AddInstruction(ifinst);
157  HBasicBlock* target = FindBlockStartingAt(dex_offset + target_offset);
158  DCHECK(target != nullptr);
159  current_block_->AddSuccessor(target);
160  target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits());
161  DCHECK(target != nullptr);
162  current_block_->AddSuccessor(target);
163  current_block_ = nullptr;
164}
165
166HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
167  if (!CanHandleCodeItem(code_item)) {
168    return nullptr;
169  }
170
171  const uint16_t* code_ptr = code_item.insns_;
172  const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_;
173  code_start_ = code_ptr;
174
175  // Setup the graph with the entry block and exit block.
176  graph_ = new (arena_) HGraph(arena_);
177  entry_block_ = new (arena_) HBasicBlock(graph_, 0);
178  graph_->AddBlock(entry_block_);
179  exit_block_ = new (arena_) HBasicBlock(graph_, kNoDexPc);
180  graph_->SetEntryBlock(entry_block_);
181  graph_->SetExitBlock(exit_block_);
182
183  InitializeLocals(code_item.registers_size_);
184  graph_->UpdateMaximumNumberOfOutVRegs(code_item.outs_size_);
185
186  // To avoid splitting blocks, we compute ahead of time the instructions that
187  // start a new block, and create these blocks.
188  ComputeBranchTargets(code_ptr, code_end);
189
190  if (!InitializeParameters(code_item.ins_size_)) {
191    return nullptr;
192  }
193
194  size_t dex_offset = 0;
195  while (code_ptr < code_end) {
196    // Update the current block if dex_offset starts a new block.
197    MaybeUpdateCurrentBlock(dex_offset);
198    const Instruction& instruction = *Instruction::At(code_ptr);
199    if (!AnalyzeDexInstruction(instruction, dex_offset)) return nullptr;
200    dex_offset += instruction.SizeInCodeUnits();
201    code_ptr += instruction.SizeInCodeUnits();
202  }
203
204  // Add the exit block at the end to give it the highest id.
205  graph_->AddBlock(exit_block_);
206  exit_block_->AddInstruction(new (arena_) HExit());
207  // Add the suspend check to the entry block.
208  entry_block_->AddInstruction(new (arena_) HSuspendCheck(0));
209  entry_block_->AddInstruction(new (arena_) HGoto());
210  return graph_;
211}
212
213void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) {
214  HBasicBlock* block = FindBlockStartingAt(index);
215  if (block == nullptr) {
216    return;
217  }
218
219  if (current_block_ != nullptr) {
220    // Branching instructions clear current_block, so we know
221    // the last instruction of the current block is not a branching
222    // instruction. We add an unconditional goto to the found block.
223    current_block_->AddInstruction(new (arena_) HGoto());
224    current_block_->AddSuccessor(block);
225  }
226  graph_->AddBlock(block);
227  current_block_ = block;
228}
229
230void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, const uint16_t* code_end) {
231  // TODO: Support switch instructions.
232  branch_targets_.SetSize(code_end - code_ptr);
233
234  // Create the first block for the dex instructions, single successor of the entry block.
235  HBasicBlock* block = new (arena_) HBasicBlock(graph_, 0);
236  branch_targets_.Put(0, block);
237  entry_block_->AddSuccessor(block);
238
239  // Iterate over all instructions and find branching instructions. Create blocks for
240  // the locations these instructions branch to.
241  size_t dex_offset = 0;
242  while (code_ptr < code_end) {
243    const Instruction& instruction = *Instruction::At(code_ptr);
244    if (instruction.IsBranch()) {
245      int32_t target = instruction.GetTargetOffset() + dex_offset;
246      // Create a block for the target instruction.
247      if (FindBlockStartingAt(target) == nullptr) {
248        block = new (arena_) HBasicBlock(graph_, target);
249        branch_targets_.Put(target, block);
250      }
251      dex_offset += instruction.SizeInCodeUnits();
252      code_ptr += instruction.SizeInCodeUnits();
253      if ((code_ptr < code_end) && (FindBlockStartingAt(dex_offset) == nullptr)) {
254        block = new (arena_) HBasicBlock(graph_, dex_offset);
255        branch_targets_.Put(dex_offset, block);
256      }
257    } else {
258      code_ptr += instruction.SizeInCodeUnits();
259      dex_offset += instruction.SizeInCodeUnits();
260    }
261  }
262}
263
264HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const {
265  DCHECK_GE(index, 0);
266  return branch_targets_.Get(index);
267}
268
269template<typename T>
270void HGraphBuilder::Unop_12x(const Instruction& instruction, Primitive::Type type) {
271  HInstruction* first = LoadLocal(instruction.VRegB(), type);
272  current_block_->AddInstruction(new (arena_) T(type, first));
273  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
274}
275
276void HGraphBuilder::Conversion_12x(const Instruction& instruction,
277                                   Primitive::Type input_type,
278                                   Primitive::Type result_type) {
279  HInstruction* first = LoadLocal(instruction.VRegB(), input_type);
280  current_block_->AddInstruction(new (arena_) HTypeConversion(result_type, first));
281  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
282}
283
284template<typename T>
285void HGraphBuilder::Binop_23x(const Instruction& instruction, Primitive::Type type) {
286  HInstruction* first = LoadLocal(instruction.VRegB(), type);
287  HInstruction* second = LoadLocal(instruction.VRegC(), type);
288  current_block_->AddInstruction(new (arena_) T(type, first, second));
289  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
290}
291
292template<typename T>
293void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) {
294  HInstruction* first = LoadLocal(instruction.VRegA(), type);
295  HInstruction* second = LoadLocal(instruction.VRegB(), type);
296  current_block_->AddInstruction(new (arena_) T(type, first, second));
297  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
298}
299
300template<typename T>
301void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
302  HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
303  HInstruction* second = GetIntConstant(instruction.VRegC_22s());
304  if (reverse) {
305    std::swap(first, second);
306  }
307  current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
308  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
309}
310
311template<typename T>
312void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
313  HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
314  HInstruction* second = GetIntConstant(instruction.VRegC_22b());
315  if (reverse) {
316    std::swap(first, second);
317  }
318  current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
319  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
320}
321
322void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) {
323  if (type == Primitive::kPrimVoid) {
324    current_block_->AddInstruction(new (arena_) HReturnVoid());
325  } else {
326    HInstruction* value = LoadLocal(instruction.VRegA(), type);
327    current_block_->AddInstruction(new (arena_) HReturn(value));
328  }
329  current_block_->AddSuccessor(exit_block_);
330  current_block_ = nullptr;
331}
332
333bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
334                                uint32_t dex_offset,
335                                uint32_t method_idx,
336                                uint32_t number_of_vreg_arguments,
337                                bool is_range,
338                                uint32_t* args,
339                                uint32_t register_index) {
340  Instruction::Code opcode = instruction.Opcode();
341  InvokeType invoke_type;
342  switch (opcode) {
343    case Instruction::INVOKE_STATIC:
344    case Instruction::INVOKE_STATIC_RANGE:
345      invoke_type = kStatic;
346      break;
347    case Instruction::INVOKE_DIRECT:
348    case Instruction::INVOKE_DIRECT_RANGE:
349      invoke_type = kDirect;
350      break;
351    case Instruction::INVOKE_VIRTUAL:
352    case Instruction::INVOKE_VIRTUAL_RANGE:
353      invoke_type = kVirtual;
354      break;
355    case Instruction::INVOKE_INTERFACE:
356    case Instruction::INVOKE_INTERFACE_RANGE:
357      invoke_type = kInterface;
358      break;
359    case Instruction::INVOKE_SUPER_RANGE:
360    case Instruction::INVOKE_SUPER:
361      invoke_type = kSuper;
362      break;
363    default:
364      LOG(FATAL) << "Unexpected invoke op: " << opcode;
365      return false;
366  }
367
368  const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
369  const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_id.proto_idx_);
370  const char* descriptor = dex_file_->StringDataByIdx(proto_id.shorty_idx_);
371  Primitive::Type return_type = Primitive::GetType(descriptor[0]);
372  bool is_instance_call = invoke_type != kStatic;
373  const size_t number_of_arguments = strlen(descriptor) - (is_instance_call ? 0 : 1);
374
375  HInvoke* invoke = nullptr;
376  if (invoke_type == kVirtual) {
377    MethodReference target_method(dex_file_, method_idx);
378    uintptr_t direct_code;
379    uintptr_t direct_method;
380    int vtable_index;
381    // TODO: Add devirtualization support.
382    compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_offset, true, true,
383                                        &invoke_type, &target_method, &vtable_index,
384                                        &direct_code, &direct_method);
385    if (vtable_index == -1) {
386      return false;
387    }
388    invoke = new (arena_) HInvokeVirtual(
389        arena_, number_of_arguments, return_type, dex_offset, vtable_index);
390  } else {
391    // Treat invoke-direct like static calls for now.
392    invoke = new (arena_) HInvokeStatic(
393        arena_, number_of_arguments, return_type, dex_offset, method_idx);
394  }
395
396  size_t start_index = 0;
397  Temporaries temps(graph_, is_instance_call ? 1 : 0);
398  if (is_instance_call) {
399    HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot);
400    HNullCheck* null_check = new (arena_) HNullCheck(arg, dex_offset);
401    current_block_->AddInstruction(null_check);
402    temps.Add(null_check);
403    invoke->SetArgumentAt(0, null_check);
404    start_index = 1;
405  }
406
407  uint32_t descriptor_index = 1;
408  uint32_t argument_index = start_index;
409  for (size_t i = start_index; i < number_of_vreg_arguments; i++, argument_index++) {
410    Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]);
411    bool is_wide = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble);
412    if (!is_range && is_wide && args[i] + 1 != args[i + 1]) {
413      LOG(WARNING) << "Non sequential register pair in " << dex_compilation_unit_->GetSymbol()
414                   << " at " << dex_offset;
415      // We do not implement non sequential register pair.
416      return false;
417    }
418    HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
419    invoke->SetArgumentAt(argument_index, arg);
420    if (is_wide) {
421      i++;
422    }
423  }
424
425  DCHECK_EQ(argument_index, number_of_arguments);
426  current_block_->AddInstruction(invoke);
427  latest_result_ = invoke;
428  return true;
429}
430
431bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction,
432                                             uint32_t dex_offset,
433                                             bool is_put) {
434  uint32_t source_or_dest_reg = instruction.VRegA_22c();
435  uint32_t obj_reg = instruction.VRegB_22c();
436  uint16_t field_index = instruction.VRegC_22c();
437
438  ScopedObjectAccess soa(Thread::Current());
439  StackHandleScope<1> hs(soa.Self());
440  Handle<mirror::ArtField> resolved_field(hs.NewHandle(
441      compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa)));
442
443  if (resolved_field.Get() == nullptr) {
444    return false;
445  }
446  if (resolved_field->IsVolatile()) {
447    return false;
448  }
449
450  Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
451  if (!IsTypeSupported(field_type)) {
452    return false;
453  }
454
455  HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot);
456  current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_offset));
457  if (is_put) {
458    Temporaries temps(graph_, 1);
459    HInstruction* null_check = current_block_->GetLastInstruction();
460    // We need one temporary for the null check.
461    temps.Add(null_check);
462    HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
463    current_block_->AddInstruction(new (arena_) HInstanceFieldSet(
464        null_check,
465        value,
466        field_type,
467        resolved_field->GetOffset()));
468  } else {
469    current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
470        current_block_->GetLastInstruction(),
471        field_type,
472        resolved_field->GetOffset()));
473
474    UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
475  }
476  return true;
477}
478
479
480
481bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
482                                           uint32_t dex_offset,
483                                           bool is_put) {
484  uint32_t source_or_dest_reg = instruction.VRegA_21c();
485  uint16_t field_index = instruction.VRegB_21c();
486
487  uint32_t storage_index;
488  bool is_referrers_class;
489  bool is_initialized;
490  bool is_volatile;
491  MemberOffset field_offset(0u);
492  Primitive::Type field_type;
493
494  bool fast_path = compiler_driver_->ComputeStaticFieldInfo(field_index,
495                                                            dex_compilation_unit_,
496                                                            is_put,
497                                                            &field_offset,
498                                                            &storage_index,
499                                                            &is_referrers_class,
500                                                            &is_volatile,
501                                                            &is_initialized,
502                                                            &field_type);
503  if (!fast_path) {
504    return false;
505  }
506
507  if (is_volatile) {
508    return false;
509  }
510
511  if (!IsTypeSupported(field_type)) {
512    return false;
513  }
514
515  HLoadClass* constant = new (arena_) HLoadClass(
516      storage_index, is_referrers_class, dex_offset);
517  current_block_->AddInstruction(constant);
518
519  HInstruction* cls = constant;
520  if (!is_initialized) {
521    cls = new (arena_) HClinitCheck(constant, dex_offset);
522    current_block_->AddInstruction(cls);
523  }
524
525  if (is_put) {
526    // We need to keep the class alive before loading the value.
527    Temporaries temps(graph_, 1);
528    temps.Add(cls);
529    HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
530    DCHECK_EQ(value->GetType(), field_type);
531    current_block_->AddInstruction(
532        new (arena_) HStaticFieldSet(cls, value, field_type, field_offset));
533  } else {
534    current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls, field_type, field_offset));
535    UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
536  }
537  return true;
538}
539
540void HGraphBuilder::BuildCheckedDiv(const Instruction& instruction,
541                                    uint32_t dex_offset,
542                                    Primitive::Type type,
543                                    bool second_is_lit) {
544  DCHECK(type == Primitive::kPrimInt);
545
546  HInstruction* first = LoadLocal(instruction.VRegB(), type);
547  HInstruction* second = second_is_lit
548      ? GetIntConstant(instruction.VRegC())
549      : LoadLocal(instruction.VRegC(), type);
550  if (!second->IsIntConstant() || (second->AsIntConstant()->GetValue() == 0)) {
551    second = new (arena_) HDivZeroCheck(second, dex_offset);
552    Temporaries temps(graph_, 1);
553    current_block_->AddInstruction(second);
554    temps.Add(current_block_->GetLastInstruction());
555  }
556
557  current_block_->AddInstruction(new (arena_) HDiv(type, first, second));
558  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
559}
560
561void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
562                                     uint32_t dex_offset,
563                                     bool is_put,
564                                     Primitive::Type anticipated_type) {
565  uint8_t source_or_dest_reg = instruction.VRegA_23x();
566  uint8_t array_reg = instruction.VRegB_23x();
567  uint8_t index_reg = instruction.VRegC_23x();
568
569  DCHECK(IsTypeSupported(anticipated_type));
570
571  // We need one temporary for the null check, one for the index, and one for the length.
572  Temporaries temps(graph_, 3);
573
574  HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot);
575  object = new (arena_) HNullCheck(object, dex_offset);
576  current_block_->AddInstruction(object);
577  temps.Add(object);
578
579  HInstruction* length = new (arena_) HArrayLength(object);
580  current_block_->AddInstruction(length);
581  temps.Add(length);
582  HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt);
583  index = new (arena_) HBoundsCheck(index, length, dex_offset);
584  current_block_->AddInstruction(index);
585  temps.Add(index);
586  if (is_put) {
587    HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type);
588    // TODO: Insert a type check node if the type is Object.
589    current_block_->AddInstruction(new (arena_) HArraySet(
590        object, index, value, anticipated_type, dex_offset));
591  } else {
592    current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type));
593    UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
594  }
595}
596
597void HGraphBuilder::BuildFilledNewArray(uint32_t dex_offset,
598                                        uint32_t type_index,
599                                        uint32_t number_of_vreg_arguments,
600                                        bool is_range,
601                                        uint32_t* args,
602                                        uint32_t register_index) {
603  HInstruction* length = GetIntConstant(number_of_vreg_arguments);
604  HInstruction* object = new (arena_) HNewArray(length, dex_offset, type_index);
605  current_block_->AddInstruction(object);
606
607  const char* descriptor = dex_file_->StringByTypeIdx(type_index);
608  DCHECK_EQ(descriptor[0], '[') << descriptor;
609  char primitive = descriptor[1];
610  DCHECK(primitive == 'I'
611      || primitive == 'L'
612      || primitive == '[') << descriptor;
613  bool is_reference_array = (primitive == 'L') || (primitive == '[');
614  Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt;
615
616  Temporaries temps(graph_, 1);
617  temps.Add(object);
618  for (size_t i = 0; i < number_of_vreg_arguments; ++i) {
619    HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type);
620    HInstruction* index = GetIntConstant(i);
621    current_block_->AddInstruction(
622        new (arena_) HArraySet(object, index, value, type, dex_offset));
623  }
624  latest_result_ = object;
625}
626
627template <typename T>
628void HGraphBuilder::BuildFillArrayData(HInstruction* object,
629                                       const T* data,
630                                       uint32_t element_count,
631                                       Primitive::Type anticipated_type,
632                                       uint32_t dex_offset) {
633  for (uint32_t i = 0; i < element_count; ++i) {
634    HInstruction* index = GetIntConstant(i);
635    HInstruction* value = GetIntConstant(data[i]);
636    current_block_->AddInstruction(new (arena_) HArraySet(
637      object, index, value, anticipated_type, dex_offset));
638  }
639}
640
641void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_offset) {
642  Temporaries temps(graph_, 1);
643  HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot);
644  HNullCheck* null_check = new (arena_) HNullCheck(array, dex_offset);
645  current_block_->AddInstruction(null_check);
646  temps.Add(null_check);
647
648  HInstruction* length = new (arena_) HArrayLength(null_check);
649  current_block_->AddInstruction(length);
650
651  int32_t payload_offset = instruction.VRegB_31t() + dex_offset;
652  const Instruction::ArrayDataPayload* payload =
653      reinterpret_cast<const Instruction::ArrayDataPayload*>(code_start_ + payload_offset);
654  const uint8_t* data = payload->data;
655  uint32_t element_count = payload->element_count;
656
657  // Implementation of this DEX instruction seems to be that the bounds check is
658  // done before doing any stores.
659  HInstruction* last_index = GetIntConstant(payload->element_count - 1);
660  current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_offset));
661
662  switch (payload->element_width) {
663    case 1:
664      BuildFillArrayData(null_check,
665                         reinterpret_cast<const int8_t*>(data),
666                         element_count,
667                         Primitive::kPrimByte,
668                         dex_offset);
669      break;
670    case 2:
671      BuildFillArrayData(null_check,
672                         reinterpret_cast<const int16_t*>(data),
673                         element_count,
674                         Primitive::kPrimShort,
675                         dex_offset);
676      break;
677    case 4:
678      BuildFillArrayData(null_check,
679                         reinterpret_cast<const int32_t*>(data),
680                         element_count,
681                         Primitive::kPrimInt,
682                         dex_offset);
683      break;
684    case 8:
685      BuildFillWideArrayData(null_check,
686                             reinterpret_cast<const int64_t*>(data),
687                             element_count,
688                             dex_offset);
689      break;
690    default:
691      LOG(FATAL) << "Unknown element width for " << payload->element_width;
692  }
693}
694
695void HGraphBuilder::BuildFillWideArrayData(HInstruction* object,
696                                           const int64_t* data,
697                                           uint32_t element_count,
698                                           uint32_t dex_offset) {
699  for (uint32_t i = 0; i < element_count; ++i) {
700    HInstruction* index = GetIntConstant(i);
701    HInstruction* value = GetLongConstant(data[i]);
702    current_block_->AddInstruction(new (arena_) HArraySet(
703      object, index, value, Primitive::kPrimLong, dex_offset));
704  }
705}
706
707void HGraphBuilder::PotentiallyAddSuspendCheck(int32_t target_offset, uint32_t dex_offset) {
708  if (target_offset <= 0) {
709    // Unconditionnally add a suspend check to backward branches. We can remove
710    // them after we recognize loops in the graph.
711    current_block_->AddInstruction(new (arena_) HSuspendCheck(dex_offset));
712  }
713}
714
715bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_offset) {
716  if (current_block_ == nullptr) {
717    return true;  // Dead code
718  }
719
720  switch (instruction.Opcode()) {
721    case Instruction::CONST_4: {
722      int32_t register_index = instruction.VRegA();
723      HIntConstant* constant = GetIntConstant(instruction.VRegB_11n());
724      UpdateLocal(register_index, constant);
725      break;
726    }
727
728    case Instruction::CONST_16: {
729      int32_t register_index = instruction.VRegA();
730      HIntConstant* constant = GetIntConstant(instruction.VRegB_21s());
731      UpdateLocal(register_index, constant);
732      break;
733    }
734
735    case Instruction::CONST: {
736      int32_t register_index = instruction.VRegA();
737      HIntConstant* constant = GetIntConstant(instruction.VRegB_31i());
738      UpdateLocal(register_index, constant);
739      break;
740    }
741
742    case Instruction::CONST_HIGH16: {
743      int32_t register_index = instruction.VRegA();
744      HIntConstant* constant = GetIntConstant(instruction.VRegB_21h() << 16);
745      UpdateLocal(register_index, constant);
746      break;
747    }
748
749    case Instruction::CONST_WIDE_16: {
750      int32_t register_index = instruction.VRegA();
751      // Get 16 bits of constant value, sign extended to 64 bits.
752      int64_t value = instruction.VRegB_21s();
753      value <<= 48;
754      value >>= 48;
755      HLongConstant* constant = GetLongConstant(value);
756      UpdateLocal(register_index, constant);
757      break;
758    }
759
760    case Instruction::CONST_WIDE_32: {
761      int32_t register_index = instruction.VRegA();
762      // Get 32 bits of constant value, sign extended to 64 bits.
763      int64_t value = instruction.VRegB_31i();
764      value <<= 32;
765      value >>= 32;
766      HLongConstant* constant = GetLongConstant(value);
767      UpdateLocal(register_index, constant);
768      break;
769    }
770
771    case Instruction::CONST_WIDE: {
772      int32_t register_index = instruction.VRegA();
773      HLongConstant* constant = GetLongConstant(instruction.VRegB_51l());
774      UpdateLocal(register_index, constant);
775      break;
776    }
777
778    case Instruction::CONST_WIDE_HIGH16: {
779      int32_t register_index = instruction.VRegA();
780      int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
781      HLongConstant* constant = GetLongConstant(value);
782      UpdateLocal(register_index, constant);
783      break;
784    }
785
786    // TODO: these instructions are also used to move floating point values, so what is
787    // the type (int or float)?
788    case Instruction::MOVE:
789    case Instruction::MOVE_FROM16:
790    case Instruction::MOVE_16: {
791      HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
792      UpdateLocal(instruction.VRegA(), value);
793      break;
794    }
795
796    // TODO: these instructions are also used to move floating point values, so what is
797    // the type (long or double)?
798    case Instruction::MOVE_WIDE:
799    case Instruction::MOVE_WIDE_FROM16:
800    case Instruction::MOVE_WIDE_16: {
801      HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong);
802      UpdateLocal(instruction.VRegA(), value);
803      break;
804    }
805
806    case Instruction::MOVE_OBJECT:
807    case Instruction::MOVE_OBJECT_16:
808    case Instruction::MOVE_OBJECT_FROM16: {
809      HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot);
810      UpdateLocal(instruction.VRegA(), value);
811      break;
812    }
813
814    case Instruction::RETURN_VOID: {
815      BuildReturn(instruction, Primitive::kPrimVoid);
816      break;
817    }
818
819#define IF_XX(comparison, cond) \
820    case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_offset); break; \
821    case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_offset); break
822
823    IF_XX(HEqual, EQ);
824    IF_XX(HNotEqual, NE);
825    IF_XX(HLessThan, LT);
826    IF_XX(HLessThanOrEqual, LE);
827    IF_XX(HGreaterThan, GT);
828    IF_XX(HGreaterThanOrEqual, GE);
829
830    case Instruction::GOTO:
831    case Instruction::GOTO_16:
832    case Instruction::GOTO_32: {
833      int32_t offset = instruction.GetTargetOffset();
834      PotentiallyAddSuspendCheck(offset, dex_offset);
835      HBasicBlock* target = FindBlockStartingAt(offset + dex_offset);
836      DCHECK(target != nullptr);
837      current_block_->AddInstruction(new (arena_) HGoto());
838      current_block_->AddSuccessor(target);
839      current_block_ = nullptr;
840      break;
841    }
842
843    case Instruction::RETURN: {
844      DCHECK_NE(return_type_, Primitive::kPrimNot);
845      DCHECK_NE(return_type_, Primitive::kPrimLong);
846      DCHECK_NE(return_type_, Primitive::kPrimDouble);
847      BuildReturn(instruction, return_type_);
848      break;
849    }
850
851    case Instruction::RETURN_OBJECT: {
852      DCHECK(return_type_ == Primitive::kPrimNot);
853      BuildReturn(instruction, return_type_);
854      break;
855    }
856
857    case Instruction::RETURN_WIDE: {
858      DCHECK(return_type_ == Primitive::kPrimDouble || return_type_ == Primitive::kPrimLong);
859      BuildReturn(instruction, return_type_);
860      break;
861    }
862
863    case Instruction::INVOKE_STATIC:
864    case Instruction::INVOKE_DIRECT:
865    case Instruction::INVOKE_VIRTUAL: {
866      uint32_t method_idx = instruction.VRegB_35c();
867      uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
868      uint32_t args[5];
869      instruction.GetVarArgs(args);
870      if (!BuildInvoke(instruction, dex_offset, method_idx, number_of_vreg_arguments, false, args, -1)) {
871        return false;
872      }
873      break;
874    }
875
876    case Instruction::INVOKE_STATIC_RANGE:
877    case Instruction::INVOKE_DIRECT_RANGE:
878    case Instruction::INVOKE_VIRTUAL_RANGE: {
879      uint32_t method_idx = instruction.VRegB_3rc();
880      uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
881      uint32_t register_index = instruction.VRegC();
882      if (!BuildInvoke(instruction, dex_offset, method_idx,
883                       number_of_vreg_arguments, true, nullptr, register_index)) {
884        return false;
885      }
886      break;
887    }
888
889    case Instruction::NEG_INT: {
890      Unop_12x<HNeg>(instruction, Primitive::kPrimInt);
891      break;
892    }
893
894    case Instruction::NEG_LONG: {
895      Unop_12x<HNeg>(instruction, Primitive::kPrimLong);
896      break;
897    }
898
899    case Instruction::NEG_FLOAT: {
900      Unop_12x<HNeg>(instruction, Primitive::kPrimFloat);
901      break;
902    }
903
904    case Instruction::NEG_DOUBLE: {
905      Unop_12x<HNeg>(instruction, Primitive::kPrimDouble);
906      break;
907    }
908
909    case Instruction::NOT_INT: {
910      Unop_12x<HNot>(instruction, Primitive::kPrimInt);
911      break;
912    }
913
914    case Instruction::NOT_LONG: {
915      Unop_12x<HNot>(instruction, Primitive::kPrimLong);
916      break;
917    }
918
919    case Instruction::INT_TO_LONG: {
920      Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong);
921      break;
922    }
923
924    case Instruction::ADD_INT: {
925      Binop_23x<HAdd>(instruction, Primitive::kPrimInt);
926      break;
927    }
928
929    case Instruction::ADD_LONG: {
930      Binop_23x<HAdd>(instruction, Primitive::kPrimLong);
931      break;
932    }
933
934    case Instruction::ADD_DOUBLE: {
935      Binop_23x<HAdd>(instruction, Primitive::kPrimDouble);
936      break;
937    }
938
939    case Instruction::ADD_FLOAT: {
940      Binop_23x<HAdd>(instruction, Primitive::kPrimFloat);
941      break;
942    }
943
944    case Instruction::SUB_INT: {
945      Binop_23x<HSub>(instruction, Primitive::kPrimInt);
946      break;
947    }
948
949    case Instruction::SUB_LONG: {
950      Binop_23x<HSub>(instruction, Primitive::kPrimLong);
951      break;
952    }
953
954    case Instruction::SUB_FLOAT: {
955      Binop_23x<HSub>(instruction, Primitive::kPrimFloat);
956      break;
957    }
958
959    case Instruction::SUB_DOUBLE: {
960      Binop_23x<HSub>(instruction, Primitive::kPrimDouble);
961      break;
962    }
963
964    case Instruction::ADD_INT_2ADDR: {
965      Binop_12x<HAdd>(instruction, Primitive::kPrimInt);
966      break;
967    }
968
969    case Instruction::MUL_INT: {
970      Binop_23x<HMul>(instruction, Primitive::kPrimInt);
971      break;
972    }
973
974    case Instruction::MUL_LONG: {
975      Binop_23x<HMul>(instruction, Primitive::kPrimLong);
976      break;
977    }
978
979    case Instruction::MUL_FLOAT: {
980      Binop_23x<HMul>(instruction, Primitive::kPrimFloat);
981      break;
982    }
983
984    case Instruction::MUL_DOUBLE: {
985      Binop_23x<HMul>(instruction, Primitive::kPrimDouble);
986      break;
987    }
988
989    case Instruction::DIV_INT: {
990      BuildCheckedDiv(instruction, dex_offset, Primitive::kPrimInt, false);
991      break;
992    }
993
994    case Instruction::DIV_FLOAT: {
995      Binop_23x<HDiv>(instruction, Primitive::kPrimFloat);
996      break;
997    }
998
999    case Instruction::DIV_DOUBLE: {
1000      Binop_23x<HDiv>(instruction, Primitive::kPrimDouble);
1001      break;
1002    }
1003
1004    case Instruction::ADD_LONG_2ADDR: {
1005      Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
1006      break;
1007    }
1008
1009    case Instruction::ADD_DOUBLE_2ADDR: {
1010      Binop_12x<HAdd>(instruction, Primitive::kPrimDouble);
1011      break;
1012    }
1013
1014    case Instruction::ADD_FLOAT_2ADDR: {
1015      Binop_12x<HAdd>(instruction, Primitive::kPrimFloat);
1016      break;
1017    }
1018
1019    case Instruction::SUB_INT_2ADDR: {
1020      Binop_12x<HSub>(instruction, Primitive::kPrimInt);
1021      break;
1022    }
1023
1024    case Instruction::SUB_LONG_2ADDR: {
1025      Binop_12x<HSub>(instruction, Primitive::kPrimLong);
1026      break;
1027    }
1028
1029    case Instruction::SUB_FLOAT_2ADDR: {
1030      Binop_12x<HSub>(instruction, Primitive::kPrimFloat);
1031      break;
1032    }
1033
1034    case Instruction::SUB_DOUBLE_2ADDR: {
1035      Binop_12x<HSub>(instruction, Primitive::kPrimDouble);
1036      break;
1037    }
1038
1039    case Instruction::MUL_INT_2ADDR: {
1040      Binop_12x<HMul>(instruction, Primitive::kPrimInt);
1041      break;
1042    }
1043
1044    case Instruction::MUL_LONG_2ADDR: {
1045      Binop_12x<HMul>(instruction, Primitive::kPrimLong);
1046      break;
1047    }
1048
1049    case Instruction::MUL_FLOAT_2ADDR: {
1050      Binop_12x<HMul>(instruction, Primitive::kPrimFloat);
1051      break;
1052    }
1053
1054    case Instruction::MUL_DOUBLE_2ADDR: {
1055      Binop_12x<HMul>(instruction, Primitive::kPrimDouble);
1056      break;
1057    }
1058
1059    case Instruction::DIV_FLOAT_2ADDR: {
1060      Binop_12x<HDiv>(instruction, Primitive::kPrimFloat);
1061      break;
1062    }
1063
1064    case Instruction::DIV_DOUBLE_2ADDR: {
1065      Binop_12x<HDiv>(instruction, Primitive::kPrimDouble);
1066      break;
1067    }
1068
1069    case Instruction::ADD_INT_LIT16: {
1070      Binop_22s<HAdd>(instruction, false);
1071      break;
1072    }
1073
1074    case Instruction::RSUB_INT: {
1075      Binop_22s<HSub>(instruction, true);
1076      break;
1077    }
1078
1079    case Instruction::MUL_INT_LIT16: {
1080      Binop_22s<HMul>(instruction, false);
1081      break;
1082    }
1083
1084    case Instruction::ADD_INT_LIT8: {
1085      Binop_22b<HAdd>(instruction, false);
1086      break;
1087    }
1088
1089    case Instruction::RSUB_INT_LIT8: {
1090      Binop_22b<HSub>(instruction, true);
1091      break;
1092    }
1093
1094    case Instruction::MUL_INT_LIT8: {
1095      Binop_22b<HMul>(instruction, false);
1096      break;
1097    }
1098
1099    case Instruction::DIV_INT_LIT16:
1100    case Instruction::DIV_INT_LIT8: {
1101      BuildCheckedDiv(instruction, dex_offset, Primitive::kPrimInt, true);
1102      break;
1103    }
1104
1105    case Instruction::NEW_INSTANCE: {
1106      current_block_->AddInstruction(
1107          new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c()));
1108      UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
1109      break;
1110    }
1111
1112    case Instruction::NEW_ARRAY: {
1113      HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt);
1114      current_block_->AddInstruction(
1115          new (arena_) HNewArray(length, dex_offset, instruction.VRegC_22c()));
1116      UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
1117      break;
1118    }
1119
1120    case Instruction::FILLED_NEW_ARRAY: {
1121      uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
1122      uint32_t type_index = instruction.VRegB_35c();
1123      uint32_t args[5];
1124      instruction.GetVarArgs(args);
1125      BuildFilledNewArray(dex_offset, type_index, number_of_vreg_arguments, false, args, 0);
1126      break;
1127    }
1128
1129    case Instruction::FILLED_NEW_ARRAY_RANGE: {
1130      uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
1131      uint32_t type_index = instruction.VRegB_3rc();
1132      uint32_t register_index = instruction.VRegC_3rc();
1133      BuildFilledNewArray(
1134          dex_offset, type_index, number_of_vreg_arguments, true, nullptr, register_index);
1135      break;
1136    }
1137
1138    case Instruction::FILL_ARRAY_DATA: {
1139      BuildFillArrayData(instruction, dex_offset);
1140      break;
1141    }
1142
1143    case Instruction::MOVE_RESULT:
1144    case Instruction::MOVE_RESULT_WIDE:
1145    case Instruction::MOVE_RESULT_OBJECT:
1146      UpdateLocal(instruction.VRegA(), latest_result_);
1147      latest_result_ = nullptr;
1148      break;
1149
1150    case Instruction::CMP_LONG: {
1151      Binop_23x<HCompare>(instruction, Primitive::kPrimLong);
1152      break;
1153    }
1154
1155    case Instruction::NOP:
1156      break;
1157
1158    case Instruction::IGET:
1159    case Instruction::IGET_WIDE:
1160    case Instruction::IGET_OBJECT:
1161    case Instruction::IGET_BOOLEAN:
1162    case Instruction::IGET_BYTE:
1163    case Instruction::IGET_CHAR:
1164    case Instruction::IGET_SHORT: {
1165      if (!BuildInstanceFieldAccess(instruction, dex_offset, false)) {
1166        return false;
1167      }
1168      break;
1169    }
1170
1171    case Instruction::IPUT:
1172    case Instruction::IPUT_WIDE:
1173    case Instruction::IPUT_OBJECT:
1174    case Instruction::IPUT_BOOLEAN:
1175    case Instruction::IPUT_BYTE:
1176    case Instruction::IPUT_CHAR:
1177    case Instruction::IPUT_SHORT: {
1178      if (!BuildInstanceFieldAccess(instruction, dex_offset, true)) {
1179        return false;
1180      }
1181      break;
1182    }
1183
1184    case Instruction::SGET:
1185    case Instruction::SGET_WIDE:
1186    case Instruction::SGET_OBJECT:
1187    case Instruction::SGET_BOOLEAN:
1188    case Instruction::SGET_BYTE:
1189    case Instruction::SGET_CHAR:
1190    case Instruction::SGET_SHORT: {
1191      if (!BuildStaticFieldAccess(instruction, dex_offset, false)) {
1192        return false;
1193      }
1194      break;
1195    }
1196
1197    case Instruction::SPUT:
1198    case Instruction::SPUT_WIDE:
1199    case Instruction::SPUT_OBJECT:
1200    case Instruction::SPUT_BOOLEAN:
1201    case Instruction::SPUT_BYTE:
1202    case Instruction::SPUT_CHAR:
1203    case Instruction::SPUT_SHORT: {
1204      if (!BuildStaticFieldAccess(instruction, dex_offset, true)) {
1205        return false;
1206      }
1207      break;
1208    }
1209
1210#define ARRAY_XX(kind, anticipated_type)                                          \
1211    case Instruction::AGET##kind: {                                               \
1212      BuildArrayAccess(instruction, dex_offset, false, anticipated_type);         \
1213      break;                                                                      \
1214    }                                                                             \
1215    case Instruction::APUT##kind: {                                               \
1216      BuildArrayAccess(instruction, dex_offset, true, anticipated_type);          \
1217      break;                                                                      \
1218    }
1219
1220    ARRAY_XX(, Primitive::kPrimInt);
1221    ARRAY_XX(_WIDE, Primitive::kPrimLong);
1222    ARRAY_XX(_OBJECT, Primitive::kPrimNot);
1223    ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean);
1224    ARRAY_XX(_BYTE, Primitive::kPrimByte);
1225    ARRAY_XX(_CHAR, Primitive::kPrimChar);
1226    ARRAY_XX(_SHORT, Primitive::kPrimShort);
1227
1228    case Instruction::ARRAY_LENGTH: {
1229      HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot);
1230      current_block_->AddInstruction(new (arena_) HArrayLength(object));
1231      UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction());
1232      break;
1233    }
1234
1235    case Instruction::CONST_STRING: {
1236      current_block_->AddInstruction(new (arena_) HLoadString(instruction.VRegB_21c(), dex_offset));
1237      UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
1238      break;
1239    }
1240
1241    case Instruction::CONST_STRING_JUMBO: {
1242      current_block_->AddInstruction(new (arena_) HLoadString(instruction.VRegB_31c(), dex_offset));
1243      UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction());
1244      break;
1245    }
1246
1247    case Instruction::CONST_CLASS: {
1248      uint16_t type_index = instruction.VRegB_21c();
1249      bool type_known_final;
1250      bool type_known_abstract;
1251      bool is_referrers_class;
1252      bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
1253          dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
1254          &type_known_final, &type_known_abstract, &is_referrers_class);
1255      if (!can_access) {
1256        return false;
1257      }
1258      current_block_->AddInstruction(
1259          new (arena_) HLoadClass(instruction.VRegB_21c(), is_referrers_class, dex_offset));
1260      UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
1261      break;
1262    }
1263
1264    default:
1265      return false;
1266  }
1267  return true;
1268}
1269
1270HIntConstant* HGraphBuilder::GetIntConstant0() {
1271  if (constant0_ != nullptr) {
1272    return constant0_;
1273  }
1274  constant0_ = new(arena_) HIntConstant(0);
1275  entry_block_->AddInstruction(constant0_);
1276  return constant0_;
1277}
1278
1279HIntConstant* HGraphBuilder::GetIntConstant1() {
1280  if (constant1_ != nullptr) {
1281    return constant1_;
1282  }
1283  constant1_ = new(arena_) HIntConstant(1);
1284  entry_block_->AddInstruction(constant1_);
1285  return constant1_;
1286}
1287
1288HIntConstant* HGraphBuilder::GetIntConstant(int32_t constant) {
1289  switch (constant) {
1290    case 0: return GetIntConstant0();
1291    case 1: return GetIntConstant1();
1292    default: {
1293      HIntConstant* instruction = new (arena_) HIntConstant(constant);
1294      entry_block_->AddInstruction(instruction);
1295      return instruction;
1296    }
1297  }
1298}
1299
1300HLongConstant* HGraphBuilder::GetLongConstant(int64_t constant) {
1301  HLongConstant* instruction = new (arena_) HLongConstant(constant);
1302  entry_block_->AddInstruction(instruction);
1303  return instruction;
1304}
1305
1306HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
1307  return locals_.Get(register_index);
1308}
1309
1310void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {
1311  HLocal* local = GetLocalAt(register_index);
1312  current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));
1313}
1314
1315HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const {
1316  HLocal* local = GetLocalAt(register_index);
1317  current_block_->AddInstruction(new (arena_) HLoadLocal(local, type));
1318  return current_block_->GetLastInstruction();
1319}
1320
1321}  // namespace art
1322