Reland "Fix incorrect accessibility check in inliner"
This reverts commit ed88cc4517b42a5291f7313bd8ccda3cd4067826.
Change-Id: I5286796768aa1e5adc83afb6d0a0ff3e153f3687
diff --git a/src/main/java/com/android/tools/r8/graph/AccessControl.java b/src/main/java/com/android/tools/r8/graph/AccessControl.java
index 854c5e7..788b358 100644
--- a/src/main/java/com/android/tools/r8/graph/AccessControl.java
+++ b/src/main/java/com/android/tools/r8/graph/AccessControl.java
@@ -38,6 +38,14 @@
public static OptionalBool isMethodAccessible(
DexEncodedMethod method,
DexClass holder,
+ ProgramMethod context,
+ AppView<? extends AppInfoWithClassHierarchy> appView) {
+ return isMethodAccessible(method, holder, context.getHolder(), appView.appInfo());
+ }
+
+ public static OptionalBool isMethodAccessible(
+ DexEncodedMethod method,
+ DexClass holder,
DexProgramClass context,
AppInfoWithClassHierarchy appInfo) {
return isMemberAccessible(method.accessFlags, holder, context, appInfo);
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
index 978646c..41f5dc8 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
@@ -388,7 +388,7 @@
return false;
}
ResolutionResult resolutionResult =
- appView.appInfo().resolveMethodOn(superType, method, instruction.itf);
+ appView.appInfo().resolveMethodOn(superType, method, instruction.isInterface);
if (!resolutionResult.isSingleResolution()) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
index abaf1c3..0f736a0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
@@ -29,15 +29,15 @@
public class InvokeDirect extends InvokeMethodWithReceiver {
- private final boolean itf;
+ private final boolean isInterface;
public InvokeDirect(DexMethod target, Value result, List<Value> arguments) {
this(target, result, arguments, false);
}
- public InvokeDirect(DexMethod target, Value result, List<Value> arguments, boolean itf) {
+ public InvokeDirect(DexMethod target, Value result, List<Value> arguments, boolean isInterface) {
super(target, result, arguments);
- this.itf = itf;
+ this.isInterface = isInterface;
// invoke-direct <init> should have no out value.
assert !target.name.toString().equals(Constants.INSTANCE_INITIALIZER_NAME)
|| result == null;
@@ -48,8 +48,9 @@
return Opcodes.INVOKE_DIRECT;
}
- public boolean isInterface() {
- return itf;
+ @Override
+ public boolean getInterfaceBit() {
+ return isInterface;
}
@Override
@@ -145,7 +146,8 @@
@Override
public void buildCf(CfBuilder builder) {
- builder.add(new CfInvoke(org.objectweb.asm.Opcodes.INVOKESPECIAL, getInvokedMethod(), itf));
+ builder.add(
+ new CfInvoke(org.objectweb.asm.Opcodes.INVOKESPECIAL, getInvokedMethod(), isInterface));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
index 3ef66ca..e95be77 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
@@ -31,6 +31,11 @@
}
@Override
+ public boolean getInterfaceBit() {
+ return true;
+ }
+
+ @Override
public int opcode() {
return Opcodes.INVOKE_INTERFACE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
index 8c059d9..e0e00ac 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
@@ -41,6 +41,8 @@
this.method = target;
}
+ public abstract boolean getInterfaceBit();
+
@Override
public DexType getReturnType() {
return method.proto.returnType;
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
index 6a1e8a2..824a283 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
@@ -36,6 +36,11 @@
}
@Override
+ public boolean getInterfaceBit() {
+ return false;
+ }
+
+ @Override
public int opcode() {
return Opcodes.INVOKE_POLYMORPHIC;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index 7cd9b1e..7f5836a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -43,6 +43,11 @@
}
@Override
+ public boolean getInterfaceBit() {
+ return isInterface;
+ }
+
+ @Override
public int opcode() {
return Opcodes.INVOKE_STATIC;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
index 0e1faf4..4815431 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
@@ -24,11 +24,16 @@
public class InvokeSuper extends InvokeMethodWithReceiver {
- public final boolean itf;
+ public final boolean isInterface;
- public InvokeSuper(DexMethod target, Value result, List<Value> arguments, boolean itf) {
+ public InvokeSuper(DexMethod target, Value result, List<Value> arguments, boolean isInterface) {
super(target, result, arguments);
- this.itf = itf;
+ this.isInterface = isInterface;
+ }
+
+ @Override
+ public boolean getInterfaceBit() {
+ return isInterface;
}
@Override
@@ -77,7 +82,8 @@
@Override
public void buildCf(CfBuilder builder) {
- builder.add(new CfInvoke(org.objectweb.asm.Opcodes.INVOKESPECIAL, getInvokedMethod(), itf));
+ builder.add(
+ new CfInvoke(org.objectweb.asm.Opcodes.INVOKESPECIAL, getInvokedMethod(), isInterface));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index 6dafcd0..2d95115 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -32,6 +32,11 @@
}
@Override
+ public boolean getInterfaceBit() {
+ return false;
+ }
+
+ @Override
public int opcode() {
return Opcodes.INVOKE_VIRTUAL;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
index 5893a3b..c4bf62f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
@@ -113,6 +114,7 @@
@Override
public boolean passesInliningConstraints(
InvokeMethod invoke,
+ SingleResolutionResult resolutionResult,
ProgramMethod singleTarget,
Reason reason,
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
@@ -167,7 +169,7 @@
}
// Abort inlining attempt if method -> target access is not right.
- if (!inliner.hasInliningAccess(method, singleTarget)) {
+ if (resolutionResult.isAccessibleFrom(method, appView.appInfo()).isPossiblyFalse()) {
whyAreYouNotInliningReporter.reportInaccessible();
return false;
}
@@ -254,6 +256,7 @@
@Override
public InlineAction computeInlining(
InvokeMethod invoke,
+ SingleResolutionResult resolutionResult,
ProgramMethod singleTarget,
ProgramMethod context,
ClassInitializationAnalysis classInitializationAnalysis,
@@ -277,7 +280,8 @@
return null;
}
- if (!passesInliningConstraints(invoke, singleTarget, reason, whyAreYouNotInliningReporter)) {
+ if (!passesInliningConstraints(
+ invoke, resolutionResult, singleTarget, reason, whyAreYouNotInliningReporter)) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ForcedInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/ForcedInliningOracle.java
index a48dece..eea6b7c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ForcedInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ForcedInliningOracle.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
@@ -42,6 +43,7 @@
@Override
public boolean passesInliningConstraints(
InvokeMethod invoke,
+ SingleResolutionResult resolutionResult,
ProgramMethod candidate,
Reason reason,
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
@@ -60,15 +62,18 @@
@Override
public InlineAction computeInlining(
InvokeMethod invoke,
+ SingleResolutionResult resolutionResult,
ProgramMethod singleTarget,
ProgramMethod context,
ClassInitializationAnalysis classInitializationAnalysis,
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
- return computeForInvoke(invoke, whyAreYouNotInliningReporter);
+ return computeForInvoke(invoke, resolutionResult, whyAreYouNotInliningReporter);
}
private InlineAction computeForInvoke(
- InvokeMethod invoke, WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
+ InvokeMethod invoke,
+ SingleResolutionResult resolutionResult,
+ WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
Inliner.InliningInfo info = invokesToInline.get(invoke);
if (info == null) {
return null;
@@ -80,7 +85,7 @@
// with neverInline() flag.
assert !info.target.getDefinition().getOptimizationInfo().neverInline();
assert passesInliningConstraints(
- invoke, info.target, Reason.FORCE, whyAreYouNotInliningReporter);
+ invoke, resolutionResult, info.target, Reason.FORCE, whyAreYouNotInliningReporter);
return new InlineAction(info.target, invoke, Reason.FORCE);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 2589e6a..17cea8b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.NestMemberClassAttribute;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.proto.ProtoInliningReasonStrategy;
import com.android.tools.r8.ir.analysis.type.Nullability;
@@ -199,29 +200,6 @@
return false;
}
- boolean hasInliningAccess(ProgramMethod context, ProgramMethod target) {
- if (!isVisibleWithFlags(target.getHolderType(), context, target.getDefinition().accessFlags)) {
- return false;
- }
- // The class needs also to be visible for us to have access.
- return isVisibleWithFlags(target.getHolderType(), context, target.getHolder().accessFlags);
- }
-
- private boolean isVisibleWithFlags(DexType target, ProgramMethod context, AccessFlags<?> flags) {
- if (flags.isPublic()) {
- return true;
- }
- if (flags.isPrivate()) {
- return NestUtils.sameNest(target, context.getHolderType(), appView);
- }
- if (flags.isProtected()) {
- return appView.appInfo().isSubtype(context.getHolderType(), target)
- || target.isSamePackage(context.getHolderType());
- }
- // package-private
- return target.isSamePackage(context.getHolderType());
- }
-
public synchronized boolean isDoubleInlineSelectedTarget(ProgramMethod method) {
return doubleInlineSelectedTargets.contains(method);
}
@@ -975,6 +953,17 @@
if (current.isInvokeMethod()) {
InvokeMethod invoke = current.asInvokeMethod();
// TODO(b/142116551): This should be equivalent to invoke.lookupSingleTarget()!
+
+ SingleResolutionResult resolutionResult =
+ appView
+ .appInfo()
+ .resolveMethod(invoke.getInvokedMethod(), invoke.getInterfaceBit())
+ .asSingleResolution();
+ if (resolutionResult == null) {
+ continue;
+ }
+
+ // TODO(b/156853206): Should not duplicate resolution.
ProgramMethod singleTarget = oracle.lookupSingleTarget(invoke, context);
if (singleTarget == null) {
WhyAreYouNotInliningReporter.handleInvokeWithUnknownTarget(invoke, appView, context);
@@ -989,6 +978,7 @@
InlineAction action =
oracle.computeInlining(
invoke,
+ resolutionResult,
singleTarget,
context,
classInitializationAnalysis,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
index a9e4736..5518ab7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.ir.optimize;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.optimize.Inliner.InlineAction;
@@ -23,12 +24,14 @@
boolean passesInliningConstraints(
InvokeMethod invoke,
+ SingleResolutionResult resolutionResult,
ProgramMethod candidate,
Reason reason,
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter);
InlineAction computeInlining(
InvokeMethod invoke,
+ SingleResolutionResult resolutionResult,
ProgramMethod singleTarget,
ProgramMethod context,
ClassInitializationAnalysis classInitializationAnalysis,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/NestUtils.java b/src/main/java/com/android/tools/r8/ir/optimize/NestUtils.java
index 3cd05c5..9db947a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/NestUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/NestUtils.java
@@ -57,7 +57,7 @@
assert encodedMethod.isPrivateMethod();
// Call to private method which has now to be interface/virtual
// (Now call to nest member private method).
- if (invoke.isInterface()) {
+ if (invoke.getInterfaceBit()) {
iterator.replaceCurrentInstruction(
new InvokeInterface(method, invoke.outValue(), invoke.inValues()));
} else {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index 1355477..da8c4cc 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -19,6 +19,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
@@ -282,6 +283,16 @@
if (user.isInvokeMethod()) {
InvokeMethod invokeMethod = user.asInvokeMethod();
+ SingleResolutionResult resolutionResult =
+ appView
+ .appInfo()
+ .resolveMethod(invokeMethod.getInvokedMethod(), invokeMethod.getInterfaceBit())
+ .asSingleResolution();
+ if (resolutionResult == null) {
+ return user; // Not eligible.
+ }
+
+ // TODO(b/156853206): Avoid duplicating resolution.
DexEncodedMethod singleTargetMethod = invokeMethod.lookupSingleTarget(appView, method);
if (singleTargetMethod == null) {
return user; // Not eligible.
@@ -321,7 +332,7 @@
InvokeMethodWithReceiver invoke = user.asInvokeMethodWithReceiver();
InliningInfo inliningInfo =
isEligibleDirectVirtualMethodCall(
- invoke, singleTarget, indirectUsers, defaultOracle);
+ invoke, resolutionResult, singleTarget, indirectUsers, defaultOracle);
if (inliningInfo != null) {
methodCallsOnInstance.put(invoke, inliningInfo);
continue;
@@ -879,6 +890,7 @@
private InliningInfo isEligibleDirectVirtualMethodCall(
InvokeMethodWithReceiver invoke,
+ SingleResolutionResult resolutionResult,
ProgramMethod singleTarget,
Set<Instruction> indirectUsers,
Supplier<InliningOracle> defaultOracle) {
@@ -896,7 +908,11 @@
if (singleTarget.getDefinition().isLibraryMethodOverride().isTrue()) {
InliningOracle inliningOracle = defaultOracle.get();
if (!inliningOracle.passesInliningConstraints(
- invoke, singleTarget, Reason.SIMPLE, NopWhyAreYouNotInliningReporter.getInstance())) {
+ invoke,
+ resolutionResult,
+ singleTarget,
+ Reason.SIMPLE,
+ NopWhyAreYouNotInliningReporter.getInstance())) {
return null;
}
}
@@ -920,13 +936,16 @@
Pair<Type, DexMethod> invokeInfo = eligibility.callsReceiver.get(0);
Type invokeType = invokeInfo.getFirst();
DexMethod indirectlyInvokedMethod = invokeInfo.getSecond();
- ResolutionResult resolutionResult =
- appView.appInfo().resolveMethodOn(eligibleClass, indirectlyInvokedMethod);
- if (!resolutionResult.isSingleResolution()) {
+ SingleResolutionResult indirectResolutionResult =
+ appView
+ .appInfo()
+ .resolveMethodOn(eligibleClass, indirectlyInvokedMethod)
+ .asSingleResolution();
+ if (indirectResolutionResult == null) {
return null;
}
ProgramMethod indirectSingleTarget =
- resolutionResult.asSingleResolution().getResolutionPair().asProgramMethod();
+ indirectResolutionResult.getResolutionPair().asProgramMethod();
if (!isEligibleIndirectVirtualMethodCall(
indirectlyInvokedMethod, invokeType, indirectSingleTarget)) {
return null;
@@ -1195,24 +1214,28 @@
return false;
}
+ SingleResolutionResult resolutionResult =
+ appView
+ .appInfo()
+ .resolveMethod(invoke.getInvokedMethod(), invoke.getInterfaceBit())
+ .asSingleResolution();
+ if (resolutionResult == null) {
+ return false;
+ }
+
// Check if the method is inline-able by standard inliner.
- DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, method);
+ // TODO(b/156853206): Should not duplicate resolution.
+ ProgramMethod singleTarget = invoke.lookupSingleProgramTarget(appView, method);
if (singleTarget == null) {
return false;
}
- DexProgramClass holder = asProgramClassOrNull(appView.definitionForHolder(singleTarget));
- if (holder == null) {
- return false;
- }
-
- ProgramMethod singleTargetMethod = new ProgramMethod(holder, singleTarget);
-
InliningOracle oracle = defaultOracle.get();
InlineAction inlineAction =
oracle.computeInlining(
invoke,
- singleTargetMethod,
+ resolutionResult,
+ singleTarget,
method,
ClassInitializationAnalysis.trivial(),
NopWhyAreYouNotInliningReporter.getInstance());