Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8237073: [lworld] Need special handling of jlO constructor invocation #481

Closed
wants to merge 5 commits into from
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -152,12 +152,14 @@ private static RuntimeException newIAE(String message, Throwable cause) {
return new IllegalArgumentException(message, cause);
}

private static final Function<Object, Object> CREATE_RESERVATION = new Function<>() {
@Override
public Object apply(Object key) {
return new Object();
}
};
private static class CacheHolder {
static final Function<Object, Object> CREATE = new Function<>() {
@Override
public Object apply(Object key) {
return new CacheHolder();
}
};
}

public final S findSpecies(K key) {
// Note: Species instantiation may throw VirtualMachineError because of
@@ -180,12 +182,12 @@ public final S findSpecies(K key) {
// concrete class if ever.
// The concrete class is published via SpeciesData instance
// returned here only after the class and species data are linked together.
Object speciesDataOrReservation = cache.computeIfAbsent(key, CREATE_RESERVATION);
Object speciesDataOrReservation = cache.computeIfAbsent(key, CacheHolder.CREATE);
// Separating the creation of a placeholder SpeciesData instance above
// from the loading and linking a real one below ensures we can never
// accidentally call computeIfAbsent recursively.
S speciesData;
if (speciesDataOrReservation.getClass() == Object.class) {
if (speciesDataOrReservation.getClass() == CacheHolder.class) {
synchronized (speciesDataOrReservation) {
Object existingSpeciesData = cache.get(key);
if (existingSpeciesData == speciesDataOrReservation) { // won the race
@@ -56,6 +56,7 @@
import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArgs;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.resources.CompilerProperties.Notes;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
@@ -2830,6 +2831,9 @@ public void visitNewClass(final JCNewClass tree) {
clazztype = TreeInfo.isEnumInit(env.tree) ?
attribIdentAsEnumType(env, (JCIdent)clazz) :
attribType(clazz, env);
if (clazztype.tsym == syms.objectType.tsym && cdef == null && !tree.classDeclRemoved()) {
log.note(tree.pos(), Notes.CantInstantiateObjectDirectly);
}
} finally {
env.info.isNewClass = false;
}
@@ -2851,7 +2851,12 @@ public void visitNewClass(JCNewClass tree) {
} else {
tree.clazz = access(c, tree.clazz, enclOp, false);
}
result = tree;
if (tree.clazz.type.tsym == syms.objectType.tsym) {
Assert.check(tree.def == null && tree.encl == null);
result = makeCall(make.Ident(syms.objectsType.tsym), names.newIdentity, List.nil());
} else {
result = tree;
}
}

// Simplify conditionals with known constant controlling expressions.
@@ -3903,3 +3903,6 @@ compiler.warn.declared.using.preview=\

compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=\
attempt to synchronize on an instance of a value-based class

compiler.note.cant.instantiate.object.directly=\
Object cannot be instantiated directly; a subclass of Object will be instantiated instead, by invoking java.util.Objects.newIdentity()
@@ -40,7 +40,7 @@ public class IntHashTable {
protected int[] ints; // the image set
protected int mask; // used to clip int's into the domain
protected int num_bindings; // the number of mappings (including DELETED)
private static final Object DELETED = new Object();
private static final Object DELETED = new Object() {};

/**
* Construct an Object {@literal ->} int hash table.
@@ -94,6 +94,7 @@ public static Names instance(Context context) {
public final Name init;
public final Name iterator;
public final Name length;
public final Name newIdentity;
public final Name next;
public final Name ordinal;
public final Name provider;
@@ -281,6 +282,7 @@ public Names(Context context) {
iterator = fromString("iterator");
length = fromString("length");
next = fromString("next");
newIdentity = fromString("newIdentity");
ordinal = fromString("ordinal");
provider = fromString("provider");
serialVersionUID = fromString("serialVersionUID");
@@ -208,7 +208,7 @@ public boolean transform(final CompilationService sjavac,

// Prepare compilation calls
List<Callable<CompilationSubResult>> compilationCalls = new ArrayList<>();
final Object lock = new Object();
final Object lock = new Object() {};
for (int i = 0; i < numCompiles; i++) {
CompileChunk cc = compileChunks[i];
if (cc.srcs.isEmpty()) {
@@ -36,10 +36,10 @@
package compiler.escapeAnalysis;

public class TestGetClass {
static Object obj = new Object();
static Object obj = new Object() {};

public static boolean test() {
if (obj.getClass() == Object.class) {
if (obj.getClass().getSuperclass() == Object.class) {
synchronized (obj) {
return true;
}
@@ -30,7 +30,7 @@ public class ForObjectDataProvider {
public static Object[][] forObjectDataProvider() {
return new Object[][]{
{TestHelper.DUMMY_CLASS_INSTANCE.objectField,
"Object[Object@" + TestHelper.DUMMY_CLASS_INSTANCE.objectField.hashCode() + "]"},
"Object[Objects$1@" + TestHelper.DUMMY_CLASS_INSTANCE.objectField.hashCode() + "]"},
{TestHelper.DUMMY_CLASS_INSTANCE.stringField,
"Object[String:\"" + TestHelper.DUMMY_CLASS_INSTANCE.stringField + "\"]"},
{TestHelper.DUMMY_CLASS_INSTANCE.booleanField,
@@ -73,7 +73,7 @@ public static void main(String[] args) throws Throwable {
}

// Try to cast using a different mechanism.
new java.lang.Object().getClass().cast(hiddenClassObj);
new java.lang.Object() {}.getClass().getSuperclass().cast(hiddenClassObj);
}

}
@@ -59,7 +59,7 @@ public static void main(String[] args) throws Throwable {
}

public static void invalidObjectToDerived() {
java.lang.Object instance = new java.lang.Object();
java.lang.Object instance = java.util.Objects.newIdentity();
int left = 23;
int right = 42;
try {
@@ -69,7 +69,7 @@ public static void invalidObjectToDerived() {
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
} catch (ClassCastException cce) {
System.out.println(cce.toString());
if (!cce.getMessage().contains("class java.lang.Object cannot be cast to class Derived (java.lang.Object is in module java.base of loader 'bootstrap'; Derived is in unnamed module of loader 'app')")) {
if (!cce.getMessage().contains("class java.util.Objects$1 cannot be cast to class Derived (java.util.Objects$1 is in module java.base of loader 'bootstrap'; Derived is in unnamed module of loader 'app')")) {
throw new RuntimeException("Wrong message: " + cce.getMessage());
}
}
@@ -80,7 +80,7 @@ public void run(CommandExecutor executor, String classHistogramArgs, String expa
output.shouldMatch("^\\s+\\d+:\\s+\\d+\\s+\\d+\\s+java.lang.String " + moduleRegex + "\\s*$");

/* Require at least one java.lang.Object */
output.shouldMatch("^\\s+\\d+:\\s+\\d+\\s+\\d+\\s+java.lang.Object " + moduleRegex + "\\s*$");
output.shouldMatch("^\\s+\\d+:\\s+\\d+\\s+\\d+\\s+java.util.Objects\\$1 " + moduleRegex + "\\s*$");

/* Require at exactly one TestClass[] */
output.shouldMatch("^\\s+\\d+:\\s+1\\s+\\d+\\s+" +
@@ -38,8 +38,8 @@

public class WaitNotifyThreadTest {

private Object monitor = new Object();
private final String OBJECT = "a java.lang.Object";
private Object monitor = java.util.Objects.newIdentity();
private final String OBJECT = "a java.util.Objects$1";
private final String OBJECT_WAIT = "java.lang.Object.wait";
private final String RUN_METHOD = "WaitNotifyThreadTest$WaitThread.run";

@@ -183,7 +183,7 @@ public void afterTest() {
public void getPropertyTest(final boolean publicLookup) throws Throwable {
final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt);
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), java.util.Objects.newIdentity().getClass());
Copy link
Member

@mlchung mlchung Jul 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks okay but this may be unclear to the reader why the returned class is not Object.class.

An alternative fix is to define an explicit TestObject class:

diff --git a/test/jdk/jdk/dynalink/BeanLinkerTest.java b/test/jdk/jdk/dynalink/BeanLinkerTest.java
index fafc1be447f..f22aab8f026 100644
--- a/test/jdk/jdk/dynalink/BeanLinkerTest.java
+++ b/test/jdk/jdk/dynalink/BeanLinkerTest.java
@@ -179,11 +179,13 @@ public class BeanLinkerTest {
         this.linker = null;
     }
 
+    static class TestObject {}
+
     @Test(dataProvider = "flags")
     public void getPropertyTest(final boolean publicLookup) throws Throwable {
         final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
         final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt);
-        Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
+        Assert.assertEquals(cs.getTarget().invoke(new TestObject(), "class"), TestObject.class);
         Assert.assertEquals(cs.getTarget().invoke(new Date(), "class"), Date.class);
     }
 
@@ -191,14 +193,14 @@ public class BeanLinkerTest {
     public void getPropertyNegativeTest(final boolean publicLookup) throws Throwable {
         final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
         final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt);
-        Assert.assertNull(cs.getTarget().invoke(new Object(), "DOES_NOT_EXIST"));
+        Assert.assertNull(cs.getTarget().invoke(new TestObject(), "DOES_NOT_EXIST"));
     }
 
     @Test(dataProvider = "flags")
     public void getPropertyTest2(final boolean publicLookup) throws Throwable {
         final MethodType mt = MethodType.methodType(Object.class, Object.class);
         final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "class", mt);
-        Assert.assertEquals(cs.getTarget().invoke(new Object()), Object.class);
+        Assert.assertEquals(cs.getTarget().invoke(new TestObject()), TestObject.class);
         Assert.assertEquals(cs.getTarget().invoke(new Date()), Date.class);
     }
 
@@ -208,7 +210,7 @@ public class BeanLinkerTest {
         final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "DOES_NOT_EXIST", mt);
 
         try {
-            cs.getTarget().invoke(new Object());
+            cs.getTarget().invoke(new TestObject());
             throw new RuntimeException("Expected NoSuchDynamicMethodException");
         } catch (final Throwable th) {
             Assert.assertTrue(th instanceof NoSuchDynamicMethodException);

Assert.assertEquals(cs.getTarget().invoke(new Date(), "class"), Date.class);
}

@@ -198,7 +198,7 @@ public void getPropertyNegativeTest(final boolean publicLookup) throws Throwable
public void getPropertyTest2(final boolean publicLookup) throws Throwable {
final MethodType mt = MethodType.methodType(Object.class, Object.class);
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "class", mt);
Assert.assertEquals(cs.getTarget().invoke(new Object()), Object.class);
Assert.assertEquals(cs.getTarget().invoke(new Object()), java.util.Objects.newIdentity().getClass());
Assert.assertEquals(cs.getTarget().invoke(new Date()), Date.class);
}

@@ -193,7 +193,7 @@ public void prelinkTransformerTest() throws Throwable {
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
MethodHandles.publicLookup(), GET_PROPERTY, mt)));
Assert.assertFalse(reachedPrelinkTransformer[0]);
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), java.util.Objects.newIdentity().getClass());
sadayapalam marked this conversation as resolved.
Show resolved Hide resolved
Assert.assertTrue(reachedPrelinkTransformer[0]);
}

@@ -212,7 +212,7 @@ public void internalObjectsFilterTest() throws Throwable {
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
MethodHandles.publicLookup(), GET_PROPERTY, mt)));
Assert.assertFalse(reachedInternalObjectsFilter[0]);
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), java.util.Objects.newIdentity().getClass());
Assert.assertTrue(reachedInternalObjectsFilter[0]);
}

@@ -51,7 +51,7 @@ public void testTypeInference() {
assertEval("import java.util.ArrayList;");
assertEval("import java.util.Arrays;");

assertType("new Object().getClass().getSuperclass() ", "Class<?>");
assertType("new Object() {}.getClass().getSuperclass().getSuperclass() ", "Class<?>");
assertType("new ArrayList().getClass().getSuperclass()", "Class<?>");
assertType("new ArrayList().getClass()", "Class<? extends ArrayList>");
assertType("ArrayList.class", "Class<ArrayList>");
@@ -509,7 +509,7 @@ public void varDeclRedefNoInit() {
assertVarDeclRedefNoInit("double", "d", "3.1415926", "0.0");
assertVarDeclRedefNoInit("boolean", "n", "true", "false");
assertVarDeclRedefNoInit("char", "c", "'x'", "'\\000'");
assertVarDeclRedefNoInit("Object", "o", "new Object()", IGNORE_VALUE, "null");
assertVarDeclRedefNoInit("Object", "o", "new String()", IGNORE_VALUE, "null");
assertVarDeclRedefNoInit("String", "s", "\"hi\"", "null");
}

@@ -68,7 +68,7 @@ void test(String opt, String expect) throws Exception {

void m(List t) {
// force a note about unchecked usage
t.add(new Object());
t.add(new Object() {});
}

private File testSrc = new File(System.getProperty("test.src", "."));
@@ -16,17 +16,17 @@ public void test() {
// or as a resource in a try-with-resources statement
try {
} catch (Exception exParam1) {
Object exParam1 = new Object();
Object exParam1 = new Object() {};
try (java.io.FileInputStream exParam1 = new java.io.FileInputStream("foo.txt")) {
Object exParam1 = new Object();
Object exParam1 = new Object() {};
} catch (IOException exParam1) {
}
}

// compiler error if resource is redeclared within the try Block as a local var
// or as an exception param of a catch clause in a try statement
try (java.io.FileInputStream exParam2 = new java.io.FileInputStream("bar.txt")) {
Object exParam2 = new Object();
Object exParam2 = new Object() {};
try (BufferedReader br = new BufferedReader(new FileReader("zee.txt"))) {
} catch (IOException exParam2) {
}
@@ -6,7 +6,7 @@
public class TwrForVariable3 implements AutoCloseable {
public static void main(String... args) {
TwrForVariable3 v1 = new TwrForVariable3();
Object v2 = new Object();
Object v2 = new Object() {};
Object v3 = new Object() {
public void close() {
}
@@ -15,7 +15,7 @@ public static void main(String... args) {
}

try (r) {
Object r = new Object();
Object r = new Object() {};
}

try (r) {
@@ -16,5 +16,5 @@ class InvalidRepAnnoOnCast {
@Target(ElementType.TYPE_PARAMETER)
@interface TC { T[] value(); }

String s = (@T(1) @T(2) String) new Object();
String s = (@T(1) @T(2) String) new Object() {};
}
@@ -1,2 +1,3 @@
InvalidRepAnnoOnCast.java:19:17: compiler.err.invalid.repeatable.annotation.not.applicable.in.context: InvalidRepAnnoOnCast.TC
1 error
InvalidRepAnnoOnCast.java:19:37: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.anonymous.class: java.lang.Object, @InvalidRepAnnoOnCast.T(1),@InvalidRepAnnoOnCast.T(2) java.lang.String)
2 errors
@@ -9,7 +9,7 @@
class DeclarationAnnotation {
Object e1 = new @DA int[5];
Object e2 = new @DA String[42];
Object e3 = new @DA Object();
Object e3 = new @DA Object() {};
Object e4 = new @DA Object() { };
}

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

// key: compiler.note.cant.instantiate.object.directly

class CantInstantiateObjectDirectly {
{ new Object(); }
}
@@ -13,7 +13,7 @@
public class UnsoundInference {

public static void main(String[] args) {
Object[] objArray = {new Object()};
Object[] objArray = {new Object() {}};
ArrayList<String> strList = new ArrayList<String>();
transferBug(objArray, strList);
String str = strList.get(0);
@@ -10,7 +10,7 @@

class T8065986a {
T8065986a() {
super(new Object<>());
super(new Object<>() {});
}

T8065986a(boolean b) {
@@ -10,7 +10,7 @@

class T8065986b {
T8065986b() {
this(new Object<>());
this(new Object<>() {});
}

T8065986b(boolean b) {
@@ -19,6 +19,6 @@ class CaptureLowerBoundDeref {
<T> K<T> m(I<? extends T> arg) { return null; }

void test(Wrapper<?> w) {
m(w.get()).take(new Object());
m(w.get()).take(new Object() {});
}
}
@@ -1,2 +1,2 @@
CaptureLowerBoundDeref.java:22:19: compiler.err.cant.apply.symbol: kindname.method, take, compiler.misc.type.captureof: 1, ?, java.lang.Object, kindname.interface, CaptureLowerBoundDeref.K<T>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, compiler.misc.type.captureof: 1, ?))
CaptureLowerBoundDeref.java:22:19: compiler.err.cant.apply.symbol: kindname.method, take, compiler.misc.type.captureof: 1, ?, compiler.misc.anonymous.class: java.lang.Object, kindname.interface, CaptureLowerBoundDeref.K<T>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.anonymous.class: java.lang.Object, compiler.misc.type.captureof: 1, ?))
1 error
@@ -25,7 +25,7 @@ void f() {
}
}
public static void main(String[] args) {
NewBeforeOuterConstructed2 c = new NewBeforeOuterConstructed2(new Object());
NewBeforeOuterConstructed2 c = new NewBeforeOuterConstructed2(new Object() {});
Middle m = c.new Middle();
m.f();
}
@@ -117,9 +117,9 @@ private void gen(StringBuilder code, int depth) {
}

code.append(".addGap(1)\n" +
".addComponent(new Object())\n" +
".addComponent(new Object() {})\n" +
".addGap(1)\n" +
".addComponent(new Object())");
".addComponent(new Object() {})");
}

class JavaSource extends SimpleJavaFileObject {