gen_common.cc revision 984305917bf57b3f8d92965e4715a0370cc5bcfb
1/*
2 * Copyright (C) 2012 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#include "dex/compiler_ir.h"
17#include "dex/compiler_internals.h"
18#include "dex/quick/arm/arm_lir.h"
19#include "dex/quick/mir_to_lir-inl.h"
20#include "entrypoints/quick/quick_entrypoints.h"
21#include "mirror/array.h"
22#include "mirror/object_array-inl.h"
23#include "mirror/object-inl.h"
24#include "verifier/method_verifier.h"
25#include <functional>
26
27namespace art {
28
29// Shortcuts to repeatedly used long types.
30typedef mirror::ObjectArray<mirror::Object> ObjArray;
31typedef mirror::ObjectArray<mirror::Class> ClassArray;
32
33/*
34 * This source files contains "gen" codegen routines that should
35 * be applicable to most targets.  Only mid-level support utilities
36 * and "op" calls may be used here.
37 */
38
39/*
40 * Generate a kPseudoBarrier marker to indicate the boundary of special
41 * blocks.
42 */
43void Mir2Lir::GenBarrier() {
44  LIR* barrier = NewLIR0(kPseudoBarrier);
45  /* Mark all resources as being clobbered */
46  DCHECK(!barrier->flags.use_def_invalid);
47  barrier->u.m.def_mask = &kEncodeAll;
48}
49
50void Mir2Lir::GenDivZeroException() {
51  LIR* branch = OpUnconditionalBranch(nullptr);
52  AddDivZeroCheckSlowPath(branch);
53}
54
55void Mir2Lir::GenDivZeroCheck(ConditionCode c_code) {
56  LIR* branch = OpCondBranch(c_code, nullptr);
57  AddDivZeroCheckSlowPath(branch);
58}
59
60void Mir2Lir::GenDivZeroCheck(RegStorage reg) {
61  LIR* branch = OpCmpImmBranch(kCondEq, reg, 0, nullptr);
62  AddDivZeroCheckSlowPath(branch);
63}
64
65void Mir2Lir::AddDivZeroCheckSlowPath(LIR* branch) {
66  class DivZeroCheckSlowPath : public Mir2Lir::LIRSlowPath {
67   public:
68    DivZeroCheckSlowPath(Mir2Lir* m2l, LIR* branch)
69        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch) {
70    }
71
72    void Compile() OVERRIDE {
73      m2l_->ResetRegPool();
74      m2l_->ResetDefTracking();
75      GenerateTargetLabel(kPseudoThrowTarget);
76      m2l_->CallRuntimeHelper(kQuickThrowDivZero, true);
77    }
78  };
79
80  AddSlowPath(new (arena_) DivZeroCheckSlowPath(this, branch));
81}
82
83void Mir2Lir::GenArrayBoundsCheck(RegStorage index, RegStorage length) {
84  class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath {
85   public:
86    ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch, RegStorage index, RegStorage length)
87        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch),
88          index_(index), length_(length) {
89    }
90
91    void Compile() OVERRIDE {
92      m2l_->ResetRegPool();
93      m2l_->ResetDefTracking();
94      GenerateTargetLabel(kPseudoThrowTarget);
95      m2l_->CallRuntimeHelperRegReg(kQuickThrowArrayBounds, index_, length_, true);
96    }
97
98   private:
99    const RegStorage index_;
100    const RegStorage length_;
101  };
102
103  LIR* branch = OpCmpBranch(kCondUge, index, length, nullptr);
104  AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, index, length));
105}
106
107void Mir2Lir::GenArrayBoundsCheck(int index, RegStorage length) {
108  class ArrayBoundsCheckSlowPath : public Mir2Lir::LIRSlowPath {
109   public:
110    ArrayBoundsCheckSlowPath(Mir2Lir* m2l, LIR* branch, int index, RegStorage length)
111        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch),
112          index_(index), length_(length) {
113    }
114
115    void Compile() OVERRIDE {
116      m2l_->ResetRegPool();
117      m2l_->ResetDefTracking();
118      GenerateTargetLabel(kPseudoThrowTarget);
119
120      RegStorage arg1_32 = m2l_->TargetReg(kArg1, kNotWide);
121      RegStorage arg0_32 = m2l_->TargetReg(kArg0, kNotWide);
122
123      m2l_->OpRegCopy(arg1_32, length_);
124      m2l_->LoadConstant(arg0_32, index_);
125      m2l_->CallRuntimeHelperRegReg(kQuickThrowArrayBounds, arg0_32, arg1_32, true);
126    }
127
128   private:
129    const int32_t index_;
130    const RegStorage length_;
131  };
132
133  LIR* branch = OpCmpImmBranch(kCondLs, length, index, nullptr);
134  AddSlowPath(new (arena_) ArrayBoundsCheckSlowPath(this, branch, index, length));
135}
136
137LIR* Mir2Lir::GenNullCheck(RegStorage reg) {
138  class NullCheckSlowPath : public Mir2Lir::LIRSlowPath {
139   public:
140    NullCheckSlowPath(Mir2Lir* m2l, LIR* branch)
141        : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch) {
142    }
143
144    void Compile() OVERRIDE {
145      m2l_->ResetRegPool();
146      m2l_->ResetDefTracking();
147      GenerateTargetLabel(kPseudoThrowTarget);
148      m2l_->CallRuntimeHelper(kQuickThrowNullPointer, true);
149    }
150  };
151
152  LIR* branch = OpCmpImmBranch(kCondEq, reg, 0, nullptr);
153  AddSlowPath(new (arena_) NullCheckSlowPath(this, branch));
154  return branch;
155}
156
157/* Perform null-check on a register.  */
158LIR* Mir2Lir::GenNullCheck(RegStorage m_reg, int opt_flags) {
159  if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) {
160    return GenExplicitNullCheck(m_reg, opt_flags);
161  }
162  return nullptr;
163}
164
165/* Perform an explicit null-check on a register.  */
166LIR* Mir2Lir::GenExplicitNullCheck(RegStorage m_reg, int opt_flags) {
167  if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
168    return NULL;
169  }
170  return GenNullCheck(m_reg);
171}
172
173void Mir2Lir::MarkPossibleNullPointerException(int opt_flags) {
174  if (cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) {
175    if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
176      return;
177    }
178    // Insert after last instruction.
179    MarkSafepointPC(last_lir_insn_);
180  }
181}
182
183void Mir2Lir::MarkPossibleNullPointerExceptionAfter(int opt_flags, LIR* after) {
184  if (cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) {
185    if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
186      return;
187    }
188    MarkSafepointPCAfter(after);
189  }
190}
191
192void Mir2Lir::MarkPossibleStackOverflowException() {
193  if (cu_->compiler_driver->GetCompilerOptions().GetImplicitStackOverflowChecks()) {
194    MarkSafepointPC(last_lir_insn_);
195  }
196}
197
198void Mir2Lir::ForceImplicitNullCheck(RegStorage reg, int opt_flags) {
199  if (cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) {
200    if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
201      return;
202    }
203    // Force an implicit null check by performing a memory operation (load) from the given
204    // register with offset 0.  This will cause a signal if the register contains 0 (null).
205    RegStorage tmp = AllocTemp();
206    // TODO: for Mips, would be best to use rZERO as the bogus register target.
207    LIR* load = Load32Disp(reg, 0, tmp);
208    FreeTemp(tmp);
209    MarkSafepointPC(load);
210  }
211}
212
213void Mir2Lir::GenCompareAndBranch(Instruction::Code opcode, RegLocation rl_src1,
214                                  RegLocation rl_src2, LIR* taken,
215                                  LIR* fall_through) {
216  DCHECK(!rl_src1.fp);
217  DCHECK(!rl_src2.fp);
218  ConditionCode cond;
219  switch (opcode) {
220    case Instruction::IF_EQ:
221      cond = kCondEq;
222      break;
223    case Instruction::IF_NE:
224      cond = kCondNe;
225      break;
226    case Instruction::IF_LT:
227      cond = kCondLt;
228      break;
229    case Instruction::IF_GE:
230      cond = kCondGe;
231      break;
232    case Instruction::IF_GT:
233      cond = kCondGt;
234      break;
235    case Instruction::IF_LE:
236      cond = kCondLe;
237      break;
238    default:
239      cond = static_cast<ConditionCode>(0);
240      LOG(FATAL) << "Unexpected opcode " << opcode;
241  }
242
243  // Normalize such that if either operand is constant, src2 will be constant
244  if (rl_src1.is_const) {
245    RegLocation rl_temp = rl_src1;
246    rl_src1 = rl_src2;
247    rl_src2 = rl_temp;
248    cond = FlipComparisonOrder(cond);
249  }
250
251  rl_src1 = LoadValue(rl_src1);
252  // Is this really an immediate comparison?
253  if (rl_src2.is_const) {
254    // If it's already live in a register or not easily materialized, just keep going
255    RegLocation rl_temp = UpdateLoc(rl_src2);
256    int32_t constant_value = mir_graph_->ConstantValue(rl_src2);
257    if ((rl_temp.location == kLocDalvikFrame) &&
258        InexpensiveConstantInt(constant_value)) {
259      // OK - convert this to a compare immediate and branch
260      OpCmpImmBranch(cond, rl_src1.reg, mir_graph_->ConstantValue(rl_src2), taken);
261      return;
262    }
263
264    // It's also commonly more efficient to have a test against zero with Eq/Ne. This is not worse
265    // for x86, and allows a cbz/cbnz for Arm and Mips. At the same time, it works around a register
266    // mismatch for 64b systems, where a reference is compared against null, as dex bytecode uses
267    // the 32b literal 0 for null.
268    if (constant_value == 0 && (cond == kCondEq || cond == kCondNe)) {
269      // Use the OpCmpImmBranch and ignore the value in the register.
270      OpCmpImmBranch(cond, rl_src1.reg, 0, taken);
271      return;
272    }
273  }
274
275  rl_src2 = LoadValue(rl_src2);
276  OpCmpBranch(cond, rl_src1.reg, rl_src2.reg, taken);
277}
278
279void Mir2Lir::GenCompareZeroAndBranch(Instruction::Code opcode, RegLocation rl_src, LIR* taken,
280                                      LIR* fall_through) {
281  ConditionCode cond;
282  DCHECK(!rl_src.fp);
283  rl_src = LoadValue(rl_src);
284  switch (opcode) {
285    case Instruction::IF_EQZ:
286      cond = kCondEq;
287      break;
288    case Instruction::IF_NEZ:
289      cond = kCondNe;
290      break;
291    case Instruction::IF_LTZ:
292      cond = kCondLt;
293      break;
294    case Instruction::IF_GEZ:
295      cond = kCondGe;
296      break;
297    case Instruction::IF_GTZ:
298      cond = kCondGt;
299      break;
300    case Instruction::IF_LEZ:
301      cond = kCondLe;
302      break;
303    default:
304      cond = static_cast<ConditionCode>(0);
305      LOG(FATAL) << "Unexpected opcode " << opcode;
306  }
307  OpCmpImmBranch(cond, rl_src.reg, 0, taken);
308}
309
310void Mir2Lir::GenIntToLong(RegLocation rl_dest, RegLocation rl_src) {
311  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
312  if (rl_src.location == kLocPhysReg) {
313    OpRegCopy(rl_result.reg, rl_src.reg);
314  } else {
315    LoadValueDirect(rl_src, rl_result.reg.GetLow());
316  }
317  OpRegRegImm(kOpAsr, rl_result.reg.GetHigh(), rl_result.reg.GetLow(), 31);
318  StoreValueWide(rl_dest, rl_result);
319}
320
321void Mir2Lir::GenIntNarrowing(Instruction::Code opcode, RegLocation rl_dest,
322                              RegLocation rl_src) {
323  rl_src = LoadValue(rl_src, kCoreReg);
324  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
325  OpKind op = kOpInvalid;
326  switch (opcode) {
327    case Instruction::INT_TO_BYTE:
328      op = kOp2Byte;
329      break;
330    case Instruction::INT_TO_SHORT:
331       op = kOp2Short;
332       break;
333    case Instruction::INT_TO_CHAR:
334       op = kOp2Char;
335       break;
336    default:
337      LOG(ERROR) << "Bad int conversion type";
338  }
339  OpRegReg(op, rl_result.reg, rl_src.reg);
340  StoreValue(rl_dest, rl_result);
341}
342
343/*
344 * Let helper function take care of everything.  Will call
345 * Array::AllocFromCode(type_idx, method, count);
346 * Note: AllocFromCode will handle checks for errNegativeArraySize.
347 */
348void Mir2Lir::GenNewArray(uint32_t type_idx, RegLocation rl_dest,
349                          RegLocation rl_src) {
350  FlushAllRegs();  /* Everything to home location */
351  const DexFile* dex_file = cu_->dex_file;
352  CompilerDriver* driver = cu_->compiler_driver;
353  if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *dex_file, type_idx)) {
354    bool is_type_initialized;  // Ignored as an array does not have an initializer.
355    bool use_direct_type_ptr;
356    uintptr_t direct_type_ptr;
357    bool is_finalizable;
358    if (kEmbedClassInCode &&
359        driver->CanEmbedTypeInCode(*dex_file, type_idx, &is_type_initialized, &use_direct_type_ptr,
360                                   &direct_type_ptr, &is_finalizable)) {
361      // The fast path.
362      if (!use_direct_type_ptr) {
363        LoadClassType(type_idx, kArg0);
364        CallRuntimeHelperRegMethodRegLocation(kQuickAllocArrayResolved, TargetReg(kArg0, kNotWide),
365                                              rl_src, true);
366      } else {
367        // Use the direct pointer.
368        CallRuntimeHelperImmMethodRegLocation(kQuickAllocArrayResolved, direct_type_ptr, rl_src,
369                                              true);
370      }
371    } else {
372      // The slow path.
373      CallRuntimeHelperImmMethodRegLocation(kQuickAllocArray, type_idx, rl_src, true);
374    }
375  } else {
376    CallRuntimeHelperImmMethodRegLocation(kQuickAllocArrayWithAccessCheck, type_idx, rl_src, true);
377  }
378  StoreValue(rl_dest, GetReturn(kRefReg));
379}
380
381/*
382 * Similar to GenNewArray, but with post-allocation initialization.
383 * Verifier guarantees we're dealing with an array class.  Current
384 * code throws runtime exception "bad Filled array req" for 'D' and 'J'.
385 * Current code also throws internal unimp if not 'L', '[' or 'I'.
386 */
387void Mir2Lir::GenFilledNewArray(CallInfo* info) {
388  int elems = info->num_arg_words;
389  int type_idx = info->index;
390  FlushAllRegs();  /* Everything to home location */
391  QuickEntrypointEnum target;
392  if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *cu_->dex_file,
393                                                       type_idx)) {
394    target = kQuickCheckAndAllocArray;
395  } else {
396    target = kQuickCheckAndAllocArrayWithAccessCheck;
397  }
398  CallRuntimeHelperImmMethodImm(target, type_idx, elems, true);
399  FreeTemp(TargetReg(kArg2, kNotWide));
400  FreeTemp(TargetReg(kArg1, kNotWide));
401  /*
402   * NOTE: the implicit target for Instruction::FILLED_NEW_ARRAY is the
403   * return region.  Because AllocFromCode placed the new array
404   * in kRet0, we'll just lock it into place.  When debugger support is
405   * added, it may be necessary to additionally copy all return
406   * values to a home location in thread-local storage
407   */
408  RegStorage ref_reg = TargetReg(kRet0, kRef);
409  LockTemp(ref_reg);
410
411  // TODO: use the correct component size, currently all supported types
412  // share array alignment with ints (see comment at head of function)
413  size_t component_size = sizeof(int32_t);
414
415  // Having a range of 0 is legal
416  if (info->is_range && (elems > 0)) {
417    /*
418     * Bit of ugliness here.  We're going generate a mem copy loop
419     * on the register range, but it is possible that some regs
420     * in the range have been promoted.  This is unlikely, but
421     * before generating the copy, we'll just force a flush
422     * of any regs in the source range that have been promoted to
423     * home location.
424     */
425    for (int i = 0; i < elems; i++) {
426      RegLocation loc = UpdateLoc(info->args[i]);
427      if (loc.location == kLocPhysReg) {
428        ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
429        Store32Disp(TargetPtrReg(kSp), SRegOffset(loc.s_reg_low), loc.reg);
430      }
431    }
432    /*
433     * TUNING note: generated code here could be much improved, but
434     * this is an uncommon operation and isn't especially performance
435     * critical.
436     */
437    // This is addressing the stack, which may be out of the 4G area.
438    RegStorage r_src = AllocTempRef();
439    RegStorage r_dst = AllocTempRef();
440    RegStorage r_idx = AllocTempRef();  // Not really a reference, but match src/dst.
441    RegStorage r_val;
442    switch (cu_->instruction_set) {
443      case kThumb2:
444      case kArm64:
445        r_val = TargetReg(kLr, kNotWide);
446        break;
447      case kX86:
448      case kX86_64:
449        FreeTemp(ref_reg);
450        r_val = AllocTemp();
451        break;
452      case kMips:
453        r_val = AllocTemp();
454        break;
455      default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set;
456    }
457    // Set up source pointer
458    RegLocation rl_first = info->args[0];
459    OpRegRegImm(kOpAdd, r_src, TargetPtrReg(kSp), SRegOffset(rl_first.s_reg_low));
460    // Set up the target pointer
461    OpRegRegImm(kOpAdd, r_dst, ref_reg,
462                mirror::Array::DataOffset(component_size).Int32Value());
463    // Set up the loop counter (known to be > 0)
464    LoadConstant(r_idx, elems - 1);
465    // Generate the copy loop.  Going backwards for convenience
466    LIR* target = NewLIR0(kPseudoTargetLabel);
467    // Copy next element
468    {
469      ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
470      LoadBaseIndexed(r_src, r_idx, r_val, 2, k32);
471      // NOTE: No dalvik register annotation, local optimizations will be stopped
472      // by the loop boundaries.
473    }
474    StoreBaseIndexed(r_dst, r_idx, r_val, 2, k32);
475    FreeTemp(r_val);
476    OpDecAndBranch(kCondGe, r_idx, target);
477    if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
478      // Restore the target pointer
479      OpRegRegImm(kOpAdd, ref_reg, r_dst,
480                  -mirror::Array::DataOffset(component_size).Int32Value());
481    }
482  } else if (!info->is_range) {
483    // TUNING: interleave
484    for (int i = 0; i < elems; i++) {
485      RegLocation rl_arg = LoadValue(info->args[i], kCoreReg);
486      Store32Disp(ref_reg,
487                  mirror::Array::DataOffset(component_size).Int32Value() + i * 4, rl_arg.reg);
488      // If the LoadValue caused a temp to be allocated, free it
489      if (IsTemp(rl_arg.reg)) {
490        FreeTemp(rl_arg.reg);
491      }
492    }
493  }
494  if (info->result.location != kLocInvalid) {
495    StoreValue(info->result, GetReturn(kRefReg));
496  }
497}
498
499//
500// Slow path to ensure a class is initialized for sget/sput.
501//
502class StaticFieldSlowPath : public Mir2Lir::LIRSlowPath {
503 public:
504  StaticFieldSlowPath(Mir2Lir* m2l, LIR* unresolved, LIR* uninit, LIR* cont, int storage_index,
505                      RegStorage r_base) :
506    LIRSlowPath(m2l, m2l->GetCurrentDexPc(), unresolved, cont), uninit_(uninit),
507               storage_index_(storage_index), r_base_(r_base) {
508  }
509
510  void Compile() {
511    LIR* unresolved_target = GenerateTargetLabel();
512    uninit_->target = unresolved_target;
513    m2l_->CallRuntimeHelperImm(kQuickInitializeStaticStorage, storage_index_, true);
514    // Copy helper's result into r_base, a no-op on all but MIPS.
515    m2l_->OpRegCopy(r_base_,  m2l_->TargetReg(kRet0, kRef));
516
517    m2l_->OpUnconditionalBranch(cont_);
518  }
519
520 private:
521  LIR* const uninit_;
522  const int storage_index_;
523  const RegStorage r_base_;
524};
525
526void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, bool is_long_or_double,
527                      bool is_object) {
528  const MirSFieldLoweringInfo& field_info = mir_graph_->GetSFieldLoweringInfo(mir);
529  cu_->compiler_driver->ProcessedStaticField(field_info.FastPut(), field_info.IsReferrersClass());
530  OpSize store_size = LoadStoreOpSize(is_long_or_double, is_object);
531  if (!SLOW_FIELD_PATH && field_info.FastPut()) {
532    DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
533    RegStorage r_base;
534    if (field_info.IsReferrersClass()) {
535      // Fast path, static storage base is this method's class
536      RegLocation rl_method = LoadCurrMethod();
537      r_base = AllocTempRef();
538      LoadRefDisp(rl_method.reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base,
539                  kNotVolatile);
540      if (IsTemp(rl_method.reg)) {
541        FreeTemp(rl_method.reg);
542      }
543    } else {
544      // Medium path, static storage base in a different class which requires checks that the other
545      // class is initialized.
546      // TODO: remove initialized check now that we are initializing classes in the compiler driver.
547      DCHECK_NE(field_info.StorageIndex(), DexFile::kDexNoIndex);
548      // May do runtime call so everything to home locations.
549      FlushAllRegs();
550      // Using fixed register to sync with possible call to runtime support.
551      RegStorage r_method = TargetReg(kArg1, kRef);
552      LockTemp(r_method);
553      LoadCurrMethodDirect(r_method);
554      r_base = TargetReg(kArg0, kRef);
555      LockTemp(r_base);
556      LoadRefDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base,
557                  kNotVolatile);
558      int32_t offset_of_field = ObjArray::OffsetOfElement(field_info.StorageIndex()).Int32Value();
559      LoadRefDisp(r_base, offset_of_field, r_base, kNotVolatile);
560      // r_base now points at static storage (Class*) or NULL if the type is not yet resolved.
561      if (!field_info.IsInitialized() &&
562          (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0) {
563        // Check if r_base is NULL or a not yet initialized class.
564
565        // The slow path is invoked if the r_base is NULL or the class pointed
566        // to by it is not initialized.
567        LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL);
568        RegStorage r_tmp = TargetReg(kArg2, kNotWide);
569        LockTemp(r_tmp);
570        LIR* uninit_branch = OpCmpMemImmBranch(kCondLt, r_tmp, r_base,
571                                          mirror::Class::StatusOffset().Int32Value(),
572                                          mirror::Class::kStatusInitialized, nullptr, nullptr);
573        LIR* cont = NewLIR0(kPseudoTargetLabel);
574
575        AddSlowPath(new (arena_) StaticFieldSlowPath(this, unresolved_branch, uninit_branch, cont,
576                                                     field_info.StorageIndex(), r_base));
577
578        FreeTemp(r_tmp);
579        // Ensure load of status and store of value don't re-order.
580        // TODO: Presumably the actual value store is control-dependent on the status load,
581        // and will thus not be reordered in any case, since stores are never speculated.
582        // Does later code "know" that the class is now initialized?  If so, we still
583        // need the barrier to guard later static loads.
584        GenMemBarrier(kLoadAny);
585      }
586      FreeTemp(r_method);
587    }
588    // rBase now holds static storage base
589    RegisterClass reg_class = RegClassForFieldLoadStore(store_size, field_info.IsVolatile());
590    if (is_long_or_double) {
591      rl_src = LoadValueWide(rl_src, reg_class);
592    } else {
593      rl_src = LoadValue(rl_src, reg_class);
594    }
595    if (is_object) {
596      StoreRefDisp(r_base, field_info.FieldOffset().Int32Value(), rl_src.reg,
597                   field_info.IsVolatile() ? kVolatile : kNotVolatile);
598    } else {
599      StoreBaseDisp(r_base, field_info.FieldOffset().Int32Value(), rl_src.reg, store_size,
600                    field_info.IsVolatile() ? kVolatile : kNotVolatile);
601    }
602    if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) {
603      MarkGCCard(rl_src.reg, r_base);
604    }
605    FreeTemp(r_base);
606  } else {
607    FlushAllRegs();  // Everything to home locations
608    QuickEntrypointEnum target =
609        is_long_or_double ? kQuickSet64Static
610            : (is_object ? kQuickSetObjStatic : kQuickSet32Static);
611    CallRuntimeHelperImmRegLocation(target, field_info.FieldIndex(), rl_src, true);
612  }
613}
614
615void Mir2Lir::GenSget(MIR* mir, RegLocation rl_dest,
616                      bool is_long_or_double, bool is_object) {
617  const MirSFieldLoweringInfo& field_info = mir_graph_->GetSFieldLoweringInfo(mir);
618  cu_->compiler_driver->ProcessedStaticField(field_info.FastGet(), field_info.IsReferrersClass());
619  OpSize load_size = LoadStoreOpSize(is_long_or_double, is_object);
620  if (!SLOW_FIELD_PATH && field_info.FastGet()) {
621    DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
622    RegStorage r_base;
623    if (field_info.IsReferrersClass()) {
624      // Fast path, static storage base is this method's class
625      RegLocation rl_method  = LoadCurrMethod();
626      r_base = AllocTempRef();
627      LoadRefDisp(rl_method.reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base,
628                  kNotVolatile);
629    } else {
630      // Medium path, static storage base in a different class which requires checks that the other
631      // class is initialized
632      DCHECK_NE(field_info.StorageIndex(), DexFile::kDexNoIndex);
633      // May do runtime call so everything to home locations.
634      FlushAllRegs();
635      // Using fixed register to sync with possible call to runtime support.
636      RegStorage r_method = TargetReg(kArg1, kRef);
637      LockTemp(r_method);
638      LoadCurrMethodDirect(r_method);
639      r_base = TargetReg(kArg0, kRef);
640      LockTemp(r_base);
641      LoadRefDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base,
642                  kNotVolatile);
643      int32_t offset_of_field = ObjArray::OffsetOfElement(field_info.StorageIndex()).Int32Value();
644      LoadRefDisp(r_base, offset_of_field, r_base, kNotVolatile);
645      // r_base now points at static storage (Class*) or NULL if the type is not yet resolved.
646      if (!field_info.IsInitialized() &&
647          (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0) {
648        // Check if r_base is NULL or a not yet initialized class.
649
650        // The slow path is invoked if the r_base is NULL or the class pointed
651        // to by it is not initialized.
652        LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL);
653        RegStorage r_tmp = TargetReg(kArg2, kNotWide);
654        LockTemp(r_tmp);
655        LIR* uninit_branch = OpCmpMemImmBranch(kCondLt, r_tmp, r_base,
656                                          mirror::Class::StatusOffset().Int32Value(),
657                                          mirror::Class::kStatusInitialized, nullptr, nullptr);
658        LIR* cont = NewLIR0(kPseudoTargetLabel);
659
660        AddSlowPath(new (arena_) StaticFieldSlowPath(this, unresolved_branch, uninit_branch, cont,
661                                                     field_info.StorageIndex(), r_base));
662
663        FreeTemp(r_tmp);
664        // Ensure load of status and load of value don't re-order.
665        GenMemBarrier(kLoadAny);
666      }
667      FreeTemp(r_method);
668    }
669    // r_base now holds static storage base
670    RegisterClass reg_class = RegClassForFieldLoadStore(load_size, field_info.IsVolatile());
671    RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
672
673    int field_offset = field_info.FieldOffset().Int32Value();
674    if (is_object) {
675      LoadRefDisp(r_base, field_offset, rl_result.reg, field_info.IsVolatile() ? kVolatile :
676          kNotVolatile);
677    } else {
678      LoadBaseDisp(r_base, field_offset, rl_result.reg, load_size, field_info.IsVolatile() ?
679          kVolatile : kNotVolatile);
680    }
681    FreeTemp(r_base);
682
683    if (is_long_or_double) {
684      StoreValueWide(rl_dest, rl_result);
685    } else {
686      StoreValue(rl_dest, rl_result);
687    }
688  } else {
689    FlushAllRegs();  // Everything to home locations
690    QuickEntrypointEnum target =
691        is_long_or_double ? kQuickGet64Static
692            : (is_object ? kQuickGetObjStatic : kQuickGet32Static);
693    CallRuntimeHelperImm(target, field_info.FieldIndex(), true);
694
695    // FIXME: pGetXXStatic always return an int or int64 regardless of rl_dest.fp.
696    if (is_long_or_double) {
697      RegLocation rl_result = GetReturnWide(kCoreReg);
698      StoreValueWide(rl_dest, rl_result);
699    } else {
700      RegLocation rl_result = GetReturn(rl_dest.ref ? kRefReg : kCoreReg);
701      StoreValue(rl_dest, rl_result);
702    }
703  }
704}
705
706// Generate code for all slow paths.
707void Mir2Lir::HandleSlowPaths() {
708  // We should check slow_paths_.Size() every time, because a new slow path
709  // may be created during slowpath->Compile().
710  for (size_t i = 0; i < slow_paths_.Size(); ++i) {
711    LIRSlowPath* slowpath = slow_paths_.Get(i);
712    slowpath->Compile();
713  }
714  slow_paths_.Reset();
715}
716
717void Mir2Lir::GenIGet(MIR* mir, int opt_flags, OpSize size,
718                      RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double,
719                      bool is_object) {
720  const MirIFieldLoweringInfo& field_info = mir_graph_->GetIFieldLoweringInfo(mir);
721  cu_->compiler_driver->ProcessedInstanceField(field_info.FastGet());
722  OpSize load_size = LoadStoreOpSize(is_long_or_double, is_object);
723  if (!SLOW_FIELD_PATH && field_info.FastGet()) {
724    RegisterClass reg_class = RegClassForFieldLoadStore(load_size, field_info.IsVolatile());
725    DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
726    rl_obj = LoadValue(rl_obj, kRefReg);
727    GenNullCheck(rl_obj.reg, opt_flags);
728    RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
729    int field_offset = field_info.FieldOffset().Int32Value();
730    LIR* load_lir;
731    if (is_object) {
732      load_lir = LoadRefDisp(rl_obj.reg, field_offset, rl_result.reg, field_info.IsVolatile() ?
733          kVolatile : kNotVolatile);
734    } else {
735      load_lir = LoadBaseDisp(rl_obj.reg, field_offset, rl_result.reg, load_size,
736                              field_info.IsVolatile() ? kVolatile : kNotVolatile);
737    }
738    MarkPossibleNullPointerExceptionAfter(opt_flags, load_lir);
739    if (is_long_or_double) {
740      StoreValueWide(rl_dest, rl_result);
741    } else {
742      StoreValue(rl_dest, rl_result);
743    }
744  } else {
745    QuickEntrypointEnum target =
746        is_long_or_double ? kQuickGet64Instance
747            : (is_object ? kQuickGetObjInstance : kQuickGet32Instance);
748    // Second argument of pGetXXInstance is always a reference.
749    DCHECK_EQ(static_cast<unsigned int>(rl_obj.wide), 0U);
750    CallRuntimeHelperImmRegLocation(target, field_info.FieldIndex(), rl_obj, true);
751
752    // FIXME: pGetXXInstance always return an int or int64 regardless of rl_dest.fp.
753    if (is_long_or_double) {
754      RegLocation rl_result = GetReturnWide(kCoreReg);
755      StoreValueWide(rl_dest, rl_result);
756    } else {
757      RegLocation rl_result = GetReturn(rl_dest.ref ? kRefReg : kCoreReg);
758      StoreValue(rl_dest, rl_result);
759    }
760  }
761}
762
763void Mir2Lir::GenIPut(MIR* mir, int opt_flags, OpSize size,
764                      RegLocation rl_src, RegLocation rl_obj, bool is_long_or_double,
765                      bool is_object) {
766  const MirIFieldLoweringInfo& field_info = mir_graph_->GetIFieldLoweringInfo(mir);
767  cu_->compiler_driver->ProcessedInstanceField(field_info.FastPut());
768  OpSize store_size = LoadStoreOpSize(is_long_or_double, is_object);
769  if (!SLOW_FIELD_PATH && field_info.FastPut()) {
770    RegisterClass reg_class = RegClassForFieldLoadStore(store_size, field_info.IsVolatile());
771    DCHECK_GE(field_info.FieldOffset().Int32Value(), 0);
772    rl_obj = LoadValue(rl_obj, kRefReg);
773    if (is_long_or_double) {
774      rl_src = LoadValueWide(rl_src, reg_class);
775    } else {
776      rl_src = LoadValue(rl_src, reg_class);
777    }
778    GenNullCheck(rl_obj.reg, opt_flags);
779    int field_offset = field_info.FieldOffset().Int32Value();
780    LIR* store;
781    if (is_object) {
782      store = StoreRefDisp(rl_obj.reg, field_offset, rl_src.reg, field_info.IsVolatile() ?
783          kVolatile : kNotVolatile);
784    } else {
785      store = StoreBaseDisp(rl_obj.reg, field_offset, rl_src.reg, store_size,
786                            field_info.IsVolatile() ? kVolatile : kNotVolatile);
787    }
788    MarkPossibleNullPointerExceptionAfter(opt_flags, store);
789    if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) {
790      MarkGCCard(rl_src.reg, rl_obj.reg);
791    }
792  } else {
793    QuickEntrypointEnum target =
794        is_long_or_double ? kQuickSet64Instance
795            : (is_object ? kQuickSetObjInstance : kQuickSet32Instance);
796    CallRuntimeHelperImmRegLocationRegLocation(target, field_info.FieldIndex(), rl_obj, rl_src,
797                                               true);
798  }
799}
800
801void Mir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index,
802                             RegLocation rl_src) {
803  bool needs_range_check = !(opt_flags & MIR_IGNORE_RANGE_CHECK);
804  bool needs_null_check = !((cu_->disable_opt & (1 << kNullCheckElimination)) &&
805      (opt_flags & MIR_IGNORE_NULL_CHECK));
806  QuickEntrypointEnum target = needs_range_check
807        ? (needs_null_check ? kQuickAputObjectWithNullAndBoundCheck
808                            : kQuickAputObjectWithBoundCheck)
809        : kQuickAputObject;
810  CallRuntimeHelperRegLocationRegLocationRegLocation(target, rl_array, rl_index, rl_src, true);
811}
812
813void Mir2Lir::GenConstClass(uint32_t type_idx, RegLocation rl_dest) {
814  RegLocation rl_method = LoadCurrMethod();
815  CheckRegLocation(rl_method);
816  RegStorage res_reg = AllocTempRef();
817  RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
818  if (!cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
819                                                        *cu_->dex_file,
820                                                        type_idx)) {
821    // Call out to helper which resolves type and verifies access.
822    // Resolved type returned in kRet0.
823    CallRuntimeHelperImmReg(kQuickInitializeTypeAndVerifyAccess, type_idx, rl_method.reg, true);
824    RegLocation rl_result = GetReturn(kRefReg);
825    StoreValue(rl_dest, rl_result);
826  } else {
827    // We're don't need access checks, load type from dex cache
828    int32_t dex_cache_offset =
829        mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value();
830    LoadRefDisp(rl_method.reg, dex_cache_offset, res_reg, kNotVolatile);
831    int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
832    LoadRefDisp(res_reg, offset_of_type, rl_result.reg, kNotVolatile);
833    if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file,
834        type_idx) || SLOW_TYPE_PATH) {
835      // Slow path, at runtime test if type is null and if so initialize
836      FlushAllRegs();
837      LIR* branch = OpCmpImmBranch(kCondEq, rl_result.reg, 0, NULL);
838      LIR* cont = NewLIR0(kPseudoTargetLabel);
839
840      // Object to generate the slow path for class resolution.
841      class SlowPath : public LIRSlowPath {
842       public:
843        SlowPath(Mir2Lir* m2l, LIR* fromfast, LIR* cont, const int type_idx,
844                 const RegLocation& rl_method, const RegLocation& rl_result) :
845                   LIRSlowPath(m2l, m2l->GetCurrentDexPc(), fromfast, cont), type_idx_(type_idx),
846                   rl_method_(rl_method), rl_result_(rl_result) {
847        }
848
849        void Compile() {
850          GenerateTargetLabel();
851
852          m2l_->CallRuntimeHelperImmReg(kQuickInitializeType, type_idx_, rl_method_.reg, true);
853          m2l_->OpRegCopy(rl_result_.reg,  m2l_->TargetReg(kRet0, kRef));
854          m2l_->OpUnconditionalBranch(cont_);
855        }
856
857       private:
858        const int type_idx_;
859        const RegLocation rl_method_;
860        const RegLocation rl_result_;
861      };
862
863      // Add to list for future.
864      AddSlowPath(new (arena_) SlowPath(this, branch, cont, type_idx, rl_method, rl_result));
865
866      StoreValue(rl_dest, rl_result);
867     } else {
868      // Fast path, we're done - just store result
869      StoreValue(rl_dest, rl_result);
870    }
871  }
872}
873
874void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) {
875  /* NOTE: Most strings should be available at compile time */
876  int32_t offset_of_string = mirror::ObjectArray<mirror::String>::OffsetOfElement(string_idx).
877                                                                                      Int32Value();
878  if (!cu_->compiler_driver->CanAssumeStringIsPresentInDexCache(
879      *cu_->dex_file, string_idx) || SLOW_STRING_PATH) {
880    // slow path, resolve string if not in dex cache
881    FlushAllRegs();
882    LockCallTemps();  // Using explicit registers
883
884    // If the Method* is already in a register, we can save a copy.
885    RegLocation rl_method = mir_graph_->GetMethodLoc();
886    RegStorage r_method;
887    if (rl_method.location == kLocPhysReg) {
888      // A temp would conflict with register use below.
889      DCHECK(!IsTemp(rl_method.reg));
890      r_method = rl_method.reg;
891    } else {
892      r_method = TargetReg(kArg2, kRef);
893      LoadCurrMethodDirect(r_method);
894    }
895    LoadRefDisp(r_method, mirror::ArtMethod::DexCacheStringsOffset().Int32Value(),
896                TargetReg(kArg0, kRef), kNotVolatile);
897
898    // Might call out to helper, which will return resolved string in kRet0
899    LoadRefDisp(TargetReg(kArg0, kRef), offset_of_string, TargetReg(kRet0, kRef), kNotVolatile);
900    LIR* fromfast = OpCmpImmBranch(kCondEq, TargetReg(kRet0, kRef), 0, NULL);
901    LIR* cont = NewLIR0(kPseudoTargetLabel);
902
903    {
904      // Object to generate the slow path for string resolution.
905      class SlowPath : public LIRSlowPath {
906       public:
907        SlowPath(Mir2Lir* m2l, LIR* fromfast, LIR* cont, RegStorage r_method, int32_t string_idx) :
908          LIRSlowPath(m2l, m2l->GetCurrentDexPc(), fromfast, cont),
909          r_method_(r_method), string_idx_(string_idx) {
910        }
911
912        void Compile() {
913          GenerateTargetLabel();
914          m2l_->CallRuntimeHelperRegImm(kQuickResolveString, r_method_, string_idx_, true);
915          m2l_->OpUnconditionalBranch(cont_);
916        }
917
918       private:
919         const RegStorage r_method_;
920         const int32_t string_idx_;
921      };
922
923      AddSlowPath(new (arena_) SlowPath(this, fromfast, cont, r_method, string_idx));
924    }
925
926    GenBarrier();
927    StoreValue(rl_dest, GetReturn(kRefReg));
928  } else {
929    RegLocation rl_method = LoadCurrMethod();
930    RegStorage res_reg = AllocTempRef();
931    RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
932    LoadRefDisp(rl_method.reg, mirror::ArtMethod::DexCacheStringsOffset().Int32Value(), res_reg,
933                kNotVolatile);
934    LoadRefDisp(res_reg, offset_of_string, rl_result.reg, kNotVolatile);
935    StoreValue(rl_dest, rl_result);
936  }
937}
938
939/*
940 * Let helper function take care of everything.  Will
941 * call Class::NewInstanceFromCode(type_idx, method);
942 */
943void Mir2Lir::GenNewInstance(uint32_t type_idx, RegLocation rl_dest) {
944  FlushAllRegs();  /* Everything to home location */
945  // alloc will always check for resolution, do we also need to verify
946  // access because the verifier was unable to?
947  const DexFile* dex_file = cu_->dex_file;
948  CompilerDriver* driver = cu_->compiler_driver;
949  if (driver->CanAccessInstantiableTypeWithoutChecks(cu_->method_idx, *dex_file, type_idx)) {
950    bool is_type_initialized;
951    bool use_direct_type_ptr;
952    uintptr_t direct_type_ptr;
953    bool is_finalizable;
954    if (kEmbedClassInCode &&
955        driver->CanEmbedTypeInCode(*dex_file, type_idx, &is_type_initialized, &use_direct_type_ptr,
956                                   &direct_type_ptr, &is_finalizable) &&
957                                   !is_finalizable) {
958      // The fast path.
959      if (!use_direct_type_ptr) {
960        LoadClassType(type_idx, kArg0);
961        if (!is_type_initialized) {
962          CallRuntimeHelperRegMethod(kQuickAllocObjectResolved, TargetReg(kArg0, kRef), true);
963        } else {
964          CallRuntimeHelperRegMethod(kQuickAllocObjectInitialized, TargetReg(kArg0, kRef), true);
965        }
966      } else {
967        // Use the direct pointer.
968        if (!is_type_initialized) {
969          CallRuntimeHelperImmMethod(kQuickAllocObjectResolved, direct_type_ptr, true);
970        } else {
971          CallRuntimeHelperImmMethod(kQuickAllocObjectInitialized, direct_type_ptr, true);
972        }
973      }
974    } else {
975      // The slow path.
976      CallRuntimeHelperImmMethod(kQuickAllocObject, type_idx, true);
977    }
978  } else {
979    CallRuntimeHelperImmMethod(kQuickAllocObjectWithAccessCheck, type_idx, true);
980  }
981  StoreValue(rl_dest, GetReturn(kRefReg));
982}
983
984void Mir2Lir::GenThrow(RegLocation rl_src) {
985  FlushAllRegs();
986  CallRuntimeHelperRegLocation(kQuickDeliverException, rl_src, true);
987}
988
989// For final classes there are no sub-classes to check and so we can answer the instance-of
990// question with simple comparisons.
991void Mir2Lir::GenInstanceofFinal(bool use_declaring_class, uint32_t type_idx, RegLocation rl_dest,
992                                 RegLocation rl_src) {
993  // X86 has its own implementation.
994  DCHECK(cu_->instruction_set != kX86 && cu_->instruction_set != kX86_64);
995
996  RegLocation object = LoadValue(rl_src, kRefReg);
997  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
998  RegStorage result_reg = rl_result.reg;
999  if (IsSameReg(result_reg, object.reg)) {
1000    result_reg = AllocTypedTemp(false, kCoreReg);
1001    DCHECK(!IsSameReg(result_reg, object.reg));
1002  }
1003  LoadConstant(result_reg, 0);     // assume false
1004  LIR* null_branchover = OpCmpImmBranch(kCondEq, object.reg, 0, NULL);
1005
1006  RegStorage check_class = AllocTypedTemp(false, kRefReg);
1007  RegStorage object_class = AllocTypedTemp(false, kRefReg);
1008
1009  LoadCurrMethodDirect(check_class);
1010  if (use_declaring_class) {
1011    LoadRefDisp(check_class, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), check_class,
1012                kNotVolatile);
1013    LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
1014                kNotVolatile);
1015  } else {
1016    LoadRefDisp(check_class, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
1017                check_class, kNotVolatile);
1018    LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
1019                kNotVolatile);
1020    int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
1021    LoadRefDisp(check_class, offset_of_type, check_class, kNotVolatile);
1022  }
1023
1024  // FIXME: what should we be comparing here? compressed or decompressed references?
1025  if (cu_->instruction_set == kThumb2) {
1026    OpRegReg(kOpCmp, check_class, object_class);  // Same?
1027    LIR* it = OpIT(kCondEq, "");   // if-convert the test
1028    LoadConstant(result_reg, 1);     // .eq case - load true
1029    OpEndIT(it);
1030  } else {
1031    GenSelectConst32(check_class, object_class, kCondEq, 1, 0, result_reg, kCoreReg);
1032  }
1033  LIR* target = NewLIR0(kPseudoTargetLabel);
1034  null_branchover->target = target;
1035  FreeTemp(object_class);
1036  FreeTemp(check_class);
1037  if (IsTemp(result_reg)) {
1038    OpRegCopy(rl_result.reg, result_reg);
1039    FreeTemp(result_reg);
1040  }
1041  StoreValue(rl_dest, rl_result);
1042}
1043
1044void Mir2Lir::GenInstanceofCallingHelper(bool needs_access_check, bool type_known_final,
1045                                         bool type_known_abstract, bool use_declaring_class,
1046                                         bool can_assume_type_is_in_dex_cache,
1047                                         uint32_t type_idx, RegLocation rl_dest,
1048                                         RegLocation rl_src) {
1049  FlushAllRegs();
1050  // May generate a call - use explicit registers
1051  LockCallTemps();
1052  RegStorage method_reg = TargetReg(kArg1, kRef);
1053  LoadCurrMethodDirect(method_reg);   // kArg1 <= current Method*
1054  RegStorage class_reg = TargetReg(kArg2, kRef);  // kArg2 will hold the Class*
1055  RegStorage ref_reg = TargetReg(kArg0, kRef);  // kArg0 will hold the ref.
1056  RegStorage ret_reg = GetReturn(kRefReg).reg;
1057  if (needs_access_check) {
1058    // Check we have access to type_idx and if not throw IllegalAccessError,
1059    // returns Class* in kArg0
1060    CallRuntimeHelperImm(kQuickInitializeTypeAndVerifyAccess, type_idx, true);
1061    OpRegCopy(class_reg, ret_reg);  // Align usage with fast path
1062    LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
1063  } else if (use_declaring_class) {
1064    LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
1065    LoadRefDisp(method_reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
1066                class_reg, kNotVolatile);
1067  } else {
1068    if (can_assume_type_is_in_dex_cache) {
1069      // Conditionally, as in the other case we will also load it.
1070      LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
1071    }
1072
1073    // Load dex cache entry into class_reg (kArg2)
1074    LoadRefDisp(method_reg, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
1075                class_reg, kNotVolatile);
1076    int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
1077    LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
1078    if (!can_assume_type_is_in_dex_cache) {
1079      LIR* slow_path_branch = OpCmpImmBranch(kCondEq, class_reg, 0, NULL);
1080      LIR* slow_path_target = NewLIR0(kPseudoTargetLabel);
1081
1082      // Should load value here.
1083      LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
1084
1085      class InitTypeSlowPath : public Mir2Lir::LIRSlowPath {
1086       public:
1087        InitTypeSlowPath(Mir2Lir* m2l, LIR* branch, LIR* cont, uint32_t type_idx,
1088                         RegLocation rl_src)
1089            : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch, cont), type_idx_(type_idx),
1090              rl_src_(rl_src) {
1091        }
1092
1093        void Compile() OVERRIDE {
1094          GenerateTargetLabel();
1095
1096          m2l_->CallRuntimeHelperImm(kQuickInitializeType, type_idx_, true);
1097          m2l_->OpRegCopy(m2l_->TargetReg(kArg2, kRef),
1098                          m2l_->TargetReg(kRet0, kRef));  // Align usage with fast path
1099          m2l_->OpUnconditionalBranch(cont_);
1100        }
1101
1102       private:
1103        uint32_t type_idx_;
1104        RegLocation rl_src_;
1105      };
1106
1107      AddSlowPath(new (arena_) InitTypeSlowPath(this, slow_path_branch, slow_path_target,
1108                                                type_idx, rl_src));
1109    }
1110  }
1111  /* kArg0 is ref, kArg2 is class. If ref==null, use directly as bool result */
1112  RegLocation rl_result = GetReturn(kCoreReg);
1113  if (!IsSameReg(rl_result.reg, ref_reg)) {
1114    // On MIPS and x86_64 rArg0 != rl_result, place false in result if branch is taken.
1115    LoadConstant(rl_result.reg, 0);
1116  }
1117  LIR* branch1 = OpCmpImmBranch(kCondEq, ref_reg, 0, NULL);
1118
1119  /* load object->klass_ */
1120  RegStorage ref_class_reg = TargetReg(kArg1, kRef);  // kArg1 will hold the Class* of ref.
1121  DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
1122  LoadRefDisp(ref_reg, mirror::Object::ClassOffset().Int32Value(),
1123              ref_class_reg, kNotVolatile);
1124  /* kArg0 is ref, kArg1 is ref->klass_, kArg2 is class */
1125  LIR* branchover = NULL;
1126  if (type_known_final) {
1127    // rl_result == ref == class.
1128    GenSelectConst32(ref_class_reg, class_reg, kCondEq, 1, 0, rl_result.reg,
1129                     kCoreReg);
1130  } else {
1131    if (cu_->instruction_set == kThumb2) {
1132      RegStorage r_tgt = LoadHelper(kQuickInstanceofNonTrivial);
1133      LIR* it = nullptr;
1134      if (!type_known_abstract) {
1135      /* Uses conditional nullification */
1136        OpRegReg(kOpCmp, ref_class_reg, class_reg);  // Same?
1137        it = OpIT(kCondEq, "EE");   // if-convert the test
1138        LoadConstant(rl_result.reg, 1);     // .eq case - load true
1139      }
1140      OpRegCopy(ref_reg, class_reg);    // .ne case - arg0 <= class
1141      OpReg(kOpBlx, r_tgt);    // .ne case: helper(class, ref->class)
1142      if (it != nullptr) {
1143        OpEndIT(it);
1144      }
1145      FreeTemp(r_tgt);
1146    } else {
1147      if (!type_known_abstract) {
1148        /* Uses branchovers */
1149        LoadConstant(rl_result.reg, 1);     // assume true
1150        branchover = OpCmpBranch(kCondEq, TargetReg(kArg1, kRef), TargetReg(kArg2, kRef), NULL);
1151      }
1152
1153      OpRegCopy(TargetReg(kArg0, kRef), class_reg);    // .ne case - arg0 <= class
1154      CallRuntimeHelper(kQuickInstanceofNonTrivial, false);
1155    }
1156  }
1157  // TODO: only clobber when type isn't final?
1158  ClobberCallerSave();
1159  /* branch targets here */
1160  LIR* target = NewLIR0(kPseudoTargetLabel);
1161  StoreValue(rl_dest, rl_result);
1162  branch1->target = target;
1163  if (branchover != nullptr) {
1164    branchover->target = target;
1165  }
1166}
1167
1168void Mir2Lir::GenInstanceof(uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src) {
1169  bool type_known_final, type_known_abstract, use_declaring_class;
1170  bool needs_access_check = !cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
1171                                                                              *cu_->dex_file,
1172                                                                              type_idx,
1173                                                                              &type_known_final,
1174                                                                              &type_known_abstract,
1175                                                                              &use_declaring_class);
1176  bool can_assume_type_is_in_dex_cache = !needs_access_check &&
1177      cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file, type_idx);
1178
1179  if ((use_declaring_class || can_assume_type_is_in_dex_cache) && type_known_final) {
1180    GenInstanceofFinal(use_declaring_class, type_idx, rl_dest, rl_src);
1181  } else {
1182    GenInstanceofCallingHelper(needs_access_check, type_known_final, type_known_abstract,
1183                               use_declaring_class, can_assume_type_is_in_dex_cache,
1184                               type_idx, rl_dest, rl_src);
1185  }
1186}
1187
1188void Mir2Lir::GenCheckCast(uint32_t insn_idx, uint32_t type_idx, RegLocation rl_src) {
1189  bool type_known_final, type_known_abstract, use_declaring_class;
1190  bool needs_access_check = !cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
1191                                                                              *cu_->dex_file,
1192                                                                              type_idx,
1193                                                                              &type_known_final,
1194                                                                              &type_known_abstract,
1195                                                                              &use_declaring_class);
1196  // Note: currently type_known_final is unused, as optimizing will only improve the performance
1197  // of the exception throw path.
1198  DexCompilationUnit* cu = mir_graph_->GetCurrentDexCompilationUnit();
1199  if (!needs_access_check && cu_->compiler_driver->IsSafeCast(cu, insn_idx)) {
1200    // Verifier type analysis proved this check cast would never cause an exception.
1201    return;
1202  }
1203  FlushAllRegs();
1204  // May generate a call - use explicit registers
1205  LockCallTemps();
1206  RegStorage method_reg = TargetReg(kArg1, kRef);
1207  LoadCurrMethodDirect(method_reg);  // kArg1 <= current Method*
1208  RegStorage class_reg = TargetReg(kArg2, kRef);  // kArg2 will hold the Class*
1209  if (needs_access_check) {
1210    // Check we have access to type_idx and if not throw IllegalAccessError,
1211    // returns Class* in kRet0
1212    // InitializeTypeAndVerifyAccess(idx, method)
1213    CallRuntimeHelperImm(kQuickInitializeTypeAndVerifyAccess, type_idx, true);
1214    OpRegCopy(class_reg, TargetReg(kRet0, kRef));  // Align usage with fast path
1215  } else if (use_declaring_class) {
1216    LoadRefDisp(method_reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
1217                class_reg, kNotVolatile);
1218  } else {
1219    // Load dex cache entry into class_reg (kArg2)
1220    LoadRefDisp(method_reg, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
1221                class_reg, kNotVolatile);
1222    int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
1223    LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
1224    if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file, type_idx)) {
1225      // Need to test presence of type in dex cache at runtime
1226      LIR* hop_branch = OpCmpImmBranch(kCondEq, class_reg, 0, NULL);
1227      LIR* cont = NewLIR0(kPseudoTargetLabel);
1228
1229      // Slow path to initialize the type.  Executed if the type is NULL.
1230      class SlowPath : public LIRSlowPath {
1231       public:
1232        SlowPath(Mir2Lir* m2l, LIR* fromfast, LIR* cont, const int type_idx,
1233                 const RegStorage class_reg) :
1234                   LIRSlowPath(m2l, m2l->GetCurrentDexPc(), fromfast, cont), type_idx_(type_idx),
1235                   class_reg_(class_reg) {
1236        }
1237
1238        void Compile() {
1239          GenerateTargetLabel();
1240
1241          // Call out to helper, which will return resolved type in kArg0
1242          // InitializeTypeFromCode(idx, method)
1243          m2l_->CallRuntimeHelperImmReg(kQuickInitializeType, type_idx_,
1244                                        m2l_->TargetReg(kArg1, kRef), true);
1245          m2l_->OpRegCopy(class_reg_, m2l_->TargetReg(kRet0, kRef));  // Align usage with fast path
1246          m2l_->OpUnconditionalBranch(cont_);
1247        }
1248
1249       public:
1250        const int type_idx_;
1251        const RegStorage class_reg_;
1252      };
1253
1254      AddSlowPath(new (arena_) SlowPath(this, hop_branch, cont, type_idx, class_reg));
1255    }
1256  }
1257  // At this point, class_reg (kArg2) has class
1258  LoadValueDirectFixed(rl_src, TargetReg(kArg0, kRef));  // kArg0 <= ref
1259
1260  // Slow path for the case where the classes are not equal.  In this case we need
1261  // to call a helper function to do the check.
1262  class SlowPath : public LIRSlowPath {
1263   public:
1264    SlowPath(Mir2Lir* m2l, LIR* fromfast, LIR* cont, bool load):
1265               LIRSlowPath(m2l, m2l->GetCurrentDexPc(), fromfast, cont), load_(load) {
1266    }
1267
1268    void Compile() {
1269      GenerateTargetLabel();
1270
1271      if (load_) {
1272        m2l_->LoadRefDisp(m2l_->TargetReg(kArg0, kRef), mirror::Object::ClassOffset().Int32Value(),
1273                          m2l_->TargetReg(kArg1, kRef), kNotVolatile);
1274      }
1275      m2l_->CallRuntimeHelperRegReg(kQuickCheckCast, m2l_->TargetReg(kArg2, kRef),
1276                                    m2l_->TargetReg(kArg1, kRef), true);
1277      m2l_->OpUnconditionalBranch(cont_);
1278    }
1279
1280   private:
1281    const bool load_;
1282  };
1283
1284  if (type_known_abstract) {
1285    // Easier case, run slow path if target is non-null (slow path will load from target)
1286    LIR* branch = OpCmpImmBranch(kCondNe, TargetReg(kArg0, kRef), 0, nullptr);
1287    LIR* cont = NewLIR0(kPseudoTargetLabel);
1288    AddSlowPath(new (arena_) SlowPath(this, branch, cont, true));
1289  } else {
1290    // Harder, more common case.  We need to generate a forward branch over the load
1291    // if the target is null.  If it's non-null we perform the load and branch to the
1292    // slow path if the classes are not equal.
1293
1294    /* Null is OK - continue */
1295    LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0, kRef), 0, nullptr);
1296    /* load object->klass_ */
1297    DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
1298    LoadRefDisp(TargetReg(kArg0, kRef), mirror::Object::ClassOffset().Int32Value(),
1299                TargetReg(kArg1, kRef), kNotVolatile);
1300
1301    LIR* branch2 = OpCmpBranch(kCondNe, TargetReg(kArg1, kRef), class_reg, nullptr);
1302    LIR* cont = NewLIR0(kPseudoTargetLabel);
1303
1304    // Add the slow path that will not perform load since this is already done.
1305    AddSlowPath(new (arena_) SlowPath(this, branch2, cont, false));
1306
1307    // Set the null check to branch to the continuation.
1308    branch1->target = cont;
1309  }
1310}
1311
1312void Mir2Lir::GenLong3Addr(OpKind first_op, OpKind second_op, RegLocation rl_dest,
1313                           RegLocation rl_src1, RegLocation rl_src2) {
1314  RegLocation rl_result;
1315  if (cu_->instruction_set == kThumb2) {
1316    /*
1317     * NOTE:  This is the one place in the code in which we might have
1318     * as many as six live temporary registers.  There are 5 in the normal
1319     * set for Arm.  Until we have spill capabilities, temporarily add
1320     * lr to the temp set.  It is safe to do this locally, but note that
1321     * lr is used explicitly elsewhere in the code generator and cannot
1322     * normally be used as a general temp register.
1323     */
1324    MarkTemp(TargetReg(kLr, kNotWide));   // Add lr to the temp pool
1325    FreeTemp(TargetReg(kLr, kNotWide));   // and make it available
1326  }
1327  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
1328  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
1329  rl_result = EvalLoc(rl_dest, kCoreReg, true);
1330  // The longs may overlap - use intermediate temp if so
1331  if ((rl_result.reg.GetLowReg() == rl_src1.reg.GetHighReg()) || (rl_result.reg.GetLowReg() == rl_src2.reg.GetHighReg())) {
1332    RegStorage t_reg = AllocTemp();
1333    OpRegRegReg(first_op, t_reg, rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
1334    OpRegRegReg(second_op, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
1335    OpRegCopy(rl_result.reg.GetLow(), t_reg);
1336    FreeTemp(t_reg);
1337  } else {
1338    OpRegRegReg(first_op, rl_result.reg.GetLow(), rl_src1.reg.GetLow(), rl_src2.reg.GetLow());
1339    OpRegRegReg(second_op, rl_result.reg.GetHigh(), rl_src1.reg.GetHigh(), rl_src2.reg.GetHigh());
1340  }
1341  /*
1342   * NOTE: If rl_dest refers to a frame variable in a large frame, the
1343   * following StoreValueWide might need to allocate a temp register.
1344   * To further work around the lack of a spill capability, explicitly
1345   * free any temps from rl_src1 & rl_src2 that aren't still live in rl_result.
1346   * Remove when spill is functional.
1347   */
1348  FreeRegLocTemps(rl_result, rl_src1);
1349  FreeRegLocTemps(rl_result, rl_src2);
1350  StoreValueWide(rl_dest, rl_result);
1351  if (cu_->instruction_set == kThumb2) {
1352    Clobber(TargetReg(kLr, kNotWide));
1353    UnmarkTemp(TargetReg(kLr, kNotWide));  // Remove lr from the temp pool
1354  }
1355}
1356
1357void Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest,
1358                             RegLocation rl_src1, RegLocation rl_shift) {
1359  QuickEntrypointEnum target;
1360  switch (opcode) {
1361    case Instruction::SHL_LONG:
1362    case Instruction::SHL_LONG_2ADDR:
1363      target = kQuickShlLong;
1364      break;
1365    case Instruction::SHR_LONG:
1366    case Instruction::SHR_LONG_2ADDR:
1367      target = kQuickShrLong;
1368      break;
1369    case Instruction::USHR_LONG:
1370    case Instruction::USHR_LONG_2ADDR:
1371      target = kQuickUshrLong;
1372      break;
1373    default:
1374      LOG(FATAL) << "Unexpected case";
1375      target = kQuickShlLong;
1376  }
1377  FlushAllRegs();   /* Send everything to home location */
1378  CallRuntimeHelperRegLocationRegLocation(target, rl_src1, rl_shift, false);
1379  RegLocation rl_result = GetReturnWide(kCoreReg);
1380  StoreValueWide(rl_dest, rl_result);
1381}
1382
1383
1384void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest,
1385                            RegLocation rl_src1, RegLocation rl_src2) {
1386  DCHECK(cu_->instruction_set != kX86 && cu_->instruction_set != kX86_64);
1387  OpKind op = kOpBkpt;
1388  bool is_div_rem = false;
1389  bool check_zero = false;
1390  bool unary = false;
1391  RegLocation rl_result;
1392  bool shift_op = false;
1393  switch (opcode) {
1394    case Instruction::NEG_INT:
1395      op = kOpNeg;
1396      unary = true;
1397      break;
1398    case Instruction::NOT_INT:
1399      op = kOpMvn;
1400      unary = true;
1401      break;
1402    case Instruction::ADD_INT:
1403    case Instruction::ADD_INT_2ADDR:
1404      op = kOpAdd;
1405      break;
1406    case Instruction::SUB_INT:
1407    case Instruction::SUB_INT_2ADDR:
1408      op = kOpSub;
1409      break;
1410    case Instruction::MUL_INT:
1411    case Instruction::MUL_INT_2ADDR:
1412      op = kOpMul;
1413      break;
1414    case Instruction::DIV_INT:
1415    case Instruction::DIV_INT_2ADDR:
1416      check_zero = true;
1417      op = kOpDiv;
1418      is_div_rem = true;
1419      break;
1420    /* NOTE: returns in kArg1 */
1421    case Instruction::REM_INT:
1422    case Instruction::REM_INT_2ADDR:
1423      check_zero = true;
1424      op = kOpRem;
1425      is_div_rem = true;
1426      break;
1427    case Instruction::AND_INT:
1428    case Instruction::AND_INT_2ADDR:
1429      op = kOpAnd;
1430      break;
1431    case Instruction::OR_INT:
1432    case Instruction::OR_INT_2ADDR:
1433      op = kOpOr;
1434      break;
1435    case Instruction::XOR_INT:
1436    case Instruction::XOR_INT_2ADDR:
1437      op = kOpXor;
1438      break;
1439    case Instruction::SHL_INT:
1440    case Instruction::SHL_INT_2ADDR:
1441      shift_op = true;
1442      op = kOpLsl;
1443      break;
1444    case Instruction::SHR_INT:
1445    case Instruction::SHR_INT_2ADDR:
1446      shift_op = true;
1447      op = kOpAsr;
1448      break;
1449    case Instruction::USHR_INT:
1450    case Instruction::USHR_INT_2ADDR:
1451      shift_op = true;
1452      op = kOpLsr;
1453      break;
1454    default:
1455      LOG(FATAL) << "Invalid word arith op: " << opcode;
1456  }
1457  if (!is_div_rem) {
1458    if (unary) {
1459      rl_src1 = LoadValue(rl_src1, kCoreReg);
1460      rl_result = EvalLoc(rl_dest, kCoreReg, true);
1461      OpRegReg(op, rl_result.reg, rl_src1.reg);
1462    } else {
1463      if ((shift_op) && (cu_->instruction_set != kArm64)) {
1464        rl_src2 = LoadValue(rl_src2, kCoreReg);
1465        RegStorage t_reg = AllocTemp();
1466        OpRegRegImm(kOpAnd, t_reg, rl_src2.reg, 31);
1467        rl_src1 = LoadValue(rl_src1, kCoreReg);
1468        rl_result = EvalLoc(rl_dest, kCoreReg, true);
1469        OpRegRegReg(op, rl_result.reg, rl_src1.reg, t_reg);
1470        FreeTemp(t_reg);
1471      } else {
1472        rl_src1 = LoadValue(rl_src1, kCoreReg);
1473        rl_src2 = LoadValue(rl_src2, kCoreReg);
1474        rl_result = EvalLoc(rl_dest, kCoreReg, true);
1475        OpRegRegReg(op, rl_result.reg, rl_src1.reg, rl_src2.reg);
1476      }
1477    }
1478    StoreValue(rl_dest, rl_result);
1479  } else {
1480    bool done = false;      // Set to true if we happen to find a way to use a real instruction.
1481    if (cu_->instruction_set == kMips || cu_->instruction_set == kArm64) {
1482      rl_src1 = LoadValue(rl_src1, kCoreReg);
1483      rl_src2 = LoadValue(rl_src2, kCoreReg);
1484      if (check_zero) {
1485        GenDivZeroCheck(rl_src2.reg);
1486      }
1487      rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
1488      done = true;
1489    } else if (cu_->instruction_set == kThumb2) {
1490      if (cu_->GetInstructionSetFeatures().HasDivideInstruction()) {
1491        // Use ARM SDIV instruction for division.  For remainder we also need to
1492        // calculate using a MUL and subtract.
1493        rl_src1 = LoadValue(rl_src1, kCoreReg);
1494        rl_src2 = LoadValue(rl_src2, kCoreReg);
1495        if (check_zero) {
1496          GenDivZeroCheck(rl_src2.reg);
1497        }
1498        rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv);
1499        done = true;
1500      }
1501    }
1502
1503    // If we haven't already generated the code use the callout function.
1504    if (!done) {
1505      FlushAllRegs();   /* Send everything to home location */
1506      LoadValueDirectFixed(rl_src2, TargetReg(kArg1, kNotWide));
1507      RegStorage r_tgt = CallHelperSetup(kQuickIdivmod);
1508      LoadValueDirectFixed(rl_src1, TargetReg(kArg0, kNotWide));
1509      if (check_zero) {
1510        GenDivZeroCheck(TargetReg(kArg1, kNotWide));
1511      }
1512      // NOTE: callout here is not a safepoint.
1513      CallHelper(r_tgt, kQuickIdivmod, false /* not a safepoint */);
1514      if (op == kOpDiv)
1515        rl_result = GetReturn(kCoreReg);
1516      else
1517        rl_result = GetReturnAlt();
1518    }
1519    StoreValue(rl_dest, rl_result);
1520  }
1521}
1522
1523/*
1524 * The following are the first-level codegen routines that analyze the format
1525 * of each bytecode then either dispatch special purpose codegen routines
1526 * or produce corresponding Thumb instructions directly.
1527 */
1528
1529// Returns true if no more than two bits are set in 'x'.
1530static bool IsPopCountLE2(unsigned int x) {
1531  x &= x - 1;
1532  return (x & (x - 1)) == 0;
1533}
1534
1535// Returns true if it added instructions to 'cu' to divide 'rl_src' by 'lit'
1536// and store the result in 'rl_dest'.
1537bool Mir2Lir::HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div,
1538                               RegLocation rl_src, RegLocation rl_dest, int lit) {
1539  if ((lit < 2) || ((cu_->instruction_set != kThumb2) && !IsPowerOfTwo(lit))) {
1540    return false;
1541  }
1542  // No divide instruction for Arm, so check for more special cases
1543  if ((cu_->instruction_set == kThumb2) && !IsPowerOfTwo(lit)) {
1544    return SmallLiteralDivRem(dalvik_opcode, is_div, rl_src, rl_dest, lit);
1545  }
1546  int k = LowestSetBit(lit);
1547  if (k >= 30) {
1548    // Avoid special cases.
1549    return false;
1550  }
1551  rl_src = LoadValue(rl_src, kCoreReg);
1552  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
1553  if (is_div) {
1554    RegStorage t_reg = AllocTemp();
1555    if (lit == 2) {
1556      // Division by 2 is by far the most common division by constant.
1557      OpRegRegImm(kOpLsr, t_reg, rl_src.reg, 32 - k);
1558      OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.reg);
1559      OpRegRegImm(kOpAsr, rl_result.reg, t_reg, k);
1560    } else {
1561      OpRegRegImm(kOpAsr, t_reg, rl_src.reg, 31);
1562      OpRegRegImm(kOpLsr, t_reg, t_reg, 32 - k);
1563      OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.reg);
1564      OpRegRegImm(kOpAsr, rl_result.reg, t_reg, k);
1565    }
1566  } else {
1567    RegStorage t_reg1 = AllocTemp();
1568    RegStorage t_reg2 = AllocTemp();
1569    if (lit == 2) {
1570      OpRegRegImm(kOpLsr, t_reg1, rl_src.reg, 32 - k);
1571      OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.reg);
1572      OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit -1);
1573      OpRegRegReg(kOpSub, rl_result.reg, t_reg2, t_reg1);
1574    } else {
1575      OpRegRegImm(kOpAsr, t_reg1, rl_src.reg, 31);
1576      OpRegRegImm(kOpLsr, t_reg1, t_reg1, 32 - k);
1577      OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.reg);
1578      OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit - 1);
1579      OpRegRegReg(kOpSub, rl_result.reg, t_reg2, t_reg1);
1580    }
1581  }
1582  StoreValue(rl_dest, rl_result);
1583  return true;
1584}
1585
1586// Returns true if it added instructions to 'cu' to multiply 'rl_src' by 'lit'
1587// and store the result in 'rl_dest'.
1588bool Mir2Lir::HandleEasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) {
1589  if (lit < 0) {
1590    return false;
1591  }
1592  if (lit == 0) {
1593    RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
1594    LoadConstant(rl_result.reg, 0);
1595    StoreValue(rl_dest, rl_result);
1596    return true;
1597  }
1598  if (lit == 1) {
1599    rl_src = LoadValue(rl_src, kCoreReg);
1600    RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
1601    OpRegCopy(rl_result.reg, rl_src.reg);
1602    StoreValue(rl_dest, rl_result);
1603    return true;
1604  }
1605  // There is RegRegRegShift on Arm, so check for more special cases
1606  if (cu_->instruction_set == kThumb2) {
1607    return EasyMultiply(rl_src, rl_dest, lit);
1608  }
1609  // Can we simplify this multiplication?
1610  bool power_of_two = false;
1611  bool pop_count_le2 = false;
1612  bool power_of_two_minus_one = false;
1613  if (IsPowerOfTwo(lit)) {
1614    power_of_two = true;
1615  } else if (IsPopCountLE2(lit)) {
1616    pop_count_le2 = true;
1617  } else if (IsPowerOfTwo(lit + 1)) {
1618    power_of_two_minus_one = true;
1619  } else {
1620    return false;
1621  }
1622  rl_src = LoadValue(rl_src, kCoreReg);
1623  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
1624  if (power_of_two) {
1625    // Shift.
1626    OpRegRegImm(kOpLsl, rl_result.reg, rl_src.reg, LowestSetBit(lit));
1627  } else if (pop_count_le2) {
1628    // Shift and add and shift.
1629    int first_bit = LowestSetBit(lit);
1630    int second_bit = LowestSetBit(lit ^ (1 << first_bit));
1631    GenMultiplyByTwoBitMultiplier(rl_src, rl_result, lit, first_bit, second_bit);
1632  } else {
1633    // Reverse subtract: (src << (shift + 1)) - src.
1634    DCHECK(power_of_two_minus_one);
1635    // TUNING: rsb dst, src, src lsl#LowestSetBit(lit + 1)
1636    RegStorage t_reg = AllocTemp();
1637    OpRegRegImm(kOpLsl, t_reg, rl_src.reg, LowestSetBit(lit + 1));
1638    OpRegRegReg(kOpSub, rl_result.reg, t_reg, rl_src.reg);
1639  }
1640  StoreValue(rl_dest, rl_result);
1641  return true;
1642}
1643
1644void Mir2Lir::GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src,
1645                               int lit) {
1646  RegLocation rl_result;
1647  OpKind op = static_cast<OpKind>(0);    /* Make gcc happy */
1648  int shift_op = false;
1649  bool is_div = false;
1650
1651  switch (opcode) {
1652    case Instruction::RSUB_INT_LIT8:
1653    case Instruction::RSUB_INT: {
1654      rl_src = LoadValue(rl_src, kCoreReg);
1655      rl_result = EvalLoc(rl_dest, kCoreReg, true);
1656      if (cu_->instruction_set == kThumb2) {
1657        OpRegRegImm(kOpRsub, rl_result.reg, rl_src.reg, lit);
1658      } else {
1659        OpRegReg(kOpNeg, rl_result.reg, rl_src.reg);
1660        OpRegImm(kOpAdd, rl_result.reg, lit);
1661      }
1662      StoreValue(rl_dest, rl_result);
1663      return;
1664    }
1665
1666    case Instruction::SUB_INT:
1667    case Instruction::SUB_INT_2ADDR:
1668      lit = -lit;
1669      // Intended fallthrough
1670    case Instruction::ADD_INT:
1671    case Instruction::ADD_INT_2ADDR:
1672    case Instruction::ADD_INT_LIT8:
1673    case Instruction::ADD_INT_LIT16:
1674      op = kOpAdd;
1675      break;
1676    case Instruction::MUL_INT:
1677    case Instruction::MUL_INT_2ADDR:
1678    case Instruction::MUL_INT_LIT8:
1679    case Instruction::MUL_INT_LIT16: {
1680      if (HandleEasyMultiply(rl_src, rl_dest, lit)) {
1681        return;
1682      }
1683      op = kOpMul;
1684      break;
1685    }
1686    case Instruction::AND_INT:
1687    case Instruction::AND_INT_2ADDR:
1688    case Instruction::AND_INT_LIT8:
1689    case Instruction::AND_INT_LIT16:
1690      op = kOpAnd;
1691      break;
1692    case Instruction::OR_INT:
1693    case Instruction::OR_INT_2ADDR:
1694    case Instruction::OR_INT_LIT8:
1695    case Instruction::OR_INT_LIT16:
1696      op = kOpOr;
1697      break;
1698    case Instruction::XOR_INT:
1699    case Instruction::XOR_INT_2ADDR:
1700    case Instruction::XOR_INT_LIT8:
1701    case Instruction::XOR_INT_LIT16:
1702      op = kOpXor;
1703      break;
1704    case Instruction::SHL_INT_LIT8:
1705    case Instruction::SHL_INT:
1706    case Instruction::SHL_INT_2ADDR:
1707      lit &= 31;
1708      shift_op = true;
1709      op = kOpLsl;
1710      break;
1711    case Instruction::SHR_INT_LIT8:
1712    case Instruction::SHR_INT:
1713    case Instruction::SHR_INT_2ADDR:
1714      lit &= 31;
1715      shift_op = true;
1716      op = kOpAsr;
1717      break;
1718    case Instruction::USHR_INT_LIT8:
1719    case Instruction::USHR_INT:
1720    case Instruction::USHR_INT_2ADDR:
1721      lit &= 31;
1722      shift_op = true;
1723      op = kOpLsr;
1724      break;
1725
1726    case Instruction::DIV_INT:
1727    case Instruction::DIV_INT_2ADDR:
1728    case Instruction::DIV_INT_LIT8:
1729    case Instruction::DIV_INT_LIT16:
1730    case Instruction::REM_INT:
1731    case Instruction::REM_INT_2ADDR:
1732    case Instruction::REM_INT_LIT8:
1733    case Instruction::REM_INT_LIT16: {
1734      if (lit == 0) {
1735        GenDivZeroException();
1736        return;
1737      }
1738      if ((opcode == Instruction::DIV_INT) ||
1739          (opcode == Instruction::DIV_INT_2ADDR) ||
1740          (opcode == Instruction::DIV_INT_LIT8) ||
1741          (opcode == Instruction::DIV_INT_LIT16)) {
1742        is_div = true;
1743      } else {
1744        is_div = false;
1745      }
1746      if (HandleEasyDivRem(opcode, is_div, rl_src, rl_dest, lit)) {
1747        return;
1748      }
1749
1750      bool done = false;
1751      if (cu_->instruction_set == kMips || cu_->instruction_set == kArm64) {
1752        rl_src = LoadValue(rl_src, kCoreReg);
1753        rl_result = GenDivRemLit(rl_dest, rl_src.reg, lit, is_div);
1754        done = true;
1755      } else if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
1756        rl_result = GenDivRemLit(rl_dest, rl_src, lit, is_div);
1757        done = true;
1758      } else if (cu_->instruction_set == kThumb2) {
1759        if (cu_->GetInstructionSetFeatures().HasDivideInstruction()) {
1760          // Use ARM SDIV instruction for division.  For remainder we also need to
1761          // calculate using a MUL and subtract.
1762          rl_src = LoadValue(rl_src, kCoreReg);
1763          rl_result = GenDivRemLit(rl_dest, rl_src.reg, lit, is_div);
1764          done = true;
1765        }
1766      }
1767
1768      if (!done) {
1769        FlushAllRegs();   /* Everything to home location. */
1770        LoadValueDirectFixed(rl_src, TargetReg(kArg0, kNotWide));
1771        Clobber(TargetReg(kArg0, kNotWide));
1772        CallRuntimeHelperRegImm(kQuickIdivmod, TargetReg(kArg0, kNotWide), lit, false);
1773        if (is_div)
1774          rl_result = GetReturn(kCoreReg);
1775        else
1776          rl_result = GetReturnAlt();
1777      }
1778      StoreValue(rl_dest, rl_result);
1779      return;
1780    }
1781    default:
1782      LOG(FATAL) << "Unexpected opcode " << opcode;
1783  }
1784  rl_src = LoadValue(rl_src, kCoreReg);
1785  rl_result = EvalLoc(rl_dest, kCoreReg, true);
1786  // Avoid shifts by literal 0 - no support in Thumb.  Change to copy.
1787  if (shift_op && (lit == 0)) {
1788    OpRegCopy(rl_result.reg, rl_src.reg);
1789  } else {
1790    OpRegRegImm(op, rl_result.reg, rl_src.reg, lit);
1791  }
1792  StoreValue(rl_dest, rl_result);
1793}
1794
1795void Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest,
1796                             RegLocation rl_src1, RegLocation rl_src2) {
1797  RegLocation rl_result;
1798  OpKind first_op = kOpBkpt;
1799  OpKind second_op = kOpBkpt;
1800  bool call_out = false;
1801  bool check_zero = false;
1802  int ret_reg = TargetReg(kRet0, kNotWide).GetReg();
1803  QuickEntrypointEnum target;
1804
1805  switch (opcode) {
1806    case Instruction::NOT_LONG:
1807      if (cu_->instruction_set == kArm64 || cu_->instruction_set == kX86_64) {
1808        GenNotLong(rl_dest, rl_src2);
1809        return;
1810      }
1811      rl_src2 = LoadValueWide(rl_src2, kCoreReg);
1812      rl_result = EvalLoc(rl_dest, kCoreReg, true);
1813      // Check for destructive overlap
1814      if (rl_result.reg.GetLowReg() == rl_src2.reg.GetHighReg()) {
1815        RegStorage t_reg = AllocTemp();
1816        OpRegCopy(t_reg, rl_src2.reg.GetHigh());
1817        OpRegReg(kOpMvn, rl_result.reg.GetLow(), rl_src2.reg.GetLow());
1818        OpRegReg(kOpMvn, rl_result.reg.GetHigh(), t_reg);
1819        FreeTemp(t_reg);
1820      } else {
1821        OpRegReg(kOpMvn, rl_result.reg.GetLow(), rl_src2.reg.GetLow());
1822        OpRegReg(kOpMvn, rl_result.reg.GetHigh(), rl_src2.reg.GetHigh());
1823      }
1824      StoreValueWide(rl_dest, rl_result);
1825      return;
1826    case Instruction::ADD_LONG:
1827    case Instruction::ADD_LONG_2ADDR:
1828      if (cu_->instruction_set != kThumb2) {
1829        GenAddLong(opcode, rl_dest, rl_src1, rl_src2);
1830        return;
1831      }
1832      first_op = kOpAdd;
1833      second_op = kOpAdc;
1834      break;
1835    case Instruction::SUB_LONG:
1836    case Instruction::SUB_LONG_2ADDR:
1837      if (cu_->instruction_set != kThumb2) {
1838        GenSubLong(opcode, rl_dest, rl_src1, rl_src2);
1839        return;
1840      }
1841      first_op = kOpSub;
1842      second_op = kOpSbc;
1843      break;
1844    case Instruction::MUL_LONG:
1845    case Instruction::MUL_LONG_2ADDR:
1846      if (cu_->instruction_set != kMips) {
1847        GenMulLong(opcode, rl_dest, rl_src1, rl_src2);
1848        return;
1849      } else {
1850        call_out = true;
1851        TargetReg(kRet0, kNotWide).GetReg();
1852        target = kQuickLmul;
1853      }
1854      break;
1855    case Instruction::DIV_LONG:
1856    case Instruction::DIV_LONG_2ADDR:
1857      if (cu_->instruction_set == kArm64 || cu_->instruction_set == kX86_64) {
1858        GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ true);
1859        return;
1860      }
1861      call_out = true;
1862      check_zero = true;
1863      ret_reg = TargetReg(kRet0, kNotWide).GetReg();
1864      target = kQuickLdiv;
1865      break;
1866    case Instruction::REM_LONG:
1867    case Instruction::REM_LONG_2ADDR:
1868      if (cu_->instruction_set == kArm64 || cu_->instruction_set == kX86_64) {
1869        GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ false);
1870        return;
1871      }
1872      call_out = true;
1873      check_zero = true;
1874      target = kQuickLmod;
1875      /* NOTE - for Arm, result is in kArg2/kArg3 instead of kRet0/kRet1 */
1876      ret_reg = (cu_->instruction_set == kThumb2) ? TargetReg(kArg2, kNotWide).GetReg() :
1877          TargetReg(kRet0, kNotWide).GetReg();
1878      break;
1879    case Instruction::AND_LONG_2ADDR:
1880    case Instruction::AND_LONG:
1881      if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64 ||
1882          cu_->instruction_set == kArm64) {
1883        return GenAndLong(opcode, rl_dest, rl_src1, rl_src2);
1884      }
1885      first_op = kOpAnd;
1886      second_op = kOpAnd;
1887      break;
1888    case Instruction::OR_LONG:
1889    case Instruction::OR_LONG_2ADDR:
1890      if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64 ||
1891          cu_->instruction_set == kArm64) {
1892        GenOrLong(opcode, rl_dest, rl_src1, rl_src2);
1893        return;
1894      }
1895      first_op = kOpOr;
1896      second_op = kOpOr;
1897      break;
1898    case Instruction::XOR_LONG:
1899    case Instruction::XOR_LONG_2ADDR:
1900      if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64 ||
1901          cu_->instruction_set == kArm64) {
1902        GenXorLong(opcode, rl_dest, rl_src1, rl_src2);
1903        return;
1904      }
1905      first_op = kOpXor;
1906      second_op = kOpXor;
1907      break;
1908    case Instruction::NEG_LONG: {
1909      GenNegLong(rl_dest, rl_src2);
1910      return;
1911    }
1912    default:
1913      LOG(FATAL) << "Invalid long arith op";
1914  }
1915  if (!call_out) {
1916    GenLong3Addr(first_op, second_op, rl_dest, rl_src1, rl_src2);
1917  } else {
1918    FlushAllRegs();   /* Send everything to home location */
1919    if (check_zero) {
1920      RegStorage r_tmp1 = TargetReg(kArg0, kWide);
1921      RegStorage r_tmp2 = TargetReg(kArg2, kWide);
1922      LoadValueDirectWideFixed(rl_src2, r_tmp2);
1923      RegStorage r_tgt = CallHelperSetup(target);
1924      GenDivZeroCheckWide(r_tmp2);
1925      LoadValueDirectWideFixed(rl_src1, r_tmp1);
1926      // NOTE: callout here is not a safepoint
1927      CallHelper(r_tgt, target, false /* not safepoint */);
1928    } else {
1929      CallRuntimeHelperRegLocationRegLocation(target, rl_src1, rl_src2, false);
1930    }
1931    // Adjust return regs in to handle case of rem returning kArg2/kArg3
1932    if (ret_reg == TargetReg(kRet0, kNotWide).GetReg())
1933      rl_result = GetReturnWide(kCoreReg);
1934    else
1935      rl_result = GetReturnWideAlt();
1936    StoreValueWide(rl_dest, rl_result);
1937  }
1938}
1939
1940void Mir2Lir::GenConst(RegLocation rl_dest, int value) {
1941  RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
1942  LoadConstantNoClobber(rl_result.reg, value);
1943  StoreValue(rl_dest, rl_result);
1944  if (value == 0) {
1945    Workaround7250540(rl_dest, rl_result.reg);
1946  }
1947}
1948
1949void Mir2Lir::GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest,
1950                                RegLocation rl_src) {
1951  /*
1952   * Don't optimize the register usage since it calls out to support
1953   * functions
1954   */
1955
1956  FlushAllRegs();   /* Send everything to home location */
1957  CallRuntimeHelperRegLocation(trampoline, rl_src, false);
1958  if (rl_dest.wide) {
1959    RegLocation rl_result;
1960    rl_result = GetReturnWide(LocToRegClass(rl_dest));
1961    StoreValueWide(rl_dest, rl_result);
1962  } else {
1963    RegLocation rl_result;
1964    rl_result = GetReturn(LocToRegClass(rl_dest));
1965    StoreValue(rl_dest, rl_result);
1966  }
1967}
1968
1969class SuspendCheckSlowPath : public Mir2Lir::LIRSlowPath {
1970 public:
1971  SuspendCheckSlowPath(Mir2Lir* m2l, LIR* branch, LIR* cont)
1972      : LIRSlowPath(m2l, m2l->GetCurrentDexPc(), branch, cont) {
1973  }
1974
1975  void Compile() OVERRIDE {
1976    m2l_->ResetRegPool();
1977    m2l_->ResetDefTracking();
1978    GenerateTargetLabel(kPseudoSuspendTarget);
1979    m2l_->CallRuntimeHelper(kQuickTestSuspend, true);
1980    if (cont_ != nullptr) {
1981      m2l_->OpUnconditionalBranch(cont_);
1982    }
1983  }
1984};
1985
1986/* Check if we need to check for pending suspend request */
1987void Mir2Lir::GenSuspendTest(int opt_flags) {
1988  if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitSuspendChecks()) {
1989    if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) {
1990      return;
1991    }
1992    FlushAllRegs();
1993    LIR* branch = OpTestSuspend(NULL);
1994    LIR* cont = NewLIR0(kPseudoTargetLabel);
1995    AddSlowPath(new (arena_) SuspendCheckSlowPath(this, branch, cont));
1996  } else {
1997    if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) {
1998      return;
1999    }
2000    FlushAllRegs();     // TODO: needed?
2001    LIR* inst = CheckSuspendUsingLoad();
2002    MarkSafepointPC(inst);
2003  }
2004}
2005
2006/* Check if we need to check for pending suspend request */
2007void Mir2Lir::GenSuspendTestAndBranch(int opt_flags, LIR* target) {
2008  if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitSuspendChecks()) {
2009    if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) {
2010      OpUnconditionalBranch(target);
2011      return;
2012    }
2013    OpTestSuspend(target);
2014    FlushAllRegs();
2015    LIR* branch = OpUnconditionalBranch(nullptr);
2016    AddSlowPath(new (arena_) SuspendCheckSlowPath(this, branch, target));
2017  } else {
2018    // For the implicit suspend check, just perform the trigger
2019    // load and branch to the target.
2020    if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) {
2021      OpUnconditionalBranch(target);
2022      return;
2023    }
2024    FlushAllRegs();
2025    LIR* inst = CheckSuspendUsingLoad();
2026    MarkSafepointPC(inst);
2027    OpUnconditionalBranch(target);
2028  }
2029}
2030
2031/* Call out to helper assembly routine that will null check obj and then lock it. */
2032void Mir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) {
2033  FlushAllRegs();
2034  CallRuntimeHelperRegLocation(kQuickLockObject, rl_src, true);
2035}
2036
2037/* Call out to helper assembly routine that will null check obj and then unlock it. */
2038void Mir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) {
2039  FlushAllRegs();
2040  CallRuntimeHelperRegLocation(kQuickUnlockObject, rl_src, true);
2041}
2042
2043/* Generic code for generating a wide constant into a VR. */
2044void Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) {
2045  RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
2046  LoadConstantWide(rl_result.reg, value);
2047  StoreValueWide(rl_dest, rl_result);
2048}
2049
2050}  // namespace art
2051