diff --git a/src/java.base/share/classes/java/lang/Object.java b/src/java.base/share/classes/java/lang/Object.java index d8f20c6c215..7b61e7b1a0f 100644 --- a/src/java.base/share/classes/java/lang/Object.java +++ b/src/java.base/share/classes/java/lang/Object.java @@ -266,11 +266,7 @@ public boolean equals(Object obj) { * @return a string representation of the object. */ public String toString() { - if (getClass().isPrimitiveClass()) { - return SharedSecrets.getJavaLangInvokeAccess().inlineObjectToString(this); - } else { - return getClass().getName() + "@" + Integer.toHexString(hashCode()); - } + return getClass().getName() + "@" + Integer.toHexString(hashCode()); } /** diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index f18bd0295bf..96fb8370cbd 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -1483,10 +1483,6 @@ public VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle filt public VarHandle insertCoordinates(VarHandle target, int pos, Object... values) { return VarHandles.insertCoordinates(target, pos, values); } - @Override - public String inlineObjectToString(Object o) { - return ValueBootstrapMethods.inlineObjectToString(o); - } }); } diff --git a/src/java.base/share/classes/java/lang/invoke/ValueBootstrapMethods.java b/src/java.base/share/classes/java/lang/invoke/ValueBootstrapMethods.java index e782569d678..267272467c6 100644 --- a/src/java.base/share/classes/java/lang/invoke/ValueBootstrapMethods.java +++ b/src/java.base/share/classes/java/lang/invoke/ValueBootstrapMethods.java @@ -95,8 +95,6 @@ private static MethodHandle generateTarget(Lookup lookup, String name, MethodTyp return inlineTypeHashCode(valType); case "equals": return substitutableInvoker(valType).asType(methodType); - case "toString": - return inlineTypeToString(valType); default: throw new IllegalArgumentException(name + " not valid method name"); } @@ -216,40 +214,6 @@ static MethodHandle inlineTypeHashCode(Class type) { return countedLoop(iterations, init, body); } - static MethodHandle inlineTypeToString(Class type) { - assert type.isValueType(); - MethodHandle[] getters = MethodHandleBuilder.getters(type); - int length = getters.length; - StringBuilder format = new StringBuilder(); - Class[] parameterTypes = new Class[length]; - // append the value class name - format.append("[").append(type.getName()); - String separator = " "; - Lookup lookup = new MethodHandles.Lookup(type.asPrimaryType()); - for (int i = 0; i < length; i++) { - MethodHandle getter = getters[i]; - Class ftype = fieldType(getter); - MethodHandleInfo fieldInfo = lookup.revealDirect(getter); - format.append(separator) - .append(fieldInfo.getName()) - .append("=\1"); - getters[i]= filterReturnValue(getter, MethodHandleBuilder.toString(ftype)); - parameterTypes[i] = String.class; - } - format.append("]"); - try { - MethodHandle target = StringConcatFactory.makeConcatWithConstants(lookup, "toString", - methodType(String.class, parameterTypes), format.toString()).dynamicInvoker(); - // apply getters - target = filterArguments(target, 0, getters); - // duplicate "this" argument from o::toString for each getter invocation - target = permuteArguments(target, methodType(String.class, type), new int[length]); - return target; - } catch (StringConcatException e) { - throw newLinkageError(e); - } - - } // ------ utility methods ------ private static boolean eq(byte a, byte b) { return a == b; } private static boolean eq(short a, short b) { return a == b; } @@ -301,27 +265,6 @@ private static boolean isSamePrimitiveClass(Object a, Object b) { return a.getClass().isPrimitiveClass() && a.getClass() == b.getClass(); } - private static String toString(Object o) { - return o != null ? o.toString() : "null"; - } - - private static MethodHandle toString(Class type) { - if (type.isArray()) { - Class componentType = type.getComponentType(); - if (componentType.isPrimitiveClass()) { - componentType = componentType.asValueType(); - } - if (componentType.isPrimitive()) { - int index = Wrapper.forPrimitiveType(componentType).ordinal(); - return ARRAYS_TO_STRING[index]; - } else { - return ARRAYS_TO_STRING[Wrapper.OBJECT.ordinal()].asType(methodType(String.class, type)); - } - } else { - return TO_STRING.asType(methodType(String.class, type)); - } - } - private static int hashCombiner(int accumulator, int value) { return accumulator * 31 + value; } @@ -338,15 +281,12 @@ private static int computeHashCode(MethodHandle[] hashers, int v, int i, Object } private static final MethodHandle[] EQUALS = initEquals(); - private static final MethodHandle[] ARRAYS_TO_STRING = initArraysToString(); private static final MethodHandle[] HASHCODE = initHashCode(); static final MethodHandle IS_SAME_INLINE_CLASS = findStatic("isSamePrimitiveClass", methodType(boolean.class, Object.class, Object.class)); static final MethodHandle IS_NULL = findStatic("isNull", methodType(boolean.class, Object.class, Object.class)); - static final MethodHandle TO_STRING = - findStatic("toString", methodType(String.class, Object.class)); static final MethodHandle FALSE = constant(boolean.class, false); static final MethodHandle TRUE = constant(boolean.class, true); @@ -366,17 +306,6 @@ private static MethodHandle[] initEquals() { return mhs; } - private static MethodHandle[] initArraysToString() { - MethodHandle[] mhs = new MethodHandle[Wrapper.COUNT]; - for (Wrapper wrapper : Wrapper.values()) { - if (wrapper == Wrapper.VOID) continue; - - Class arrayType = wrapper.arrayType(); - mhs[wrapper.ordinal()] = findStatic(Arrays.class, "toString", methodType(String.class, arrayType)); - } - return mhs; - } - private static MethodHandle[] initHashCode() { MethodHandle[] mhs = new MethodHandle[Wrapper.COUNT]; for (Wrapper wrapper : Wrapper.values()) { @@ -591,33 +520,6 @@ private static int inlineObjectHashCode(Object o) { } }; - /** - * Invoke the bootstrap methods hashCode for the given primitive class object. - * @param o the instance to hash. - * @return the string representation of the given primitive class object. - */ - static String inlineObjectToString(Object o) { - try { - // Note: javac disallows user to call super.hashCode if user implementated - // risk for recursion for experts crafting byte-code - if (!o.getClass().isPrimitiveClass()) - throw new InternalError("must be primitive type: " + o.getClass().getName()); - Class type = o.getClass().asValueType(); - return (String) TOSTRING_METHOD_HANDLES.get(type).invoke(o); - } catch (Error|RuntimeException e) { - throw e; - } catch (Throwable e) { - if (VERBOSE) e.printStackTrace(); - throw new InternalError(e); - } - } - - private static ClassValue TOSTRING_METHOD_HANDLES = new ClassValue<>() { - @Override protected MethodHandle computeValue(Class type) { - return MethodHandleBuilder.inlineTypeToString(type.asValueType()); - } - }; - private static final Comparator TYPE_SORTER = (mh1, mh2) -> { // sort the getters with the return type Class t1 = mh1.type().returnType(); diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java index bf89c91acf6..767108cdb8e 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java @@ -122,8 +122,6 @@ VarHandle memoryAccessVarHandle(Class carrier, boolean skipAlignmentMaskCheck */ VarHandle insertCoordinates(VarHandle target, int pos, Object... values); - String inlineObjectToString(Object o); - /** * Returns a native method handle with given arguments as fallback and steering info. * diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeArray.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeArray.java index 0de09f53111..89a5febac3f 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeArray.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeArray.java @@ -394,7 +394,7 @@ static Object test6() { static void verifyTest6() { Object n = test6(); - Asserts.assertEQ(n.toString(), "[MyValue6 foo=124]"); + Asserts.assertEQ(n.toString(), "MyValue6@" + Integer.toHexString(n.hashCode())); } static Object test6Box() { @@ -403,7 +403,7 @@ static Object test6Box() { static void verifyTest6Box() { Object n = test6Box(); - Asserts.assertEQ(n.toString(), "[MyValue6Box foo=124]"); + Asserts.assertEQ(n.toString(), "MyValue6Box@" + Integer.toHexString(n.hashCode())); } static int test7(MyValue7[][] arr) { diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/WithFieldAccessorTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/WithFieldAccessorTest.java index 89a82a1d209..64a5a4f4388 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/WithFieldAccessorTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/WithFieldAccessorTest.java @@ -54,15 +54,15 @@ public static V make(char c, long l, int i) { public static void main(String... args) throws Throwable { V v = __WithField(V.make('a', 5, 10).c, 'b'); - if (!v.toString().equals("[WithFieldAccessorTest$V c=b l=5 i=10]")) { + if (!v.toString().equals("WithFieldAccessorTest$V@" + Integer.toHexString(v.hashCode()))) { throw new AssertionError("Withfield of 'c' didn't work!" + v.toString()); } v = __WithField(V.make('a', 5, 10).l, 25); - if (!v.toString().equals("[WithFieldAccessorTest$V c=a l=25 i=10]")) { + if (!v.toString().equals("WithFieldAccessorTest$V@" + Integer.toHexString(v.hashCode()))) { throw new AssertionError("Withfield of 'l' didn't work!" + v.toString()); } v = __WithField(V.make('a', 5, 10).i, 20); - if (!v.toString().equals("[WithFieldAccessorTest$V c=a l=5 i=20]")) { + if (!v.toString().equals("WithFieldAccessorTest$V@" + Integer.toHexString(v.hashCode()))) { throw new AssertionError("Withfield of 'i' didn't work!" + v.toString()); } } diff --git a/test/jdk/valhalla/valuetypes/ObjectMethods.java b/test/jdk/valhalla/valuetypes/ObjectMethods.java index 399cdf2427c..0b5630e0c28 100644 --- a/test/jdk/valhalla/valuetypes/ObjectMethods.java +++ b/test/jdk/valhalla/valuetypes/ObjectMethods.java @@ -26,9 +26,12 @@ * @test * @summary test Object methods on inline types * @run testng/othervm -Xint -Dvalue.bsm.salt=1 ObjectMethods - * @run testng/othervm -Xcomp -Dvalue.bsm.salt=1 ObjectMethods * @run testng/othervm -Dvalue.bsm.salt=1 -XX:InlineFieldMaxFlatSize=0 ObjectMethods */ + +/* To be enabled by JDK-8267932 + * @run testng/othervm -Xcomp -Dvalue.bsm.salt=1 ObjectMethods + */ import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; @@ -128,33 +131,28 @@ public void testNumber(Number n1, Number n2, boolean isSubstitutable, boolean is assertTrue(n1.equals(n2) == isEquals); } + @DataProvider(name="toStringTests") Object[][] toStringTests() { return new Object[][] { - { Point.makePoint(100, 200), "[Point x=100 y=200]" }, - { Line.makeLine(1, 2, 3, 4), "[Line p1=[Point x=1 y=2] p2=[Point x=3 y=4]]"}, - { VALUE, - "[Value char_v=z byte_v=1 boolean_v=false int_v=0 short_v=3 long_v=4 double_v=0.0 " + - "float_v=0.0 number_v=[Value$IntValue i=10] point_v=[Point x=200 y=200] point_ref=null ref_v=null]" }, - { VALUE1, - "[Value char_v=z byte_v=1 boolean_v=false int_v=0 short_v=3 long_v=4 double_v=0.0 " + - "float_v=0.0 number_v=[Value$IntValue i=20] point_v=[Point x=100 y=100] " + - "point_ref=[Point x=200 y=200] ref_v=[Point x=300 y=300]]" }, + { Point.makePoint(100, 200) }, + { Line.makeLine(1, 2, 3, 4) }, + { VALUE }, + { VALUE1 }, { new Value.Builder() .setReference(List.of("ref")) - .setNumber(new Value.IntNumber(99)).build(), - "[Value char_v=\u0000 byte_v=0 boolean_v=false int_v=0 short_v=0 long_v=0 double_v=0.0 " + - "float_v=0.0 number_v=99 point_v=[Point x=0 y=0] point_ref=null ref_v=[ref]]" }, + .setNumber(new Value.IntNumber(99)).build() }, // enclosing instance field `this$0` should be filtered - { MyValue1.default, "[ObjectMethods$MyValue1 p=[Point x=0 y=0] np=null]" }, - { new MyValue1(0,0, null), "[ObjectMethods$MyValue1 p=[Point x=0 y=0] np=null]" }, - { new MyValue1(0,0, P1), "[ObjectMethods$MyValue1 p=[Point x=0 y=0] np=[Point x=1 y=2]]" }, + { MyValue1.default }, + { new MyValue1(0,0, null) }, + { new MyValue1(0,0, P1) }, }; } @Test(dataProvider="toStringTests") - public void testToString(Object o, String s) { - assertTrue(o.toString().equals(s), o.toString()); + public void testToString(Object o) { + String expected = String.format("%s@%s", o.getClass().getName(), Integer.toHexString(o.hashCode())); + assertEquals(o.toString(), expected); } @DataProvider(name="hashcodeTests") @@ -175,6 +173,7 @@ Object[][] hashcodeTests() { @Test(dataProvider="hashcodeTests") public void testHashCode(Object o, int hash) { assertEquals(o.hashCode(), hash); + assertEquals(System.identityHashCode(o), hash); } private static Object[] hashCodeComponents(Object o) { diff --git a/test/jdk/valhalla/valuetypes/ValueBootstrapMethods.java b/test/jdk/valhalla/valuetypes/ValueBootstrapMethods.java index 1055c377194..6aede133376 100644 --- a/test/jdk/valhalla/valuetypes/ValueBootstrapMethods.java +++ b/test/jdk/valhalla/valuetypes/ValueBootstrapMethods.java @@ -60,11 +60,6 @@ public static void main(String... args) throws Throwable { assertEquals(hash, value.localHashCode()); assertEquals(hash, value.hashCode()); - Method toString = test.getMethod("toString", valueClass); - String s = (String)toString.invoke(null, value); - assertEquals(s, value.localToString()); - assertEquals(s, value.toString()); - Method equals = test.getMethod("equals", valueClass, Object.class); boolean rc = (boolean)equals.invoke(null, value, value); if (!rc) { @@ -91,12 +86,6 @@ List values() { public int localHashCode() { return values().hashCode(); } - - public String localToString() { - System.out.println(l); - return String.format("[%s i=%s d=%s s=%s l=%s]", Value.class.getName(), - i, String.valueOf(d), s, l.toString()); - } } /* @@ -165,21 +154,6 @@ static void generate(Class c, String className, Path path) throws IOException mv.visitMaxs(-1, -1); mv.visitEnd(); - mv = cw.visitMethod( - ACC_PUBLIC + ACC_STATIC + ACC_FINAL, - "toString", - Type.getMethodDescriptor(Type.getType(String.class), type), - null, - null); - - mv.visitVarInsn(ALOAD, 0); - mv.visitInvokeDynamicInsn("toString", - Type.getMethodDescriptor(Type.getType(String.class), type), - bootstrap, type); - mv.visitInsn(ARETURN); - mv.visitMaxs(-1, -1); - mv.visitEnd(); - cw.visitEnd(); byte[] classBytes = cw.toByteArray(); diff --git a/test/langtools/tools/javac/valhalla/lworld-values/AnonymousValueType.java b/test/langtools/tools/javac/valhalla/lworld-values/AnonymousValueType.java index aa62c5b88a8..26b915f891c 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/AnonymousValueType.java +++ b/test/langtools/tools/javac/valhalla/lworld-values/AnonymousValueType.java @@ -38,7 +38,7 @@ public int compareTo(String o) { return 0; } }; - if (!o.toString().equals("[AnonymousValueType$1 x=10]")) + if (!o.toString().equals("AnonymousValueType$1@" + Integer.toHexString(o.hashCode()))) throw new AssertionError("Broken"); } } diff --git a/test/langtools/tools/javac/valhalla/lworld-values/InlineDiamondTest.java b/test/langtools/tools/javac/valhalla/lworld-values/InlineDiamondTest.java index a10125e9d46..c1d0ca9b8af 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/InlineDiamondTest.java +++ b/test/langtools/tools/javac/valhalla/lworld-values/InlineDiamondTest.java @@ -47,7 +47,7 @@ public static void main(String [] args) { InlineDiamondTest idt = new InlineDiamondTest<>(); I is = idt.get(); String toString = is.toString(); - if (!toString.equals("[InlineDiamondTest$Y x=42]")) + if (!toString.equals("InlineDiamondTest$Y@" + Integer.toHexString(is.hashCode()))) throw new AssertionError("Expected: " + toString); } } diff --git a/test/langtools/tools/javac/valhalla/lworld-values/LubWithInlines.java b/test/langtools/tools/javac/valhalla/lworld-values/LubWithInlines.java index 8520d3aa866..c3998f56c08 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/LubWithInlines.java +++ b/test/langtools/tools/javac/valhalla/lworld-values/LubWithInlines.java @@ -43,7 +43,7 @@ static primitive class XNodeWrapper implements I { } public static void main(String [] args) { I i = foo(null); - if (!i.toString().equals("[LubWithInlines$XNodeWrapper i=42]")) + if (!i.toString().equals("LubWithInlines$XNodeWrapper@" + Integer.toHexString(i.hashCode()))) throw new AssertionError("Unexpected: " + i); } } diff --git a/test/langtools/tools/javac/valhalla/lworld-values/ValueBootstrapMethodsTest.java b/test/langtools/tools/javac/valhalla/lworld-values/ValueBootstrapMethodsTest.java index 47a52256366..e74164a0cab 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/ValueBootstrapMethodsTest.java +++ b/test/langtools/tools/javac/valhalla/lworld-values/ValueBootstrapMethodsTest.java @@ -55,8 +55,7 @@ public int localHashCode() { public String localToString() { System.out.println(l); - return String.format("[%s i=%s d=%s s=%s l=%s]", Value.class.getName(), - i, String.valueOf(d), s, l.toString()); + return String.format("%s@%s", Value.class.getName(), Integer.toHexString(localHashCode())); } @Override