diff options
author | Chengnian Sun <cnsun@google.com> | 2017-03-23 19:48:14 +0000 |
---|---|---|
committer | Yue Gan <yueg@google.com> | 2017-03-24 12:17:53 +0000 |
commit | 7bb3ba00d231399a4ffcbf2b22753eed1e249a30 (patch) | |
tree | c80e0591b341cef1968f0d900e97e83501a75cf6 /src/tools/android | |
parent | 18203b85c03b1ac35a7871c9a9d1794cc659a111 (diff) |
rewrite Long.compare(long, long) to JVM instruction lcmp, so that devices with
API level below 19 can still use Long.compare(long, long)
RELNOTES: n/a
--
PiperOrigin-RevId: 151040972
MOS_MIGRATED_REVID=151040972
Diffstat (limited to 'src/tools/android')
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java | 24 | ||||
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/desugar/LongCompareMethodRewriter.java | 58 | ||||
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/desugar/ObjectsRequireNonNullMethodRewriter.java (renamed from src/tools/android/java/com/google/devtools/build/android/desugar/ObjectsRequireNonNullMethodInliner.java) | 7 |
3 files changed, 80 insertions, 9 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java b/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java index 1711f57a99..7be39052bd 100644 --- a/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java +++ b/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java @@ -101,6 +101,14 @@ class Desugar { public boolean onlyDesugarJavac9ForLint; @Option( + name = "rewrite_calls_to_long_compare", + defaultValue = "true", + help = "rewrite calls to Long.compare(long, long) to the JVM instruction lcmp", + category = "misc" + ) + public boolean enableRewritingOfLongCompare; + + @Option( name = "output", allowMultiple = true, defaultValue = "", @@ -264,7 +272,10 @@ class Desugar { } if (!allowCallsToObjectsNonNull) { - visitor = new ObjectsRequireNonNullMethodInliner(visitor); + visitor = new ObjectsRequireNonNullMethodRewriter(visitor); + } + if (options.enableRewritingOfLongCompare) { + visitor = new LongCompareMethodRewriter(visitor); } reader.accept(visitor, 0); @@ -313,7 +324,10 @@ class Desugar { if (!allowCallsToObjectsNonNull) { // Not sure whether there will be implicit null check emitted by javac, so we rerun // the inliner again - visitor = new ObjectsRequireNonNullMethodInliner(visitor); + visitor = new ObjectsRequireNonNullMethodRewriter(visitor); + } + if (options.enableRewritingOfLongCompare) { + visitor = new LongCompareMethodRewriter(visitor); } reader.accept(visitor, 0); String filename = @@ -321,10 +335,10 @@ class Desugar { outputFileProvider.write(filename, writer.toByteArray()); } } - - Map<Path, LambdaInfo> leftBehind = lambdas.drain(); - checkState(leftBehind.isEmpty(), "Didn't process %s", leftBehind); } + + Map<Path, LambdaInfo> leftBehind = lambdas.drain(); + checkState(leftBehind.isEmpty(), "Didn't process %s", leftBehind); } } } diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/LongCompareMethodRewriter.java b/src/tools/android/java/com/google/devtools/build/android/desugar/LongCompareMethodRewriter.java new file mode 100644 index 0000000000..23d7a0d0b1 --- /dev/null +++ b/src/tools/android/java/com/google/devtools/build/android/desugar/LongCompareMethodRewriter.java @@ -0,0 +1,58 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.android.desugar; + +import static org.objectweb.asm.Opcodes.ASM5; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.LCMP; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; + +/** + * This class rewrites any call to Long.compare with the JVM instruction lcmp that is semantically + * equivalent to Long.compare. + */ +public class LongCompareMethodRewriter extends ClassVisitor { + + public LongCompareMethodRewriter(ClassVisitor cv) { + super(ASM5, cv); + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor visitor = super.cv.visitMethod(access, name, desc, signature, exceptions); + return visitor == null ? visitor : new LongCompareMethodVisitor(visitor); + } + + private static class LongCompareMethodVisitor extends MethodVisitor { + + public LongCompareMethodVisitor(MethodVisitor visitor) { + super(ASM5, visitor); + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { + if (opcode != INVOKESTATIC + || !owner.equals("java/lang/Long") + || !name.equals("compare") + || !desc.equals("(JJ)I")) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + super.visitInsn(LCMP); + } + } +} diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/ObjectsRequireNonNullMethodInliner.java b/src/tools/android/java/com/google/devtools/build/android/desugar/ObjectsRequireNonNullMethodRewriter.java index e56cfe1d1b..5ce0bee6a1 100644 --- a/src/tools/android/java/com/google/devtools/build/android/desugar/ObjectsRequireNonNullMethodInliner.java +++ b/src/tools/android/java/com/google/devtools/build/android/desugar/ObjectsRequireNonNullMethodRewriter.java @@ -25,12 +25,11 @@ import org.objectweb.asm.MethodVisitor; /** * This class desugars any call to Objects.requireNonNull(Object o), Objects.requireNonNull(Object * o, String msg), and Objects.requireNonNull(Object o, Supplier msg), by replacing the call with - * o.getClass(). Note that currently we discard the message, as inlining the message involves - * changes to the control flow graph, which further requires re-computation of the stack map frames. + * o.getClass(). */ -public class ObjectsRequireNonNullMethodInliner extends ClassVisitor { +public class ObjectsRequireNonNullMethodRewriter extends ClassVisitor { - public ObjectsRequireNonNullMethodInliner(ClassVisitor cv) { + public ObjectsRequireNonNullMethodRewriter(ClassVisitor cv) { super(ASM5, cv); } |