/* * Copyright (C) 2017 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 Main { /// CHECK-START: java.lang.Integer Main.foo(int) disassembly (after) /// CHECK: <> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf /// CHECK: pAllocObjectInitialized /// CHECK: Return [<>] public static Integer foo(int a) { return Integer.valueOf(a); } /// CHECK-START: java.lang.Integer Main.foo2() disassembly (after) /// CHECK: <> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf /// CHECK-NOT: pAllocObjectInitialized /// CHECK: Return [<>] public static Integer foo2() { return Integer.valueOf(-42); } /// CHECK-START: java.lang.Integer Main.foo3() disassembly (after) /// CHECK: <> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf /// CHECK-NOT: pAllocObjectInitialized /// CHECK: Return [<>] public static Integer foo3() { return Integer.valueOf(42); } /// CHECK-START: java.lang.Integer Main.foo4() disassembly (after) /// CHECK: <> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf /// CHECK: pAllocObjectInitialized /// CHECK: Return [<>] public static Integer foo4() { return Integer.valueOf(55555); } /// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) builder (after) /// CHECK: <> ParameterValue /// CHECK: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf /// CHECK-NOT: NullCheck [<>] /// CHECK: <> InvokeVirtual [<>] method_name:java.lang.Byte.byteValue /// CHECK: Return [<>] /// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) inliner (after) /// CHECK: <> ParameterValue /// CHECK: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf /// CHECK: <> InstanceFieldGet [<>] field_name:java.lang.Byte.value /// CHECK: Return [<>] /// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) instruction_simplifier$after_inlining (after) /// CHECK: <> ParameterValue /// CHECK: Return [<>] /// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) dead_code_elimination$after_inlining (after) /// CHECK-NOT: InvokeStaticOrDirect /// CHECK-NOT: InstanceFieldGet public static byte $noinline$boxUnboxByte(byte value) { return Byte.valueOf(value).byteValue(); } /// CHECK-START: short Main.$noinline$boxUnboxShort(short) builder (after) /// CHECK: <> ParameterValue /// CHECK: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Short.valueOf intrinsic:ShortValueOf /// CHECK-NOT: NullCheck [<>] /// CHECK: <> InvokeVirtual [<>] method_name:java.lang.Short.shortValue /// CHECK: Return [<>] /// CHECK-START: short Main.$noinline$boxUnboxShort(short) inliner (after) /// CHECK: <> ParameterValue /// CHECK: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Short.valueOf intrinsic:ShortValueOf /// CHECK: <> InstanceFieldGet [<>] field_name:java.lang.Short.value /// CHECK: Return [<>] /// CHECK-START: short Main.$noinline$boxUnboxShort(short) instruction_simplifier$after_inlining (after) /// CHECK: <> ParameterValue /// CHECK: Return [<>] /// CHECK-START: short Main.$noinline$boxUnboxShort(short) dead_code_elimination$after_inlining (after) /// CHECK-NOT: InvokeStaticOrDirect /// CHECK-NOT: InstanceFieldGet public static short $noinline$boxUnboxShort(short value) { return Short.valueOf(value).shortValue(); } /// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) builder (after) /// CHECK: <> ParameterValue /// CHECK: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Character.valueOf intrinsic:CharacterValueOf /// CHECK-NOT: NullCheck [<>] /// CHECK: <> InvokeVirtual [<>] method_name:java.lang.Character.charValue /// CHECK: Return [<>] /// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) inliner (after) /// CHECK: <> ParameterValue /// CHECK: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Character.valueOf intrinsic:CharacterValueOf /// CHECK: <> InstanceFieldGet [<>] field_name:java.lang.Character.value /// CHECK: Return [<>] /// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) instruction_simplifier$after_inlining (after) /// CHECK: <> ParameterValue /// CHECK: Return [<>] /// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) dead_code_elimination$after_inlining (after) /// CHECK-NOT: InvokeStaticOrDirect /// CHECK-NOT: InstanceFieldGet public static char $noinline$boxUnboxCharacter(char value) { return Character.valueOf(value).charValue(); } /// CHECK-START: int Main.$noinline$boxUnboxInteger(int) builder (after) /// CHECK: <> ParameterValue /// CHECK: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf /// CHECK-NOT: NullCheck [<>] /// CHECK: <> InvokeVirtual [<>] method_name:java.lang.Integer.intValue /// CHECK: Return [<>] /// CHECK-START: int Main.$noinline$boxUnboxInteger(int) inliner (after) /// CHECK: <> ParameterValue /// CHECK: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf /// CHECK: <> InstanceFieldGet [<>] field_name:java.lang.Integer.value /// CHECK: Return [<>] /// CHECK-START: int Main.$noinline$boxUnboxInteger(int) instruction_simplifier$after_inlining (after) /// CHECK: <> ParameterValue /// CHECK: Return [<>] /// CHECK-START: int Main.$noinline$boxUnboxInteger(int) dead_code_elimination$after_inlining (after) /// CHECK-NOT: InvokeStaticOrDirect /// CHECK-NOT: InstanceFieldGet public static int $noinline$boxUnboxInteger(int value) { return Integer.valueOf(value).intValue(); } /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) builder (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf /// CHECK-DAG: <> Phi /// CHECK-DAG: <> NullCheck [<>] /// CHECK-DAG: <> InvokeVirtual [<>] method_name:java.lang.Byte.byteValue /// CHECK-DAG: <> And /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) instruction_simplifier (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf /// CHECK-DAG: <> Phi /// CHECK-DAG: <> NullCheck [<>] /// CHECK-DAG: <> InvokeVirtual [<>] method_name:java.lang.Byte.byteValue /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) inliner (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf /// CHECK-DAG: <> Phi /// CHECK-DAG: <> NullCheck [<>] /// CHECK-DAG: <> InstanceFieldGet [<>] field_name:java.lang.Byte.value /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) instruction_simplifier$after_inlining (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf /// CHECK-DAG: <> Phi /// CHECK-DAG: <> NullCheck [<>] /// CHECK-DAG: <> InstanceFieldGet [<>] field_name:java.lang.Byte.value /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) dead_code_elimination$after_inlining (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf /// CHECK-DAG: <> NullCheck [<>] /// CHECK-DAG: <> InstanceFieldGet [<>] field_name:java.lang.Byte.value /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) instruction_simplifier$after_gvn (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf /// CHECK-DAG: <> InstanceFieldGet [<>] field_name:java.lang.Byte.value /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) disassembly (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf /// CHECK-DAG: <> InstanceFieldGet [<>] field_name:java.lang.Byte.value /// CHECK-DAG: Return [<>] public static int $noinline$boxUnboxByteAsUint8(byte value) { Byte boxed = Byte.valueOf(value); // Hide the unboxing from the initial instruction simplifier pass or the one after inlining, // so that after inlining we can merge the `TypeConversion` into `InstanceFieldGet` with // a modified type. The Phi shall be eliminated by `dead_code_elimination$after_inlining`. // The null check that shall be eliminated by `instruction_simplifier$after_gvn (after)` Byte merged = $inline$returnTrue() ? boxed : null; // Due to the type mismatch, we shall not simplify the unboxing. The boxing and unboxing // shall be kept during subsequent simplifier passes all the way to the disassembly. return merged.byteValue() & 0xff; } public static boolean $inline$returnTrue() { return true; } public static void main(String[] args) { assertEqual("42", foo(intField)); assertEqual(foo(intField), foo(intField2)); assertEqual("-42", foo2()); assertEqual("42", foo3()); assertEqual("55555", foo4()); assertEqual("55555", foo(intField3)); assertEqual("-129", foo(intFieldMinus129)); assertEqual("-128", foo(intFieldMinus128)); assertEqual(foo(intFieldMinus128), foo(intFieldMinus128)); assertEqual("-127", foo(intFieldMinus127)); assertEqual(foo(intFieldMinus127), foo(intFieldMinus127)); assertEqual("126", foo(intField126)); assertEqual(foo(intField126), foo(intField126)); assertEqual("127", foo(intField127)); assertEqual(foo(intField127), foo(intField127)); assertEqual("128", foo(intField128)); assertEqual(42, (int) $noinline$boxUnboxByte((byte) 42)); assertEqual(-42, (int) $noinline$boxUnboxByte((byte) -42)); assertEqual(42, (int) $noinline$boxUnboxShort((short) 42)); assertEqual(-42, (int) $noinline$boxUnboxShort((short) -42)); assertEqual((int) (char) 42, (int) $noinline$boxUnboxCharacter((char) 42)); assertEqual((int) (char) -42, (int) $noinline$boxUnboxCharacter((char) -42)); assertEqual(42, $noinline$boxUnboxInteger(42)); assertEqual(-42, $noinline$boxUnboxInteger(-42)); assertEqual(42, $noinline$boxUnboxByteAsUint8((byte) 42)); assertEqual(-42 & 0xff, $noinline$boxUnboxByteAsUint8((byte) -42)); } static void assertEqual(String a, Integer b) { if (!a.equals(b.toString())) { throw new Error("Expected " + a + ", got " + b); } } static void assertEqual(Integer a, Integer b) { if (a != b) { throw new Error("Expected " + a + ", got " + b); } } static void assertEqual(int a, int b) { if (a != b) { throw new Error("Expected " + a + ", got " + b); } } static int intField = 42; static int intField2 = 42; static int intField3 = 55555; // Edge cases. static int intFieldMinus129 = -129; static int intFieldMinus128 = -128; static int intFieldMinus127 = -127; static int intField126 = 126; static int intField127 = 127; static int intField128 = 128; }