| // 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.debuginfo; |
| |
| import static org.junit.Assert.assertEquals; |
| |
| import com.android.tools.r8.CompilationFailedException; |
| import com.android.tools.r8.CompilationMode; |
| import com.android.tools.r8.D8; |
| import com.android.tools.r8.D8Command; |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.utils.AndroidApp; |
| import com.android.tools.r8.utils.AndroidAppConsumers; |
| import com.android.tools.r8.utils.StringUtils; |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.concurrent.ExecutionException; |
| import org.junit.Test; |
| |
| public class SynchronizedMethodTestRunner extends DebugInfoTestBase { |
| |
| static Class clazz = SynchronizedMethodTest.class; |
| |
| @Test |
| public void testSynchronizedMethod() throws Exception { |
| AndroidApp d8App = compileWithD8(clazz); |
| AndroidApp dxApp = getDxCompiledSources(); |
| |
| String expected = StringUtils.lines("42", "42", "2", "2"); |
| assertEquals(expected, runOnJava(clazz)); |
| assertEquals(expected, runOnArt(d8App, clazz.getCanonicalName())); |
| assertEquals(expected, runOnArt(dxApp, clazz.getCanonicalName())); |
| |
| checkSyncStatic(inspectMethod(d8App, clazz, "int", "syncStatic", "int")); |
| checkSyncStatic(inspectMethod(dxApp, clazz, "int", "syncStatic", "int")); |
| |
| checkSyncInstance(inspectMethod(d8App, clazz, "int", "syncInstance", "int")); |
| checkSyncInstance(inspectMethod(dxApp, clazz, "int", "syncInstance", "int")); |
| |
| checkThrowing(inspectMethod(d8App, clazz, "int", "throwing", "int"), false); |
| checkThrowing(inspectMethod(dxApp, clazz, "int", "throwing", "int"), true); |
| |
| checkMonitorExitRegression( |
| inspectMethod(d8App, clazz, "int", "monitorExitRegression", "int"), false); |
| checkMonitorExitRegression( |
| inspectMethod(dxApp, clazz, "int", "monitorExitRegression", "int"), true); |
| } |
| |
| private void checkSyncStatic(DebugInfoInspector info) { |
| info.checkStartLine(9); |
| info.checkLineHasExactLocals(9, "x", "int"); |
| info.checkLineHasExactLocals(10, "x", "int"); |
| info.checkNoLine(11); |
| info.checkLineHasExactLocals(12, "x", "int"); |
| info.checkNoLine(13); |
| } |
| |
| private void checkSyncInstance(DebugInfoInspector info) { |
| String[] locals = {"this", clazz.getCanonicalName(), "x", "int"}; |
| info.checkStartLine(16); |
| info.checkLineHasExactLocals(16, locals); |
| info.checkLineHasExactLocals(17, locals); |
| info.checkNoLine(18); |
| info.checkLineHasExactLocals(19, locals); |
| info.checkNoLine(20); |
| } |
| |
| private void checkThrowing(DebugInfoInspector info, boolean dx) { |
| info.checkStartLine(23); |
| if (!dx) { |
| info.checkLineHasExactLocals(23, "cond", "int"); |
| } |
| info.checkLineHasExactLocals(24, "cond", "int", "x", "int"); |
| info.checkLineHasExactLocals(25, "cond", "int", "x", "int"); |
| info.checkNoLine(26); |
| info.checkLineHasExactLocals(27, "cond", "int", "x", "int"); |
| } |
| |
| private void checkMonitorExitRegression(DebugInfoInspector info, boolean dx) { |
| info.checkStartLine(31); |
| for (int line : Arrays.asList(32, 34, 36, 38, 40, 42, 44, 48, 50, 52)) { |
| if (dx && line == 40) { |
| continue; |
| } |
| info.checkLineHasExactLocals(line, "cond", "int", "x", "int"); |
| } |
| } |
| |
| @Test |
| public void testMonitorExitLineInRelease() |
| throws CompilationFailedException, IOException, ExecutionException { |
| AndroidAppConsumers sink = new AndroidAppConsumers(); |
| D8.run(D8Command.builder() |
| .addProgramFiles(ToolHelper.getClassFileForTestClass(clazz)) |
| .setMode(CompilationMode.RELEASE) |
| .setProgramConsumer(sink.wrapDexIndexedConsumer(null)) |
| .build()); |
| AndroidApp app = sink.build(); |
| DebugInfoInspector inspector = inspectMethod(app, clazz, "int", "syncStatic", "int"); |
| // The first line of syncStatic is 9 and thus the synthetic exit for the exceptional case will |
| // have line number 8. In a release build we want to ensure that the synthetic exit does not |
| // have an associated line. |
| inspector.checkStartLine(9); |
| inspector.checkNoLine(8); |
| // Also ensure we did not emit a preamble position at line zero. |
| inspector.checkNoLine(0); |
| } |
| } |