Merge "Allow synthetic methods in the root set"
diff --git a/src/cf_segments/java/com/android/tools/r8/cf_segments/Metrics.java b/src/cf_segments/java/com/android/tools/r8/cf_segments/Metrics.java
index 1336c65..57786e1 100644
--- a/src/cf_segments/java/com/android/tools/r8/cf_segments/Metrics.java
+++ b/src/cf_segments/java/com/android/tools/r8/cf_segments/Metrics.java
@@ -65,8 +65,8 @@
public final SegmentInfo methodInfo = new SegmentInfo("Method");
public final SegmentInfo size = new SegmentInfo("Size").increment(1, 0);
public final SegmentInfo stores = new SegmentInfo("Stores", false);
- public final SegmentInfo stackMapTable = new SegmentInfo("StackmapTable");
- public final SegmentInfo stackmapTableOtherEntries = new SegmentInfo("StackmapTableOtherEntries");
+ public final SegmentInfo stackMapTable = new SegmentInfo("StackMapTable");
+ public final SegmentInfo stackmapTableOtherEntries = new SegmentInfo("StackMapTableOtherEntries");
public final SegmentInfo stackMapTableFullFrameEntries = new SegmentInfo("StackMapFullFrame");
public List<SegmentInfo> asList() {
@@ -106,7 +106,7 @@
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
- asList().forEach(s -> builder.append(s.name + "\t" + s.size + "\t" + s.items + "\n"));
+ asList().forEach(s -> builder.append("- " + s.name + ": " + s.size + " / " + s.items + "\n"));
return builder.toString();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index a453346..170c39e 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -2536,11 +2536,8 @@
// Values live at entry to a block that is an exceptional successor are only live
// until the throwing instruction in this block. They are live until the end of
// the block only if they are used in normal flow as well.
- // TODO(b/119771771): This makes the bootstrap test fail for the CF backend with what
- // looks like inconsistent stack maps. It is safe to not do this, but we should
- // double check if that is what we want.
boolean isExceptionalSuccessor = exceptionalSuccessors.contains(successor);
- if (isExceptionalSuccessor && options.isGeneratingDex()) {
+ if (isExceptionalSuccessor) {
liveAtThrowingInstruction.addAll(liveAtEntrySets.get(successor).liveValues);
} else {
live.addAll(liveAtEntrySets.get(successor).liveValues);
diff --git a/src/test/java/com/android/tools/r8/debug/BreakOnIfTest.java b/src/test/java/com/android/tools/r8/debug/BreakOnIfTest.java
new file mode 100644
index 0000000..43338ee
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/BreakOnIfTest.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, 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.debug;
+
+public class BreakOnIfTest {
+
+ public static void main(String[] args) {
+ if (args == null) {
+ System.out.println("args null");
+ }
+ System.out.println("after if");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/BreakOnIfTestRunner.java b/src/test/java/com/android/tools/r8/debug/BreakOnIfTestRunner.java
new file mode 100644
index 0000000..e61d6f8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/BreakOnIfTestRunner.java
@@ -0,0 +1,47 @@
+// Copyright (c) 2019, 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.debug;
+
+import com.android.tools.r8.ToolHelper;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class BreakOnIfTestRunner extends DebugTestBase {
+
+ private static final Class CLASS = BreakOnIfTest.class;
+ private static final String FILE = CLASS.getSimpleName() + ".java";
+ private static final String NAME = CLASS.getCanonicalName();
+
+ private final DebugTestConfig config;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> setup() {
+ DelayedDebugTestConfig cf =
+ temp -> new CfDebugTestConfig().addPaths(ToolHelper.getClassPathForTests());
+ DelayedDebugTestConfig d8 =
+ temp -> new D8DebugTestConfig().compileAndAddClasses(temp, CLASS);
+ return ImmutableList.of(new Object[]{"CF", cf}, new Object[]{"D8", d8});
+ }
+
+ public BreakOnIfTestRunner(String name, DelayedDebugTestConfig config) {
+ this.config = config.getConfig(temp);
+ }
+
+ @Test
+ public void test() throws Throwable {
+ runDebugTest(
+ config,
+ NAME,
+ breakpoint(NAME, "main", 9),
+ run(),
+ checkLine(FILE, 9),
+ stepOver(),
+ checkLine(FILE, 12),
+ run());
+ }
+}
diff --git a/tools/golem_build.py b/tools/golem_build.py
index 30d46bc..5448589 100755
--- a/tools/golem_build.py
+++ b/tools/golem_build.py
@@ -10,7 +10,7 @@
GRADLE_ARGS = ['--no-daemon']
BUILD_TARGETS = ['R8', 'D8', 'R8LibApiOnly', 'buildExampleJars', 'CompatDx',
- 'downloadAndroidCts', 'downloadDx']
+ 'downloadAndroidCts', 'downloadDx', 'buildCfSegments']
def Main():
gradle.RunGradle(GRADLE_ARGS + BUILD_TARGETS)
diff --git a/tools/run_bootstrap_benchmark.py b/tools/run_bootstrap_benchmark.py
index 9f2f7e4..90834f8 100755
--- a/tools/run_bootstrap_benchmark.py
+++ b/tools/run_bootstrap_benchmark.py
@@ -12,8 +12,6 @@
import toolhelper
import utils
-PINNED_R8_JAR = os.path.join(utils.REPO_ROOT, 'third_party/r8/r8.jar')
-PINNED_PGR8_JAR = os.path.join(utils.REPO_ROOT, 'third_party/r8/r8-pg6.0.1.jar')
def parse_arguments(argv):
parser = argparse.ArgumentParser(
@@ -50,7 +48,7 @@
d8_pg_output = os.path.join(temp, 'd8pg.zip')
return_code = minify_tool.minify_tool(
- input_jar=PINNED_R8_JAR,
+ input_jar=utils.PINNED_R8_JAR,
output_jar=r8_output,
debug=False,
build=False,
@@ -63,8 +61,9 @@
print "BootstrapR8(CodeSize):", utils.uncompressed_size(r8_output)
print "BootstrapR8Dex(CodeSize):", utils.uncompressed_size(d8_r8_output)
- dex(PINNED_PGR8_JAR, d8_pg_output)
- print "BootstrapR8PG(CodeSize):", utils.uncompressed_size(PINNED_PGR8_JAR)
+ dex(utils.PINNED_PGR8_JAR, d8_pg_output)
+ print "BootstrapR8PG(CodeSize):", utils.uncompressed_size(
+ utils.PINNED_PGR8_JAR)
print "BootstrapR8PGDex(CodeSize):", utils.uncompressed_size(d8_pg_output)
sys.exit(0)
diff --git a/tools/test_framework.py b/tools/test_framework.py
index 6bc2f90..7400541 100755
--- a/tools/test_framework.py
+++ b/tools/test_framework.py
@@ -54,13 +54,13 @@
' <NAME>-<segment>(CodeSize): <bytes>), the full size is reported'
' with <NAME>-Total(CodeSize)')
parser.add_argument('--print-memoryuse',
- help = 'Prints the line \'<NAME>-Total(MemoryUse):' +
- ' <mem>\' at the end where <mem> is the peak' +
- ' peak resident set size (VmHWM) in bytes.',
+ help = 'Prints the line \'<NAME>-Total(MemoryUse):'
+ ' <mem>\' at the end where <mem> is the peak'
+ ' peak resident set size (VmHWM) in bytes.',
default = False,
action = 'store_true')
parser.add_argument('--output',
- help = 'Output directory to keep the generated files')
+ help = 'Output directory to keep the generated files')
return parser.parse_args()
def Main():
diff --git a/tools/test_r8cfsegments.py b/tools/test_r8cfsegments.py
new file mode 100755
index 0000000..d160b03
--- /dev/null
+++ b/tools/test_r8cfsegments.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+# Copyright (c) 2019, 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.
+
+# Run R8 or PG on 'third_party/r8/r8.jar'.
+# Report Golem-compatible CodeSize and RunTimeRaw values:
+#
+# <NAME>-Total(CodeSize): <size>
+# <NAME>-Total(RunTimeRaw>: <time> ms
+#
+# and also detailed segment sizes for each classfile segment:
+#
+# <NAME>-Code(CodeSize): <size>
+# <NAME>-AnnotationSets(CodeSize): <size>
+# ...
+#
+# Uses the R8CfSegments Java tool (Gradle target).
+
+from __future__ import print_function
+import argparse
+import golem
+import minify_tool
+import os
+import sys
+import utils
+
+def parse_arguments():
+ parser = argparse.ArgumentParser(
+ description = 'Run R8 or PG on'
+ ' third_party/r8/r8.jar.'
+ ' Report Golem-compatible CodeSize and RunTimeRaw values.')
+ parser.add_argument('--tool',
+ choices = ['pg', 'r8'],
+ required = True,
+ help = 'Compiler tool to use.')
+ parser.add_argument('--golem',
+ help = 'Running on golem, link in third_party resources.',
+ default = False,
+ action = 'store_true')
+ parser.add_argument('--name',
+ required = True,
+ help = 'Results will be printed using the specified benchmark name (e.g.'
+ ' <NAME>-<segment>(CodeSize): <bytes>), the full size is reported'
+ ' with <NAME>-Total(CodeSize)')
+ parser.add_argument('--print-memoryuse',
+ help = 'Prints the line \'<NAME>-Total(MemoryUse):'
+ ' <mem>\' at the end where <mem> is the peak'
+ ' peak resident set size (VmHWM) in bytes.',
+ default = False,
+ action = 'store_true')
+ parser.add_argument('--output',
+ help = 'Output directory to keep the generated files')
+ return parser.parse_args()
+
+
+def Main():
+ utils.check_java_version()
+ args = parse_arguments()
+ output_dir = args.output
+ if args.golem:
+ golem.link_third_party()
+ with utils.TempDir() as temp_dir:
+ if not output_dir:
+ output_dir = temp_dir
+ track_memory_file = None
+ if args.print_memoryuse:
+ track_memory_file = os.path.join(output_dir, utils.MEMORY_USE_TMP_FILE)
+ if args.tool == 'pg':
+ utils.print_cfsegments(args.name, [utils.PINNED_PGR8_JAR])
+ else:
+ out_file = os.path.join(output_dir, 'out.jar')
+ return_code = minify_tool.minify_tool(
+ input_jar=utils.PINNED_R8_JAR,
+ output_jar=out_file,
+ debug=False,
+ build=False,
+ track_memory_file=track_memory_file,
+ benchmark_name=args.name + "-Total")
+ if return_code != 0:
+ sys.exit(return_code)
+
+ utils.print_cfsegments(args.name, [out_file])
+
+
+if __name__ == '__main__':
+ sys.exit(Main())
diff --git a/tools/utils.py b/tools/utils.py
index ad85089..0f7aa96 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -53,7 +53,16 @@
GENERATED_LICENSE = os.path.join(GENERATED_LICENSE_DIR, 'LICENSE')
RT_JAR = os.path.join(REPO_ROOT, 'third_party/openjdk/openjdk-rt-1.8/rt.jar')
R8LIB_KEEP_RULES = os.path.join(REPO_ROOT, 'src/main/keep.txt')
-RETRACE_JAR = os.path.join(THIRD_PARTY, 'proguard', 'proguard6.0.1', 'lib', 'retrace.jar')
+RETRACE_JAR = os.path.join(
+ THIRD_PARTY,
+ 'proguard',
+ 'proguard6.0.1',
+ 'lib',
+ 'retrace.jar')
+CF_SEGMENTS_JAR = os.path.join(LIBS, 'cf_segments.jar')
+PINNED_R8_JAR = os.path.join(REPO_ROOT, 'third_party/r8/r8.jar')
+PINNED_PGR8_JAR = os.path.join(REPO_ROOT, 'third_party/r8/r8-pg6.0.1.jar')
+
# Common environment setup.
USER_HOME = os.path.expanduser('~')
@@ -372,9 +381,39 @@
return result
+# Return a dictionary: {segment_name -> segments_size}
+def getCfSegmentSizes(cfFile):
+ cmd = ['java',
+ '-cp',
+ CF_SEGMENTS_JAR,
+ 'com.android.tools.r8.cf_segments.MeasureLib',
+ cfFile]
+ PrintCmd(cmd)
+ output = subprocess.check_output(cmd)
+
+ matches = DEX_SEGMENTS_RESULT_PATTERN.findall(output)
+
+ if matches is None or len(matches) == 0:
+ raise Exception('CfSegments failed to return any output for' \
+ ' the file: ' + cfFile)
+
+ result = {}
+
+ for match in matches:
+ result[match[0]] = int(match[1])
+
+ return result
+
+
def get_maven_path(version):
return os.path.join('com', 'android', 'tools', 'r8', version)
+def print_cfsegments(prefix, cf_files):
+ for cf_file in cf_files:
+ for segment_name, size in getCfSegmentSizes(cf_file).items():
+ print('{}-{}(CodeSize): {}'
+ .format(prefix, segment_name, size))
+
def print_dexsegments(prefix, dex_files):
for segment_name, size in getDexSegmentSizes(dex_files).items():
print('{}-{}(CodeSize): {}'