diff options
Diffstat (limited to 'test')
29 files changed, 2626 insertions, 502 deletions
diff --git a/test/004-ThreadStress/check b/test/004-ThreadStress/check index ffbb8cf17e..77e4cdbda0 100755 --- a/test/004-ThreadStress/check +++ b/test/004-ThreadStress/check @@ -14,5 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Only compare the last line. -tail -n 1 "$2" | diff --strip-trailing-cr -q "$1" - >/dev/null
\ No newline at end of file +# Do not compare numbers, so replace numbers with 'N'. +sed '-es/[0-9][0-9]*/N/g' "$2" | diff --strip-trailing-cr -q "$1" - >/dev/null
\ No newline at end of file diff --git a/test/004-ThreadStress/expected.txt b/test/004-ThreadStress/expected.txt index a26fb4f191..772faf6e9f 100644 --- a/test/004-ThreadStress/expected.txt +++ b/test/004-ThreadStress/expected.txt @@ -1 +1,11 @@ +JNI_OnLoad called +Starting worker for N +Starting worker for N +Starting worker for N +Starting worker for N +Starting worker for N +Finishing worker +Finishing worker +Finishing worker +Finishing worker Finishing worker diff --git a/test/004-ThreadStress/src/Main.java b/test/004-ThreadStress/src/Main.java index acd8e8b344..5cae3983bf 100644 --- a/test/004-ThreadStress/src/Main.java +++ b/test/004-ThreadStress/src/Main.java @@ -93,9 +93,7 @@ public class Main implements Runnable { killTemp = osClass.getDeclaredMethod("kill", int.class, int.class); } catch (Exception e) { - if (!e.getClass().getName().equals("ErrnoException")) { - e.printStackTrace(System.out); - } + Main.printThrowable(e); } pid = pidTemp; @@ -109,8 +107,8 @@ public class Main implements Runnable { kill.invoke(null, pid, sigquit); } catch (OutOfMemoryError e) { } catch (Exception e) { - if (!e.getClass().getName().equals("ErrnoException")) { - e.printStackTrace(System.out); + if (!e.getClass().getName().equals(Main.errnoExceptionName)) { + Main.printThrowable(e); } } return true; @@ -268,6 +266,7 @@ public class Main implements Runnable { } public static void main(String[] args) throws Exception { + System.loadLibrary(args[0]); parseAndRun(args); } @@ -399,12 +398,21 @@ public class Main implements Runnable { System.out.println(frequencyMap); } - runTest(numberOfThreads, numberOfDaemons, operationsPerThread, lock, frequencyMap); + try { + runTest(numberOfThreads, numberOfDaemons, operationsPerThread, lock, frequencyMap); + } catch (Throwable t) { + // In this case, the output should not contain all the required + // "Finishing worker" lines. + Main.printThrowable(t); + } } public static void runTest(final int numberOfThreads, final int numberOfDaemons, final int operationsPerThread, final Object lock, Map<Operation, Double> frequencyMap) throws Exception { + final Thread mainThread = Thread.currentThread(); + final Barrier startBarrier = new Barrier(numberOfThreads + numberOfDaemons + 1); + // Each normal thread is going to do operationsPerThread // operations. Each daemon thread will loop over all // the operations and will not stop. @@ -438,8 +446,9 @@ public class Main implements Runnable { } // Randomize the operation order Collections.shuffle(Arrays.asList(operations)); - threadStresses[t] = t < numberOfThreads ? new Main(lock, t, operations) : - new Daemon(lock, t, operations); + threadStresses[t] = (t < numberOfThreads) + ? new Main(lock, t, operations) + : new Daemon(lock, t, operations, mainThread, startBarrier); } // Enable to dump operation counts per thread to make sure its @@ -474,32 +483,41 @@ public class Main implements Runnable { runners[r] = new Thread("Runner thread " + r) { final Main threadStress = ts; public void run() { - int id = threadStress.id; - System.out.println("Starting worker for " + id); - while (threadStress.nextOperation < operationsPerThread) { - try { - Thread thread = new Thread(ts, "Worker thread " + id); - thread.start(); + try { + int id = threadStress.id; + // No memory hungry task are running yet, so println() should succeed. + System.out.println("Starting worker for " + id); + // Wait until all runners and daemons reach the starting point. + startBarrier.await(); + // Run the stress tasks. + while (threadStress.nextOperation < operationsPerThread) { try { + Thread thread = new Thread(ts, "Worker thread " + id); + thread.start(); thread.join(); - } catch (InterruptedException e) { - } - System.out.println("Thread exited for " + id + " with " - + (operationsPerThread - threadStress.nextOperation) - + " operations remaining."); - } catch (OutOfMemoryError e) { - // Ignore OOME since we need to print "Finishing worker" for the test - // to pass. - } - } - // Keep trying to print "Finishing worker" until it succeeds. - while (true) { - try { - System.out.println("Finishing worker"); - break; - } catch (OutOfMemoryError e) { + if (DEBUG) { + System.out.println( + "Thread exited for " + id + " with " + + (operationsPerThread - threadStress.nextOperation) + + " operations remaining."); + } + } catch (OutOfMemoryError e) { + // Ignore OOME since we need to print "Finishing worker" + // for the test to pass. This OOM can come from creating + // the Thread or from the DEBUG output. + // Note that the Thread creation may fail repeatedly, + // preventing the runner from making any progress, + // especially if the number of daemons is too high. + } } + // Print "Finishing worker" through JNI to avoid OOME. + Main.printString(Main.finishingWorkerMessage); + } catch (Throwable t) { + Main.printThrowable(t); + // Interrupt the main thread, so that it can orderly shut down + // instead of waiting indefinitely for some Barrier. + mainThread.interrupt(); } } }; @@ -532,6 +550,9 @@ public class Main implements Runnable { for (int r = 0; r < runners.length; r++) { runners[r].start(); } + // Wait for all threads to reach the starting point. + startBarrier.await(); + // Wait for runners to finish. for (int r = 0; r < runners.length; r++) { runners[r].join(); } @@ -574,8 +595,14 @@ public class Main implements Runnable { } private static class Daemon extends Main { - private Daemon(Object lock, int id, Operation[] operations) { + private Daemon(Object lock, + int id, + Operation[] operations, + Thread mainThread, + Barrier startBarrier) { super(lock, id, operations); + this.mainThread = mainThread; + this.startBarrier = startBarrier; } public void run() { @@ -583,26 +610,74 @@ public class Main implements Runnable { if (DEBUG) { System.out.println("Starting ThreadStress Daemon " + id); } - int i = 0; - while (true) { - Operation operation = operations[i]; - if (DEBUG) { - System.out.println("ThreadStress Daemon " + id - + " operation " + i - + " is " + operation); + startBarrier.await(); + try { + int i = 0; + while (true) { + Operation operation = operations[i]; + if (DEBUG) { + System.out.println("ThreadStress Daemon " + id + + " operation " + i + + " is " + operation); + } + operation.perform(); + i = (i + 1) % operations.length; } - operation.perform(); - i = (i + 1) % operations.length; + } catch (OutOfMemoryError e) { + // Catch OutOfMemoryErrors since these can cause the test to fail it they print + // the stack trace after "Finishing worker". Note that operations should catch + // their own OOME, this guards only agains OOME in the DEBUG output. } - } catch (OutOfMemoryError e) { - // Catch OutOfMemoryErrors since these can cause the test to fail it they print - // the stack trace after "Finishing worker". - } finally { if (DEBUG) { System.out.println("Finishing ThreadStress Daemon for " + id); } + } catch (Throwable t) { + Main.printThrowable(t); + // Interrupt the main thread, so that it can orderly shut down + // instead of waiting indefinitely for some Barrier. + mainThread.interrupt(); + } + } + + final Thread mainThread; + final Barrier startBarrier; + } + + // Note: java.util.concurrent.CyclicBarrier.await() allocates memory and may throw OOM. + // That is highly undesirable in this test, so we use our own simple barrier class. + // The only memory allocation that can happen here is the lock inflation which uses + // a native allocation. As such, it should succeed even if the Java heap is full. + // If the native allocation surprisingly fails, the program shall abort(). + private static class Barrier { + public Barrier(int initialCount) { + count = initialCount; + } + + public synchronized void await() throws InterruptedException { + --count; + if (count != 0) { + do { + wait(); + } while (count != 0); // Check for spurious wakeup. + } else { + notifyAll(); } } + + private int count; } + // Printing a String/Throwable through JNI requires only native memory and space + // in the local reference table, so it should succeed even if the Java heap is full. + private static native void printString(String s); + private static native void printThrowable(Throwable t); + + static final String finishingWorkerMessage; + static final String errnoExceptionName; + static { + // We pre-allocate the strings in class initializer to avoid const-string + // instructions in code using these strings later as they may throw OOME. + finishingWorkerMessage = "Finishing worker\n"; + errnoExceptionName = "ErrnoException"; + } } diff --git a/test/004-ThreadStress/thread_stress.cc b/test/004-ThreadStress/thread_stress.cc new file mode 100644 index 0000000000..573c352423 --- /dev/null +++ b/test/004-ThreadStress/thread_stress.cc @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +#include <iostream> + +#include "jni.h" +#include "mirror/string.h" +#include "mirror/throwable.h" +#include "scoped_thread_state_change.h" + +namespace art { + +extern "C" JNIEXPORT void JNICALL Java_Main_printString(JNIEnv*, jclass, jstring s) { + ScopedObjectAccess soa(Thread::Current()); + std::cout << soa.Decode<mirror::String*>(s)->ToModifiedUtf8(); +} + +extern "C" JNIEXPORT void JNICALL Java_Main_printThrowable(JNIEnv*, jclass, jthrowable t) { + ScopedObjectAccess soa(Thread::Current()); + std::cout << soa.Decode<mirror::Throwable*>(t)->Dump(); +} + +} // namespace art diff --git a/test/004-UnsafeTest/src/Main.java b/test/004-UnsafeTest/src/Main.java index b2f905e0ee..9d4618a07c 100644 --- a/test/004-UnsafeTest/src/Main.java +++ b/test/004-UnsafeTest/src/Main.java @@ -39,16 +39,24 @@ public class Main { } } - private static Unsafe getUnsafe() throws Exception { + private static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException { Class<?> unsafeClass = Unsafe.class; Field f = unsafeClass.getDeclaredField("theUnsafe"); f.setAccessible(true); return (Unsafe) f.get(null); } - public static void main(String[] args) throws Exception { + public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { System.loadLibrary(args[0]); Unsafe unsafe = getUnsafe(); + + testArrayBaseOffset(unsafe); + testArrayIndexScale(unsafe); + testGetAndPutAndCAS(unsafe); + testGetAndPutVolatile(unsafe); + } + + private static void testArrayBaseOffset(Unsafe unsafe) { check(unsafe.arrayBaseOffset(boolean[].class), vmArrayBaseOffset(boolean[].class), "Unsafe.arrayBaseOffset(boolean[])"); check(unsafe.arrayBaseOffset(byte[].class), vmArrayBaseOffset(byte[].class), @@ -65,7 +73,9 @@ public class Main { "Unsafe.arrayBaseOffset(long[])"); check(unsafe.arrayBaseOffset(Object[].class), vmArrayBaseOffset(Object[].class), "Unsafe.arrayBaseOffset(Object[])"); + } + private static void testArrayIndexScale(Unsafe unsafe) { check(unsafe.arrayIndexScale(boolean[].class), vmArrayIndexScale(boolean[].class), "Unsafe.arrayIndexScale(boolean[])"); check(unsafe.arrayIndexScale(byte[].class), vmArrayIndexScale(byte[].class), @@ -82,7 +92,9 @@ public class Main { "Unsafe.arrayIndexScale(long[])"); check(unsafe.arrayIndexScale(Object[].class), vmArrayIndexScale(Object[].class), "Unsafe.arrayIndexScale(Object[])"); + } + private static void testGetAndPutAndCAS(Unsafe unsafe) throws NoSuchFieldException { TestClass t = new TestClass(); int intValue = 12345678; @@ -185,12 +197,58 @@ public class Main { } } + private static void testGetAndPutVolatile(Unsafe unsafe) throws NoSuchFieldException { + TestVolatileClass tv = new TestVolatileClass(); + + int intValue = 12345678; + Field volatileIntField = TestVolatileClass.class.getDeclaredField("volatileIntVar"); + long volatileIntOffset = unsafe.objectFieldOffset(volatileIntField); + check(unsafe.getIntVolatile(tv, volatileIntOffset), + 0, + "Unsafe.getIntVolatile(Object, long) - initial"); + unsafe.putIntVolatile(tv, volatileIntOffset, intValue); + check(tv.volatileIntVar, intValue, "Unsafe.putIntVolatile(Object, long, int)"); + check(unsafe.getIntVolatile(tv, volatileIntOffset), + intValue, + "Unsafe.getIntVolatile(Object, long)"); + + long longValue = 1234567887654321L; + Field volatileLongField = TestVolatileClass.class.getDeclaredField("volatileLongVar"); + long volatileLongOffset = unsafe.objectFieldOffset(volatileLongField); + check(unsafe.getLongVolatile(tv, volatileLongOffset), + 0, + "Unsafe.getLongVolatile(Object, long) - initial"); + unsafe.putLongVolatile(tv, volatileLongOffset, longValue); + check(tv.volatileLongVar, longValue, "Unsafe.putLongVolatile(Object, long, long)"); + check(unsafe.getLongVolatile(tv, volatileLongOffset), + longValue, + "Unsafe.getLongVolatile(Object, long)"); + + Object objectValue = new Object(); + Field volatileObjectField = TestVolatileClass.class.getDeclaredField("volatileObjectVar"); + long volatileObjectOffset = unsafe.objectFieldOffset(volatileObjectField); + check(unsafe.getObjectVolatile(tv, volatileObjectOffset), + null, + "Unsafe.getObjectVolatile(Object, long) - initial"); + unsafe.putObjectVolatile(tv, volatileObjectOffset, objectValue); + check(tv.volatileObjectVar, objectValue, "Unsafe.putObjectVolatile(Object, long, Object)"); + check(unsafe.getObjectVolatile(tv, volatileObjectOffset), + objectValue, + "Unsafe.getObjectVolatile(Object, long)"); + } + private static class TestClass { public int intVar = 0; public long longVar = 0; public Object objectVar = null; } + private static class TestVolatileClass { + public volatile int volatileIntVar = 0; + public volatile long volatileLongVar = 0; + public volatile Object volatileObjectVar = null; + } + private static native int vmArrayBaseOffset(Class clazz); private static native int vmArrayIndexScale(Class clazz); } diff --git a/test/100-reflect2/expected.txt b/test/100-reflect2/expected.txt index d878e69aed..dd89d644a8 100644 --- a/test/100-reflect2/expected.txt +++ b/test/100-reflect2/expected.txt @@ -33,7 +33,7 @@ z (class java.lang.Character) 14 (class java.lang.Short) [java.lang.String(int,int,char[]), public java.lang.String(), public java.lang.String(byte[]), public java.lang.String(byte[],int), public java.lang.String(byte[],int,int), public java.lang.String(byte[],int,int,int), public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException, public java.lang.String(byte[],int,int,java.nio.charset.Charset), public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException, public java.lang.String(byte[],java.nio.charset.Charset), public java.lang.String(char[]), public java.lang.String(char[],int,int), public java.lang.String(int[],int,int), public java.lang.String(java.lang.String), public java.lang.String(java.lang.StringBuffer), public java.lang.String(java.lang.StringBuilder)] [private final int java.lang.String.count, private int java.lang.String.hash, private static final java.io.ObjectStreamField[] java.lang.String.serialPersistentFields, private static final long java.lang.String.serialVersionUID, public static final java.util.Comparator java.lang.String.CASE_INSENSITIVE_ORDER] -[native void java.lang.String.getCharsNoCheck(int,int,char[],int), native void java.lang.String.setCharAt(int,char), private int java.lang.String.indexOfSupplementary(int,int), private int java.lang.String.lastIndexOfSupplementary(int,int), private native int java.lang.String.fastIndexOf(int,int), private native java.lang.String java.lang.String.fastSubstring(int,int), public boolean java.lang.String.contains(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.StringBuffer), public boolean java.lang.String.endsWith(java.lang.String), public boolean java.lang.String.equals(java.lang.Object), public boolean java.lang.String.equalsIgnoreCase(java.lang.String), public boolean java.lang.String.isEmpty(), public boolean java.lang.String.matches(java.lang.String), public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int), public boolean java.lang.String.regionMatches(int,java.lang.String,int,int), public boolean java.lang.String.startsWith(java.lang.String), public boolean java.lang.String.startsWith(java.lang.String,int), public byte[] java.lang.String.getBytes(), public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException, public byte[] java.lang.String.getBytes(java.nio.charset.Charset), public int java.lang.String.codePointAt(int), public int java.lang.String.codePointBefore(int), public int java.lang.String.codePointCount(int,int), public int java.lang.String.compareTo(java.lang.Object), public int java.lang.String.compareToIgnoreCase(java.lang.String), public int java.lang.String.hashCode(), public int java.lang.String.indexOf(int), public int java.lang.String.indexOf(int,int), public int java.lang.String.indexOf(java.lang.String), public int java.lang.String.indexOf(java.lang.String,int), public int java.lang.String.lastIndexOf(int), public int java.lang.String.lastIndexOf(int,int), public int java.lang.String.lastIndexOf(java.lang.String), public int java.lang.String.lastIndexOf(java.lang.String,int), public int java.lang.String.length(), public int java.lang.String.offsetByCodePoints(int,int), public java.lang.CharSequence java.lang.String.subSequence(int,int), public java.lang.String java.lang.String.replace(char,char), public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence), public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String), public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String), public java.lang.String java.lang.String.substring(int), public java.lang.String java.lang.String.substring(int,int), public java.lang.String java.lang.String.toLowerCase(), public java.lang.String java.lang.String.toLowerCase(java.util.Locale), public java.lang.String java.lang.String.toString(), public java.lang.String java.lang.String.toUpperCase(), public java.lang.String java.lang.String.toUpperCase(java.util.Locale), public java.lang.String java.lang.String.trim(), public java.lang.String[] java.lang.String.split(java.lang.String), public java.lang.String[] java.lang.String.split(java.lang.String,int), public native char java.lang.String.charAt(int), public native char[] java.lang.String.toCharArray(), public native int java.lang.String.compareTo(java.lang.String), public native java.lang.String java.lang.String.concat(java.lang.String), public native java.lang.String java.lang.String.intern(), public static java.lang.String java.lang.String.copyValueOf(char[]), public static java.lang.String java.lang.String.copyValueOf(char[],int,int), public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[]), public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[]), public static java.lang.String java.lang.String.valueOf(boolean), public static java.lang.String java.lang.String.valueOf(char), public static java.lang.String java.lang.String.valueOf(char[]), public static java.lang.String java.lang.String.valueOf(char[],int,int), public static java.lang.String java.lang.String.valueOf(double), public static java.lang.String java.lang.String.valueOf(float), public static java.lang.String java.lang.String.valueOf(int), public static java.lang.String java.lang.String.valueOf(java.lang.Object), public static java.lang.String java.lang.String.valueOf(long), public void java.lang.String.getBytes(int,int,byte[],int), public void java.lang.String.getChars(int,int,char[],int), static int java.lang.String.indexOf(char[],int,int,char[],int,int,int), static int java.lang.String.indexOf(java.lang.String,java.lang.String,int), static int java.lang.String.lastIndexOf(char[],int,int,char[],int,int,int), static int java.lang.String.lastIndexOf(java.lang.String,java.lang.String,int)] +[native void java.lang.String.getCharsNoCheck(int,int,char[],int), native void java.lang.String.setCharAt(int,char), private boolean java.lang.String.nonSyncContentEquals(java.lang.AbstractStringBuilder), private int java.lang.String.indexOfSupplementary(int,int), private int java.lang.String.lastIndexOfSupplementary(int,int), private native int java.lang.String.fastIndexOf(int,int), private native java.lang.String java.lang.String.fastSubstring(int,int), public boolean java.lang.String.contains(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.CharSequence), public boolean java.lang.String.contentEquals(java.lang.StringBuffer), public boolean java.lang.String.endsWith(java.lang.String), public boolean java.lang.String.equals(java.lang.Object), public boolean java.lang.String.equalsIgnoreCase(java.lang.String), public boolean java.lang.String.isEmpty(), public boolean java.lang.String.matches(java.lang.String), public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int), public boolean java.lang.String.regionMatches(int,java.lang.String,int,int), public boolean java.lang.String.startsWith(java.lang.String), public boolean java.lang.String.startsWith(java.lang.String,int), public byte[] java.lang.String.getBytes(), public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException, public byte[] java.lang.String.getBytes(java.nio.charset.Charset), public int java.lang.String.codePointAt(int), public int java.lang.String.codePointBefore(int), public int java.lang.String.codePointCount(int,int), public int java.lang.String.compareTo(java.lang.Object), public int java.lang.String.compareToIgnoreCase(java.lang.String), public int java.lang.String.hashCode(), public int java.lang.String.indexOf(int), public int java.lang.String.indexOf(int,int), public int java.lang.String.indexOf(java.lang.String), public int java.lang.String.indexOf(java.lang.String,int), public int java.lang.String.lastIndexOf(int), public int java.lang.String.lastIndexOf(int,int), public int java.lang.String.lastIndexOf(java.lang.String), public int java.lang.String.lastIndexOf(java.lang.String,int), public int java.lang.String.length(), public int java.lang.String.offsetByCodePoints(int,int), public java.lang.CharSequence java.lang.String.subSequence(int,int), public java.lang.String java.lang.String.replace(char,char), public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence), public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String), public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String), public java.lang.String java.lang.String.substring(int), public java.lang.String java.lang.String.substring(int,int), public java.lang.String java.lang.String.toLowerCase(), public java.lang.String java.lang.String.toLowerCase(java.util.Locale), public java.lang.String java.lang.String.toString(), public java.lang.String java.lang.String.toUpperCase(), public java.lang.String java.lang.String.toUpperCase(java.util.Locale), public java.lang.String java.lang.String.trim(), public java.lang.String[] java.lang.String.split(java.lang.String), public java.lang.String[] java.lang.String.split(java.lang.String,int), public native char java.lang.String.charAt(int), public native char[] java.lang.String.toCharArray(), public native int java.lang.String.compareTo(java.lang.String), public native java.lang.String java.lang.String.concat(java.lang.String), public native java.lang.String java.lang.String.intern(), public static java.lang.String java.lang.String.copyValueOf(char[]), public static java.lang.String java.lang.String.copyValueOf(char[],int,int), public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[]), public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[]), public static java.lang.String java.lang.String.join(java.lang.CharSequence,java.lang.CharSequence[]), public static java.lang.String java.lang.String.join(java.lang.CharSequence,java.lang.Iterable), public static java.lang.String java.lang.String.valueOf(boolean), public static java.lang.String java.lang.String.valueOf(char), public static java.lang.String java.lang.String.valueOf(char[]), public static java.lang.String java.lang.String.valueOf(char[],int,int), public static java.lang.String java.lang.String.valueOf(double), public static java.lang.String java.lang.String.valueOf(float), public static java.lang.String java.lang.String.valueOf(int), public static java.lang.String java.lang.String.valueOf(java.lang.Object), public static java.lang.String java.lang.String.valueOf(long), public void java.lang.String.getBytes(int,int,byte[],int), public void java.lang.String.getChars(int,int,char[],int), static int java.lang.String.indexOf(char[],int,int,char[],int,int,int), static int java.lang.String.indexOf(java.lang.String,java.lang.String,int), static int java.lang.String.lastIndexOf(char[],int,int,char[],int,int,int), static int java.lang.String.lastIndexOf(java.lang.String,java.lang.String,int), void java.lang.String.getChars(char[],int)] [] [interface java.io.Serializable, interface java.lang.Comparable, interface java.lang.CharSequence] 0 diff --git a/test/201-built-in-exception-detail-messages/src/Main.java b/test/201-built-in-exception-detail-messages/src/Main.java index 52d4259330..f0bb6ddd4f 100644 --- a/test/201-built-in-exception-detail-messages/src/Main.java +++ b/test/201-built-in-exception-detail-messages/src/Main.java @@ -461,7 +461,7 @@ public class Main { "hello there".substring(9,14); fail(); } catch (StringIndexOutOfBoundsException ex) { - assertEquals("length=11; regionStart=9; regionLength=5", ex.getMessage()); + assertEquals("length=11; index=14", ex.getMessage()); } } } diff --git a/test/450-checker-types/src/Main.java b/test/450-checker-types/src/Main.java index 08b6cec35f..36f14d8779 100644 --- a/test/450-checker-types/src/Main.java +++ b/test/450-checker-types/src/Main.java @@ -30,6 +30,11 @@ class Super implements Interface { public void $noinline$f() { throw new RuntimeException(); } + + public int $inline$h(boolean cond) { + Super obj = (cond ? this : null); + return obj.hashCode(); + } } class SubclassA extends Super { @@ -620,6 +625,46 @@ public class Main { o.mainField = 0; } + /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (before) + /// CHECK-DAG: <<Arg:l\d+>> NewInstance + /// CHECK-DAG: InvokeVirtual [<<Arg>>,{{z\d+}}] method_name:Super.$inline$h + + /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (after) + /// CHECK-DAG: <<Arg:l\d+>> NewInstance + /// CHECK-DAG: <<Null:l\d+>> NullConstant + /// CHECK-DAG: <<Phi:l\d+>> Phi [<<Arg>>,<<Null>>] klass:SubclassA + /// CHECK-DAG: <<NCPhi:l\d+>> NullCheck [<<Phi>>] + /// CHECK-DAG: InvokeVirtual [<<NCPhi>>] method_name:Super.hashCode + + public void testThisArgumentMoreSpecific(boolean cond) { + // Inlining method from Super will build it with `this` typed as Super. + // Running RTP will sharpen it to SubclassA. + SubclassA obj = new SubclassA(); + ((Super) obj).$inline$h(cond); + } + + public static int $inline$hashCode(Super obj) { + return obj.hashCode(); + } + + /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (before) + /// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA + // Note: The ArtMethod* (typed as int or long) is optional after sharpening. + /// CHECK-DAG: InvokeStaticOrDirect [<<Arg>>{{(,[ij]\d+)?}}] method_name:Main.$inline$hashCode + + /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (after) + /// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA + /// CHECK-DAG: <<NCArg:l\d+>> NullCheck [<<Arg>>] klass:SubclassA + /// CHECK-DAG: InvokeVirtual [<<NCArg>>] method_name:Super.hashCode + + public void testExplicitArgumentMoreSpecific(SubclassA obj) { + // Inlining a method will build it with reference types from its signature, + // here the callee graph is built with Super as the type of its only argument. + // Running RTP after its ParameterValue instructions are replaced with actual + // arguments will type the inner graph more precisely. + $inline$hashCode(obj); + } + /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (before) /// CHECK: <<Int:i\d+>> IntConstant 0 /// CHECK: <<Phi:l\d+>> Phi klass:Main exact:false diff --git a/test/458-checker-instruction-simplification/smali/SmaliTests.smali b/test/458-checker-instruction-simplification/smali/SmaliTests.smali index ede599b213..6845961f39 100644 --- a/test/458-checker-instruction-simplification/smali/SmaliTests.smali +++ b/test/458-checker-instruction-simplification/smali/SmaliTests.smali @@ -191,3 +191,139 @@ .end method +## CHECK-START: int SmaliTests.AddSubConst(int) instruction_simplifier (before) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<Const7:i\d+>> IntConstant 7 +## CHECK-DAG: <<Const8:i\d+>> IntConstant 8 +## CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<Const7>>] +## CHECK-DAG: <<Sub:i\d+>> Sub [<<Add>>,<<Const8>>] +## CHECK-DAG: Return [<<Sub>>] + +## CHECK-START: int SmaliTests.AddSubConst(int) instruction_simplifier (after) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 +## CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<ConstM1>>] +## CHECK-DAG: Return [<<Add>>] + +.method public static AddSubConst(I)I + .registers 3 + + .prologue + add-int/lit8 v0, p0, 7 + + const/16 v1, 8 + + sub-int v0, v0, v1 + + return v0 +.end method + +## CHECK-START: int SmaliTests.SubAddConst(int) instruction_simplifier (before) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<Const3:i\d+>> IntConstant 3 +## CHECK-DAG: <<Const4:i\d+>> IntConstant 4 +## CHECK-DAG: <<Sub:i\d+>> Sub [<<ArgValue>>,<<Const3>>] +## CHECK-DAG: <<Add:i\d+>> Add [<<Sub>>,<<Const4>>] +## CHECK-DAG: Return [<<Add>>] + +## CHECK-START: int SmaliTests.SubAddConst(int) instruction_simplifier (after) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 +## CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<Const1>>] +## CHECK-DAG: Return [<<Add>>] + +.method public static SubAddConst(I)I + .registers 2 + + .prologue + const/4 v0, 3 + + sub-int v0, p0, v0 + + add-int/lit8 v0, v0, 4 + + return v0 +.end method + +## CHECK-START: int SmaliTests.SubSubConst1(int) instruction_simplifier (before) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<Const9:i\d+>> IntConstant 9 +## CHECK-DAG: <<Const10:i\d+>> IntConstant 10 +## CHECK-DAG: <<Sub1:i\d+>> Sub [<<ArgValue>>,<<Const9>>] +## CHECK-DAG: <<Sub2:i\d+>> Sub [<<Sub1>>,<<Const10>>] +## CHECK-DAG: Return [<<Sub2>>] + +## CHECK-START: int SmaliTests.SubSubConst1(int) instruction_simplifier (after) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<ConstM19:i\d+>> IntConstant -19 +## CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<ConstM19>>] +## CHECK-DAG: Return [<<Add>>] + +.method public static SubSubConst1(I)I + .registers 3 + + .prologue + const/16 v1, 9 + + sub-int v0, p0, v1 + + const/16 v1, 10 + + sub-int v0, v0, v1 + + return v0 +.end method + +## CHECK-START: int SmaliTests.SubSubConst2(int) instruction_simplifier (before) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<Const11:i\d+>> IntConstant 11 +## CHECK-DAG: <<Const12:i\d+>> IntConstant 12 +## CHECK-DAG: <<Sub1:i\d+>> Sub [<<Const11>>,<<ArgValue>>] +## CHECK-DAG: <<Sub2:i\d+>> Sub [<<Sub1>>,<<Const12>>] +## CHECK-DAG: Return [<<Sub2>>] + +## CHECK-START: int SmaliTests.SubSubConst2(int) instruction_simplifier (after) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 +## CHECK-DAG: <<Sub:i\d+>> Sub [<<ConstM1>>,<<ArgValue>>] +## CHECK-DAG: Return [<<Sub>>] + +.method public static SubSubConst2(I)I + .registers 3 + + .prologue + rsub-int/lit8 v0, p0, 11 + + const/16 v1, 12 + + sub-int v0, v0, v1 + + return v0 +.end method + +## CHECK-START: int SmaliTests.SubSubConst3(int) instruction_simplifier (before) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<Const15:i\d+>> IntConstant 15 +## CHECK-DAG: <<Const16:i\d+>> IntConstant 16 +## CHECK-DAG: <<Sub1:i\d+>> Sub [<<ArgValue>>,<<Const16>>] +## CHECK-DAG: <<Sub2:i\d+>> Sub [<<Const15>>,<<Sub1>>] +## CHECK-DAG: Return [<<Sub2>>] + +## CHECK-START: int SmaliTests.SubSubConst3(int) instruction_simplifier (after) +## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue +## CHECK-DAG: <<Const31:i\d+>> IntConstant 31 +## CHECK-DAG: <<Sub:i\d+>> Sub [<<Const31>>,<<ArgValue>>] +## CHECK-DAG: Return [<<Sub>>] + +.method public static SubSubConst3(I)I + .registers 2 + + .prologue + const/16 v0, 16 + + sub-int v0, p0, v0 + + rsub-int/lit8 v0, v0, 15 + + return v0 +.end method diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java index 53c2e0b820..c717eaa85e 100644 --- a/test/458-checker-instruction-simplification/src/Main.java +++ b/test/458-checker-instruction-simplification/src/Main.java @@ -18,6 +18,8 @@ import java.lang.reflect.Method; public class Main { + static boolean doThrow = false; + public static void assertBooleanEquals(boolean expected, boolean result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); @@ -58,41 +60,66 @@ public class Main { * Tiny programs exercising optimizations of arithmetic identities. */ - /// CHECK-START: long Main.Add0(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$Add0(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const0:j\d+>> LongConstant 0 /// CHECK-DAG: <<Add:j\d+>> Add [<<Const0>>,<<Arg>>] /// CHECK-DAG: Return [<<Add>>] - /// CHECK-START: long Main.Add0(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Add0(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.Add0(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Add0(long) instruction_simplifier (after) /// CHECK-NOT: Add - public static long Add0(long arg) { + public static long $noinline$Add0(long arg) { + if (doThrow) { throw new Error(); } return 0 + arg; } - /// CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$AddAddSubAddConst(int) instruction_simplifier (before) + /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue + /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 + /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 + /// CHECK-DAG: <<ConstM3:i\d+>> IntConstant -3 + /// CHECK-DAG: <<Const4:i\d+>> IntConstant 4 + /// CHECK-DAG: <<Add1:i\d+>> Add [<<ArgValue>>,<<Const1>>] + /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<Const2>>] + /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add2>>,<<ConstM3>>] + /// CHECK-DAG: <<Add4:i\d+>> Add [<<Add3>>,<<Const4>>] + /// CHECK-DAG: Return [<<Add4>>] + + /// CHECK-START: int Main.$noinline$AddAddSubAddConst(int) instruction_simplifier (after) + /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue + /// CHECK-DAG: <<Const4:i\d+>> IntConstant 4 + /// CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<Const4>>] + /// CHECK-DAG: Return [<<Add>>] + + public static int $noinline$AddAddSubAddConst(int arg) { + if (doThrow) { throw new Error(); } + return arg + 1 + 2 - 3 + 4; + } + + /// CHECK-START: int Main.$noinline$AndAllOnes(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<ConstF:i\d+>> IntConstant -1 /// CHECK-DAG: <<And:i\d+>> And [<<Arg>>,<<ConstF>>] /// CHECK-DAG: Return [<<And>>] - /// CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$AndAllOnes(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$AndAllOnes(int) instruction_simplifier (after) /// CHECK-NOT: And - public static int AndAllOnes(int arg) { + public static int $noinline$AndAllOnes(int arg) { + if (doThrow) { throw new Error(); } return arg & -1; } - /// CHECK-START: int Main.UShr28And15(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$UShr28And15(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const28:i\d+>> IntConstant 28 /// CHECK-DAG: <<Const15:i\d+>> IntConstant 15 @@ -100,20 +127,21 @@ public class Main { /// CHECK-DAG: <<And:i\d+>> And [<<UShr>>,<<Const15>>] /// CHECK-DAG: Return [<<And>>] - /// CHECK-START: int Main.UShr28And15(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$UShr28And15(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const28:i\d+>> IntConstant 28 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Arg>>,<<Const28>>] /// CHECK-DAG: Return [<<UShr>>] - /// CHECK-START: int Main.UShr28And15(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$UShr28And15(int) instruction_simplifier (after) /// CHECK-NOT: And - public static int UShr28And15(int arg) { + public static int $noinline$UShr28And15(int arg) { + if (doThrow) { throw new Error(); } return (arg >>> 28) & 15; } - /// CHECK-START: long Main.UShr60And15(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$UShr60And15(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const60:i\d+>> IntConstant 60 /// CHECK-DAG: <<Const15:j\d+>> LongConstant 15 @@ -121,20 +149,21 @@ public class Main { /// CHECK-DAG: <<And:j\d+>> And [<<UShr>>,<<Const15>>] /// CHECK-DAG: Return [<<And>>] - /// CHECK-START: long Main.UShr60And15(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$UShr60And15(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const60:i\d+>> IntConstant 60 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Arg>>,<<Const60>>] /// CHECK-DAG: Return [<<UShr>>] - /// CHECK-START: long Main.UShr60And15(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$UShr60And15(long) instruction_simplifier (after) /// CHECK-NOT: And - public static long UShr60And15(long arg) { + public static long $noinline$UShr60And15(long arg) { + if (doThrow) { throw new Error(); } return (arg >>> 60) & 15; } - /// CHECK-START: int Main.UShr28And7(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$UShr28And7(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const28:i\d+>> IntConstant 28 /// CHECK-DAG: <<Const7:i\d+>> IntConstant 7 @@ -142,7 +171,7 @@ public class Main { /// CHECK-DAG: <<And:i\d+>> And [<<UShr>>,<<Const7>>] /// CHECK-DAG: Return [<<And>>] - /// CHECK-START: int Main.UShr28And7(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$UShr28And7(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const28:i\d+>> IntConstant 28 /// CHECK-DAG: <<Const7:i\d+>> IntConstant 7 @@ -150,11 +179,12 @@ public class Main { /// CHECK-DAG: <<And:i\d+>> And [<<UShr>>,<<Const7>>] /// CHECK-DAG: Return [<<And>>] - public static int UShr28And7(int arg) { + public static int $noinline$UShr28And7(int arg) { + if (doThrow) { throw new Error(); } return (arg >>> 28) & 7; } - /// CHECK-START: long Main.UShr60And7(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$UShr60And7(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const60:i\d+>> IntConstant 60 /// CHECK-DAG: <<Const7:j\d+>> LongConstant 7 @@ -162,7 +192,7 @@ public class Main { /// CHECK-DAG: <<And:j\d+>> And [<<UShr>>,<<Const7>>] /// CHECK-DAG: Return [<<And>>] - /// CHECK-START: long Main.UShr60And7(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$UShr60And7(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const60:i\d+>> IntConstant 60 /// CHECK-DAG: <<Const7:j\d+>> LongConstant 7 @@ -170,11 +200,12 @@ public class Main { /// CHECK-DAG: <<And:j\d+>> And [<<UShr>>,<<Const7>>] /// CHECK-DAG: Return [<<And>>] - public static long UShr60And7(long arg) { + public static long $noinline$UShr60And7(long arg) { + if (doThrow) { throw new Error(); } return (arg >>> 60) & 7; } - /// CHECK-START: int Main.Shr24And255(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$Shr24And255(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const24:i\d+>> IntConstant 24 /// CHECK-DAG: <<Const255:i\d+>> IntConstant 255 @@ -182,21 +213,22 @@ public class Main { /// CHECK-DAG: <<And:i\d+>> And [<<Shr>>,<<Const255>>] /// CHECK-DAG: Return [<<And>>] - /// CHECK-START: int Main.Shr24And255(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$Shr24And255(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const24:i\d+>> IntConstant 24 /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Arg>>,<<Const24>>] /// CHECK-DAG: Return [<<UShr>>] - /// CHECK-START: int Main.Shr24And255(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$Shr24And255(int) instruction_simplifier (after) /// CHECK-NOT: Shr /// CHECK-NOT: And - public static int Shr24And255(int arg) { + public static int $noinline$Shr24And255(int arg) { + if (doThrow) { throw new Error(); } return (arg >> 24) & 255; } - /// CHECK-START: long Main.Shr56And255(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$Shr56And255(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const56:i\d+>> IntConstant 56 /// CHECK-DAG: <<Const255:j\d+>> LongConstant 255 @@ -204,21 +236,22 @@ public class Main { /// CHECK-DAG: <<And:j\d+>> And [<<Shr>>,<<Const255>>] /// CHECK-DAG: Return [<<And>>] - /// CHECK-START: long Main.Shr56And255(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Shr56And255(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const56:i\d+>> IntConstant 56 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Arg>>,<<Const56>>] /// CHECK-DAG: Return [<<UShr>>] - /// CHECK-START: long Main.Shr56And255(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Shr56And255(long) instruction_simplifier (after) /// CHECK-NOT: Shr /// CHECK-NOT: And - public static long Shr56And255(long arg) { + public static long $noinline$Shr56And255(long arg) { + if (doThrow) { throw new Error(); } return (arg >> 56) & 255; } - /// CHECK-START: int Main.Shr24And127(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$Shr24And127(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const24:i\d+>> IntConstant 24 /// CHECK-DAG: <<Const127:i\d+>> IntConstant 127 @@ -226,7 +259,7 @@ public class Main { /// CHECK-DAG: <<And:i\d+>> And [<<Shr>>,<<Const127>>] /// CHECK-DAG: Return [<<And>>] - /// CHECK-START: int Main.Shr24And127(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$Shr24And127(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const24:i\d+>> IntConstant 24 /// CHECK-DAG: <<Const127:i\d+>> IntConstant 127 @@ -234,11 +267,12 @@ public class Main { /// CHECK-DAG: <<And:i\d+>> And [<<Shr>>,<<Const127>>] /// CHECK-DAG: Return [<<And>>] - public static int Shr24And127(int arg) { + public static int $noinline$Shr24And127(int arg) { + if (doThrow) { throw new Error(); } return (arg >> 24) & 127; } - /// CHECK-START: long Main.Shr56And127(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$Shr56And127(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const56:i\d+>> IntConstant 56 /// CHECK-DAG: <<Const127:j\d+>> LongConstant 127 @@ -246,7 +280,7 @@ public class Main { /// CHECK-DAG: <<And:j\d+>> And [<<Shr>>,<<Const127>>] /// CHECK-DAG: Return [<<And>>] - /// CHECK-START: long Main.Shr56And127(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Shr56And127(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const56:i\d+>> IntConstant 56 /// CHECK-DAG: <<Const127:j\d+>> LongConstant 127 @@ -254,267 +288,361 @@ public class Main { /// CHECK-DAG: <<And:j\d+>> And [<<Shr>>,<<Const127>>] /// CHECK-DAG: Return [<<And>>] - public static long Shr56And127(long arg) { + public static long $noinline$Shr56And127(long arg) { + if (doThrow) { throw new Error(); } return (arg >> 56) & 127; } - /// CHECK-START: long Main.Div1(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$Div1(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const1:j\d+>> LongConstant 1 /// CHECK-DAG: <<Div:j\d+>> Div [<<Arg>>,<<Const1>>] /// CHECK-DAG: Return [<<Div>>] - /// CHECK-START: long Main.Div1(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Div1(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.Div1(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Div1(long) instruction_simplifier (after) /// CHECK-NOT: Div - public static long Div1(long arg) { + public static long $noinline$Div1(long arg) { + if (doThrow) { throw new Error(); } return arg / 1; } - /// CHECK-START: int Main.DivN1(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$DivN1(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<ConstN1:i\d+>> IntConstant -1 /// CHECK-DAG: <<Div:i\d+>> Div [<<Arg>>,<<ConstN1>>] /// CHECK-DAG: Return [<<Div>>] - /// CHECK-START: int Main.DivN1(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$DivN1(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Neg:i\d+>> Neg [<<Arg>>] /// CHECK-DAG: Return [<<Neg>>] - /// CHECK-START: int Main.DivN1(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$DivN1(int) instruction_simplifier (after) /// CHECK-NOT: Div - public static int DivN1(int arg) { + public static int $noinline$DivN1(int arg) { + if (doThrow) { throw new Error(); } return arg / -1; } - /// CHECK-START: long Main.Mul1(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$Mul1(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const1:j\d+>> LongConstant 1 /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Const1>>,<<Arg>>] /// CHECK-DAG: Return [<<Mul>>] - /// CHECK-START: long Main.Mul1(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Mul1(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.Mul1(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Mul1(long) instruction_simplifier (after) /// CHECK-NOT: Mul - public static long Mul1(long arg) { + public static long $noinline$Mul1(long arg) { + if (doThrow) { throw new Error(); } return arg * 1; } - /// CHECK-START: int Main.MulN1(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$MulN1(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<ConstN1:i\d+>> IntConstant -1 /// CHECK-DAG: <<Mul:i\d+>> Mul [<<Arg>>,<<ConstN1>>] /// CHECK-DAG: Return [<<Mul>>] - /// CHECK-START: int Main.MulN1(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$MulN1(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Neg:i\d+>> Neg [<<Arg>>] /// CHECK-DAG: Return [<<Neg>>] - /// CHECK-START: int Main.MulN1(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$MulN1(int) instruction_simplifier (after) /// CHECK-NOT: Mul - public static int MulN1(int arg) { + public static int $noinline$MulN1(int arg) { + if (doThrow) { throw new Error(); } return arg * -1; } - /// CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$MulPowerOfTwo128(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const128:j\d+>> LongConstant 128 /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Const128>>,<<Arg>>] /// CHECK-DAG: Return [<<Mul>>] - /// CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$MulPowerOfTwo128(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const7:i\d+>> IntConstant 7 /// CHECK-DAG: <<Shl:j\d+>> Shl [<<Arg>>,<<Const7>>] /// CHECK-DAG: Return [<<Shl>>] - /// CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$MulPowerOfTwo128(long) instruction_simplifier (after) /// CHECK-NOT: Mul - public static long MulPowerOfTwo128(long arg) { + public static long $noinline$MulPowerOfTwo128(long arg) { + if (doThrow) { throw new Error(); } return arg * 128; } - /// CHECK-START: int Main.Or0(int) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$MulMulMulConst(long) instruction_simplifier (before) + /// CHECK-DAG: <<ArgValue:j\d+>> ParameterValue + /// CHECK-DAG: <<Const10:j\d+>> LongConstant 10 + /// CHECK-DAG: <<Const11:j\d+>> LongConstant 11 + /// CHECK-DAG: <<Const12:j\d+>> LongConstant 12 + /// CHECK-DAG: <<Mul1:j\d+>> Mul [<<Const10>>,<<ArgValue>>] + /// CHECK-DAG: <<Mul2:j\d+>> Mul [<<Mul1>>,<<Const11>>] + /// CHECK-DAG: <<Mul3:j\d+>> Mul [<<Mul2>>,<<Const12>>] + /// CHECK-DAG: Return [<<Mul3>>] + + /// CHECK-START: long Main.$noinline$MulMulMulConst(long) instruction_simplifier (after) + /// CHECK-DAG: <<ArgValue:j\d+>> ParameterValue + /// CHECK-DAG: <<Const1320:j\d+>> LongConstant 1320 + /// CHECK-DAG: <<Mul:j\d+>> Mul [<<ArgValue>>,<<Const1320>>] + /// CHECK-DAG: Return [<<Mul>>] + + public static long $noinline$MulMulMulConst(long arg) { + if (doThrow) { throw new Error(); } + return 10 * arg * 11 * 12; + } + + /// CHECK-START: int Main.$noinline$Or0(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Or:i\d+>> Or [<<Arg>>,<<Const0>>] /// CHECK-DAG: Return [<<Or>>] - /// CHECK-START: int Main.Or0(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$Or0(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: int Main.Or0(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$Or0(int) instruction_simplifier (after) /// CHECK-NOT: Or - public static int Or0(int arg) { + public static int $noinline$Or0(int arg) { + if (doThrow) { throw new Error(); } return arg | 0; } - /// CHECK-START: long Main.OrSame(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$OrSame(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Or:j\d+>> Or [<<Arg>>,<<Arg>>] /// CHECK-DAG: Return [<<Or>>] - /// CHECK-START: long Main.OrSame(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$OrSame(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.OrSame(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$OrSame(long) instruction_simplifier (after) /// CHECK-NOT: Or - public static long OrSame(long arg) { + public static long $noinline$OrSame(long arg) { + if (doThrow) { throw new Error(); } return arg | arg; } - /// CHECK-START: int Main.Shl0(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$Shl0(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Shl:i\d+>> Shl [<<Arg>>,<<Const0>>] /// CHECK-DAG: Return [<<Shl>>] - /// CHECK-START: int Main.Shl0(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$Shl0(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: int Main.Shl0(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$Shl0(int) instruction_simplifier (after) /// CHECK-NOT: Shl - public static int Shl0(int arg) { + public static int $noinline$Shl0(int arg) { + if (doThrow) { throw new Error(); } return arg << 0; } - /// CHECK-START: long Main.Shr0(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$Shr0(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Shr:j\d+>> Shr [<<Arg>>,<<Const0>>] /// CHECK-DAG: Return [<<Shr>>] - /// CHECK-START: long Main.Shr0(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Shr0(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.Shr0(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Shr0(long) instruction_simplifier (after) /// CHECK-NOT: Shr - public static long Shr0(long arg) { + public static long $noinline$Shr0(long arg) { + if (doThrow) { throw new Error(); } return arg >> 0; } - /// CHECK-START: long Main.Shr64(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$Shr64(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const64:i\d+>> IntConstant 64 /// CHECK-DAG: <<Shr:j\d+>> Shr [<<Arg>>,<<Const64>>] /// CHECK-DAG: Return [<<Shr>>] - /// CHECK-START: long Main.Shr64(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Shr64(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.Shr64(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Shr64(long) instruction_simplifier (after) /// CHECK-NOT: Shr - public static long Shr64(long arg) { + public static long $noinline$Shr64(long arg) { + if (doThrow) { throw new Error(); } return arg >> 64; } - /// CHECK-START: long Main.Sub0(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$Sub0(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const0:j\d+>> LongConstant 0 /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Arg>>,<<Const0>>] /// CHECK-DAG: Return [<<Sub>>] - /// CHECK-START: long Main.Sub0(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Sub0(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.Sub0(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$Sub0(long) instruction_simplifier (after) /// CHECK-NOT: Sub - public static long Sub0(long arg) { + public static long $noinline$Sub0(long arg) { + if (doThrow) { throw new Error(); } return arg - 0; } - /// CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$SubAliasNeg(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const0>>,<<Arg>>] /// CHECK-DAG: Return [<<Sub>>] - /// CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$SubAliasNeg(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Neg:i\d+>> Neg [<<Arg>>] /// CHECK-DAG: Return [<<Neg>>] - /// CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$SubAliasNeg(int) instruction_simplifier (after) /// CHECK-NOT: Sub - public static int SubAliasNeg(int arg) { + public static int $noinline$SubAliasNeg(int arg) { + if (doThrow) { throw new Error(); } return 0 - arg; } - /// CHECK-START: long Main.UShr0(long) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$SubAddConst1(int) instruction_simplifier (before) + /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue + /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5 + /// CHECK-DAG: <<Const6:i\d+>> IntConstant 6 + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const5>>,<<ArgValue>>] + /// CHECK-DAG: <<Add:i\d+>> Add [<<Sub>>,<<Const6>>] + /// CHECK-DAG: Return [<<Add>>] + + /// CHECK-START: int Main.$noinline$SubAddConst1(int) instruction_simplifier (after) + /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue + /// CHECK-DAG: <<Const11:i\d+>> IntConstant 11 + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const11>>,<<ArgValue>>] + /// CHECK-DAG: Return [<<Sub>>] + + public static int $noinline$SubAddConst1(int arg) { + if (doThrow) { throw new Error(); } + return 5 - arg + 6; + } + + /// CHECK-START: int Main.$noinline$SubAddConst2(int) instruction_simplifier (before) + /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue + /// CHECK-DAG: <<Const14:i\d+>> IntConstant 14 + /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 + /// CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<Const13>>] + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const14>>,<<Add>>] + /// CHECK-DAG: Return [<<Sub>>] + + /// CHECK-START: int Main.$noinline$SubAddConst2(int) instruction_simplifier (after) + /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue + /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 + /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const1>>,<<ArgValue>>] + /// CHECK-DAG: Return [<<Sub>>] + + public static int $noinline$SubAddConst2(int arg) { + if (doThrow) { throw new Error(); } + return 14 - (arg + 13); + } + + /// CHECK-START: long Main.$noinline$SubSubConst(long) instruction_simplifier (before) + /// CHECK-DAG: <<ArgValue:j\d+>> ParameterValue + /// CHECK-DAG: <<Const17:j\d+>> LongConstant 17 + /// CHECK-DAG: <<Const18:j\d+>> LongConstant 18 + /// CHECK-DAG: <<Sub1:j\d+>> Sub [<<Const18>>,<<ArgValue>>] + /// CHECK-DAG: <<Sub2:j\d+>> Sub [<<Const17>>,<<Sub1>>] + /// CHECK-DAG: Return [<<Sub2>>] + + /// CHECK-START: long Main.$noinline$SubSubConst(long) instruction_simplifier (after) + /// CHECK-DAG: <<ArgValue:j\d+>> ParameterValue + /// CHECK-DAG: <<ConstM1:j\d+>> LongConstant -1 + /// CHECK-DAG: <<Add:j\d+>> Add [<<ArgValue>>,<<ConstM1>>] + /// CHECK-DAG: Return [<<Add>>] + + public static long $noinline$SubSubConst(long arg) { + if (doThrow) { throw new Error(); } + return 17 - (18 - arg); + } + + /// CHECK-START: long Main.$noinline$UShr0(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Arg>>,<<Const0>>] /// CHECK-DAG: Return [<<UShr>>] - /// CHECK-START: long Main.UShr0(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$UShr0(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.UShr0(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$UShr0(long) instruction_simplifier (after) /// CHECK-NOT: UShr - public static long UShr0(long arg) { + public static long $noinline$UShr0(long arg) { + if (doThrow) { throw new Error(); } return arg >>> 0; } - /// CHECK-START: int Main.Xor0(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$Xor0(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Xor:i\d+>> Xor [<<Arg>>,<<Const0>>] /// CHECK-DAG: Return [<<Xor>>] - /// CHECK-START: int Main.Xor0(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$Xor0(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: int Main.Xor0(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$Xor0(int) instruction_simplifier (after) /// CHECK-NOT: Xor - public static int Xor0(int arg) { + public static int $noinline$Xor0(int arg) { + if (doThrow) { throw new Error(); } return arg ^ 0; } - /// CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$XorAllOnes(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<ConstF:i\d+>> IntConstant -1 /// CHECK-DAG: <<Xor:i\d+>> Xor [<<Arg>>,<<ConstF>>] /// CHECK-DAG: Return [<<Xor>>] - /// CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$XorAllOnes(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>] /// CHECK-DAG: Return [<<Not>>] - /// CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$XorAllOnes(int) instruction_simplifier (after) /// CHECK-NOT: Xor - public static int XorAllOnes(int arg) { + public static int $noinline$XorAllOnes(int arg) { + if (doThrow) { throw new Error(); } return arg ^ -1; } @@ -525,7 +653,7 @@ public class Main { * `InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop`. */ - /// CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$AddNegs1(int, int) instruction_simplifier (before) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Neg1:i\d+>> Neg [<<Arg1>>] @@ -533,7 +661,7 @@ public class Main { /// CHECK-DAG: <<Add:i\d+>> Add [<<Neg1>>,<<Neg2>>] /// CHECK-DAG: Return [<<Add>>] - /// CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$AddNegs1(int, int) instruction_simplifier (after) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-NOT: Neg @@ -541,7 +669,8 @@ public class Main { /// CHECK-DAG: <<Neg:i\d+>> Neg [<<Add>>] /// CHECK-DAG: Return [<<Neg>>] - public static int AddNegs1(int arg1, int arg2) { + public static int $noinline$AddNegs1(int arg1, int arg2) { + if (doThrow) { throw new Error(); } return -arg1 + -arg2; } @@ -556,7 +685,7 @@ public class Main { * increasing the register pressure by creating or extending live ranges. */ - /// CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$AddNegs2(int, int) instruction_simplifier (before) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Neg1:i\d+>> Neg [<<Arg1>>] @@ -566,7 +695,7 @@ public class Main { /// CHECK-DAG: <<Or:i\d+>> Or [<<Add1>>,<<Add2>>] /// CHECK-DAG: Return [<<Or>>] - /// CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$AddNegs2(int, int) instruction_simplifier (after) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Neg1:i\d+>> Neg [<<Arg1>>] @@ -577,7 +706,7 @@ public class Main { /// CHECK-DAG: <<Or:i\d+>> Or [<<Add1>>,<<Add2>>] /// CHECK-DAG: Return [<<Or>>] - /// CHECK-START: int Main.AddNegs2(int, int) GVN (after) + /// CHECK-START: int Main.$noinline$AddNegs2(int, int) GVN (after) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Neg1:i\d+>> Neg [<<Arg1>>] @@ -586,7 +715,8 @@ public class Main { /// CHECK-DAG: <<Or:i\d+>> Or [<<Add>>,<<Add>>] /// CHECK-DAG: Return [<<Or>>] - public static int AddNegs2(int arg1, int arg2) { + public static int $noinline$AddNegs2(int arg1, int arg2) { + if (doThrow) { throw new Error(); } int temp1 = -arg1; int temp2 = -arg2; return (temp1 + temp2) | (temp1 + temp2); @@ -600,7 +730,7 @@ public class Main { * the loop. */ - /// CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$AddNegs3(long, long) instruction_simplifier (before) // -------------- Arguments and initial negation operations. /// CHECK-DAG: <<Arg1:j\d+>> ParameterValue /// CHECK-DAG: <<Arg2:j\d+>> ParameterValue @@ -612,7 +742,7 @@ public class Main { /// CHECK: <<Add:j\d+>> Add [<<Neg1>>,<<Neg2>>] /// CHECK: Goto - /// CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$AddNegs3(long, long) instruction_simplifier (after) // -------------- Arguments and initial negation operations. /// CHECK-DAG: <<Arg1:j\d+>> ParameterValue /// CHECK-DAG: <<Arg2:j\d+>> ParameterValue @@ -625,7 +755,8 @@ public class Main { /// CHECK-NOT: Neg /// CHECK: Goto - public static long AddNegs3(long arg1, long arg2) { + public static long $noinline$AddNegs3(long arg1, long arg2) { + if (doThrow) { throw new Error(); } long res = 0; long n_arg1 = -arg1; long n_arg2 = -arg2; @@ -641,24 +772,25 @@ public class Main { * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitAdd`. */ - /// CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$AddNeg1(long, long) instruction_simplifier (before) /// CHECK-DAG: <<Arg1:j\d+>> ParameterValue /// CHECK-DAG: <<Arg2:j\d+>> ParameterValue /// CHECK-DAG: <<Neg:j\d+>> Neg [<<Arg1>>] /// CHECK-DAG: <<Add:j\d+>> Add [<<Neg>>,<<Arg2>>] /// CHECK-DAG: Return [<<Add>>] - /// CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$AddNeg1(long, long) instruction_simplifier (after) /// CHECK-DAG: <<Arg1:j\d+>> ParameterValue /// CHECK-DAG: <<Arg2:j\d+>> ParameterValue /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Arg2>>,<<Arg1>>] /// CHECK-DAG: Return [<<Sub>>] - /// CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$AddNeg1(long, long) instruction_simplifier (after) /// CHECK-NOT: Neg /// CHECK-NOT: Add - public static long AddNeg1(long arg1, long arg2) { + public static long $noinline$AddNeg1(long arg1, long arg2) { + if (doThrow) { throw new Error(); } return -arg1 + arg2; } @@ -671,7 +803,7 @@ public class Main { * increasing the register pressure by creating or extending live ranges. */ - /// CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$AddNeg2(long, long) instruction_simplifier (before) /// CHECK-DAG: <<Arg1:j\d+>> ParameterValue /// CHECK-DAG: <<Arg2:j\d+>> ParameterValue /// CHECK-DAG: <<Neg:j\d+>> Neg [<<Arg2>>] @@ -680,7 +812,7 @@ public class Main { /// CHECK-DAG: <<Res:j\d+>> Or [<<Add1>>,<<Add2>>] /// CHECK-DAG: Return [<<Res>>] - /// CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$AddNeg2(long, long) instruction_simplifier (after) /// CHECK-DAG: <<Arg1:j\d+>> ParameterValue /// CHECK-DAG: <<Arg2:j\d+>> ParameterValue /// CHECK-DAG: <<Neg:j\d+>> Neg [<<Arg2>>] @@ -689,10 +821,11 @@ public class Main { /// CHECK-DAG: <<Res:j\d+>> Or [<<Add1>>,<<Add2>>] /// CHECK-DAG: Return [<<Res>>] - /// CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$AddNeg2(long, long) instruction_simplifier (after) /// CHECK-NOT: Sub - public static long AddNeg2(long arg1, long arg2) { + public static long $noinline$AddNeg2(long arg1, long arg2) { + if (doThrow) { throw new Error(); } long temp = -arg2; return (arg1 + temp) | (arg1 + temp); } @@ -702,20 +835,21 @@ public class Main { * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNeg`. */ - /// CHECK-START: long Main.NegNeg1(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$NegNeg1(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Neg1:j\d+>> Neg [<<Arg>>] /// CHECK-DAG: <<Neg2:j\d+>> Neg [<<Neg1>>] /// CHECK-DAG: Return [<<Neg2>>] - /// CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$NegNeg1(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$NegNeg1(long) instruction_simplifier (after) /// CHECK-NOT: Neg - public static long NegNeg1(long arg) { + public static long $noinline$NegNeg1(long arg) { + if (doThrow) { throw new Error(); } return -(-arg); } @@ -726,29 +860,30 @@ public class Main { * and in `InstructionSimplifierVisitor::VisitAdd`. */ - /// CHECK-START: int Main.NegNeg2(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$NegNeg2(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Neg1:i\d+>> Neg [<<Arg>>] /// CHECK-DAG: <<Neg2:i\d+>> Neg [<<Neg1>>] /// CHECK-DAG: <<Add:i\d+>> Add [<<Neg2>>,<<Neg1>>] /// CHECK-DAG: Return [<<Add>>] - /// CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$NegNeg2(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Arg>>,<<Arg>>] /// CHECK-DAG: Return [<<Sub>>] - /// CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$NegNeg2(int) instruction_simplifier (after) /// CHECK-NOT: Neg /// CHECK-NOT: Add - /// CHECK-START: int Main.NegNeg2(int) constant_folding_after_inlining (after) + /// CHECK-START: int Main.$noinline$NegNeg2(int) constant_folding_after_inlining (after) /// CHECK: <<Const0:i\d+>> IntConstant 0 /// CHECK-NOT: Neg /// CHECK-NOT: Add /// CHECK: Return [<<Const0>>] - public static int NegNeg2(int arg) { + public static int $noinline$NegNeg2(int arg) { + if (doThrow) { throw new Error(); } int temp = -arg; return temp + -temp; } @@ -760,22 +895,23 @@ public class Main { * and in `InstructionSimplifierVisitor::VisitSub`. */ - /// CHECK-START: long Main.NegNeg3(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$NegNeg3(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const0:j\d+>> LongConstant 0 /// CHECK-DAG: <<Neg:j\d+>> Neg [<<Arg>>] /// CHECK-DAG: <<Sub:j\d+>> Sub [<<Const0>>,<<Neg>>] /// CHECK-DAG: Return [<<Sub>>] - /// CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$NegNeg3(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$NegNeg3(long) instruction_simplifier (after) /// CHECK-NOT: Neg /// CHECK-NOT: Sub - public static long NegNeg3(long arg) { + public static long $noinline$NegNeg3(long arg) { + if (doThrow) { throw new Error(); } return 0 - -arg; } @@ -785,23 +921,24 @@ public class Main { * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNeg`. */ - /// CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$NegSub1(int, int) instruction_simplifier (before) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Arg1>>,<<Arg2>>] /// CHECK-DAG: <<Neg:i\d+>> Neg [<<Sub>>] /// CHECK-DAG: Return [<<Neg>>] - /// CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$NegSub1(int, int) instruction_simplifier (after) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Arg2>>,<<Arg1>>] /// CHECK-DAG: Return [<<Sub>>] - /// CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$NegSub1(int, int) instruction_simplifier (after) /// CHECK-NOT: Neg - public static int NegSub1(int arg1, int arg2) { + public static int $noinline$NegSub1(int arg1, int arg2) { + if (doThrow) { throw new Error(); } return -(arg1 - arg2); } @@ -815,7 +952,7 @@ public class Main { * increasing the register pressure by creating or extending live ranges. */ - /// CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$NegSub2(int, int) instruction_simplifier (before) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Arg1>>,<<Arg2>>] @@ -824,7 +961,7 @@ public class Main { /// CHECK-DAG: <<Or:i\d+>> Or [<<Neg1>>,<<Neg2>>] /// CHECK-DAG: Return [<<Or>>] - /// CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$NegSub2(int, int) instruction_simplifier (after) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Arg1>>,<<Arg2>>] @@ -833,7 +970,8 @@ public class Main { /// CHECK-DAG: <<Or:i\d+>> Or [<<Neg1>>,<<Neg2>>] /// CHECK-DAG: Return [<<Or>>] - public static int NegSub2(int arg1, int arg2) { + public static int $noinline$NegSub2(int arg1, int arg2) { + if (doThrow) { throw new Error(); } int temp = arg1 - arg2; return -temp | -temp; } @@ -843,41 +981,43 @@ public class Main { * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNot`. */ - /// CHECK-START: long Main.NotNot1(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$NotNot1(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Not1:j\d+>> Not [<<Arg>>] /// CHECK-DAG: <<Not2:j\d+>> Not [<<Not1>>] /// CHECK-DAG: Return [<<Not2>>] - /// CHECK-START: long Main.NotNot1(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$NotNot1(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: long Main.NotNot1(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$NotNot1(long) instruction_simplifier (after) /// CHECK-NOT: Not - public static long NotNot1(long arg) { + public static long $noinline$NotNot1(long arg) { + if (doThrow) { throw new Error(); } return ~~arg; } - /// CHECK-START: int Main.NotNot2(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$NotNot2(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Not1:i\d+>> Not [<<Arg>>] /// CHECK-DAG: <<Not2:i\d+>> Not [<<Not1>>] /// CHECK-DAG: <<Add:i\d+>> Add [<<Not2>>,<<Not1>>] /// CHECK-DAG: Return [<<Add>>] - /// CHECK-START: int Main.NotNot2(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$NotNot2(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Not:i\d+>> Not [<<Arg>>] /// CHECK-DAG: <<Add:i\d+>> Add [<<Arg>>,<<Not>>] /// CHECK-DAG: Return [<<Add>>] - /// CHECK-START: int Main.NotNot2(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$NotNot2(int) instruction_simplifier (after) /// CHECK: Not /// CHECK-NOT: Not - public static int NotNot2(int arg) { + public static int $noinline$NotNot2(int arg) { + if (doThrow) { throw new Error(); } int temp = ~arg; return temp + ~temp; } @@ -887,24 +1027,25 @@ public class Main { * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitSub`. */ - /// CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$SubNeg1(int, int) instruction_simplifier (before) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Neg:i\d+>> Neg [<<Arg1>>] /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Neg>>,<<Arg2>>] /// CHECK-DAG: Return [<<Sub>>] - /// CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$SubNeg1(int, int) instruction_simplifier (after) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Add:i\d+>> Add [<<Arg1>>,<<Arg2>>] /// CHECK-DAG: <<Neg:i\d+>> Neg [<<Add>>] /// CHECK-DAG: Return [<<Neg>>] - /// CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$SubNeg1(int, int) instruction_simplifier (after) /// CHECK-NOT: Sub - public static int SubNeg1(int arg1, int arg2) { + public static int $noinline$SubNeg1(int arg1, int arg2) { + if (doThrow) { throw new Error(); } return -arg1 - arg2; } @@ -918,7 +1059,7 @@ public class Main { * increasing the register pressure by creating or extending live ranges. */ - /// CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$SubNeg2(int, int) instruction_simplifier (before) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Neg:i\d+>> Neg [<<Arg1>>] @@ -927,7 +1068,7 @@ public class Main { /// CHECK-DAG: <<Or:i\d+>> Or [<<Sub1>>,<<Sub2>>] /// CHECK-DAG: Return [<<Or>>] - /// CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$SubNeg2(int, int) instruction_simplifier (after) /// CHECK-DAG: <<Arg1:i\d+>> ParameterValue /// CHECK-DAG: <<Arg2:i\d+>> ParameterValue /// CHECK-DAG: <<Neg:i\d+>> Neg [<<Arg1>>] @@ -936,10 +1077,11 @@ public class Main { /// CHECK-DAG: <<Or:i\d+>> Or [<<Sub1>>,<<Sub2>>] /// CHECK-DAG: Return [<<Or>>] - /// CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$SubNeg2(int, int) instruction_simplifier (after) /// CHECK-NOT: Add - public static int SubNeg2(int arg1, int arg2) { + public static int $noinline$SubNeg2(int arg1, int arg2) { + if (doThrow) { throw new Error(); } int temp = -arg1; return (temp - arg2) | (temp - arg2); } @@ -951,7 +1093,7 @@ public class Main { * the loop. */ - /// CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$SubNeg3(long, long) instruction_simplifier (before) // -------------- Arguments and initial negation operation. /// CHECK-DAG: <<Arg1:j\d+>> ParameterValue /// CHECK-DAG: <<Arg2:j\d+>> ParameterValue @@ -962,7 +1104,7 @@ public class Main { /// CHECK: <<Sub:j\d+>> Sub [<<Neg>>,<<Arg2>>] /// CHECK: Goto - /// CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$SubNeg3(long, long) instruction_simplifier (after) // -------------- Arguments and initial negation operation. /// CHECK-DAG: <<Arg1:j\d+>> ParameterValue /// CHECK-DAG: <<Arg2:j\d+>> ParameterValue @@ -974,7 +1116,8 @@ public class Main { /// CHECK-NOT: Neg /// CHECK: Goto - public static long SubNeg3(long arg1, long arg2) { + public static long $noinline$SubNeg3(long arg1, long arg2) { + if (doThrow) { throw new Error(); } long res = 0; long temp = -arg1; for (long i = 0; i < 1; i++) { @@ -983,7 +1126,7 @@ public class Main { return res; } - /// CHECK-START: boolean Main.EqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (before) + /// CHECK-START: boolean Main.$noinline$EqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (before) /// CHECK-DAG: <<Arg:z\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 @@ -993,15 +1136,16 @@ public class Main { /// CHECK-DAG: <<NotCond:i\d+>> Select [<<Const1>>,<<Const0>>,<<Cond>>] /// CHECK-DAG: Return [<<NotCond>>] - /// CHECK-START: boolean Main.EqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (after) + /// CHECK-START: boolean Main.$noinline$EqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (after) /// CHECK-DAG: <<True:i\d+>> IntConstant 1 /// CHECK-DAG: Return [<<True>>] - public static boolean EqualBoolVsIntConst(boolean arg) { + public static boolean $noinline$EqualBoolVsIntConst(boolean arg) { + if (doThrow) { throw new Error(); } return (arg ? 0 : 1) != 2; } - /// CHECK-START: boolean Main.NotEqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (before) + /// CHECK-START: boolean Main.$noinline$NotEqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (before) /// CHECK-DAG: <<Arg:z\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 @@ -1011,11 +1155,12 @@ public class Main { /// CHECK-DAG: <<NotCond:i\d+>> Select [<<Const1>>,<<Const0>>,<<Cond>>] /// CHECK-DAG: Return [<<NotCond>>] - /// CHECK-START: boolean Main.NotEqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (after) + /// CHECK-START: boolean Main.$noinline$NotEqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (after) /// CHECK-DAG: <<False:i\d+>> IntConstant 0 /// CHECK-DAG: Return [<<False>>] - public static boolean NotEqualBoolVsIntConst(boolean arg) { + public static boolean $noinline$NotEqualBoolVsIntConst(boolean arg) { + if (doThrow) { throw new Error(); } return (arg ? 0 : 1) == 2; } @@ -1025,7 +1170,7 @@ public class Main { * remove the second. */ - /// CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_bce (before) + /// CHECK-START: boolean Main.$noinline$NotNotBool(boolean) instruction_simplifier_after_bce (before) /// CHECK-DAG: <<Arg:z\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 @@ -1033,7 +1178,7 @@ public class Main { /// CHECK-DAG: <<NotNotArg:i\d+>> Select [<<Const1>>,<<Const0>>,<<NotArg>>] /// CHECK-DAG: Return [<<NotNotArg>>] - /// CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_bce (after) + /// CHECK-START: boolean Main.$noinline$NotNotBool(boolean) instruction_simplifier_after_bce (after) /// CHECK-DAG: <<Arg:z\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] @@ -1041,81 +1186,86 @@ public class Main { return !arg; } - public static boolean NotNotBool(boolean arg) { + public static boolean $noinline$NotNotBool(boolean arg) { + if (doThrow) { throw new Error(); } return !(NegateValue(arg)); } - /// CHECK-START: float Main.Div2(float) instruction_simplifier (before) + /// CHECK-START: float Main.$noinline$Div2(float) instruction_simplifier (before) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<Const2:f\d+>> FloatConstant 2 /// CHECK-DAG: <<Div:f\d+>> Div [<<Arg>>,<<Const2>>] /// CHECK-DAG: Return [<<Div>>] - /// CHECK-START: float Main.Div2(float) instruction_simplifier (after) + /// CHECK-START: float Main.$noinline$Div2(float) instruction_simplifier (after) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<ConstP5:f\d+>> FloatConstant 0.5 /// CHECK-DAG: <<Mul:f\d+>> Mul [<<Arg>>,<<ConstP5>>] /// CHECK-DAG: Return [<<Mul>>] - /// CHECK-START: float Main.Div2(float) instruction_simplifier (after) + /// CHECK-START: float Main.$noinline$Div2(float) instruction_simplifier (after) /// CHECK-NOT: Div - public static float Div2(float arg) { + public static float $noinline$Div2(float arg) { + if (doThrow) { throw new Error(); } return arg / 2.0f; } - /// CHECK-START: double Main.Div2(double) instruction_simplifier (before) + /// CHECK-START: double Main.$noinline$Div2(double) instruction_simplifier (before) /// CHECK-DAG: <<Arg:d\d+>> ParameterValue /// CHECK-DAG: <<Const2:d\d+>> DoubleConstant 2 /// CHECK-DAG: <<Div:d\d+>> Div [<<Arg>>,<<Const2>>] /// CHECK-DAG: Return [<<Div>>] - /// CHECK-START: double Main.Div2(double) instruction_simplifier (after) + /// CHECK-START: double Main.$noinline$Div2(double) instruction_simplifier (after) /// CHECK-DAG: <<Arg:d\d+>> ParameterValue /// CHECK-DAG: <<ConstP5:d\d+>> DoubleConstant 0.5 /// CHECK-DAG: <<Mul:d\d+>> Mul [<<Arg>>,<<ConstP5>>] /// CHECK-DAG: Return [<<Mul>>] - /// CHECK-START: double Main.Div2(double) instruction_simplifier (after) + /// CHECK-START: double Main.$noinline$Div2(double) instruction_simplifier (after) /// CHECK-NOT: Div - public static double Div2(double arg) { + public static double $noinline$Div2(double arg) { + if (doThrow) { throw new Error(); } return arg / 2.0; } - /// CHECK-START: float Main.DivMP25(float) instruction_simplifier (before) + /// CHECK-START: float Main.$noinline$DivMP25(float) instruction_simplifier (before) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<ConstMP25:f\d+>> FloatConstant -0.25 /// CHECK-DAG: <<Div:f\d+>> Div [<<Arg>>,<<ConstMP25>>] /// CHECK-DAG: Return [<<Div>>] - /// CHECK-START: float Main.DivMP25(float) instruction_simplifier (after) + /// CHECK-START: float Main.$noinline$DivMP25(float) instruction_simplifier (after) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<ConstM4:f\d+>> FloatConstant -4 /// CHECK-DAG: <<Mul:f\d+>> Mul [<<Arg>>,<<ConstM4>>] /// CHECK-DAG: Return [<<Mul>>] - /// CHECK-START: float Main.DivMP25(float) instruction_simplifier (after) + /// CHECK-START: float Main.$noinline$DivMP25(float) instruction_simplifier (after) /// CHECK-NOT: Div - public static float DivMP25(float arg) { + public static float $noinline$DivMP25(float arg) { + if (doThrow) { throw new Error(); } return arg / -0.25f; } - /// CHECK-START: double Main.DivMP25(double) instruction_simplifier (before) + /// CHECK-START: double Main.$noinline$DivMP25(double) instruction_simplifier (before) /// CHECK-DAG: <<Arg:d\d+>> ParameterValue /// CHECK-DAG: <<ConstMP25:d\d+>> DoubleConstant -0.25 /// CHECK-DAG: <<Div:d\d+>> Div [<<Arg>>,<<ConstMP25>>] /// CHECK-DAG: Return [<<Div>>] - /// CHECK-START: double Main.DivMP25(double) instruction_simplifier (after) + /// CHECK-START: double Main.$noinline$DivMP25(double) instruction_simplifier (after) /// CHECK-DAG: <<Arg:d\d+>> ParameterValue /// CHECK-DAG: <<ConstM4:d\d+>> DoubleConstant -4 /// CHECK-DAG: <<Mul:d\d+>> Mul [<<Arg>>,<<ConstM4>>] /// CHECK-DAG: Return [<<Mul>>] - /// CHECK-START: double Main.DivMP25(double) instruction_simplifier (after) + /// CHECK-START: double Main.$noinline$DivMP25(double) instruction_simplifier (after) /// CHECK-NOT: Div - public static double DivMP25(double arg) { + public static double $noinline$DivMP25(double arg) { + if (doThrow) { throw new Error(); } return arg / -0.25f; } @@ -1123,18 +1273,19 @@ public class Main { * Test strength reduction of factors of the form (2^n + 1). */ - /// CHECK-START: int Main.mulPow2Plus1(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$mulPow2Plus1(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const9:i\d+>> IntConstant 9 /// CHECK: Mul [<<Arg>>,<<Const9>>] - /// CHECK-START: int Main.mulPow2Plus1(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$mulPow2Plus1(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 /// CHECK: <<Shift:i\d+>> Shl [<<Arg>>,<<Const3>>] /// CHECK-NEXT: Add [<<Arg>>,<<Shift>>] - public static int mulPow2Plus1(int arg) { + public static int $noinline$mulPow2Plus1(int arg) { + if (doThrow) { throw new Error(); } return arg * 9; } @@ -1142,62 +1293,69 @@ public class Main { * Test strength reduction of factors of the form (2^n - 1). */ - /// CHECK-START: long Main.mulPow2Minus1(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$mulPow2Minus1(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const31:j\d+>> LongConstant 31 /// CHECK: Mul [<<Const31>>,<<Arg>>] - /// CHECK-START: long Main.mulPow2Minus1(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$mulPow2Minus1(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5 /// CHECK: <<Shift:j\d+>> Shl [<<Arg>>,<<Const5>>] /// CHECK-NEXT: Sub [<<Shift>>,<<Arg>>] - public static long mulPow2Minus1(long arg) { + public static long $noinline$mulPow2Minus1(long arg) { + if (doThrow) { throw new Error(); } return arg * 31; } - /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier_after_bce (before) + /// CHECK-START: int Main.$noinline$booleanFieldNotEqualOne() instruction_simplifier_after_bce (before) /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54 + /// CHECK-DAG: <<doThrow:z\d+>> StaticFieldGet /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet /// CHECK-DAG: <<NE:z\d+>> NotEqual [<<Field>>,<<Const1>>] /// CHECK-DAG: <<Select:i\d+>> Select [<<Const13>>,<<Const54>>,<<NE>>] /// CHECK-DAG: Return [<<Select>>] - /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier_after_bce (after) + /// CHECK-START: int Main.$noinline$booleanFieldNotEqualOne() instruction_simplifier_after_bce (after) + /// CHECK-DAG: <<doThrow:z\d+>> StaticFieldGet /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const54>>,<<Const13>>,<<Field>>] /// CHECK-DAG: Return [<<Select>>] - public static int booleanFieldNotEqualOne() { + public static int $noinline$booleanFieldNotEqualOne() { + if (doThrow) { throw new Error(); } return (booleanField == $inline$true()) ? 13 : 54; } - /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier_after_bce (before) + /// CHECK-START: int Main.$noinline$booleanFieldEqualZero() instruction_simplifier_after_bce (before) /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54 + /// CHECK-DAG: <<doThrow:z\d+>> StaticFieldGet /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet /// CHECK-DAG: <<NE:z\d+>> Equal [<<Field>>,<<Const0>>] /// CHECK-DAG: <<Select:i\d+>> Select [<<Const13>>,<<Const54>>,<<NE>>] /// CHECK-DAG: Return [<<Select>>] - /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier_after_bce (after) + /// CHECK-START: int Main.$noinline$booleanFieldEqualZero() instruction_simplifier_after_bce (after) + /// CHECK-DAG: <<doThrow:z\d+>> StaticFieldGet /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const54>>,<<Const13>>,<<Field>>] /// CHECK-DAG: Return [<<Select>>] - public static int booleanFieldEqualZero() { + public static int $noinline$booleanFieldEqualZero() { + if (doThrow) { throw new Error(); } return (booleanField != $inline$false()) ? 13 : 54; } - /// CHECK-START: int Main.intConditionNotEqualOne(int) instruction_simplifier_after_bce (before) + /// CHECK-START: int Main.$noinline$intConditionNotEqualOne(int) instruction_simplifier_after_bce (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 @@ -1210,7 +1368,7 @@ public class Main { /// CHECK-DAG: <<Result:i\d+>> Select [<<Const13>>,<<Const54>>,<<NE>>] /// CHECK-DAG: Return [<<Result>>] - /// CHECK-START: int Main.intConditionNotEqualOne(int) instruction_simplifier_after_bce (after) + /// CHECK-START: int Main.$noinline$intConditionNotEqualOne(int) instruction_simplifier_after_bce (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 @@ -1221,11 +1379,12 @@ public class Main { // Note that we match `LE` from Select because there are two identical // LessThanOrEqual instructions. - public static int intConditionNotEqualOne(int i) { + public static int $noinline$intConditionNotEqualOne(int i) { + if (doThrow) { throw new Error(); } return ((i > 42) == $inline$true()) ? 13 : 54; } - /// CHECK-START: int Main.intConditionEqualZero(int) instruction_simplifier_after_bce (before) + /// CHECK-START: int Main.$noinline$intConditionEqualZero(int) instruction_simplifier_after_bce (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 @@ -1238,7 +1397,7 @@ public class Main { /// CHECK-DAG: <<Result:i\d+>> Select [<<Const13>>,<<Const54>>,<<NE>>] /// CHECK-DAG: Return [<<Result>>] - /// CHECK-START: int Main.intConditionEqualZero(int) instruction_simplifier_after_bce (after) + /// CHECK-START: int Main.$noinline$intConditionEqualZero(int) instruction_simplifier_after_bce (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 @@ -1249,16 +1408,17 @@ public class Main { // Note that we match `LE` from Select because there are two identical // LessThanOrEqual instructions. - public static int intConditionEqualZero(int i) { + public static int $noinline$intConditionEqualZero(int i) { + if (doThrow) { throw new Error(); } return ((i > 42) != $inline$false()) ? 13 : 54; } // Test that conditions on float/double are not flipped. - /// CHECK-START: int Main.floatConditionNotEqualOne(float) builder (after) + /// CHECK-START: int Main.$noinline$floatConditionNotEqualOne(float) builder (after) /// CHECK: LessThanOrEqual - /// CHECK-START: int Main.floatConditionNotEqualOne(float) instruction_simplifier_before_codegen (after) + /// CHECK-START: int Main.$noinline$floatConditionNotEqualOne(float) instruction_simplifier_before_codegen (after) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54 @@ -1267,14 +1427,15 @@ public class Main { /// CHECK-DAG: <<Select:i\d+>> Select [<<Const13>>,<<Const54>>,<<LE>>] /// CHECK-DAG: Return [<<Select>>] - public static int floatConditionNotEqualOne(float f) { + public static int $noinline$floatConditionNotEqualOne(float f) { + if (doThrow) { throw new Error(); } return ((f > 42.0f) == true) ? 13 : 54; } - /// CHECK-START: int Main.doubleConditionEqualZero(double) builder (after) + /// CHECK-START: int Main.$noinline$doubleConditionEqualZero(double) builder (after) /// CHECK: LessThanOrEqual - /// CHECK-START: int Main.doubleConditionEqualZero(double) instruction_simplifier_before_codegen (after) + /// CHECK-START: int Main.$noinline$doubleConditionEqualZero(double) instruction_simplifier_before_codegen (after) /// CHECK-DAG: <<Arg:d\d+>> ParameterValue /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13 /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54 @@ -1283,42 +1444,45 @@ public class Main { /// CHECK-DAG: <<Select:i\d+>> Select [<<Const13>>,<<Const54>>,<<LE>>] /// CHECK-DAG: Return [<<Select>>] - public static int doubleConditionEqualZero(double d) { + public static int $noinline$doubleConditionEqualZero(double d) { + if (doThrow) { throw new Error(); } return ((d > 42.0) != false) ? 13 : 54; } - /// CHECK-START: int Main.intToDoubleToInt(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$intToDoubleToInt(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Double>>] /// CHECK-DAG: Return [<<Int>>] - /// CHECK-START: int Main.intToDoubleToInt(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$intToDoubleToInt(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: int Main.intToDoubleToInt(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$intToDoubleToInt(int) instruction_simplifier (after) /// CHECK-NOT: TypeConversion - public static int intToDoubleToInt(int value) { + public static int $noinline$intToDoubleToInt(int value) { + if (doThrow) { throw new Error(); } // Lossless conversion followed by a conversion back. return (int) (double) value; } - /// CHECK-START: java.lang.String Main.intToDoubleToIntPrint(int) instruction_simplifier (before) + /// CHECK-START: java.lang.String Main.$noinline$intToDoubleToIntPrint(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: {{i\d+}} TypeConversion [<<Double>>] - /// CHECK-START: java.lang.String Main.intToDoubleToIntPrint(int) instruction_simplifier (after) + /// CHECK-START: java.lang.String Main.$noinline$intToDoubleToIntPrint(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: {{d\d+}} TypeConversion [<<Arg>>] - /// CHECK-START: java.lang.String Main.intToDoubleToIntPrint(int) instruction_simplifier (after) + /// CHECK-START: java.lang.String Main.$noinline$intToDoubleToIntPrint(int) instruction_simplifier (after) /// CHECK-DAG: TypeConversion /// CHECK-NOT: TypeConversion - public static String intToDoubleToIntPrint(int value) { + public static String $noinline$intToDoubleToIntPrint(int value) { + if (doThrow) { throw new Error(); } // Lossless conversion followed by a conversion back // with another use of the intermediate result. double d = (double) value; @@ -1326,55 +1490,58 @@ public class Main { return "d=" + d + ", i=" + i; } - /// CHECK-START: int Main.byteToDoubleToInt(byte) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$byteToDoubleToInt(byte) instruction_simplifier (before) /// CHECK-DAG: <<Arg:b\d+>> ParameterValue /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Double>>] /// CHECK-DAG: Return [<<Int>>] - /// CHECK-START: int Main.byteToDoubleToInt(byte) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$byteToDoubleToInt(byte) instruction_simplifier (after) /// CHECK-DAG: <<Arg:b\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: int Main.byteToDoubleToInt(byte) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$byteToDoubleToInt(byte) instruction_simplifier (after) /// CHECK-NOT: TypeConversion - public static int byteToDoubleToInt(byte value) { + public static int $noinline$byteToDoubleToInt(byte value) { + if (doThrow) { throw new Error(); } // Lossless conversion followed by another conversion, use implicit conversion. return (int) (double) value; } - /// CHECK-START: int Main.floatToDoubleToInt(float) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$floatToDoubleToInt(float) instruction_simplifier (before) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Double>>] /// CHECK-DAG: Return [<<Int>>] - /// CHECK-START: int Main.floatToDoubleToInt(float) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$floatToDoubleToInt(float) instruction_simplifier (after) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: Return [<<Int>>] - /// CHECK-START: int Main.floatToDoubleToInt(float) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$floatToDoubleToInt(float) instruction_simplifier (after) /// CHECK-DAG: TypeConversion /// CHECK-NOT: TypeConversion - public static int floatToDoubleToInt(float value) { + public static int $noinline$floatToDoubleToInt(float value) { + if (doThrow) { throw new Error(); } // Lossless conversion followed by another conversion. return (int) (double) value; } - /// CHECK-START: java.lang.String Main.floatToDoubleToIntPrint(float) instruction_simplifier (before) + /// CHECK-START: java.lang.String Main.$noinline$floatToDoubleToIntPrint(float) instruction_simplifier (before) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: {{i\d+}} TypeConversion [<<Double>>] - /// CHECK-START: java.lang.String Main.floatToDoubleToIntPrint(float) instruction_simplifier (after) + /// CHECK-START: java.lang.String Main.$noinline$floatToDoubleToIntPrint(float) instruction_simplifier (after) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: {{i\d+}} TypeConversion [<<Double>>] - public static String floatToDoubleToIntPrint(float value) { + public static String $noinline$floatToDoubleToIntPrint(float value) { + if (doThrow) { throw new Error(); } // Lossless conversion followed by another conversion with // an extra use of the intermediate result. double d = (double) value; @@ -1382,176 +1549,186 @@ public class Main { return "d=" + d + ", i=" + i; } - /// CHECK-START: short Main.byteToDoubleToShort(byte) instruction_simplifier (before) + /// CHECK-START: short Main.$noinline$byteToDoubleToShort(byte) instruction_simplifier (before) /// CHECK-DAG: <<Arg:b\d+>> ParameterValue /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Double>>] /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<Int>>] /// CHECK-DAG: Return [<<Short>>] - /// CHECK-START: short Main.byteToDoubleToShort(byte) instruction_simplifier (after) + /// CHECK-START: short Main.$noinline$byteToDoubleToShort(byte) instruction_simplifier (after) /// CHECK-DAG: <<Arg:b\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - /// CHECK-START: short Main.byteToDoubleToShort(byte) instruction_simplifier (after) + /// CHECK-START: short Main.$noinline$byteToDoubleToShort(byte) instruction_simplifier (after) /// CHECK-NOT: TypeConversion - public static short byteToDoubleToShort(byte value) { + public static short $noinline$byteToDoubleToShort(byte value) { + if (doThrow) { throw new Error(); } // Originally, this is byte->double->int->short. The first conversion is lossless, // so we merge this with the second one to byte->int which we omit as it's an implicit // conversion. Then we eliminate the resulting byte->short as an implicit conversion. return (short) (double) value; } - /// CHECK-START: short Main.charToDoubleToShort(char) instruction_simplifier (before) + /// CHECK-START: short Main.$noinline$charToDoubleToShort(char) instruction_simplifier (before) /// CHECK-DAG: <<Arg:c\d+>> ParameterValue /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Double>>] /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<Int>>] /// CHECK-DAG: Return [<<Short>>] - /// CHECK-START: short Main.charToDoubleToShort(char) instruction_simplifier (after) + /// CHECK-START: short Main.$noinline$charToDoubleToShort(char) instruction_simplifier (after) /// CHECK-DAG: <<Arg:c\d+>> ParameterValue /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: Return [<<Short>>] - /// CHECK-START: short Main.charToDoubleToShort(char) instruction_simplifier (after) + /// CHECK-START: short Main.$noinline$charToDoubleToShort(char) instruction_simplifier (after) /// CHECK-DAG: TypeConversion /// CHECK-NOT: TypeConversion - public static short charToDoubleToShort(char value) { + public static short $noinline$charToDoubleToShort(char value) { + if (doThrow) { throw new Error(); } // Originally, this is char->double->int->short. The first conversion is lossless, // so we merge this with the second one to char->int which we omit as it's an implicit // conversion. Then we are left with the resulting char->short conversion. return (short) (double) value; } - /// CHECK-START: short Main.floatToIntToShort(float) instruction_simplifier (before) + /// CHECK-START: short Main.$noinline$floatToIntToShort(float) instruction_simplifier (before) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<Int>>] /// CHECK-DAG: Return [<<Short>>] - /// CHECK-START: short Main.floatToIntToShort(float) instruction_simplifier (after) + /// CHECK-START: short Main.$noinline$floatToIntToShort(float) instruction_simplifier (after) /// CHECK-DAG: <<Arg:f\d+>> ParameterValue /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<Int>>] /// CHECK-DAG: Return [<<Short>>] - public static short floatToIntToShort(float value) { + public static short $noinline$floatToIntToShort(float value) { + if (doThrow) { throw new Error(); } // Lossy FP to integral conversion followed by another conversion: no simplification. return (short) value; } - /// CHECK-START: int Main.intToFloatToInt(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$intToFloatToInt(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Float:f\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Float>>] /// CHECK-DAG: Return [<<Int>>] - /// CHECK-START: int Main.intToFloatToInt(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$intToFloatToInt(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Float:f\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Float>>] /// CHECK-DAG: Return [<<Int>>] - public static int intToFloatToInt(int value) { + public static int $noinline$intToFloatToInt(int value) { + if (doThrow) { throw new Error(); } // Lossy integral to FP conversion followed another conversion: no simplification. return (int) (float) value; } - /// CHECK-START: double Main.longToIntToDouble(long) instruction_simplifier (before) + /// CHECK-START: double Main.$noinline$longToIntToDouble(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Int>>] /// CHECK-DAG: Return [<<Double>>] - /// CHECK-START: double Main.longToIntToDouble(long) instruction_simplifier (after) + /// CHECK-START: double Main.$noinline$longToIntToDouble(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Int>>] /// CHECK-DAG: Return [<<Double>>] - public static double longToIntToDouble(long value) { + public static double $noinline$longToIntToDouble(long value) { + if (doThrow) { throw new Error(); } // Lossy long-to-int conversion followed an integral to FP conversion: no simplification. return (double) (int) value; } - /// CHECK-START: long Main.longToIntToLong(long) instruction_simplifier (before) + /// CHECK-START: long Main.$noinline$longToIntToLong(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Long:j\d+>> TypeConversion [<<Int>>] /// CHECK-DAG: Return [<<Long>>] - /// CHECK-START: long Main.longToIntToLong(long) instruction_simplifier (after) + /// CHECK-START: long Main.$noinline$longToIntToLong(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Long:j\d+>> TypeConversion [<<Int>>] /// CHECK-DAG: Return [<<Long>>] - public static long longToIntToLong(long value) { + public static long $noinline$longToIntToLong(long value) { + if (doThrow) { throw new Error(); } // Lossy long-to-int conversion followed an int-to-long conversion: no simplification. return (long) (int) value; } - /// CHECK-START: short Main.shortToCharToShort(short) instruction_simplifier (before) + /// CHECK-START: short Main.$noinline$shortToCharToShort(short) instruction_simplifier (before) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: <<Char:c\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<Char>>] /// CHECK-DAG: Return [<<Short>>] - /// CHECK-START: short Main.shortToCharToShort(short) instruction_simplifier (after) + /// CHECK-START: short Main.$noinline$shortToCharToShort(short) instruction_simplifier (after) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - public static short shortToCharToShort(short value) { + public static short $noinline$shortToCharToShort(short value) { + if (doThrow) { throw new Error(); } // Integral conversion followed by non-widening integral conversion to original type. return (short) (char) value; } - /// CHECK-START: int Main.shortToLongToInt(short) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$shortToLongToInt(short) instruction_simplifier (before) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: <<Long:j\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Int:i\d+>> TypeConversion [<<Long>>] /// CHECK-DAG: Return [<<Int>>] - /// CHECK-START: int Main.shortToLongToInt(short) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$shortToLongToInt(short) instruction_simplifier (after) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: Return [<<Arg>>] - public static int shortToLongToInt(short value) { + public static int $noinline$shortToLongToInt(short value) { + if (doThrow) { throw new Error(); } // Integral conversion followed by non-widening integral conversion, use implicit conversion. return (int) (long) value; } - /// CHECK-START: byte Main.shortToCharToByte(short) instruction_simplifier (before) + /// CHECK-START: byte Main.$noinline$shortToCharToByte(short) instruction_simplifier (before) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: <<Char:c\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: <<Byte:b\d+>> TypeConversion [<<Char>>] /// CHECK-DAG: Return [<<Byte>>] - /// CHECK-START: byte Main.shortToCharToByte(short) instruction_simplifier (after) + /// CHECK-START: byte Main.$noinline$shortToCharToByte(short) instruction_simplifier (after) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: <<Byte:b\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: Return [<<Byte>>] - public static byte shortToCharToByte(short value) { + public static byte $noinline$shortToCharToByte(short value) { + if (doThrow) { throw new Error(); } // Integral conversion followed by non-widening integral conversion losing bits // from the original type. Simplify to use only one conversion. return (byte) (char) value; } - /// CHECK-START: java.lang.String Main.shortToCharToBytePrint(short) instruction_simplifier (before) + /// CHECK-START: java.lang.String Main.$noinline$shortToCharToBytePrint(short) instruction_simplifier (before) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: <<Char:c\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: {{b\d+}} TypeConversion [<<Char>>] - /// CHECK-START: java.lang.String Main.shortToCharToBytePrint(short) instruction_simplifier (after) + /// CHECK-START: java.lang.String Main.$noinline$shortToCharToBytePrint(short) instruction_simplifier (after) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: <<Char:c\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: {{b\d+}} TypeConversion [<<Char>>] - public static String shortToCharToBytePrint(short value) { + public static String $noinline$shortToCharToBytePrint(short value) { + if (doThrow) { throw new Error(); } // Integral conversion followed by non-widening integral conversion losing bits // from the original type with an extra use of the intermediate result. char c = (char) value; @@ -1559,7 +1736,7 @@ public class Main { return "c=" + ((int) c) + ", b=" + ((int) b); // implicit conversions. } - /// CHECK-START: byte Main.longAnd0xffToByte(long) instruction_simplifier (before) + /// CHECK-START: byte Main.$noinline$longAnd0xffToByte(long) instruction_simplifier (before) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Mask:j\d+>> LongConstant 255 /// CHECK-DAG: <<And:j\d+>> And [<<Mask>>,<<Arg>>] @@ -1567,58 +1744,61 @@ public class Main { /// CHECK-DAG: <<Byte:b\d+>> TypeConversion [<<Int>>] /// CHECK-DAG: Return [<<Byte>>] - /// CHECK-START: byte Main.longAnd0xffToByte(long) instruction_simplifier (after) + /// CHECK-START: byte Main.$noinline$longAnd0xffToByte(long) instruction_simplifier (after) /// CHECK-DAG: <<Arg:j\d+>> ParameterValue /// CHECK-DAG: <<Byte:b\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: Return [<<Byte>>] - /// CHECK-START: byte Main.longAnd0xffToByte(long) instruction_simplifier (after) + /// CHECK-START: byte Main.$noinline$longAnd0xffToByte(long) instruction_simplifier (after) /// CHECK-NOT: And - public static byte longAnd0xffToByte(long value) { + public static byte $noinline$longAnd0xffToByte(long value) { + if (doThrow) { throw new Error(); } return (byte) (value & 0xff); } - /// CHECK-START: char Main.intAnd0x1ffffToChar(int) instruction_simplifier (before) + /// CHECK-START: char Main.$noinline$intAnd0x1ffffToChar(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Mask:i\d+>> IntConstant 131071 /// CHECK-DAG: <<And:i\d+>> And [<<Mask>>,<<Arg>>] /// CHECK-DAG: <<Char:c\d+>> TypeConversion [<<And>>] /// CHECK-DAG: Return [<<Char>>] - /// CHECK-START: char Main.intAnd0x1ffffToChar(int) instruction_simplifier (after) + /// CHECK-START: char Main.$noinline$intAnd0x1ffffToChar(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Char:c\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: Return [<<Char>>] - /// CHECK-START: char Main.intAnd0x1ffffToChar(int) instruction_simplifier (after) + /// CHECK-START: char Main.$noinline$intAnd0x1ffffToChar(int) instruction_simplifier (after) /// CHECK-NOT: And - public static char intAnd0x1ffffToChar(int value) { + public static char $noinline$intAnd0x1ffffToChar(int value) { + if (doThrow) { throw new Error(); } // Keeping all significant bits and one more. return (char) (value & 0x1ffff); } - /// CHECK-START: short Main.intAnd0x17fffToShort(int) instruction_simplifier (before) + /// CHECK-START: short Main.$noinline$intAnd0x17fffToShort(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Mask:i\d+>> IntConstant 98303 /// CHECK-DAG: <<And:i\d+>> And [<<Mask>>,<<Arg>>] /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<And>>] /// CHECK-DAG: Return [<<Short>>] - /// CHECK-START: short Main.intAnd0x17fffToShort(int) instruction_simplifier (after) + /// CHECK-START: short Main.$noinline$intAnd0x17fffToShort(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Mask:i\d+>> IntConstant 98303 /// CHECK-DAG: <<And:i\d+>> And [<<Mask>>,<<Arg>>] /// CHECK-DAG: <<Short:s\d+>> TypeConversion [<<And>>] /// CHECK-DAG: Return [<<Short>>] - public static short intAnd0x17fffToShort(int value) { + public static short $noinline$intAnd0x17fffToShort(int value) { + if (doThrow) { throw new Error(); } // No simplification: clearing a significant bit. return (short) (value & 0x17fff); } - /// CHECK-START: double Main.shortAnd0xffffToShortToDouble(short) instruction_simplifier (before) + /// CHECK-START: double Main.$noinline$shortAnd0xffffToShortToDouble(short) instruction_simplifier (before) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: <<Mask:i\d+>> IntConstant 65535 /// CHECK-DAG: <<And:i\d+>> And [<<Mask>>,<<Arg>>] @@ -1626,45 +1806,49 @@ public class Main { /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Same>>] /// CHECK-DAG: Return [<<Double>>] - /// CHECK-START: double Main.shortAnd0xffffToShortToDouble(short) instruction_simplifier (after) + /// CHECK-START: double Main.$noinline$shortAnd0xffffToShortToDouble(short) instruction_simplifier (after) /// CHECK-DAG: <<Arg:s\d+>> ParameterValue /// CHECK-DAG: <<Double:d\d+>> TypeConversion [<<Arg>>] /// CHECK-DAG: Return [<<Double>>] - public static double shortAnd0xffffToShortToDouble(short value) { + public static double $noinline$shortAnd0xffffToShortToDouble(short value) { + if (doThrow) { throw new Error(); } short same = (short) (value & 0xffff); return (double) same; } - /// CHECK-START: int Main.intReverseCondition(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$intReverseCondition(int) instruction_simplifier (before) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 /// CHECK-DAG: <<LE:z\d+>> LessThanOrEqual [<<Const42>>,<<Arg>>] - /// CHECK-START: int Main.intReverseCondition(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$intReverseCondition(int) instruction_simplifier (after) /// CHECK-DAG: <<Arg:i\d+>> ParameterValue /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42 /// CHECK-DAG: <<GE:z\d+>> GreaterThanOrEqual [<<Arg>>,<<Const42>>] - public static int intReverseCondition(int i) { + public static int $noinline$intReverseCondition(int i) { + if (doThrow) { throw new Error(); } return (42 > i) ? 13 : 54; } - /// CHECK-START: int Main.intReverseConditionNaN(int) instruction_simplifier (before) + /// CHECK-START: int Main.$noinline$intReverseConditionNaN(int) instruction_simplifier (before) /// CHECK-DAG: <<Const42:d\d+>> DoubleConstant 42 /// CHECK-DAG: <<Result:d\d+>> InvokeStaticOrDirect /// CHECK-DAG: <<CMP:i\d+>> Compare [<<Const42>>,<<Result>>] - /// CHECK-START: int Main.intReverseConditionNaN(int) instruction_simplifier (after) + /// CHECK-START: int Main.$noinline$intReverseConditionNaN(int) instruction_simplifier (after) /// CHECK-DAG: <<Const42:d\d+>> DoubleConstant 42 /// CHECK-DAG: <<Result:d\d+>> InvokeStaticOrDirect /// CHECK-DAG: <<EQ:z\d+>> Equal [<<Result>>,<<Const42>>] - public static int intReverseConditionNaN(int i) { + public static int $noinline$intReverseConditionNaN(int i) { + if (doThrow) { throw new Error(); } return (42 != Math.sqrt(i)) ? 13 : 54; } - public static int runSmaliTest(String name, boolean input) { + public static int $noinline$runSmaliTest(String name, boolean input) { + if (doThrow) { throw new Error(); } try { Class<?> c = Class.forName("SmaliTests"); Method m = c.getMethod(name, new Class[] { boolean.class }); @@ -1674,155 +1858,291 @@ public class Main { } } + public static int $noinline$runSmaliTestConst(String name, int arg) { + if (doThrow) { throw new Error(); } + try { + Class<?> c = Class.forName("SmaliTests"); + Method m = c.getMethod(name, int.class); + return (Integer) m.invoke(null, arg); + } catch (Exception ex) { + throw new Error(ex); + } + } + + /// CHECK-START: int Main.$noinline$intUnnecessaryShiftMasking(int, int) instruction_simplifier (before) + /// CHECK: <<Value:i\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<Const31:i\d+>> IntConstant 31 + /// CHECK-DAG: <<And:i\d+>> And [<<Shift>>,<<Const31>>] + /// CHECK-DAG: <<Shl:i\d+>> Shl [<<Value>>,<<And>>] + /// CHECK-DAG: Return [<<Shl>>] + + /// CHECK-START: int Main.$noinline$intUnnecessaryShiftMasking(int, int) instruction_simplifier (after) + /// CHECK: <<Value:i\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<Shl:i\d+>> Shl [<<Value>>,<<Shift>>] + /// CHECK-DAG: Return [<<Shl>>] + + public static int $noinline$intUnnecessaryShiftMasking(int value, int shift) { + if (doThrow) { throw new Error(); } + return value << (shift & 31); + } + + /// CHECK-START: long Main.$noinline$longUnnecessaryShiftMasking(long, int) instruction_simplifier (before) + /// CHECK: <<Value:j\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<Const63:i\d+>> IntConstant 63 + /// CHECK-DAG: <<And:i\d+>> And [<<Shift>>,<<Const63>>] + /// CHECK-DAG: <<Shr:j\d+>> Shr [<<Value>>,<<And>>] + /// CHECK-DAG: Return [<<Shr>>] + + /// CHECK-START: long Main.$noinline$longUnnecessaryShiftMasking(long, int) instruction_simplifier (after) + /// CHECK: <<Value:j\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<Shr:j\d+>> Shr [<<Value>>,<<Shift>>] + /// CHECK-DAG: Return [<<Shr>>] + + public static long $noinline$longUnnecessaryShiftMasking(long value, int shift) { + if (doThrow) { throw new Error(); } + return value >> (shift & 63); + } + + /// CHECK-START: int Main.$noinline$intUnnecessaryWiderShiftMasking(int, int) instruction_simplifier (before) + /// CHECK: <<Value:i\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<Const255:i\d+>> IntConstant 255 + /// CHECK-DAG: <<And:i\d+>> And [<<Shift>>,<<Const255>>] + /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Value>>,<<And>>] + /// CHECK-DAG: Return [<<UShr>>] + + /// CHECK-START: int Main.$noinline$intUnnecessaryWiderShiftMasking(int, int) instruction_simplifier (after) + /// CHECK: <<Value:i\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Value>>,<<Shift>>] + /// CHECK-DAG: Return [<<UShr>>] + + public static int $noinline$intUnnecessaryWiderShiftMasking(int value, int shift) { + if (doThrow) { throw new Error(); } + return value >>> (shift & 0xff); + } + + /// CHECK-START: long Main.$noinline$longSmallerShiftMasking(long, int) instruction_simplifier (before) + /// CHECK: <<Value:j\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 + /// CHECK-DAG: <<And:i\d+>> And [<<Shift>>,<<Const3>>] + /// CHECK-DAG: <<Shl:j\d+>> Shl [<<Value>>,<<And>>] + /// CHECK-DAG: Return [<<Shl>>] + + /// CHECK-START: long Main.$noinline$longSmallerShiftMasking(long, int) instruction_simplifier (after) + /// CHECK: <<Value:j\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 + /// CHECK-DAG: <<And:i\d+>> And [<<Shift>>,<<Const3>>] + /// CHECK-DAG: <<Shl:j\d+>> Shl [<<Value>>,<<And>>] + /// CHECK-DAG: Return [<<Shl>>] + + public static long $noinline$longSmallerShiftMasking(long value, int shift) { + if (doThrow) { throw new Error(); } + return value << (shift & 3); + } + + /// CHECK-START: int Main.$noinline$otherUseOfUnnecessaryShiftMasking(int, int) instruction_simplifier (before) + /// CHECK: <<Value:i\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<Const31:i\d+>> IntConstant 31 + /// CHECK-DAG: <<And:i\d+>> And [<<Shift>>,<<Const31>>] + /// CHECK-DAG: <<Shr:i\d+>> Shr [<<Value>>,<<And>>] + /// CHECK-DAG: <<Add:i\d+>> Add [<<Shr>>,<<And>>] + /// CHECK-DAG: Return [<<Add>>] + + /// CHECK-START: int Main.$noinline$otherUseOfUnnecessaryShiftMasking(int, int) instruction_simplifier (after) + /// CHECK: <<Value:i\d+>> ParameterValue + /// CHECK: <<Shift:i\d+>> ParameterValue + /// CHECK-DAG: <<Const31:i\d+>> IntConstant 31 + /// CHECK-DAG: <<And:i\d+>> And [<<Shift>>,<<Const31>>] + /// CHECK-DAG: <<Shr:i\d+>> Shr [<<Value>>,<<Shift>>] + /// CHECK-DAG: <<Add:i\d+>> Add [<<Shr>>,<<And>>] + /// CHECK-DAG: Return [<<Add>>] + + public static int $noinline$otherUseOfUnnecessaryShiftMasking(int value, int shift) { + if (doThrow) { throw new Error(); } + int temp = shift & 31; + return (value >> temp) + temp; + } + public static void main(String[] args) { int arg = 123456; - assertLongEquals(Add0(arg), arg); - assertIntEquals(AndAllOnes(arg), arg); - assertLongEquals(Div1(arg), arg); - assertIntEquals(DivN1(arg), -arg); - assertLongEquals(Mul1(arg), arg); - assertIntEquals(MulN1(arg), -arg); - assertLongEquals(MulPowerOfTwo128(arg), (128 * arg)); - assertIntEquals(Or0(arg), arg); - assertLongEquals(OrSame(arg), arg); - assertIntEquals(Shl0(arg), arg); - assertLongEquals(Shr0(arg), arg); - assertLongEquals(Shr64(arg), arg); - assertLongEquals(Sub0(arg), arg); - assertIntEquals(SubAliasNeg(arg), -arg); - assertLongEquals(UShr0(arg), arg); - assertIntEquals(Xor0(arg), arg); - assertIntEquals(XorAllOnes(arg), ~arg); - assertIntEquals(AddNegs1(arg, arg + 1), -(arg + arg + 1)); - assertIntEquals(AddNegs2(arg, arg + 1), -(arg + arg + 1)); - assertLongEquals(AddNegs3(arg, arg + 1), -(2 * arg + 1)); - assertLongEquals(AddNeg1(arg, arg + 1), 1); - assertLongEquals(AddNeg2(arg, arg + 1), -1); - assertLongEquals(NegNeg1(arg), arg); - assertIntEquals(NegNeg2(arg), 0); - assertLongEquals(NegNeg3(arg), arg); - assertIntEquals(NegSub1(arg, arg + 1), 1); - assertIntEquals(NegSub2(arg, arg + 1), 1); - assertLongEquals(NotNot1(arg), arg); - assertIntEquals(NotNot2(arg), -1); - assertIntEquals(SubNeg1(arg, arg + 1), -(arg + arg + 1)); - assertIntEquals(SubNeg2(arg, arg + 1), -(arg + arg + 1)); - assertLongEquals(SubNeg3(arg, arg + 1), -(2 * arg + 1)); - assertBooleanEquals(EqualBoolVsIntConst(true), true); - assertBooleanEquals(EqualBoolVsIntConst(true), true); - assertBooleanEquals(NotEqualBoolVsIntConst(false), false); - assertBooleanEquals(NotEqualBoolVsIntConst(false), false); - assertBooleanEquals(NotNotBool(true), true); - assertBooleanEquals(NotNotBool(false), false); - assertFloatEquals(Div2(100.0f), 50.0f); - assertDoubleEquals(Div2(150.0), 75.0); - assertFloatEquals(DivMP25(100.0f), -400.0f); - assertDoubleEquals(DivMP25(150.0), -600.0); - assertIntEquals(UShr28And15(0xc1234567), 0xc); - assertLongEquals(UShr60And15(0xc123456787654321L), 0xcL); - assertIntEquals(UShr28And7(0xc1234567), 0x4); - assertLongEquals(UShr60And7(0xc123456787654321L), 0x4L); - assertIntEquals(Shr24And255(0xc1234567), 0xc1); - assertLongEquals(Shr56And255(0xc123456787654321L), 0xc1L); - assertIntEquals(Shr24And127(0xc1234567), 0x41); - assertLongEquals(Shr56And127(0xc123456787654321L), 0x41L); - assertIntEquals(0, mulPow2Plus1(0)); - assertIntEquals(9, mulPow2Plus1(1)); - assertIntEquals(18, mulPow2Plus1(2)); - assertIntEquals(900, mulPow2Plus1(100)); - assertIntEquals(111105, mulPow2Plus1(12345)); - assertLongEquals(0, mulPow2Minus1(0)); - assertLongEquals(31, mulPow2Minus1(1)); - assertLongEquals(62, mulPow2Minus1(2)); - assertLongEquals(3100, mulPow2Minus1(100)); - assertLongEquals(382695, mulPow2Minus1(12345)); + assertLongEquals(arg, $noinline$Add0(arg)); + assertIntEquals(5, $noinline$AddAddSubAddConst(1)); + assertIntEquals(arg, $noinline$AndAllOnes(arg)); + assertLongEquals(arg, $noinline$Div1(arg)); + assertIntEquals(-arg, $noinline$DivN1(arg)); + assertLongEquals(arg, $noinline$Mul1(arg)); + assertIntEquals(-arg, $noinline$MulN1(arg)); + assertLongEquals((128 * arg), $noinline$MulPowerOfTwo128(arg)); + assertLongEquals(2640, $noinline$MulMulMulConst(2)); + assertIntEquals(arg, $noinline$Or0(arg)); + assertLongEquals(arg, $noinline$OrSame(arg)); + assertIntEquals(arg, $noinline$Shl0(arg)); + assertLongEquals(arg, $noinline$Shr0(arg)); + assertLongEquals(arg, $noinline$Shr64(arg)); + assertLongEquals(arg, $noinline$Sub0(arg)); + assertIntEquals(-arg, $noinline$SubAliasNeg(arg)); + assertIntEquals(9, $noinline$SubAddConst1(2)); + assertIntEquals(-2, $noinline$SubAddConst2(3)); + assertLongEquals(3, $noinline$SubSubConst(4)); + assertLongEquals(arg, $noinline$UShr0(arg)); + assertIntEquals(arg, $noinline$Xor0(arg)); + assertIntEquals(~arg, $noinline$XorAllOnes(arg)); + assertIntEquals(-(arg + arg + 1), $noinline$AddNegs1(arg, arg + 1)); + assertIntEquals(-(arg + arg + 1), $noinline$AddNegs2(arg, arg + 1)); + assertLongEquals(-(2 * arg + 1), $noinline$AddNegs3(arg, arg + 1)); + assertLongEquals(1, $noinline$AddNeg1(arg, arg + 1)); + assertLongEquals(-1, $noinline$AddNeg2(arg, arg + 1)); + assertLongEquals(arg, $noinline$NegNeg1(arg)); + assertIntEquals(0, $noinline$NegNeg2(arg)); + assertLongEquals(arg, $noinline$NegNeg3(arg)); + assertIntEquals(1, $noinline$NegSub1(arg, arg + 1)); + assertIntEquals(1, $noinline$NegSub2(arg, arg + 1)); + assertLongEquals(arg, $noinline$NotNot1(arg)); + assertIntEquals(-1, $noinline$NotNot2(arg)); + assertIntEquals(-(arg + arg + 1), $noinline$SubNeg1(arg, arg + 1)); + assertIntEquals(-(arg + arg + 1), $noinline$SubNeg2(arg, arg + 1)); + assertLongEquals(-(2 * arg + 1), $noinline$SubNeg3(arg, arg + 1)); + assertBooleanEquals(true, $noinline$EqualBoolVsIntConst(true)); + assertBooleanEquals(true, $noinline$EqualBoolVsIntConst(true)); + assertBooleanEquals(false, $noinline$NotEqualBoolVsIntConst(false)); + assertBooleanEquals(false, $noinline$NotEqualBoolVsIntConst(false)); + assertBooleanEquals(true, $noinline$NotNotBool(true)); + assertBooleanEquals(false, $noinline$NotNotBool(false)); + assertFloatEquals(50.0f, $noinline$Div2(100.0f)); + assertDoubleEquals(75.0, $noinline$Div2(150.0)); + assertFloatEquals(-400.0f, $noinline$DivMP25(100.0f)); + assertDoubleEquals(-600.0, $noinline$DivMP25(150.0)); + assertIntEquals(0xc, $noinline$UShr28And15(0xc1234567)); + assertLongEquals(0xcL, $noinline$UShr60And15(0xc123456787654321L)); + assertIntEquals(0x4, $noinline$UShr28And7(0xc1234567)); + assertLongEquals(0x4L, $noinline$UShr60And7(0xc123456787654321L)); + assertIntEquals(0xc1, $noinline$Shr24And255(0xc1234567)); + assertLongEquals(0xc1L, $noinline$Shr56And255(0xc123456787654321L)); + assertIntEquals(0x41, $noinline$Shr24And127(0xc1234567)); + assertLongEquals(0x41L, $noinline$Shr56And127(0xc123456787654321L)); + assertIntEquals(0, $noinline$mulPow2Plus1(0)); + assertIntEquals(9, $noinline$mulPow2Plus1(1)); + assertIntEquals(18, $noinline$mulPow2Plus1(2)); + assertIntEquals(900, $noinline$mulPow2Plus1(100)); + assertIntEquals(111105, $noinline$mulPow2Plus1(12345)); + assertLongEquals(0, $noinline$mulPow2Minus1(0)); + assertLongEquals(31, $noinline$mulPow2Minus1(1)); + assertLongEquals(62, $noinline$mulPow2Minus1(2)); + assertLongEquals(3100, $noinline$mulPow2Minus1(100)); + assertLongEquals(382695, $noinline$mulPow2Minus1(12345)); booleanField = false; - assertIntEquals(booleanFieldNotEqualOne(), 54); - assertIntEquals(booleanFieldEqualZero(), 54); + assertIntEquals($noinline$booleanFieldNotEqualOne(), 54); + assertIntEquals($noinline$booleanFieldEqualZero(), 54); booleanField = true; - assertIntEquals(booleanFieldNotEqualOne(), 13); - assertIntEquals(booleanFieldEqualZero(), 13); - assertIntEquals(intConditionNotEqualOne(6), 54); - assertIntEquals(intConditionNotEqualOne(43), 13); - assertIntEquals(intConditionEqualZero(6), 54); - assertIntEquals(intConditionEqualZero(43), 13); - assertIntEquals(floatConditionNotEqualOne(6.0f), 54); - assertIntEquals(floatConditionNotEqualOne(43.0f), 13); - assertIntEquals(doubleConditionEqualZero(6.0), 54); - assertIntEquals(doubleConditionEqualZero(43.0), 13); - - assertIntEquals(1234567, intToDoubleToInt(1234567)); - assertIntEquals(Integer.MIN_VALUE, intToDoubleToInt(Integer.MIN_VALUE)); - assertIntEquals(Integer.MAX_VALUE, intToDoubleToInt(Integer.MAX_VALUE)); - assertStringEquals("d=7654321.0, i=7654321", intToDoubleToIntPrint(7654321)); - assertIntEquals(12, byteToDoubleToInt((byte) 12)); - assertIntEquals(Byte.MIN_VALUE, byteToDoubleToInt(Byte.MIN_VALUE)); - assertIntEquals(Byte.MAX_VALUE, byteToDoubleToInt(Byte.MAX_VALUE)); - assertIntEquals(11, floatToDoubleToInt(11.3f)); - assertStringEquals("d=12.25, i=12", floatToDoubleToIntPrint(12.25f)); - assertIntEquals(123, byteToDoubleToShort((byte) 123)); - assertIntEquals(Byte.MIN_VALUE, byteToDoubleToShort(Byte.MIN_VALUE)); - assertIntEquals(Byte.MAX_VALUE, byteToDoubleToShort(Byte.MAX_VALUE)); - assertIntEquals(1234, charToDoubleToShort((char) 1234)); - assertIntEquals(Character.MIN_VALUE, charToDoubleToShort(Character.MIN_VALUE)); - assertIntEquals(/* sign-extended */ -1, charToDoubleToShort(Character.MAX_VALUE)); - assertIntEquals(12345, floatToIntToShort(12345.75f)); - assertIntEquals(Short.MAX_VALUE, floatToIntToShort((float)(Short.MIN_VALUE - 1))); - assertIntEquals(Short.MIN_VALUE, floatToIntToShort((float)(Short.MAX_VALUE + 1))); - assertIntEquals(-54321, intToFloatToInt(-54321)); - assertDoubleEquals((double) 0x12345678, longToIntToDouble(0x1234567812345678L)); - assertDoubleEquals(0.0, longToIntToDouble(Long.MIN_VALUE)); - assertDoubleEquals(-1.0, longToIntToDouble(Long.MAX_VALUE)); - assertLongEquals(0x0000000012345678L, longToIntToLong(0x1234567812345678L)); - assertLongEquals(0xffffffff87654321L, longToIntToLong(0x1234567887654321L)); - assertLongEquals(0L, longToIntToLong(Long.MIN_VALUE)); - assertLongEquals(-1L, longToIntToLong(Long.MAX_VALUE)); - assertIntEquals((short) -5678, shortToCharToShort((short) -5678)); - assertIntEquals(Short.MIN_VALUE, shortToCharToShort(Short.MIN_VALUE)); - assertIntEquals(Short.MAX_VALUE, shortToCharToShort(Short.MAX_VALUE)); - assertIntEquals(5678, shortToLongToInt((short) 5678)); - assertIntEquals(Short.MIN_VALUE, shortToLongToInt(Short.MIN_VALUE)); - assertIntEquals(Short.MAX_VALUE, shortToLongToInt(Short.MAX_VALUE)); - assertIntEquals(0x34, shortToCharToByte((short) 0x1234)); - assertIntEquals(-0x10, shortToCharToByte((short) 0x12f0)); - assertIntEquals(0, shortToCharToByte(Short.MIN_VALUE)); - assertIntEquals(-1, shortToCharToByte(Short.MAX_VALUE)); - assertStringEquals("c=1025, b=1", shortToCharToBytePrint((short) 1025)); - assertStringEquals("c=1023, b=-1", shortToCharToBytePrint((short) 1023)); - assertStringEquals("c=65535, b=-1", shortToCharToBytePrint((short) -1)); - - assertIntEquals(0x21, longAnd0xffToByte(0x1234432112344321L)); - assertIntEquals(0, longAnd0xffToByte(Long.MIN_VALUE)); - assertIntEquals(-1, longAnd0xffToByte(Long.MAX_VALUE)); - assertIntEquals(0x1234, intAnd0x1ffffToChar(0x43211234)); - assertIntEquals(0, intAnd0x1ffffToChar(Integer.MIN_VALUE)); - assertIntEquals(Character.MAX_VALUE, intAnd0x1ffffToChar(Integer.MAX_VALUE)); - assertIntEquals(0x4321, intAnd0x17fffToShort(0x87654321)); - assertIntEquals(0x0888, intAnd0x17fffToShort(0x88888888)); - assertIntEquals(0, intAnd0x17fffToShort(Integer.MIN_VALUE)); - assertIntEquals(Short.MAX_VALUE, intAnd0x17fffToShort(Integer.MAX_VALUE)); - - assertDoubleEquals(0.0, shortAnd0xffffToShortToDouble((short) 0)); - assertDoubleEquals(1.0, shortAnd0xffffToShortToDouble((short) 1)); - assertDoubleEquals(-2.0, shortAnd0xffffToShortToDouble((short) -2)); - assertDoubleEquals(12345.0, shortAnd0xffffToShortToDouble((short) 12345)); - assertDoubleEquals((double)Short.MAX_VALUE, shortAnd0xffffToShortToDouble(Short.MAX_VALUE)); - assertDoubleEquals((double)Short.MIN_VALUE, shortAnd0xffffToShortToDouble(Short.MIN_VALUE)); - - assertIntEquals(intReverseCondition(41), 13); - assertIntEquals(intReverseConditionNaN(-5), 13); + assertIntEquals(13, $noinline$booleanFieldNotEqualOne()); + assertIntEquals(13, $noinline$booleanFieldEqualZero()); + assertIntEquals(54, $noinline$intConditionNotEqualOne(6)); + assertIntEquals(13, $noinline$intConditionNotEqualOne(43)); + assertIntEquals(54, $noinline$intConditionEqualZero(6)); + assertIntEquals(13, $noinline$intConditionEqualZero(43)); + assertIntEquals(54, $noinline$floatConditionNotEqualOne(6.0f)); + assertIntEquals(13, $noinline$floatConditionNotEqualOne(43.0f)); + assertIntEquals(54, $noinline$doubleConditionEqualZero(6.0)); + assertIntEquals(13, $noinline$doubleConditionEqualZero(43.0)); + + assertIntEquals(1234567, $noinline$intToDoubleToInt(1234567)); + assertIntEquals(Integer.MIN_VALUE, $noinline$intToDoubleToInt(Integer.MIN_VALUE)); + assertIntEquals(Integer.MAX_VALUE, $noinline$intToDoubleToInt(Integer.MAX_VALUE)); + assertStringEquals("d=7654321.0, i=7654321", $noinline$intToDoubleToIntPrint(7654321)); + assertIntEquals(12, $noinline$byteToDoubleToInt((byte) 12)); + assertIntEquals(Byte.MIN_VALUE, $noinline$byteToDoubleToInt(Byte.MIN_VALUE)); + assertIntEquals(Byte.MAX_VALUE, $noinline$byteToDoubleToInt(Byte.MAX_VALUE)); + assertIntEquals(11, $noinline$floatToDoubleToInt(11.3f)); + assertStringEquals("d=12.25, i=12", $noinline$floatToDoubleToIntPrint(12.25f)); + assertIntEquals(123, $noinline$byteToDoubleToShort((byte) 123)); + assertIntEquals(Byte.MIN_VALUE, $noinline$byteToDoubleToShort(Byte.MIN_VALUE)); + assertIntEquals(Byte.MAX_VALUE, $noinline$byteToDoubleToShort(Byte.MAX_VALUE)); + assertIntEquals(1234, $noinline$charToDoubleToShort((char) 1234)); + assertIntEquals(Character.MIN_VALUE, $noinline$charToDoubleToShort(Character.MIN_VALUE)); + assertIntEquals(/* sign-extended */ -1, $noinline$charToDoubleToShort(Character.MAX_VALUE)); + assertIntEquals(12345, $noinline$floatToIntToShort(12345.75f)); + assertIntEquals(Short.MAX_VALUE, $noinline$floatToIntToShort((float)(Short.MIN_VALUE - 1))); + assertIntEquals(Short.MIN_VALUE, $noinline$floatToIntToShort((float)(Short.MAX_VALUE + 1))); + assertIntEquals(-54321, $noinline$intToFloatToInt(-54321)); + assertDoubleEquals((double) 0x12345678, $noinline$longToIntToDouble(0x1234567812345678L)); + assertDoubleEquals(0.0, $noinline$longToIntToDouble(Long.MIN_VALUE)); + assertDoubleEquals(-1.0, $noinline$longToIntToDouble(Long.MAX_VALUE)); + assertLongEquals(0x0000000012345678L, $noinline$longToIntToLong(0x1234567812345678L)); + assertLongEquals(0xffffffff87654321L, $noinline$longToIntToLong(0x1234567887654321L)); + assertLongEquals(0L, $noinline$longToIntToLong(Long.MIN_VALUE)); + assertLongEquals(-1L, $noinline$longToIntToLong(Long.MAX_VALUE)); + assertIntEquals((short) -5678, $noinline$shortToCharToShort((short) -5678)); + assertIntEquals(Short.MIN_VALUE, $noinline$shortToCharToShort(Short.MIN_VALUE)); + assertIntEquals(Short.MAX_VALUE, $noinline$shortToCharToShort(Short.MAX_VALUE)); + assertIntEquals(5678, $noinline$shortToLongToInt((short) 5678)); + assertIntEquals(Short.MIN_VALUE, $noinline$shortToLongToInt(Short.MIN_VALUE)); + assertIntEquals(Short.MAX_VALUE, $noinline$shortToLongToInt(Short.MAX_VALUE)); + assertIntEquals(0x34, $noinline$shortToCharToByte((short) 0x1234)); + assertIntEquals(-0x10, $noinline$shortToCharToByte((short) 0x12f0)); + assertIntEquals(0, $noinline$shortToCharToByte(Short.MIN_VALUE)); + assertIntEquals(-1, $noinline$shortToCharToByte(Short.MAX_VALUE)); + assertStringEquals("c=1025, b=1", $noinline$shortToCharToBytePrint((short) 1025)); + assertStringEquals("c=1023, b=-1", $noinline$shortToCharToBytePrint((short) 1023)); + assertStringEquals("c=65535, b=-1", $noinline$shortToCharToBytePrint((short) -1)); + + assertIntEquals(0x21, $noinline$longAnd0xffToByte(0x1234432112344321L)); + assertIntEquals(0, $noinline$longAnd0xffToByte(Long.MIN_VALUE)); + assertIntEquals(-1, $noinline$longAnd0xffToByte(Long.MAX_VALUE)); + assertIntEquals(0x1234, $noinline$intAnd0x1ffffToChar(0x43211234)); + assertIntEquals(0, $noinline$intAnd0x1ffffToChar(Integer.MIN_VALUE)); + assertIntEquals(Character.MAX_VALUE, $noinline$intAnd0x1ffffToChar(Integer.MAX_VALUE)); + assertIntEquals(0x4321, $noinline$intAnd0x17fffToShort(0x87654321)); + assertIntEquals(0x0888, $noinline$intAnd0x17fffToShort(0x88888888)); + assertIntEquals(0, $noinline$intAnd0x17fffToShort(Integer.MIN_VALUE)); + assertIntEquals(Short.MAX_VALUE, $noinline$intAnd0x17fffToShort(Integer.MAX_VALUE)); + + assertDoubleEquals(0.0, $noinline$shortAnd0xffffToShortToDouble((short) 0)); + assertDoubleEquals(1.0, $noinline$shortAnd0xffffToShortToDouble((short) 1)); + assertDoubleEquals(-2.0, $noinline$shortAnd0xffffToShortToDouble((short) -2)); + assertDoubleEquals(12345.0, $noinline$shortAnd0xffffToShortToDouble((short) 12345)); + assertDoubleEquals((double)Short.MAX_VALUE, + $noinline$shortAnd0xffffToShortToDouble(Short.MAX_VALUE)); + assertDoubleEquals((double)Short.MIN_VALUE, + $noinline$shortAnd0xffffToShortToDouble(Short.MIN_VALUE)); + + assertIntEquals(13, $noinline$intReverseCondition(41)); + assertIntEquals(13, $noinline$intReverseConditionNaN(-5)); for (String condition : new String[] { "Equal", "NotEqual" }) { for (String constant : new String[] { "True", "False" }) { for (String side : new String[] { "Rhs", "Lhs" }) { String name = condition + constant + side; - assertIntEquals(runSmaliTest(name, true), 5); - assertIntEquals(runSmaliTest(name, false), 3); + assertIntEquals(5, $noinline$runSmaliTest(name, true)); + assertIntEquals(3, $noinline$runSmaliTest(name, false)); } } } + + assertIntEquals(0, $noinline$runSmaliTestConst("AddSubConst", 1)); + assertIntEquals(3, $noinline$runSmaliTestConst("SubAddConst", 2)); + assertIntEquals(-16, $noinline$runSmaliTestConst("SubSubConst1", 3)); + assertIntEquals(-5, $noinline$runSmaliTestConst("SubSubConst2", 4)); + assertIntEquals(26, $noinline$runSmaliTestConst("SubSubConst3", 5)); + assertIntEquals(0x5e6f7808, $noinline$intUnnecessaryShiftMasking(0xabcdef01, 3)); + assertIntEquals(0x5e6f7808, $noinline$intUnnecessaryShiftMasking(0xabcdef01, 3 + 32)); + assertLongEquals(0xffffffffffffeaf3L, $noinline$longUnnecessaryShiftMasking(0xabcdef0123456789L, 50)); + assertLongEquals(0xffffffffffffeaf3L, $noinline$longUnnecessaryShiftMasking(0xabcdef0123456789L, 50 + 64)); + assertIntEquals(0x2af37b, $noinline$intUnnecessaryWiderShiftMasking(0xabcdef01, 10)); + assertIntEquals(0x2af37b, $noinline$intUnnecessaryWiderShiftMasking(0xabcdef01, 10 + 128)); + assertLongEquals(0xaf37bc048d159e24L, $noinline$longSmallerShiftMasking(0xabcdef0123456789L, 2)); + assertLongEquals(0xaf37bc048d159e24L, $noinline$longSmallerShiftMasking(0xabcdef0123456789L, 2 + 256)); + assertIntEquals(0xfffd5e7c, $noinline$otherUseOfUnnecessaryShiftMasking(0xabcdef01, 13)); + assertIntEquals(0xfffd5e7c, $noinline$otherUseOfUnnecessaryShiftMasking(0xabcdef01, 13 + 512)); } private static boolean $inline$true() { return true; } diff --git a/test/478-checker-clinit-check-pruning/expected.txt b/test/478-checker-clinit-check-pruning/expected.txt index 7de097f666..6f73b656ed 100644 --- a/test/478-checker-clinit-check-pruning/expected.txt +++ b/test/478-checker-clinit-check-pruning/expected.txt @@ -10,3 +10,4 @@ Main$ClassWithClinit9's static initializer Main$ClassWithClinit10's static initializer Main$ClassWithClinit11's static initializer Main$ClassWithClinit12's static initializer +Main$ClassWithClinit13's static initializer diff --git a/test/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java index 79935134b4..6fc12f138c 100644 --- a/test/478-checker-clinit-check-pruning/src/Main.java +++ b/test/478-checker-clinit-check-pruning/src/Main.java @@ -16,6 +16,8 @@ public class Main { + static boolean doThrow = false; + /* * Ensure an inlined static invoke explicitly triggers the * initialization check of the called method's declaring class, and @@ -310,12 +312,12 @@ public class Main { /// CHECK-START: void Main.constClassAndInvokeStatic(java.lang.Iterable) liveness (before) /// CHECK-NOT: ClinitCheck - static void constClassAndInvokeStatic(Iterable it) { + static void constClassAndInvokeStatic(Iterable<?> it) { $opt$inline$ignoreClass(ClassWithClinit7.class); ClassWithClinit7.someStaticMethod(it); } - static void $opt$inline$ignoreClass(Class c) { + static void $opt$inline$ignoreClass(Class<?> c) { } static class ClassWithClinit7 { @@ -324,7 +326,7 @@ public class Main { } // Note: not inlined from constClassAndInvokeStatic() but fully inlined from main(). - static void someStaticMethod(Iterable it) { + static void someStaticMethod(Iterable<?> it) { // We're not inlining invoke-interface at the moment. it.iterator(); } @@ -341,7 +343,7 @@ public class Main { /// CHECK-START: void Main.sgetAndInvokeStatic(java.lang.Iterable) liveness (before) /// CHECK-NOT: ClinitCheck - static void sgetAndInvokeStatic(Iterable it) { + static void sgetAndInvokeStatic(Iterable<?> it) { $opt$inline$ignoreInt(ClassWithClinit8.value); ClassWithClinit8.someStaticMethod(it); } @@ -356,7 +358,7 @@ public class Main { } // Note: not inlined from sgetAndInvokeStatic() but fully inlined from main(). - static void someStaticMethod(Iterable it) { + static void someStaticMethod(Iterable<?> it) { // We're not inlining invoke-interface at the moment. it.iterator(); } @@ -372,7 +374,7 @@ public class Main { /// CHECK: ClinitCheck /// CHECK: InvokeStaticOrDirect clinit_check:none - static void constClassSgetAndInvokeStatic(Iterable it) { + static void constClassSgetAndInvokeStatic(Iterable<?> it) { $opt$inline$ignoreClass(ClassWithClinit9.class); $opt$inline$ignoreInt(ClassWithClinit9.value); ClassWithClinit9.someStaticMethod(it); @@ -385,7 +387,7 @@ public class Main { } // Note: not inlined from constClassSgetAndInvokeStatic() but fully inlined from main(). - static void someStaticMethod(Iterable it) { + static void someStaticMethod(Iterable<?> it) { // We're not inlining invoke-interface at the moment. it.iterator(); } @@ -403,12 +405,12 @@ public class Main { /// CHECK-START: void Main.inlinedInvokeStaticViaNonStatic(java.lang.Iterable) liveness (before) /// CHECK-NOT: ClinitCheck - static void inlinedInvokeStaticViaNonStatic(Iterable it) { + static void inlinedInvokeStaticViaNonStatic(Iterable<?> it) { inlinedInvokeStaticViaNonStaticHelper(null); inlinedInvokeStaticViaNonStaticHelper(it); } - static void inlinedInvokeStaticViaNonStaticHelper(Iterable it) { + static void inlinedInvokeStaticViaNonStaticHelper(Iterable<?> it) { ClassWithClinit10.inlinedForNull(it); } @@ -418,7 +420,7 @@ public class Main { System.out.println("Main$ClassWithClinit10's static initializer"); } - static void inlinedForNull(Iterable it) { + static void inlinedForNull(Iterable<?> it) { if (it != null) { // We're not inlining invoke-interface at the moment. it.iterator(); @@ -443,7 +445,7 @@ public class Main { /// CHECK-START: void Main.inlinedInvokeStaticViaStatic(java.lang.Iterable) liveness (before) /// CHECK-NOT: ClinitCheck - static void inlinedInvokeStaticViaStatic(Iterable it) { + static void inlinedInvokeStaticViaStatic(Iterable<?> it) { ClassWithClinit11.callInlinedForNull(it); } @@ -453,11 +455,11 @@ public class Main { System.out.println("Main$ClassWithClinit11's static initializer"); } - static void callInlinedForNull(Iterable it) { + static void callInlinedForNull(Iterable<?> it) { inlinedForNull(it); } - static void inlinedForNull(Iterable it) { + static void inlinedForNull(Iterable<?> it) { // We're not inlining invoke-interface at the moment. it.iterator(); } @@ -475,7 +477,7 @@ public class Main { /// CHECK-START: void Main.inlinedInvokeStaticViaStaticTwice(java.lang.Iterable) liveness (before) /// CHECK-NOT: ClinitCheck - static void inlinedInvokeStaticViaStaticTwice(Iterable it) { + static void inlinedInvokeStaticViaStaticTwice(Iterable<?> it) { ClassWithClinit12.callInlinedForNull(null); ClassWithClinit12.callInlinedForNull(it); } @@ -486,11 +488,11 @@ public class Main { System.out.println("Main$ClassWithClinit12's static initializer"); } - static void callInlinedForNull(Iterable it) { + static void callInlinedForNull(Iterable<?> it) { inlinedForNull(it); } - static void inlinedForNull(Iterable it) { + static void inlinedForNull(Iterable<?> it) { if (it != null) { // We're not inlining invoke-interface at the moment. it.iterator(); @@ -498,6 +500,28 @@ public class Main { } } + static class ClassWithClinit13 { + static { + System.out.println("Main$ClassWithClinit13's static initializer"); + } + + public static void $inline$forwardToGetIterator(Iterable<?> it) { + $noinline$getIterator(it); + } + + public static void $noinline$getIterator(Iterable<?> it) { + // We're not inlining invoke-interface at the moment. + it.iterator(); + } + } + + // TODO: Write checker statements. + static Object $noinline$testInliningAndNewInstance(Iterable<?> it) { + if (doThrow) { throw new Error(); } + ClassWithClinit13.$inline$forwardToGetIterator(it); + return new ClassWithClinit13(); + } + // TODO: Add a test for the case of a static method whose declaring // class type index is not available (i.e. when `storage_index` // equals `DexFile::kDexNoIndex` in @@ -517,5 +541,6 @@ public class Main { inlinedInvokeStaticViaNonStatic(it); inlinedInvokeStaticViaStatic(it); inlinedInvokeStaticViaStaticTwice(it); + $noinline$testInliningAndNewInstance(it); } } diff --git a/test/530-checker-loops1/src/Main.java b/test/530-checker-loops1/src/Main.java index 948a7b7dcc..dde4d62475 100644 --- a/test/530-checker-loops1/src/Main.java +++ b/test/530-checker-loops1/src/Main.java @@ -562,7 +562,7 @@ public class Main { // /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (after) /// CHECK-NOT: BoundsCheck - // TODO: also CHECK-NOT: Deoptimize, see b/27151190 + /// CHECK-NOT: Deoptimize private static void linearTriangularOnTwoArrayLengths(int n) { int[] a = new int[n]; for (int i = 0; i < a.length; i++) { @@ -604,7 +604,7 @@ public class Main { // /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (after) /// CHECK-NOT: BoundsCheck - // TODO: also CHECK-NOT: Deoptimize, see b/27151190 + /// CHECK-NOT: Deoptimize private static void linearTriangularOnParameter(int n) { int[] a = new int[n]; for (int i = 0; i < n; i++) { @@ -619,56 +619,56 @@ public class Main { } } - /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (before) + /// CHECK-START: void Main.linearTriangularStrictLower(int) BCE (before) /// CHECK-DAG: BoundsCheck /// CHECK-DAG: BoundsCheck /// CHECK-DAG: BoundsCheck /// CHECK-DAG: BoundsCheck // - /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (after) + /// CHECK-START: void Main.linearTriangularStrictLower(int) BCE (after) /// CHECK-NOT: BoundsCheck - // TODO: also CHECK-NOT: Deoptimize, see b/27151190 - private static void linearTriangularVariationsInnerStrict(int n) { + /// CHECK-NOT: Deoptimize + private static void linearTriangularStrictLower(int n) { int[] a = new int[n]; for (int i = 0; i < n; i++) { for (int j = 0; j < i; j++) { a[j] += 1; } - for (int j = i - 1; j > -1; j--) { + for (int j = i - 1; j >= 0; j--) { a[j] += 1; } for (int j = i; j < n; j++) { a[j] += 1; } - for (int j = n - 1; j > i - 1; j--) { + for (int j = n - 1; j >= i; j--) { a[j] += 1; } } verifyTriangular(a); } - /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (before) + /// CHECK-START: void Main.linearTriangularStrictUpper(int) BCE (before) /// CHECK-DAG: BoundsCheck /// CHECK-DAG: BoundsCheck /// CHECK-DAG: BoundsCheck /// CHECK-DAG: BoundsCheck // - /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (after) + /// CHECK-START: void Main.linearTriangularStrictUpper(int) BCE (after) /// CHECK-NOT: BoundsCheck - // TODO: also CHECK-NOT: Deoptimize, see b/27151190 - private static void linearTriangularVariationsInnerNonStrict(int n) { + /// CHECK-NOT: Deoptimize + private static void linearTriangularStrictUpper(int n) { int[] a = new int[n]; for (int i = 0; i < n; i++) { - for (int j = 0; j <= i - 1; j++) { + for (int j = 0; j <= i; j++) { a[j] += 1; } - for (int j = i - 1; j >= 0; j--) { + for (int j = i; j >= 0; j--) { a[j] += 1; } - for (int j = i; j <= n - 1; j++) { + for (int j = i + 1; j < n; j++) { a[j] += 1; } - for (int j = n - 1; j >= i; j--) { + for (int j = n - 1; j >= i + 1; j--) { a[j] += 1; } } @@ -802,8 +802,8 @@ public class Main { linearTriangularOnTwoArrayLengths(10); linearTriangularOnOneArrayLength(10); linearTriangularOnParameter(10); - linearTriangularVariationsInnerStrict(10); - linearTriangularVariationsInnerNonStrict(10); + linearTriangularStrictLower(10); + linearTriangularStrictUpper(10); { int[] t = linearTriangularOOB(); for (int i = 0; i < 200; i++) { diff --git a/test/530-checker-loops2/src/Main.java b/test/530-checker-loops2/src/Main.java index b12fbd6091..7acf0080f8 100644 --- a/test/530-checker-loops2/src/Main.java +++ b/test/530-checker-loops2/src/Main.java @@ -31,7 +31,7 @@ public class Main { // /// CHECK-START: void Main.bubble(int[]) BCE (after) /// CHECK-NOT: BoundsCheck - // TODO: also CHECK-NOT: Deoptimize, see b/27151190 + /// CHECK-NOT: Deoptimize private static void bubble(int[] a) { for (int i = a.length; --i >= 0;) { for (int j = 0; j < i; j++) { @@ -301,6 +301,53 @@ public class Main { } while (-1 <= i); } + /// CHECK-START: void Main.justRightTriangular1() BCE (before) + /// CHECK-DAG: BoundsCheck + // + /// CHECK-START: void Main.justRightTriangular1() BCE (after) + /// CHECK-NOT: BoundsCheck + /// CHECK-NOT: Deoptimize + private static void justRightTriangular1() { + int[] a = { 1 } ; + for (int i = Integer.MIN_VALUE + 5; i <= Integer.MIN_VALUE + 10; i++) { + for (int j = Integer.MIN_VALUE + 4; j < i - 5; j++) { + sResult += a[j - (Integer.MIN_VALUE + 4)]; + } + } + } + + /// CHECK-START: void Main.justRightTriangular2() BCE (before) + /// CHECK-DAG: BoundsCheck + // + /// CHECK-START: void Main.justRightTriangular2() BCE (after) + /// CHECK-NOT: BoundsCheck + /// CHECK-NOT: Deoptimize + private static void justRightTriangular2() { + int[] a = { 1 } ; + for (int i = Integer.MIN_VALUE + 5; i <= 10; i++) { + for (int j = 4; j < i - 5; j++) { + sResult += a[j - 4]; + } + } + } + + /// CHECK-START: void Main.justOOBTriangular() BCE (before) + /// CHECK-DAG: BoundsCheck + // + /// CHECK-START: void Main.justOOBTriangular() BCE (after) + /// CHECK-DAG: Deoptimize + // + /// CHECK-START: void Main.justOOBTriangular() BCE (after) + /// CHECK-NOT: BoundsCheck + private static void justOOBTriangular() { + int[] a = { 1 } ; + for (int i = Integer.MIN_VALUE + 4; i <= 10; i++) { + for (int j = 4; j < i - 5; j++) { + sResult += a[j - 4]; + } + } + } + /// CHECK-START: void Main.hiddenOOB1(int) BCE (before) /// CHECK-DAG: BoundsCheck // @@ -315,7 +362,6 @@ public class Main { // Dangerous loop where careless static range analysis would yield strict upper bound // on index j of 5. When, for instance, lo and thus i = -2147483648, the upper bound // becomes really positive due to arithmetic wrap-around, causing OOB. - // Dynamic BCE is feasible though, since it checks the range. for (int j = 4; j < i - 5; j++) { sResult += a[j - 4]; } @@ -336,13 +382,32 @@ public class Main { // Dangerous loop where careless static range analysis would yield strict lower bound // on index j of 5. When, for instance, hi and thus i = 2147483647, the upper bound // becomes really negative due to arithmetic wrap-around, causing OOB. - // Dynamic BCE is feasible though, since it checks the range. for (int j = 6; j > i + 5; j--) { sResult += a[j - 6]; } } } + /// CHECK-START: void Main.hiddenOOB3(int) BCE (before) + /// CHECK-DAG: BoundsCheck + // + /// CHECK-START: void Main.hiddenOOB3(int) BCE (after) + /// CHECK-DAG: Deoptimize + // + /// CHECK-START: void Main.hiddenOOB3(int) BCE (after) + /// CHECK-NOT: BoundsCheck + private static void hiddenOOB3(int hi) { + int[] a = { 11 } ; + for (int i = -1; i <= hi; i++) { + // Dangerous loop where careless static range analysis would yield strict lower bound + // on index j of 0. For large i, the initial value of j becomes really negative due + // to arithmetic wrap-around, causing OOB. + for (int j = i + 1; j < 1; j++) { + sResult += a[j]; + } + } + } + /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (before) /// CHECK-DAG: BoundsCheck // @@ -376,7 +441,6 @@ public class Main { for (int i = -1; i <= 0; i++) { // Dangerous loop similar as above where the loop is now finite, but the // loop still goes out of bounds for i = -1 due to the large upper bound. - // Dynamic BCE is feasible though, since it checks the range. for (int j = -4; j < 2147483646 * i - 3; j++) { sResult += a[j + 4]; } @@ -432,6 +496,25 @@ public class Main { } } + /// CHECK-START: int Main.doNotHoist(int[]) BCE (before) + /// CHECK-DAG: BoundsCheck + // + /// CHECK-START: int Main.doNotHoist(int[]) BCE (after) + /// CHECK-NOT: BoundsCheck + public static int doNotHoist(int[] a) { + int n = a.length; + int x = 0; + // BCE applies, but hoisting would crash the loop. + for (int i = -10000; i < 10000; i++) { + for (int j = 0; j <= 1; j++) { + if (0 <= i && i < n) + x += a[i]; + } + } + return x; + } + + /// CHECK-START: int[] Main.add() BCE (before) /// CHECK-DAG: BoundsCheck // @@ -687,7 +770,7 @@ public class Main { /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after) // Order matters: /// CHECK: Deoptimize loop:<<Loop:B\d+>> - // CHECK-NOT: Goto loop:<<Loop>> + /// CHECK-NOT: Goto loop:<<Loop>> /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>> /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>> /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>> @@ -839,6 +922,8 @@ public class Main { expectEquals(55, justRightDown1()); expectEquals(55, justRightDown2()); expectEquals(55, justRightDown3()); + + // Large bounds OOB. sResult = 0; try { justOOBUp(); @@ -890,6 +975,23 @@ public class Main { } expectEquals(1055, sResult); + // Triangular. + sResult = 0; + justRightTriangular1(); + expectEquals(1, sResult); + if (HEAVY) { + sResult = 0; + justRightTriangular2(); + expectEquals(1, sResult); + } + sResult = 0; + try { + justOOBTriangular(); + } catch (ArrayIndexOutOfBoundsException e) { + sResult += 1000; + } + expectEquals(1001, sResult); + // Hidden OOB. sResult = 0; try { @@ -912,6 +1014,15 @@ public class Main { sResult += 1000; } expectEquals(1, sResult); + sResult = 0; + try { + hiddenOOB3(-1); // no OOB + } catch (ArrayIndexOutOfBoundsException e) { + sResult += 1000; + } + expectEquals(11, sResult); + + // Expensive hidden OOB test. if (HEAVY) { sResult = 0; try { @@ -920,7 +1031,16 @@ public class Main { sResult += 1000; } expectEquals(1002, sResult); + sResult = 0; + try { + hiddenOOB3(2147483647); // OOB + } catch (ArrayIndexOutOfBoundsException e) { + sResult += 1000; + } + expectEquals(1011, sResult); } + + // More hidden OOB. sResult = 0; try { hiddenInfiniteOOB(); @@ -966,6 +1086,9 @@ public class Main { expectEquals(i < 128 ? i : 0, a200[i]); } + // No hoisting after BCE. + expectEquals(110, doNotHoist(x)); + // Addition. { int[] e1 ={ 1, 2, 3, 4, 4, 4, 4, 3, 2, 1 }; diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java index 24ed2feff7..26475ae55c 100644 --- a/test/536-checker-intrinsic-optimization/src/Main.java +++ b/test/536-checker-intrinsic-optimization/src/Main.java @@ -30,6 +30,18 @@ public class Main { } } + public static void assertCharEquals(char expected, char result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + public static void assertStringContains(String searchTerm, String result) { + if (result == null || !result.contains(searchTerm)) { + throw new Error("Search term: " + searchTerm + ", not found in: " + result); + } + } + public static void main(String[] args) { stringEqualsSame(); stringArgumentNotNull("Foo"); @@ -41,6 +53,57 @@ public class Main { assertBooleanEquals(true, $opt$noinline$isStringEmpty("")); assertBooleanEquals(false, $opt$noinline$isStringEmpty("abc")); assertBooleanEquals(false, $opt$noinline$isStringEmpty("0123456789")); + + assertCharEquals('a', $opt$noinline$stringCharAt("a", 0)); + assertCharEquals('a', $opt$noinline$stringCharAt("abc", 0)); + assertCharEquals('b', $opt$noinline$stringCharAt("abc", 1)); + assertCharEquals('c', $opt$noinline$stringCharAt("abc", 2)); + assertCharEquals('7', $opt$noinline$stringCharAt("0123456789", 7)); + + try { + $opt$noinline$stringCharAt("abc", -1); + throw new Error("Should throw SIOOB."); + } catch (StringIndexOutOfBoundsException sioob) { + assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); + assertStringContains("Main.$opt$noinline$stringCharAt", sioob.getStackTrace()[1].toString()); + } + try { + $opt$noinline$stringCharAt("abc", 3); + throw new Error("Should throw SIOOB."); + } catch (StringIndexOutOfBoundsException sioob) { + assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); + assertStringContains("Main.$opt$noinline$stringCharAt", sioob.getStackTrace()[1].toString()); + } + try { + $opt$noinline$stringCharAt("abc", Integer.MAX_VALUE); + throw new Error("Should throw SIOOB."); + } catch (StringIndexOutOfBoundsException sioob) { + assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); + assertStringContains("Main.$opt$noinline$stringCharAt", sioob.getStackTrace()[1].toString()); + } + + assertCharEquals('7', $opt$noinline$stringCharAtCatch("0123456789", 7)); + assertCharEquals('\0', $opt$noinline$stringCharAtCatch("0123456789", 10)); + + assertIntEquals('a' + 'b' + 'c', $opt$noinline$stringSumChars("abc")); + assertIntEquals('a' + 'b' + 'c', $opt$noinline$stringSumLeadingChars("abcdef", 3)); + try { + $opt$noinline$stringSumLeadingChars("abcdef", 7); + throw new Error("Should throw SIOOB."); + } catch (StringIndexOutOfBoundsException sioob) { + assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); + assertStringContains("Main.$opt$noinline$stringSumLeadingChars", + sioob.getStackTrace()[1].toString()); + } + assertIntEquals('a' + 'b' + 'c' + 'd', $opt$noinline$stringSum4LeadingChars("abcdef")); + try { + $opt$noinline$stringSum4LeadingChars("abc"); + throw new Error("Should throw SIOOB."); + } catch (StringIndexOutOfBoundsException sioob) { + assertStringContains("java.lang.String.charAt", sioob.getStackTrace()[0].toString()); + assertStringContains("Main.$opt$noinline$stringSum4LeadingChars", + sioob.getStackTrace()[1].toString()); + } } /// CHECK-START: int Main.$opt$noinline$getStringLength(java.lang.String) instruction_simplifier (before) @@ -81,6 +144,144 @@ public class Main { return s.isEmpty(); } + /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) instruction_simplifier (before) + /// CHECK-DAG: <<Char:c\d+>> InvokeVirtual intrinsic:StringCharAt + /// CHECK-DAG: Return [<<Char>>] + + /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) instruction_simplifier (after) + /// CHECK-DAG: <<String:l\d+>> ParameterValue + /// CHECK-DAG: <<Pos:i\d+>> ParameterValue + /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>] + /// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true + /// CHECK-DAG: BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true + /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Pos>>] is_string_char_at:true + /// CHECK-DAG: Return [<<Char>>] + + /// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) instruction_simplifier (after) + /// CHECK-NOT: InvokeVirtual intrinsic:StringCharAt + + static public char $opt$noinline$stringCharAt(String s, int pos) { + if (doThrow) { throw new Error(); } + return s.charAt(pos); + } + + /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (before) + /// CHECK-DAG: <<Char:c\d+>> InvokeVirtual intrinsic:StringCharAt + /// CHECK-DAG: Return [<<Char>>] + + /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (after) + /// CHECK-DAG: <<String:l\d+>> ParameterValue + /// CHECK-DAG: <<Pos:i\d+>> ParameterValue + /// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>] + /// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true + /// CHECK-DAG: BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true + /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Pos>>] is_string_char_at:true + /// CHECK-DAG: Return [<<Char>>] + + /// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (after) + /// CHECK-NOT: InvokeVirtual intrinsic:StringCharAt + + static public char $opt$noinline$stringCharAtCatch(String s, int pos) { + if (doThrow) { throw new Error(); } + try { + return s.charAt(pos); + } catch (StringIndexOutOfBoundsException ignored) { + return '\0'; + } + } + + /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) instruction_simplifier (before) + /// CHECK-DAG: InvokeVirtual intrinsic:StringLength + /// CHECK-DAG: InvokeVirtual intrinsic:StringCharAt + + /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) instruction_simplifier (after) + /// CHECK-DAG: ArrayLength is_string_length:true + /// CHECK-DAG: ArrayLength is_string_length:true + /// CHECK-DAG: BoundsCheck is_string_char_at:true + /// CHECK-DAG: ArrayGet is_string_char_at:true + + /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) instruction_simplifier (after) + /// CHECK-NOT: InvokeVirtual intrinsic:StringLength + /// CHECK-NOT: InvokeVirtual intrinsic:StringCharAt + + /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) GVN (after) + /// CHECK-DAG: ArrayLength is_string_length:true + /// CHECK-NOT: ArrayLength is_string_length:true + + /// CHECK-START: int Main.$opt$noinline$stringSumChars(java.lang.String) BCE (after) + /// CHECK-NOT: BoundsCheck + + static public int $opt$noinline$stringSumChars(String s) { + if (doThrow) { throw new Error(); } + int sum = 0; + int len = s.length(); + for (int i = 0; i < len; ++i) { + sum += s.charAt(i); + } + return sum; + } + + /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) instruction_simplifier (before) + /// CHECK-DAG: InvokeVirtual intrinsic:StringCharAt + + /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) instruction_simplifier (after) + /// CHECK-DAG: ArrayLength is_string_length:true + /// CHECK-DAG: BoundsCheck is_string_char_at:true + /// CHECK-DAG: ArrayGet is_string_char_at:true + + /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) instruction_simplifier (after) + /// CHECK-NOT: InvokeVirtual intrinsic:StringCharAt + + /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) BCE (after) + /// CHECK-DAG: Deoptimize env:[[{{[^\]]*}}]] + + /// CHECK-START: int Main.$opt$noinline$stringSumLeadingChars(java.lang.String, int) BCE (after) + /// CHECK-NOT: BoundsCheck is_string_char_at:true + + static public int $opt$noinline$stringSumLeadingChars(String s, int n) { + if (doThrow) { throw new Error(); } + int sum = 0; + for (int i = 0; i < n; ++i) { + sum += s.charAt(i); + } + return sum; + } + + /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) instruction_simplifier (before) + /// CHECK-DAG: InvokeVirtual intrinsic:StringCharAt + /// CHECK-DAG: InvokeVirtual intrinsic:StringCharAt + /// CHECK-DAG: InvokeVirtual intrinsic:StringCharAt + /// CHECK-DAG: InvokeVirtual intrinsic:StringCharAt + + /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) instruction_simplifier (after) + /// CHECK-DAG: ArrayLength is_string_length:true + /// CHECK-DAG: BoundsCheck is_string_char_at:true + /// CHECK-DAG: ArrayGet is_string_char_at:true + /// CHECK-DAG: ArrayLength is_string_length:true + /// CHECK-DAG: BoundsCheck is_string_char_at:true + /// CHECK-DAG: ArrayGet is_string_char_at:true + /// CHECK-DAG: ArrayLength is_string_length:true + /// CHECK-DAG: BoundsCheck is_string_char_at:true + /// CHECK-DAG: ArrayGet is_string_char_at:true + /// CHECK-DAG: ArrayLength is_string_length:true + /// CHECK-DAG: BoundsCheck is_string_char_at:true + /// CHECK-DAG: ArrayGet is_string_char_at:true + + /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) instruction_simplifier (after) + /// CHECK-NOT: InvokeVirtual intrinsic:StringCharAt + + /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) BCE (after) + /// CHECK-DAG: Deoptimize env:[[{{[^\]]*}}]] + + /// CHECK-START: int Main.$opt$noinline$stringSum4LeadingChars(java.lang.String) BCE (after) + /// CHECK-NOT: BoundsCheck is_string_char_at:true + + static public int $opt$noinline$stringSum4LeadingChars(String s) { + if (doThrow) { throw new Error(); } + int sum = s.charAt(0) + s.charAt(1) + s.charAt(2) + s.charAt(3); + return sum; + } + /// CHECK-START: boolean Main.stringEqualsSame() instruction_simplifier (before) /// CHECK: InvokeStaticOrDirect diff --git a/test/552-checker-sharpening/src/Main.java b/test/552-checker-sharpening/src/Main.java index 3d985bfaf0..09a77ed285 100644 --- a/test/552-checker-sharpening/src/Main.java +++ b/test/552-checker-sharpening/src/Main.java @@ -28,6 +28,12 @@ public class Main { } } + public static void assertClassEquals(Class<?> expected, Class<?> result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + public static boolean doThrow = false; private static int $noinline$foo(int x) { @@ -251,6 +257,66 @@ public class Main { return "non-boot-image-string"; } + /// CHECK-START: java.lang.Class Main.$noinline$getStringClass() sharpening (before) + /// CHECK: LoadClass load_kind:DexCacheViaMethod class_name:java.lang.String + + /// CHECK-START-X86: java.lang.Class Main.$noinline$getStringClass() sharpening (after) + // Note: load kind depends on PIC/non-PIC + // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. + /// CHECK: LoadClass load_kind:{{BootImageAddress|DexCachePcRelative|DexCacheViaMethod}} class_name:java.lang.String + + /// CHECK-START-X86_64: java.lang.Class Main.$noinline$getStringClass() sharpening (after) + // Note: load kind depends on PIC/non-PIC + // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. + /// CHECK: LoadClass load_kind:{{BootImageAddress|DexCachePcRelative|DexCacheViaMethod}} class_name:java.lang.String + + /// CHECK-START-ARM: java.lang.Class Main.$noinline$getStringClass() sharpening (after) + // Note: load kind depends on PIC/non-PIC + // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. + /// CHECK: LoadClass load_kind:{{BootImageAddress|DexCachePcRelative|DexCacheViaMethod}} class_name:java.lang.String + + /// CHECK-START-ARM64: java.lang.Class Main.$noinline$getStringClass() sharpening (after) + // Note: load kind depends on PIC/non-PIC + // TODO: Remove DexCacheViaMethod when read barrier config supports BootImageAddress. + /// CHECK: LoadClass load_kind:{{BootImageAddress|DexCachePcRelative|DexCacheViaMethod}} class_name:java.lang.String + + public static Class<?> $noinline$getStringClass() { + // Prevent inlining to avoid the string comparison being optimized away. + if (doThrow) { throw new Error(); } + // String class is known to be in the boot image. + return String.class; + } + + /// CHECK-START: java.lang.Class Main.$noinline$getOtherClass() sharpening (before) + /// CHECK: LoadClass load_kind:DexCacheViaMethod class_name:Other + + /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) + /// CHECK: LoadClass load_kind:DexCachePcRelative class_name:Other + + /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (after) + /// CHECK-DAG: X86ComputeBaseMethodAddress + /// CHECK-DAG: LoadClass load_kind:DexCachePcRelative class_name:Other + + /// CHECK-START-X86_64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) + /// CHECK: LoadClass load_kind:DexCachePcRelative class_name:Other + + /// CHECK-START-ARM: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) + /// CHECK: LoadClass load_kind:DexCachePcRelative class_name:Other + + /// CHECK-START-ARM: java.lang.Class Main.$noinline$getOtherClass() dex_cache_array_fixups_arm (after) + /// CHECK-DAG: ArmDexCacheArraysBase + /// CHECK-DAG: LoadClass load_kind:DexCachePcRelative class_name:Other + + /// CHECK-START-ARM64: java.lang.Class Main.$noinline$getOtherClass() sharpening (after) + /// CHECK: LoadClass load_kind:DexCachePcRelative class_name:Other + + public static Class<?> $noinline$getOtherClass() { + // Prevent inlining to avoid the string comparison being optimized away. + if (doThrow) { throw new Error(); } + // Other class is not in the boot image. + return Other.class; + } + public static void main(String[] args) { assertIntEquals(1, testSimple(1)); assertIntEquals(1, testDiamond(false, 1)); @@ -262,5 +328,10 @@ public class Main { assertIntEquals(-6, testLoopWithDiamond(new int[]{ 3, 4 }, true, 1)); assertStringEquals("", $noinline$getBootImageString()); assertStringEquals("non-boot-image-string", $noinline$getNonBootImageString()); + assertClassEquals(String.class, $noinline$getStringClass()); + assertClassEquals(Other.class, $noinline$getOtherClass()); } } + +class Other { +} diff --git a/test/600-verifier-fails/expected.txt b/test/600-verifier-fails/expected.txt index 8399969a2d..eaa0c933c4 100644 --- a/test/600-verifier-fails/expected.txt +++ b/test/600-verifier-fails/expected.txt @@ -2,3 +2,4 @@ passed A passed B passed C passed D +passed E diff --git a/test/600-verifier-fails/src/Main.java b/test/600-verifier-fails/src/Main.java index 64c3d5c16a..fa25d58e43 100644 --- a/test/600-verifier-fails/src/Main.java +++ b/test/600-verifier-fails/src/Main.java @@ -38,7 +38,6 @@ public class Main { test("B"); test("C"); test("D"); - // TODO: enable again - // test("E"); + test("E"); } } diff --git a/test/608-checker-unresolved-lse/expected.txt b/test/608-checker-unresolved-lse/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/608-checker-unresolved-lse/expected.txt diff --git a/test/608-checker-unresolved-lse/info.txt b/test/608-checker-unresolved-lse/info.txt new file mode 100644 index 0000000000..466d5f44ec --- /dev/null +++ b/test/608-checker-unresolved-lse/info.txt @@ -0,0 +1,3 @@ +Regression test for the load store elimination optimization, +which used to wrongly remove field stores in the presence of +unresolved accesses. diff --git a/test/608-checker-unresolved-lse/run b/test/608-checker-unresolved-lse/run new file mode 100644 index 0000000000..226891f65a --- /dev/null +++ b/test/608-checker-unresolved-lse/run @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Copyright (C) 2016 The Android Open Source Project +# +# 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. + +# Use secondary switch to add secondary dex file to class path. +exec ${RUN} "${@}" --secondary diff --git a/test/608-checker-unresolved-lse/src-dex2oat-unresolved/MissingSuperClass.java b/test/608-checker-unresolved-lse/src-dex2oat-unresolved/MissingSuperClass.java new file mode 100644 index 0000000000..b11b9be78e --- /dev/null +++ b/test/608-checker-unresolved-lse/src-dex2oat-unresolved/MissingSuperClass.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +public class MissingSuperClass { +} diff --git a/test/608-checker-unresolved-lse/src/Main.java b/test/608-checker-unresolved-lse/src/Main.java new file mode 100644 index 0000000000..c6f8854b49 --- /dev/null +++ b/test/608-checker-unresolved-lse/src/Main.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +// We make Main extend an unresolved super class. This will lead to an +// unresolved access to Foo.field, as we won't know if Main can access +// a package private field. +public class Main extends MissingSuperClass { + + public static void main(String[] args) { + instanceFieldTest(); + staticFieldTest(); + instanceFieldTest2(); + } + + /// CHECK-START: void Main.instanceFieldTest() inliner (before) + /// CHECK-NOT: InstanceFieldSet + + /// CHECK-START: void Main.instanceFieldTest() inliner (after) + /// CHECK: InstanceFieldSet + /// CHECK: UnresolvedInstanceFieldGet + + // Load store elimination used to remove the InstanceFieldSet, thinking + // that the UnresolvedInstanceFieldGet was not related. However inlining + // can put you in a situation where the UnresolvedInstanceFieldGet resolves + // to the same field as the one in InstanceFieldSet. So the InstanceFieldSet + // must be preserved. + + /// CHECK-START: void Main.instanceFieldTest() load_store_elimination (after) + /// CHECK: InstanceFieldSet + /// CHECK: UnresolvedInstanceFieldGet + public static void instanceFieldTest() { + Foo f = new Foo(); + if (f.iField != 42) { + throw new Error("Expected 42, got " + f.iField); + } + } + + /// CHECK-START: void Main.instanceFieldTest2() inliner (before) + /// CHECK-NOT: InstanceFieldSet + /// CHECK-NOT: InstanceFieldGet + + /// CHECK-START: void Main.instanceFieldTest2() inliner (after) + /// CHECK: InstanceFieldSet + /// CHECK: InstanceFieldGet + /// CHECK: UnresolvedInstanceFieldSet + /// CHECK: InstanceFieldGet + + // Load store elimination will eliminate the first InstanceFieldGet because + // it simply follows an InstanceFieldSet. It must however not eliminate the second + // InstanceFieldGet, as the UnresolvedInstanceFieldSet might resolve to the same + // field. + + /// CHECK-START: void Main.instanceFieldTest2() load_store_elimination (after) + /// CHECK: InstanceFieldSet + /// CHECK-NOT: InstanceFieldGet + /// CHECK: UnresolvedInstanceFieldSet + /// CHECK: InstanceFieldGet + public static void instanceFieldTest2() { + Foo f = new Foo(); + int a = f.$inline$GetInstanceField(); + f.iField = 43; + a = f.$inline$GetInstanceField(); + if (a != 43) { + throw new Error("Expected 43, got " + a); + } + } + + /// CHECK-START: void Main.staticFieldTest() inliner (before) + /// CHECK-NOT: StaticFieldSet + + /// CHECK-START: void Main.staticFieldTest() inliner (after) + /// CHECK: StaticFieldSet + /// CHECK: StaticFieldSet + /// CHECK: UnresolvedStaticFieldGet + + /// CHECK-START: void Main.staticFieldTest() load_store_elimination (after) + /// CHECK: StaticFieldSet + /// CHECK: StaticFieldSet + /// CHECK: UnresolvedStaticFieldGet + public static void staticFieldTest() { + // Ensure Foo is initialized. + Foo f = new Foo(); + f.$inline$StaticSet42(); + f.$inline$StaticSet43(); + if (Foo.sField != 43) { + throw new Error("Expected 43, got " + Foo.sField); + } + } +} + +class Foo { + // field needs to be package-private to make the access in Main.main + // unresolved. + int iField; + static int sField; + + public void $inline$StaticSet42() { + sField = 42; + } + + public void $inline$StaticSet43() { + sField = 43; + } + + public int $inline$GetInstanceField() { + return iField; + } + + // Constructor needs to be public to get it resolved in Main.main + // and therefore inlined. + public Foo() { + iField = 42; + } +} diff --git a/test/Android.libarttest.mk b/test/Android.libarttest.mk index 859847449b..01790aea12 100644 --- a/test/Android.libarttest.mk +++ b/test/Android.libarttest.mk @@ -25,6 +25,7 @@ LIBARTTEST_COMMON_SRC_FILES := \ 004-SignalTest/signaltest.cc \ 004-ReferenceMap/stack_walk_refmap_jni.cc \ 004-StackWalk/stack_walk_jni.cc \ + 004-ThreadStress/thread_stress.cc \ 004-UnsafeTest/unsafe_test.cc \ 044-proxy/native_proxy.cc \ 051-thread/thread_test.cc \ diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index ee651b5494..dd6b6f3fbc 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -209,9 +209,10 @@ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES), $(IMAGE_TYPES), $(PICTEST_TYPES), $(DEBUGGABLE_TYPES), $(ART_TEST_RUN_TEST_SKIP), $(ALL_ADDRESS_SIZES)) -# Disable 137-cfi (b/27391690). +# Disable 149-suspend-all-stress, its output is flaky (b/28988206). # Disable 577-profile-foreign-dex (b/27454772). TEST_ART_BROKEN_ALL_TARGET_TESTS := \ + 149-suspend-all-stress \ 577-profile-foreign-dex \ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \ @@ -293,7 +294,8 @@ TEST_ART_BROKEN_NO_PREBUILD_TESTS := \ 147-stripped-dex-fallback \ 554-jit-profile-file \ 529-checker-unresolved \ - 555-checker-regression-x86const + 555-checker-regression-x86const \ + 608-checker-unresolved-lse ifneq (,$(filter no-prebuild,$(PREBUILD_TYPES))) ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),no-prebuild, \ diff --git a/test/dexdump/all.dex b/test/dexdump/all.dex Binary files differnew file mode 100644 index 0000000000..caf678da4a --- /dev/null +++ b/test/dexdump/all.dex diff --git a/test/dexdump/all.lst b/test/dexdump/all.lst new file mode 100644 index 0000000000..17ab9cacdd --- /dev/null +++ b/test/dexdump/all.lst @@ -0,0 +1,21 @@ +#all.dex +0x0000043c 8 A <init> ()V (none) -1 +0x00000454 58 A arrays ()V (none) -1 +0x000004a0 130 A binary_ops ()V (none) -1 +0x00000534 66 A binary_ops_2addr ()V (none) -1 +0x00000588 34 A binary_ops_lit16 ()V (none) -1 +0x000005bc 46 A binary_ops_lit8 ()V (none) -1 +0x000005fc 22 A compares ()V (none) -1 +0x00000624 50 A conditionals ()V (none) -1 +0x00000668 56 A constants ()V (none) -1 +0x000006b0 108 A misc ()V (none) -1 +0x0000072c 46 A moves ()V (none) -1 +0x0000076c 32 A packed_switch ()V (none) -1 +0x0000079c 2 A return32 ()I (none) -1 +0x000007b0 2 A return64 ()I (none) -1 +0x000007c4 2 A return_object ()Ljava/lang/Object; (none) -1 +0x000007d8 44 A sparse_switch ()V (none) -1 +0x00000814 58 A static_fields ()V (none) -1 +0x00000860 44 A unary_ops ()V (none) -1 +0x0000089c 58 A instance_fields ()V (none) -1 +0x000008e8 30 A invokes ()V (none) -1 diff --git a/test/dexdump/all.txt b/test/dexdump/all.txt new file mode 100644 index 0000000000..af4fb4c12c --- /dev/null +++ b/test/dexdump/all.txt @@ -0,0 +1,622 @@ +Processing 'all.dex'... +Opened 'all.dex', DEX version '035' +DEX file header: +magic : 'dex\n035\0' +checksum : d5134208 +signature : 7af6...100f +file_size : 2572 +header_size : 112 +link_size : 0 +link_off : 0 (0x000000) +string_ids_size : 46 +string_ids_off : 112 (0x000070) +type_ids_size : 10 +type_ids_off : 296 (0x000128) +proto_ids_size : 3 +proto_ids_off : 336 (0x000150) +field_ids_size : 14 +field_ids_off : 372 (0x000174) +method_ids_size : 21 +method_ids_off : 484 (0x0001e4) +class_defs_size : 1 +class_defs_off : 652 (0x00028c) +data_size : 1888 +data_off : 684 (0x0002ac) + +Class #0 header: +class_idx : 4 +access_flags : 1 (0x0001) +superclass_idx : 5 +interfaces_off : 0 (0x000000) +source_file_idx : -1 +annotations_off : 0 (0x000000) +class_data_off : 2310 (0x000906) +static_fields_size : 7 +instance_fields_size: 7 +direct_methods_size : 18 +virtual_methods_size: 2 + +Class #0 - + Class descriptor : 'LA;' + Access flags : 0x0001 (PUBLIC) + Superclass : 'Ljava/lang/Object;' + Interfaces - + Static fields - + #0 : (in LA;) + name : 'sB' + type : 'B' + access : 0x000a (PRIVATE STATIC) + #1 : (in LA;) + name : 'sC' + type : 'C' + access : 0x000a (PRIVATE STATIC) + #2 : (in LA;) + name : 'sI' + type : 'I' + access : 0x000a (PRIVATE STATIC) + #3 : (in LA;) + name : 'sJ' + type : 'J' + access : 0x000a (PRIVATE STATIC) + #4 : (in LA;) + name : 'sO' + type : 'LA;' + access : 0x000a (PRIVATE STATIC) + #5 : (in LA;) + name : 'sS' + type : 'S' + access : 0x000a (PRIVATE STATIC) + #6 : (in LA;) + name : 'sZ' + type : 'Z' + access : 0x000a (PRIVATE STATIC) + Instance fields - + #0 : (in LA;) + name : 'mB' + type : 'B' + access : 0x0002 (PRIVATE) + #1 : (in LA;) + name : 'mC' + type : 'C' + access : 0x0002 (PRIVATE) + #2 : (in LA;) + name : 'mI' + type : 'I' + access : 0x0002 (PRIVATE) + #3 : (in LA;) + name : 'mJ' + type : 'J' + access : 0x0002 (PRIVATE) + #4 : (in LA;) + name : 'mO' + type : 'LA;' + access : 0x0002 (PRIVATE) + #5 : (in LA;) + name : 'mS' + type : 'S' + access : 0x0002 (PRIVATE) + #6 : (in LA;) + name : 'mZ' + type : 'Z' + access : 0x0002 (PRIVATE) + Direct methods - + #0 : (in LA;) + name : '<init>' + type : '()V' + access : 0x10001 (PUBLIC CONSTRUCTOR) + code - + registers : 1 + ins : 1 + outs : 1 + insns size : 4 16-bit code units +00042c: |[00042c] A.<init>:()V +00043c: 7010 1400 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0014 +000442: 0e00 |0003: return-void + catches : (none) + positions : + locals : + + #1 : (in LA;) + name : 'arrays' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 3 + ins : 0 + outs : 0 + insns size : 29 16-bit code units +000444: |[000444] A.arrays:()V +000454: 4400 0102 |0000: aget v0, v1, v2 +000458: 4500 0102 |0002: aget-wide v0, v1, v2 +00045c: 4600 0102 |0004: aget-object v0, v1, v2 +000460: 4700 0102 |0006: aget-boolean v0, v1, v2 +000464: 4800 0102 |0008: aget-byte v0, v1, v2 +000468: 4900 0102 |000a: aget-char v0, v1, v2 +00046c: 4a00 0102 |000c: aget-short v0, v1, v2 +000470: 4b00 0102 |000e: aput v0, v1, v2 +000474: 4c00 0102 |0010: aput-wide v0, v1, v2 +000478: 4d00 0102 |0012: aput-object v0, v1, v2 +00047c: 4e00 0102 |0014: aput-boolean v0, v1, v2 +000480: 4f00 0102 |0016: aput-byte v0, v1, v2 +000484: 5000 0102 |0018: aput-char v0, v1, v2 +000488: 5100 0102 |001a: aput-short v0, v1, v2 +00048c: 0e00 |001c: return-void + catches : (none) + positions : + locals : + + #2 : (in LA;) + name : 'binary_ops' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 3 + ins : 0 + outs : 0 + insns size : 65 16-bit code units +000490: |[000490] A.binary_ops:()V +0004a0: 9000 0102 |0000: add-int v0, v1, v2 +0004a4: 9100 0102 |0002: sub-int v0, v1, v2 +0004a8: 9200 0102 |0004: mul-int v0, v1, v2 +0004ac: 9300 0102 |0006: div-int v0, v1, v2 +0004b0: 9400 0102 |0008: rem-int v0, v1, v2 +0004b4: 9500 0102 |000a: and-int v0, v1, v2 +0004b8: 9600 0102 |000c: or-int v0, v1, v2 +0004bc: 9700 0102 |000e: xor-int v0, v1, v2 +0004c0: 9800 0102 |0010: shl-int v0, v1, v2 +0004c4: 9900 0102 |0012: shr-int v0, v1, v2 +0004c8: 9a00 0102 |0014: ushr-int v0, v1, v2 +0004cc: 9b00 0102 |0016: add-long v0, v1, v2 +0004d0: 9c00 0102 |0018: sub-long v0, v1, v2 +0004d4: 9d00 0102 |001a: mul-long v0, v1, v2 +0004d8: 9e00 0102 |001c: div-long v0, v1, v2 +0004dc: 9f00 0102 |001e: rem-long v0, v1, v2 +0004e0: a000 0102 |0020: and-long v0, v1, v2 +0004e4: a100 0102 |0022: or-long v0, v1, v2 +0004e8: a200 0102 |0024: xor-long v0, v1, v2 +0004ec: a300 0102 |0026: shl-long v0, v1, v2 +0004f0: a400 0102 |0028: shr-long v0, v1, v2 +0004f4: a500 0102 |002a: ushr-long v0, v1, v2 +0004f8: a600 0102 |002c: add-float v0, v1, v2 +0004fc: a700 0102 |002e: sub-float v0, v1, v2 +000500: a800 0102 |0030: mul-float v0, v1, v2 +000504: a900 0102 |0032: div-float v0, v1, v2 +000508: aa00 0102 |0034: rem-float v0, v1, v2 +00050c: ab00 0102 |0036: add-double v0, v1, v2 +000510: ac00 0102 |0038: sub-double v0, v1, v2 +000514: ad00 0102 |003a: mul-double v0, v1, v2 +000518: ae00 0102 |003c: div-double v0, v1, v2 +00051c: af00 0102 |003e: rem-double v0, v1, v2 +000520: 0e00 |0040: return-void + catches : (none) + positions : + locals : + + #3 : (in LA;) + name : 'binary_ops_2addr' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 2 + ins : 0 + outs : 0 + insns size : 33 16-bit code units +000524: |[000524] A.binary_ops_2addr:()V +000534: b010 |0000: add-int/2addr v0, v1 +000536: b110 |0001: sub-int/2addr v0, v1 +000538: b210 |0002: mul-int/2addr v0, v1 +00053a: b310 |0003: div-int/2addr v0, v1 +00053c: b410 |0004: rem-int/2addr v0, v1 +00053e: b510 |0005: and-int/2addr v0, v1 +000540: b610 |0006: or-int/2addr v0, v1 +000542: b710 |0007: xor-int/2addr v0, v1 +000544: b810 |0008: shl-int/2addr v0, v1 +000546: b910 |0009: shr-int/2addr v0, v1 +000548: ba10 |000a: ushr-int/2addr v0, v1 +00054a: bb10 |000b: add-long/2addr v0, v1 +00054c: bc10 |000c: sub-long/2addr v0, v1 +00054e: bd10 |000d: mul-long/2addr v0, v1 +000550: be10 |000e: div-long/2addr v0, v1 +000552: bf10 |000f: rem-long/2addr v0, v1 +000554: c010 |0010: and-long/2addr v0, v1 +000556: c110 |0011: or-long/2addr v0, v1 +000558: c210 |0012: xor-long/2addr v0, v1 +00055a: c310 |0013: shl-long/2addr v0, v1 +00055c: c410 |0014: shr-long/2addr v0, v1 +00055e: c510 |0015: ushr-long/2addr v0, v1 +000560: c610 |0016: add-float/2addr v0, v1 +000562: c710 |0017: sub-float/2addr v0, v1 +000564: c810 |0018: mul-float/2addr v0, v1 +000566: c910 |0019: div-float/2addr v0, v1 +000568: ca10 |001a: rem-float/2addr v0, v1 +00056a: cb10 |001b: add-double/2addr v0, v1 +00056c: cc10 |001c: sub-double/2addr v0, v1 +00056e: cd10 |001d: mul-double/2addr v0, v1 +000570: ce10 |001e: div-double/2addr v0, v1 +000572: cf10 |001f: rem-double/2addr v0, v1 +000574: 0e00 |0020: return-void + catches : (none) + positions : + locals : + + #4 : (in LA;) + name : 'binary_ops_lit16' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 2 + ins : 0 + outs : 0 + insns size : 17 16-bit code units +000578: |[000578] A.binary_ops_lit16:()V +000588: d010 3412 |0000: add-int/lit16 v0, v1, #int 4660 // #1234 +00058c: d110 3412 |0002: rsub-int v0, v1, #int 4660 // #1234 +000590: d210 3412 |0004: mul-int/lit16 v0, v1, #int 4660 // #1234 +000594: d310 3412 |0006: div-int/lit16 v0, v1, #int 4660 // #1234 +000598: d410 3412 |0008: rem-int/lit16 v0, v1, #int 4660 // #1234 +00059c: d510 3412 |000a: and-int/lit16 v0, v1, #int 4660 // #1234 +0005a0: d610 3412 |000c: or-int/lit16 v0, v1, #int 4660 // #1234 +0005a4: d710 3412 |000e: xor-int/lit16 v0, v1, #int 4660 // #1234 +0005a8: 0e00 |0010: return-void + catches : (none) + positions : + locals : + + #5 : (in LA;) + name : 'binary_ops_lit8' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 2 + ins : 0 + outs : 0 + insns size : 23 16-bit code units +0005ac: |[0005ac] A.binary_ops_lit8:()V +0005bc: d800 0112 |0000: add-int/lit8 v0, v1, #int 18 // #12 +0005c0: d900 0112 |0002: rsub-int/lit8 v0, v1, #int 18 // #12 +0005c4: da00 0112 |0004: mul-int/lit8 v0, v1, #int 18 // #12 +0005c8: db00 0112 |0006: div-int/lit8 v0, v1, #int 18 // #12 +0005cc: dc00 0112 |0008: rem-int/lit8 v0, v1, #int 18 // #12 +0005d0: dd00 0112 |000a: and-int/lit8 v0, v1, #int 18 // #12 +0005d4: de00 0112 |000c: or-int/lit8 v0, v1, #int 18 // #12 +0005d8: df00 0112 |000e: xor-int/lit8 v0, v1, #int 18 // #12 +0005dc: e000 0112 |0010: shl-int/lit8 v0, v1, #int 18 // #12 +0005e0: e100 0112 |0012: shr-int/lit8 v0, v1, #int 18 // #12 +0005e4: e200 0112 |0014: ushr-int/lit8 v0, v1, #int 18 // #12 +0005e8: 0e00 |0016: return-void + catches : (none) + positions : + locals : + + #6 : (in LA;) + name : 'compares' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 3 + ins : 0 + outs : 0 + insns size : 11 16-bit code units +0005ec: |[0005ec] A.compares:()V +0005fc: 2d00 0102 |0000: cmpl-float v0, v1, v2 +000600: 2e00 0102 |0002: cmpg-float v0, v1, v2 +000604: 2f00 0102 |0004: cmpl-double v0, v1, v2 +000608: 3000 0102 |0006: cmpg-double v0, v1, v2 +00060c: 3100 0102 |0008: cmp-long v0, v1, v2 +000610: 0e00 |000a: return-void + catches : (none) + positions : + locals : + + #7 : (in LA;) + name : 'conditionals' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 2 + ins : 0 + outs : 0 + insns size : 25 16-bit code units +000614: |[000614] A.conditionals:()V +000624: 3210 1800 |0000: if-eq v0, v1, 0018 // +0018 +000628: 3310 1600 |0002: if-ne v0, v1, 0018 // +0016 +00062c: 3410 1400 |0004: if-lt v0, v1, 0018 // +0014 +000630: 3510 1200 |0006: if-ge v0, v1, 0018 // +0012 +000634: 3610 1000 |0008: if-gt v0, v1, 0018 // +0010 +000638: 3710 0e00 |000a: if-le v0, v1, 0018 // +000e +00063c: 3800 0c00 |000c: if-eqz v0, 0018 // +000c +000640: 3900 0a00 |000e: if-nez v0, 0018 // +000a +000644: 3a00 0800 |0010: if-ltz v0, 0018 // +0008 +000648: 3b00 0600 |0012: if-gez v0, 0018 // +0006 +00064c: 3c00 0400 |0014: if-gtz v0, 0018 // +0004 +000650: 3d00 0200 |0016: if-lez v0, 0018 // +0002 +000654: 0e00 |0018: return-void + catches : (none) + positions : + locals : + + #8 : (in LA;) + name : 'constants' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 1 + ins : 0 + outs : 0 + insns size : 28 16-bit code units +000658: |[000658] A.constants:()V +000668: 1210 |0000: const/4 v0, #int 1 // #1 +00066a: 1300 3412 |0001: const/16 v0, #int 4660 // #1234 +00066e: 1400 7856 3412 |0003: const v0, #float 5.69046e-28 // #12345678 +000674: 1500 3412 |0006: const/high16 v0, #int 305397760 // #1234 +000678: 1600 3412 |0008: const-wide/16 v0, #int 4660 // #1234 +00067c: 1700 7856 3412 |000a: const-wide/32 v0, #float 5.69046e-28 // #12345678 +000682: 1800 efcd ab90 7856 3412 |000d: const-wide v0, #double 5.62635e-221 // #1234567890abcdef +00068c: 1900 3412 |0012: const-wide/high16 v0, #long 1311673391471656960 // #1234 +000690: 1a00 2c00 |0014: const-string v0, "string" // string@002c +000694: 1b00 2c00 0000 |0016: const-string/jumbo v0, "string" // string@0000002c +00069a: 1c00 0500 |0019: const-class v0, Ljava/lang/Object; // type@0005 +00069e: 0e00 |001b: return-void + catches : (none) + positions : + locals : + + #9 : (in LA;) + name : 'misc' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 5 + ins : 0 + outs : 0 + insns size : 54 16-bit code units +0006a0: |[0006a0] A.misc:()V +0006b0: 0000 |0000: nop // spacer +0006b2: 1d00 |0001: monitor-enter v0 +0006b4: 1e00 |0002: monitor-exit v0 +0006b6: 1f00 0500 |0003: check-cast v0, Ljava/lang/Object; // type@0005 +0006ba: 2010 0500 |0005: instance-of v0, v1, Ljava/lang/Object; // type@0005 +0006be: 2110 |0007: array-length v0, v1 +0006c0: 2200 0500 |0008: new-instance v0, Ljava/lang/Object; // type@0005 +0006c4: 2310 0500 |000a: new-array v0, v1, Ljava/lang/Object; // type@0005 +0006c8: 2454 0900 1032 |000c: filled-new-array {v0, v1, v2, v3, v4}, [Ljava/lang/Object; // type@0009 +0006ce: 2505 0900 0000 |000f: filled-new-array/range {v0, v1, v2, v3, v4}, [Ljava/lang/Object; // type@0009 +0006d4: 2600 0c00 0000 |0012: fill-array-data v0, 0000001e // +0000000c +0006da: 2700 |0015: throw v0 +0006dc: 2806 |0016: goto 001c // +0006 +0006de: 2900 0500 |0017: goto/16 001c // +0005 +0006e2: 2a00 0300 0000 |0019: goto/32 #00000003 +0006e8: 0e00 |001c: return-void +0006ea: 0000 |001d: nop // spacer +0006ec: 0003 0400 0a00 0000 0100 0000 0200 ... |001e: array-data (24 units) + catches : (none) + positions : + locals : + + #10 : (in LA;) + name : 'moves' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 2 + ins : 0 + outs : 0 + insns size : 23 16-bit code units +00071c: |[00071c] A.moves:()V +00072c: 0110 |0000: move v0, v1 +00072e: 0200 0100 |0001: move/from16 v0, v1 +000732: 0300 0000 0100 |0003: move/16 v0, v1 +000738: 0410 |0006: move-wide v0, v1 +00073a: 0500 0100 |0007: move-wide/from16 v0, v1 +00073e: 0600 0000 0100 |0009: move-wide/16 v0, v1 +000744: 0710 |000c: move-object v0, v1 +000746: 0800 0100 |000d: move-object/from16 v0, v1 +00074a: 0900 0000 0100 |000f: move-object/16 v0, v1 +000750: 0a00 |0012: move-result v0 +000752: 0b00 |0013: move-result-wide v0 +000754: 0c00 |0014: move-result-object v0 +000756: 0d00 |0015: move-exception v0 +000758: 0e00 |0016: return-void + catches : (none) + positions : + locals : + + #11 : (in LA;) + name : 'packed_switch' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 1 + ins : 0 + outs : 0 + insns size : 16 16-bit code units +00075c: |[00075c] A.packed_switch:()V +00076c: 2b00 0800 0000 |0000: packed-switch v0, 00000008 // +00000008 +000772: 0e00 |0003: return-void +000774: 28ff |0004: goto 0003 // -0001 +000776: 28fe |0005: goto 0003 // -0002 +000778: 28fd |0006: goto 0003 // -0003 +00077a: 0000 |0007: nop // spacer +00077c: 0001 0200 feff ff7f 0500 0000 0600 ... |0008: packed-switch-data (8 units) + catches : (none) + positions : + locals : + + #12 : (in LA;) + name : 'return32' + type : '()I' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 1 + ins : 0 + outs : 0 + insns size : 1 16-bit code units +00078c: |[00078c] A.return32:()I +00079c: 0f00 |0000: return v0 + catches : (none) + positions : + locals : + + #13 : (in LA;) + name : 'return64' + type : '()I' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 2 + ins : 0 + outs : 0 + insns size : 1 16-bit code units +0007a0: |[0007a0] A.return64:()I +0007b0: 1000 |0000: return-wide v0 + catches : (none) + positions : + locals : + + #14 : (in LA;) + name : 'return_object' + type : '()Ljava/lang/Object;' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 1 + ins : 0 + outs : 0 + insns size : 1 16-bit code units +0007b4: |[0007b4] A.return_object:()Ljava/lang/Object; +0007c4: 1100 |0000: return-object v0 + catches : (none) + positions : + locals : + + #15 : (in LA;) + name : 'sparse_switch' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 2 + ins : 0 + outs : 0 + insns size : 22 16-bit code units +0007c8: |[0007c8] A.sparse_switch:()V +0007d8: 2c00 0400 0000 |0000: sparse-switch v0, 00000004 // +00000004 +0007de: 0e00 |0003: return-void +0007e0: 0002 0400 1111 0000 2222 0000 3333 ... |0004: sparse-switch-data (18 units) + catches : (none) + positions : + locals : + + #16 : (in LA;) + name : 'static_fields' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 1 + ins : 0 + outs : 0 + insns size : 29 16-bit code units +000804: |[000804] A.static_fields:()V +000814: 6000 0900 |0000: sget v0, LA;.sI:I // field@0009 +000818: 6100 0a00 |0002: sget-wide v0, LA;.sJ:J // field@000a +00081c: 6200 0b00 |0004: sget-object v0, LA;.sO:LA; // field@000b +000820: 6300 0d00 |0006: sget-boolean v0, LA;.sZ:Z // field@000d +000824: 6400 0700 |0008: sget-byte v0, LA;.sB:B // field@0007 +000828: 6500 0800 |000a: sget-char v0, LA;.sC:C // field@0008 +00082c: 6600 0c00 |000c: sget-short v0, LA;.sS:S // field@000c +000830: 6700 0900 |000e: sput v0, LA;.sI:I // field@0009 +000834: 6800 0a00 |0010: sput-wide v0, LA;.sJ:J // field@000a +000838: 6900 0b00 |0012: sput-object v0, LA;.sO:LA; // field@000b +00083c: 6a00 0d00 |0014: sput-boolean v0, LA;.sZ:Z // field@000d +000840: 6b00 0700 |0016: sput-byte v0, LA;.sB:B // field@0007 +000844: 6c00 0800 |0018: sput-char v0, LA;.sC:C // field@0008 +000848: 6d00 0500 |001a: sput-short v0, LA;.mS:S // field@0005 +00084c: 0e00 |001c: return-void + catches : (none) + positions : + locals : + + #17 : (in LA;) + name : 'unary_ops' + type : '()V' + access : 0x0009 (PUBLIC STATIC) + code - + registers : 2 + ins : 0 + outs : 0 + insns size : 22 16-bit code units +000850: |[000850] A.unary_ops:()V +000860: 7b10 |0000: neg-int v0, v1 +000862: 7c10 |0001: not-int v0, v1 +000864: 7d10 |0002: neg-long v0, v1 +000866: 7e10 |0003: not-long v0, v1 +000868: 7f10 |0004: neg-float v0, v1 +00086a: 8010 |0005: neg-double v0, v1 +00086c: 8110 |0006: int-to-long v0, v1 +00086e: 8210 |0007: int-to-float v0, v1 +000870: 8310 |0008: int-to-double v0, v1 +000872: 8410 |0009: long-to-int v0, v1 +000874: 8510 |000a: long-to-float v0, v1 +000876: 8610 |000b: long-to-double v0, v1 +000878: 8710 |000c: float-to-int v0, v1 +00087a: 8810 |000d: float-to-long v0, v1 +00087c: 8910 |000e: float-to-double v0, v1 +00087e: 8a10 |000f: double-to-int v0, v1 +000880: 8b10 |0010: double-to-long v0, v1 +000882: 8c10 |0011: double-to-float v0, v1 +000884: 8d10 |0012: int-to-byte v0, v1 +000886: 8e10 |0013: int-to-char v0, v1 +000888: 8f10 |0014: int-to-short v0, v1 +00088a: 0e00 |0015: return-void + catches : (none) + positions : + locals : + + Virtual methods - + #0 : (in LA;) + name : 'instance_fields' + type : '()V' + access : 0x0001 (PUBLIC) + code - + registers : 2 + ins : 1 + outs : 0 + insns size : 29 16-bit code units +00088c: |[00088c] A.instance_fields:()V +00089c: 5210 0900 |0000: iget v0, v1, LA;.sI:I // field@0009 +0008a0: 5310 0a00 |0002: iget-wide v0, v1, LA;.sJ:J // field@000a +0008a4: 5410 0b00 |0004: iget-object v0, v1, LA;.sO:LA; // field@000b +0008a8: 5510 0d00 |0006: iget-boolean v0, v1, LA;.sZ:Z // field@000d +0008ac: 5610 0700 |0008: iget-byte v0, v1, LA;.sB:B // field@0007 +0008b0: 5710 0800 |000a: iget-char v0, v1, LA;.sC:C // field@0008 +0008b4: 5810 0c00 |000c: iget-short v0, v1, LA;.sS:S // field@000c +0008b8: 5910 0900 |000e: iput v0, v1, LA;.sI:I // field@0009 +0008bc: 5a10 0a00 |0010: iput-wide v0, v1, LA;.sJ:J // field@000a +0008c0: 5b10 0b00 |0012: iput-object v0, v1, LA;.sO:LA; // field@000b +0008c4: 5c10 0d00 |0014: iput-boolean v0, v1, LA;.sZ:Z // field@000d +0008c8: 5d10 0700 |0016: iput-byte v0, v1, LA;.sB:B // field@0007 +0008cc: 5e10 0800 |0018: iput-char v0, v1, LA;.sC:C // field@0008 +0008d0: 5f10 0c00 |001a: iput-short v0, v1, LA;.sS:S // field@000c +0008d4: 0e00 |001c: return-void + catches : (none) + positions : + locals : + + #1 : (in LA;) + name : 'invokes' + type : '()V' + access : 0x0001 (PUBLIC) + code - + registers : 5 + ins : 1 + outs : 1 + insns size : 15 16-bit code units +0008d8: |[0008d8] A.invokes:()V +0008e8: 6e54 0a00 1032 |0000: invoke-virtual {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a +0008ee: 6f54 0a00 1032 |0003: invoke-super {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a +0008f4: 7054 0a00 1032 |0006: invoke-direct {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a +0008fa: 7154 0a00 1032 |0009: invoke-static {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a +000900: 7254 0a00 1032 |000c: invoke-interface {v0, v1, v2, v3, v4}, LA;.invokes:()V // method@000a + catches : (none) + positions : + locals : + + source_file_idx : -1 (unknown) + diff --git a/test/dexdump/all.xml b/test/dexdump/all.xml new file mode 100644 index 0000000000..b623ecb2c1 --- /dev/null +++ b/test/dexdump/all.xml @@ -0,0 +1,211 @@ +<api> +<package name="" +> +<class name="A" + extends="java.lang.Object" + interface="false" + abstract="false" + static="false" + final="false" + visibility="public" +> +<constructor name="A" + type="A" + static="false" + final="false" + visibility="public" +> +</constructor> +<method name="arrays" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="binary_ops" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="binary_ops_2addr" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="binary_ops_lit16" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="binary_ops_lit8" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="compares" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="conditionals" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="constants" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="misc" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="moves" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="packed_switch" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="return32" + return="int" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="return64" + return="int" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="return_object" + return="java.lang.Object" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="sparse_switch" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="static_fields" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="unary_ops" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + visibility="public" +> +</method> +<method name="instance_fields" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + visibility="public" +> +</method> +<method name="invokes" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + visibility="public" +> +</method> +</class> +</package> +</api> |