| // Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| package com.android.tools.r8.ir.code; | |
| import com.android.tools.r8.cf.code.CfInvoke; | |
| import com.android.tools.r8.dex.code.DexInstruction; | |
| import com.android.tools.r8.dex.code.DexInvokeSuper; | |
| import com.android.tools.r8.dex.code.DexInvokeSuperRange; | |
| import com.android.tools.r8.graph.AppView; | |
| import com.android.tools.r8.graph.DexClassAndMethod; | |
| 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.UseRegistry; | |
| import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis; | |
| import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption; | |
| import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query; | |
| import com.android.tools.r8.ir.analysis.type.DynamicType; | |
| import com.android.tools.r8.ir.conversion.CfBuilder; | |
| import com.android.tools.r8.ir.conversion.DexBuilder; | |
| import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget; | |
| import com.android.tools.r8.ir.optimize.InliningConstraints; | |
| import com.android.tools.r8.lightir.LirBuilder; | |
| import com.android.tools.r8.shaking.AppInfoWithLiveness; | |
| import java.util.List; | |
| public class InvokeSuper extends InvokeMethodWithReceiver { | |
| // TODO(b/145775365): The interface bit should never be needed once invoke special is in the IR. | |
| public final boolean isInterface; | |
| public InvokeSuper(DexMethod target, Value result, List<Value> arguments, boolean isInterface) { | |
| super(target, result, arguments); | |
| this.isInterface = isInterface; | |
| } | |
| @Override | |
| public boolean getInterfaceBit() { | |
| return isInterface; | |
| } | |
| @Override | |
| public int opcode() { | |
| return Opcodes.INVOKE_SUPER; | |
| } | |
| @Override | |
| public <T> T accept(InstructionVisitor<T> visitor) { | |
| return visitor.visit(this); | |
| } | |
| @Override | |
| public InvokeType getType() { | |
| return InvokeType.SUPER; | |
| } | |
| @Override | |
| protected String getTypeString() { | |
| return "Super"; | |
| } | |
| @Override | |
| public void buildDex(DexBuilder builder) { | |
| DexInstruction instruction; | |
| int argumentRegisters = requiredArgumentRegisters(); | |
| builder.requestOutgoingRegisters(argumentRegisters); | |
| if (needsRangedInvoke(builder)) { | |
| assert argumentsConsecutive(builder); | |
| int firstRegister = argumentRegisterValue(0, builder); | |
| instruction = new DexInvokeSuperRange(firstRegister, argumentRegisters, getInvokedMethod()); | |
| } else { | |
| int[] individualArgumentRegisters = new int[5]; | |
| int argumentRegistersCount = fillArgumentRegisters(builder, individualArgumentRegisters); | |
| instruction = | |
| new DexInvokeSuper( | |
| argumentRegistersCount, | |
| getInvokedMethod(), | |
| individualArgumentRegisters[0], // C | |
| individualArgumentRegisters[1], // D | |
| individualArgumentRegisters[2], // E | |
| individualArgumentRegisters[3], // F | |
| individualArgumentRegisters[4]); // G | |
| } | |
| addInvokeAndMoveResult(instruction, builder); | |
| } | |
| @Override | |
| public void buildCf(CfBuilder builder) { | |
| builder.add( | |
| new CfInvoke(org.objectweb.asm.Opcodes.INVOKESPECIAL, getInvokedMethod(), isInterface), | |
| this); | |
| } | |
| @Override | |
| public boolean identicalNonValueNonPositionParts(Instruction other) { | |
| return other.isInvokeSuper() && super.identicalNonValueNonPositionParts(other); | |
| } | |
| @Override | |
| public boolean isInvokeSuper() { | |
| return true; | |
| } | |
| @Override | |
| public InvokeSuper asInvokeSuper() { | |
| return this; | |
| } | |
| @Override | |
| public DexClassAndMethod lookupSingleTarget( | |
| AppView<?> appView, ProgramMethod context, DynamicType dynamicReceiverType) { | |
| if (appView.appInfo().hasLiveness() && context != null) { | |
| AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness(); | |
| AppInfoWithLiveness appInfo = appViewWithLiveness.appInfo(); | |
| if (appInfo.isSubtype(context.getHolderType(), getInvokedMethod().holder)) { | |
| return appInfo.lookupSuperTarget(getInvokedMethod(), context, appViewWithLiveness); | |
| } | |
| } | |
| return null; | |
| } | |
| @Override | |
| public ConstraintWithTarget inliningConstraint( | |
| InliningConstraints inliningConstraints, ProgramMethod context) { | |
| return inliningConstraints.forInvokeSuper(getInvokedMethod(), context); | |
| } | |
| @Override | |
| public boolean definitelyTriggersClassInitialization( | |
| DexType clazz, | |
| ProgramMethod context, | |
| AppView<AppInfoWithLiveness> appView, | |
| Query mode, | |
| AnalysisAssumption assumption) { | |
| return ClassInitializationAnalysis.InstructionUtils.forInvokeSuper( | |
| this, clazz, context, appView, mode, assumption); | |
| } | |
| @Override | |
| void internalRegisterUse(UseRegistry<?> registry, DexClassAndMethod context) { | |
| registry.registerInvokeSuper(getInvokedMethod()); | |
| } | |
| @Override | |
| public void buildLir(LirBuilder<Value, ?> builder) { | |
| builder.addInvokeSuper(getInvokedMethod(), arguments(), isInterface); | |
| } | |
| } |