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

8261782: [lworld] Add support for PrimitiveObject interface #344

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -27,7 +27,39 @@

/**
* A restricted interface implemented by all identity objects.
* @since 1.14
*/
* IdentityObject: An object with identity.
*
* *Identity* is a property of certain objects, determined at instance creation
* time and preserved throughout the life of the object. While an object's field
* values may change, its identity is constant. Object identities are unique: no
* two objects created by different instance creation operations can have the same
* identity.
*
* Every object is either an *identity object* or a *primitive object*. Primitive
* objects lack identity.
*
* The following operations have special behavior when applied to identity objects:
*
* - The `==` operator, and the default implementation of the `Object.equals`
* method, compare the identities of their operands, producing `true` for an
* identity object only if the object is being compared to itself.
*
* - The `System.identityHashCode` method, and the default implementation of the
* `Object.hashCode` method, generate a hash code from an identity object's
* identity.
*
* - The `synchronized` modifier and `synchronized` statement are only able to
* successfully acquire a lock when applied to an identity object.
*
* A class may implement `IdentityObject` or `PrimitiveObject`, but never both.
* Primitive classes always implement `PrimitiveObject`, while all other concrete
* classes (except `Object`) implicitly implement `IdentityObject`.
*
* Abstract classes and interfaces may implement or extend this interface if they
* wish to guarantee that all instances of the class or interface have identity.
*
* @since 1.16
*/
public interface IdentityObject {
}
@@ -0,0 +1,66 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/

package java.lang;

/**
* A restricted interface implemented by all primitive objects.
*
* A primitive object is an instance of a primitive class, lacking identity.
*
* Every object is either an *identity object* or a *primitive object*. Identity
* objects have a unique identity determined for them at instance creation time and
* preserved throughout their life.
*
* Primitive objects do *not* have an identity. Instead, they simply aggregate a
* set of immutable field values. The lack of identity enables certain performance
* optimizations by Java Virtual Machine implementations.
* The following operations have special behavior when applied to primitive
* objects:
*
* - The `==` operator, and the default implementation of the `Object.equals`
* method, compare the values of the operands' fields. Primitive objects
* created at different points in a program may be `==`.
*
* - The `System.identityHashCode` method, and the default implementation of the
* `Object.hashCode` method, generate a hash code from the hash codes of a
* primitive object's fields.
*
* - The `synchronized` modifier and `synchronized` statement always fail when
* applied to a primitive object.
*
* A class may implement `PrimitiveObject` or `IdentityObject`, but never both.
* Primitive classes always implement `PrimitiveObject`, while all other concrete
* classes (except `Object`) implicitly implement `IdentityObject`.
*
* Abstract classes and interfaces may implement or extend this interface if they
* wish to guarantee that all instances of the class or interface are primitive
* objects.
*
* @since 1.16
*/

public interface PrimitiveObject {
}
@@ -223,6 +223,7 @@ public static Symtab instance(Context context) {
public final Type typeDescriptorType;
public final Type recordType;
public final Type identityObjectType;
public final Type primitiveObjectType;
public final Type valueBasedType;

/** The symbol representing the length field of an array.
@@ -598,6 +599,7 @@ public String toString() {
typeDescriptorType = enterClass("java.lang.invoke.TypeDescriptor");
recordType = enterClass("java.lang.Record");
identityObjectType = enterClass("java.lang.IdentityObject");
primitiveObjectType = enterClass("java.lang.PrimitiveObject");
valueBasedType = enterClass("jdk.internal.ValueBased");

synthesizeEmptyInterfaceIfMissing(autoCloseableType);
@@ -607,6 +609,7 @@ public String toString() {
synthesizeEmptyInterfaceIfMissing(serializedLambdaType);
synthesizeEmptyInterfaceIfMissing(stringConcatFactory);
synthesizeEmptyInterfaceIfMissing(identityObjectType);
synthesizeEmptyInterfaceIfMissing(primitiveObjectType);
synthesizeBoxTypeIfMissing(doubleType);
synthesizeBoxTypeIfMissing(floatType);
synthesizeBoxTypeIfMissing(voidType);
@@ -2241,7 +2241,7 @@ public Type asSuper(Type t, Symbol sym, boolean checkReferenceProjection) {
if (!isPrimitiveClass(t))
return syms.objectType;
}
if (sym.type == syms.identityObjectType) {
if (sym == syms.identityObjectType.tsym) {
// IdentityObject is super interface of every concrete identity class other than jlO
if (t.isPrimitiveClass() || t.tsym == syms.objectType.tsym)
return null;
@@ -2250,6 +2250,12 @@ public Type asSuper(Type t, Symbol sym, boolean checkReferenceProjection) {
if (t.hasTag(CLASS) && !t.isReferenceProjection() && !t.tsym.isInterface() && !t.tsym.isAbstract()) {
return syms.identityObjectType;
} // else fall through and look for explicit coded super interface
} else if (sym == syms.primitiveObjectType.tsym) {
if (t.isPrimitiveClass() || t.isReferenceProjection())
return syms.primitiveObjectType;
if (t.hasTag(ARRAY) || t.tsym == syms.objectType.tsym)
return null;
// else fall through and look for explicit coded super interface
}
return asSuper.visit(t, sym);
}
@@ -2695,8 +2695,14 @@ void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
}
checkCompatibleConcretes(pos, c);

if (c.isPrimitiveClass() && types.asSuper(c, syms.identityObjectType.tsym, true) != null) {
boolean implementsIdentityObject = types.asSuper(c, syms.identityObjectType.tsym, true) != null;
boolean implementsPrimitiveObject = types.asSuper(c, syms.primitiveObjectType.tsym, true) != null;
if (c.isPrimitiveClass() && implementsIdentityObject) {
log.error(pos, Errors.PrimitiveClassMustNotImplementIdentityObject(c));
} else if (implementsPrimitiveObject && !c.isPrimitiveClass() && !c.isReferenceProjection() && !c.tsym.isInterface() && !c.tsym.isAbstract()) {
log.error(pos, Errors.IdentityClassMustNotImplementPrimitiveObject(c));
} else if (implementsPrimitiveObject && implementsIdentityObject) {
log.error(pos, Errors.MutuallyIncompatibleSuperInterfaces(c));
}
}

@@ -3820,6 +3820,14 @@ compiler.err.generic.parameterization.with.primitive.class=\
compiler.err.primitive.class.must.not.implement.identity.object=\
The primitive class {0} attempts to implement the incompatible interface IdentityObject

# 0: type
compiler.err.identity.class.must.not.implement.primitive.object=\
The identity class {0} attempts to implement the incompatible interface PrimitiveObject

# 0: type
compiler.err.mutually.incompatible.super.interfaces=\
The type {0} attempts to implement the mutually incompatible interfaces PrimitiveObject and IdentityObject

# 0: symbol, 1: type
compiler.err.concrete.supertype.for.primitive.class=\
The concrete class {1} is not allowed to be a super class of the primitive class {0} either directly or indirectly
@@ -0,0 +1,29 @@
/*
* 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.err.identity.class.must.not.implement.primitive.object
// key: compiler.err.mutually.incompatible.super.interfaces

class Identity implements PrimitiveObject {
abstract class Inner implements IdentityObject, PrimitiveObject {}
}
@@ -29,8 +29,7 @@
*/

public class InstanceOfTopTypeTest {
interface InlineObject {}
static primitive class V implements InlineObject {
static primitive class V {
int x = 42;
}

@@ -39,28 +38,28 @@ public static void main(String [] args) {
Object o = new InstanceOfTopTypeTest();
if (o instanceof IdentityObject)
points++; // 1
if (o instanceof InlineObject)
if (o instanceof PrimitiveObject)
throw new AssertionError("Broken");
o = new V();
if (o instanceof IdentityObject)
throw new AssertionError("Broken");
if (o instanceof InlineObject)
if (o instanceof PrimitiveObject)
points++; // 2
Object [] oa = new InstanceOfTopTypeTest[] { new InstanceOfTopTypeTest() };
if (oa instanceof IdentityObject)
points++; // 3
if (oa[0] instanceof IdentityObject)
points++; // 4
if (oa[0] instanceof InlineObject)
if (oa[0] instanceof PrimitiveObject)
throw new AssertionError("Broken");
oa = new V[] { new V() };
if (oa instanceof IdentityObject)
points++; // 5
if (oa[0] instanceof IdentityObject)
throw new AssertionError("Broken");
if (oa[0] instanceof InlineObject)
if (oa[0] instanceof PrimitiveObject)
points++;
if (points != 6)
throw new AssertionError("Broken top type set up" + points);
if (points != 4)
throw new AssertionError("Broken top type set up " + points);
}
}