blob: f731e39a0389e9a1b3c9c79cba3790acebf31061 [file] [log] [blame]
// Copyright (c) 2016, 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.graph;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import com.android.tools.r8.smali.SmaliTestBase;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
public class TargetLookupTest extends SmaliTestBase {
@Test
public void lookupDirect() {
SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
builder.addDefaultConstructor();
builder.addMethodRaw(
" .method private static x()I",
" .locals 1",
" const v0, 0",
" return v0",
" .end method"
);
// Instance method invoking static method using invoke-direct. This does not run on Art, but
// results in an IncompatibleClassChangeError.
builder.addMethodRaw(
" .method public y()I",
" .locals 1",
" invoke-direct {p0}, " + builder.getCurrentClassDescriptor() + "->x()I",
" move-result v0",
" return v0",
" .end method"
);
builder.addMainMethod(
2,
" sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
" new-instance v1, LTest;",
" invoke-direct {v1}, " + builder.getCurrentClassDescriptor() + "-><init>()V",
" :try_start",
" invoke-virtual {v1}, " + builder.getCurrentClassDescriptor() + "->y()I",
" :try_end",
" const-string v1, \"ERROR\"",
" invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(Ljava/lang/String;)V",
" :return",
" return-void",
" .catch Ljava/lang/IncompatibleClassChangeError; {:try_start .. :try_end} :catch",
" :catch",
" const-string v1, \"OK\"",
" invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(Ljava/lang/String;)V",
" goto :return"
);
DexApplication application = buildApplication(builder);
AppInfo appInfo = new AppInfo(application);
DexEncodedMethod method =
getMethod(application, DEFAULT_CLASS_NAME, "int", "x", ImmutableList.of());
assertNull(appInfo.lookupVirtualTarget(method.method.holder, method.method));
assertNull(appInfo.lookupDirectTarget(method.method));
assertNotNull(appInfo.lookupStaticTarget(method.method));
assertEquals("OK", runArt(application, new InternalOptions()));
}
@Test
public void lookupDirectSuper() {
SmaliBuilder builder = new SmaliBuilder("TestSuper");
builder.addDefaultConstructor();
builder.addMethodRaw(
" .method private static x()I",
" .locals 1",
" const v0, 0",
" return v0",
" .end method"
);
builder.addClass("Test", "TestSuper");
builder.addDefaultConstructor();
// Instance method invoking static method in superclass using invoke-direct. This does not run
// on Art, but results in an IncompatibleClassChangeError.
builder.addMethodRaw(
" .method public y()I",
" .locals 1",
" invoke-direct {p0}, " + builder.getCurrentClassDescriptor() + "->x()I",
" move-result v0",
" return v0",
" .end method"
);
builder.addMainMethod(
2,
" sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
" new-instance v1, LTest;",
" invoke-direct {v1}, " + builder.getCurrentClassDescriptor() + "-><init>()V",
" :try_start",
" invoke-virtual {v1}, " + builder.getCurrentClassDescriptor() + "->y()I",
" :try_end",
" const-string v1, \"ERROR\"",
" invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(Ljava/lang/String;)V",
" :return",
" return-void",
" .catch Ljava/lang/IncompatibleClassChangeError; {:try_start .. :try_end} :catch",
" :catch",
" const-string v1, \"OK\"",
" invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(Ljava/lang/String;)V",
" goto :return"
);
DexApplication application = buildApplication(builder);
AppInfo appInfo = new AppInfo(application);
DexMethod methodXOnTestSuper =
getMethod(application, "TestSuper", "int", "x", ImmutableList.of()).method;
DexMethod methodYOnTest =
getMethod(application, "Test", "int", "y", ImmutableList.of()).method;
DexType classTestSuper = methodXOnTestSuper.getHolder();
DexType classTest = methodYOnTest.getHolder();
DexProto methodXProto = methodXOnTestSuper.proto;
DexString methodXName = methodXOnTestSuper.name;
DexMethod methodXOnTest =
application.dexItemFactory.createMethod(classTest, methodXProto, methodXName);
assertNull(appInfo.lookupVirtualTarget(classTestSuper, methodXOnTestSuper));
assertNull(appInfo.lookupVirtualTarget(classTest, methodXOnTestSuper));
assertNull(appInfo.lookupVirtualTarget(classTest, methodXOnTest));
assertNull(appInfo.lookupDirectTarget(methodXOnTestSuper));
assertNull(appInfo.lookupDirectTarget(methodXOnTest));
assertNotNull(appInfo.lookupStaticTarget(methodXOnTestSuper));
assertNotNull(appInfo.lookupStaticTarget(methodXOnTest));
assertEquals("OK", runArt(application, new InternalOptions()));
}
}