• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4 package com.android.tools.r8.ir.code;
5 
6 import com.android.tools.r8.code.InvokeDirectRange;
7 import com.android.tools.r8.dex.Constants;
8 import com.android.tools.r8.graph.AppInfoWithSubtyping;
9 import com.android.tools.r8.graph.DexEncodedMethod;
10 import com.android.tools.r8.graph.DexMethod;
11 import com.android.tools.r8.ir.conversion.DexBuilder;
12 import com.android.tools.r8.ir.optimize.Inliner.InlineAction;
13 import com.android.tools.r8.ir.optimize.InliningOracle;
14 import java.util.List;
15 
16 public class InvokeDirect extends InvokeMethodWithReceiver {
17 
InvokeDirect(DexMethod target, Value result, List<Value> arguments)18   public InvokeDirect(DexMethod target, Value result, List<Value> arguments) {
19     super(target, result, arguments);
20   }
21 
22   @Override
getType()23   public Type getType() {
24     return Type.DIRECT;
25   }
26 
27   @Override
getTypeString()28   protected String getTypeString() {
29     return "Direct";
30   }
31 
32   @Override
computeSingleTarget(AppInfoWithSubtyping appInfo)33   public DexEncodedMethod computeSingleTarget(AppInfoWithSubtyping appInfo) {
34     return appInfo.lookupDirectTarget(getInvokedMethod());
35   }
36 
37   @Override
buildDex(DexBuilder builder)38   public void buildDex(DexBuilder builder) {
39     com.android.tools.r8.code.Instruction instruction;
40     int argumentRegisters = requiredArgumentRegisters();
41     builder.requestOutgoingRegisters(argumentRegisters);
42     if (needsRangedInvoke(builder)) {
43       assert argumentsConsecutive(builder);
44       int firstRegister = argumentRegisterValue(0, builder);
45       instruction = new InvokeDirectRange(firstRegister, argumentRegisters, getInvokedMethod());
46     } else {
47       int[] individualArgumentRegisters = new int[5];
48       int argumentRegistersCount = fillArgumentRegisters(builder, individualArgumentRegisters);
49       instruction = new com.android.tools.r8.code.InvokeDirect(
50           argumentRegistersCount,
51           getInvokedMethod(),
52           individualArgumentRegisters[0],  // C
53           individualArgumentRegisters[1],  // D
54           individualArgumentRegisters[2],  // E
55           individualArgumentRegisters[3],  // F
56           individualArgumentRegisters[4]); // G
57     }
58     addInvokeAndMoveResult(instruction, builder);
59   }
60 
61   /**
62    * Two invokes of a constructor are only allowed to be considered equal if the object
63    * they are initializing is the same. Art rejects code that has objects created by
64    * different new-instance instructions flow to one constructor invoke.
65    */
sameConstructorReceiverValue(Invoke other)66   public boolean sameConstructorReceiverValue(Invoke other) {
67     if (!getInvokedMethod().name.toString().equals(Constants.INSTANCE_INITIALIZER_NAME)) {
68       return true;
69     }
70     return inValues.get(0) == other.inValues.get(0);
71   }
72 
73   @Override
identicalNonValueParts(Instruction other)74   public boolean identicalNonValueParts(Instruction other) {
75     if (!other.isInvokeDirect()) {
76       return false;
77     }
78     return super.identicalNonValueParts(other);
79   }
80 
81   @Override
isInvokeDirect()82   public boolean isInvokeDirect() {
83     return true;
84   }
85 
86   @Override
asInvokeDirect()87   public InvokeDirect asInvokeDirect() {
88     return this;
89   }
90 
91   @Override
computeInlining(InliningOracle decider)92   public InlineAction computeInlining(InliningOracle decider) {
93     return decider.computeForInvokeDirect(this);
94   }
95 }
96