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

8262104: [lworld] Runtime should automagically have primitive classes implement PrimitiveObject #349

Closed
wants to merge 1 commit into from
Closed
Changes from all 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
@@ -961,7 +961,6 @@ static bool put_after_lookup(const Symbol* name, const Symbol* sig, NameSigHash*
void ClassFileParser::parse_interfaces(const ClassFileStream* stream,
int itfs_len,
ConstantPool* cp,
bool is_inline_type,
bool* const has_nonstatic_concrete_methods,
// FIXME: lots of these functions
// declare their parameters as const,
@@ -1017,7 +1016,7 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* stream,
}

InstanceKlass* ik = InstanceKlass::cast(interf);
if (is_inline_type && ik->invalid_inline_super()) {
if (is_inline_type() && ik->invalid_inline_super()) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
@@ -1038,6 +1037,11 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* stream,
if (ik->name() == vmSymbols::java_lang_IdentityObject()) {
_implements_identityObject = true;
}
if (ik->name() == vmSymbols::java_lang_PrimitiveObject()) {
// further checks for "is_invalid_super_for_inline_type()" needed later
// needs field parsing, delay unitl post_process_parse_stream()
_implements_primitiveObject = true;
}
_temp_local_interfaces->append(ik);
}

@@ -4601,6 +4605,9 @@ static Array<InstanceKlass*>* compute_transitive_interfaces(const InstanceKlass*
if (length == 1 && result->at(0) == vmClasses::IdentityObject_klass()) {
return Universe::the_single_IdentityObject_klass_array();
}
if (length == 1 && result->at(0) == vmClasses::PrimitiveObject_klass()) {
return Universe::the_single_PrimitiveObject_klass_array();
}

Array<InstanceKlass*>* const new_result =
MetadataFactory::new_array<InstanceKlass*>(loader_data, length, CHECK_NULL);
@@ -5719,6 +5726,9 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
if (_has_injected_identityObject) {
ik->set_has_injected_identityObject();
}
if (_has_injected_primitiveObject) {
ik->set_has_injected_primitiveObject();
}

assert(_fac != NULL, "invariant");
ik->set_static_oop_field_count(_fac->count[STATIC_OOP] + _fac->count[STATIC_INLINE]);
@@ -5967,9 +5977,15 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
// it's official
set_klass(ik);

// the common single interface arrays need setup here to provide the
// correct answer to "compute_transitive_interfaces()", during
// "SystemDictionary::initialize()"
if (ik->name() == vmSymbols::java_lang_IdentityObject()) {
Universe::initialize_the_single_IdentityObject_klass_array(ik, CHECK);
}
if (ik->name() == vmSymbols::java_lang_PrimitiveObject()) {
Universe::initialize_the_single_PrimitiveObject_klass_array(ik, CHECK);
}

debug_only(ik->verify();)
}
@@ -6122,6 +6138,8 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
_invalid_identity_super(false),
_implements_identityObject(false),
_has_injected_identityObject(false),
_implements_primitiveObject(false),
_has_injected_primitiveObject(false),
_has_finalizer(false),
_has_empty_finalizer(false),
_has_vanilla_constructor(false),
@@ -6465,7 +6483,6 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
parse_interfaces(stream,
_itfs_len,
cp,
is_inline_type(),
&_has_nonstatic_concrete_methods,
&_is_declared_atomic,
CHECK);
@@ -6613,13 +6630,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
if (is_inline_type()) {
const InstanceKlass* super_ik = _super_klass;
if (super_ik->invalid_inline_super()) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"inline class %s has an invalid super class %s",
_class_name->as_klass_external_name(),
_super_klass->external_name());
classfile_icce_error("inline class %s has an invalid super class %s", _super_klass, THREAD);
return;
}
}
@@ -6651,11 +6662,25 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
_temp_local_interfaces->append(vmClasses::IdentityObject_klass());
_has_injected_identityObject = true;
}
// Check if declared as PrimitiveObject...else add if needed
if (_implements_primitiveObject) {
if (!is_inline_type() && invalid_inline_super()) {
classfile_icce_error("class %s can not implement %s, neither valid inline classes or valid supertype",
vmClasses::PrimitiveObject_klass(), THREAD);
return;
}
} else if (is_inline_type()) {
_temp_local_interfaces->append(vmClasses::PrimitiveObject_klass());
_has_injected_primitiveObject = true;
}

int itfs_len = _temp_local_interfaces->length();
if (itfs_len == 0) {
_local_interfaces = Universe::the_empty_instance_klass_array();
} else if (itfs_len == 1 && _temp_local_interfaces->at(0) == vmClasses::IdentityObject_klass()) {
_local_interfaces = Universe::the_single_IdentityObject_klass_array();
} else if (itfs_len == 1 && _temp_local_interfaces->at(0) == vmClasses::PrimitiveObject_klass()) {
_local_interfaces = Universe::the_single_PrimitiveObject_klass_array();
} else {
_local_interfaces = MetadataFactory::new_array<InstanceKlass*>(_loader_data, itfs_len, NULL, CHECK);
for (int i = 0; i < itfs_len; i++) {
@@ -213,6 +213,8 @@ class ClassFileParser {
bool _invalid_identity_super; // if true, invalid super type for an identity type.
bool _implements_identityObject;
bool _has_injected_identityObject;
bool _implements_primitiveObject;
bool _has_injected_primitiveObject;

// precomputed flags
bool _has_finalizer;
@@ -263,7 +265,6 @@ class ClassFileParser {
void parse_interfaces(const ClassFileStream* const stream,
const int itfs_len,
ConstantPool* const cp,
bool is_inline_type,
bool* has_nonstatic_concrete_methods,
bool* is_declared_atomic,
TRAPS);
@@ -400,26 +400,36 @@ InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS

bool identity_object_implemented = false;
bool identity_object_specified = false;
bool primitive_object_implemented = false;
bool primitive_object_specified = false;
for (i = 0; i < actual_num_interfaces; i++) {
if (k->local_interfaces()->at(i) == vmClasses::IdentityObject_klass()) {
identity_object_implemented = true;
break;
}
if (k->local_interfaces()->at(i) == vmClasses::PrimitiveObject_klass()) {
primitive_object_implemented = true;
break;
}
}
for (i = 0; i < specified_num_interfaces; i++) {
if (lookup_class_by_id(_interfaces->at(i)) == vmClasses::IdentityObject_klass()) {
identity_object_specified = true;
break;
}
if (lookup_class_by_id(_interfaces->at(i)) == vmClasses::PrimitiveObject_klass()) {
primitive_object_specified = true;
break;
}
}

expected_num_interfaces = actual_num_interfaces;
if (identity_object_implemented && !identity_object_specified) {
if ( (identity_object_implemented && !identity_object_specified) ||
(primitive_object_implemented && !primitive_object_specified) ){
// Backwards compatibility -- older classlists do not know about
// java.lang.IdentityObject.
// java.lang.IdentityObject or java.lang.PrimitiveObject
expected_num_interfaces--;
}

if (specified_num_interfaces != expected_num_interfaces) {
print_specified_interfaces();
print_actual_interfaces(k);
@@ -684,6 +694,11 @@ InstanceKlass* ClassListParser::lookup_interface_for_current_class(Symbol* inter
// java.lang.IdentityObject.
return vmClasses::IdentityObject_klass();
}
if (interface_name == vmSymbols::java_lang_PrimitiveObject()) {
// Backwards compatibility -- older classlists do not know about
// java.lang.PrimitiveObject.
return vmClasses::PrimitiveObject_klass();
}

const int n = _interfaces->length();
if (n == 0) {
@@ -51,6 +51,7 @@
/* well-known classes */ \
do_klass(Object_klass, java_lang_Object ) \
do_klass(IdentityObject_klass, java_lang_IdentityObject ) \
do_klass(PrimitiveObject_klass, java_lang_PrimitiveObject ) \
do_klass(String_klass, java_lang_String ) \
do_klass(Class_klass, java_lang_Class ) \
do_klass(Cloneable_klass, java_lang_Cloneable ) \
@@ -56,6 +56,7 @@
template(java_lang_System, "java/lang/System") \
template(java_lang_Object, "java/lang/Object") \
template(java_lang_IdentityObject, "java/lang/IdentityObject") \
template(java_lang_PrimitiveObject, "java/lang/PrimitiveObject") \
template(java_lang_Class, "java/lang/Class") \
template(java_lang_Package, "java/lang/Package") \
template(java_lang_Module, "java/lang/Module") \
@@ -130,6 +130,7 @@ Array<u2>* Universe::_the_empty_short_array = NULL;
Array<Klass*>* Universe::_the_empty_klass_array = NULL;
Array<InstanceKlass*>* Universe::_the_empty_instance_klass_array = NULL;
Array<InstanceKlass*>* Universe::_the_single_IdentityObject_klass_array = NULL;
Array<InstanceKlass*>* Universe::_the_single_PrimitiveObject_klass_array = NULL;
Array<Method*>* Universe::_the_empty_method_array = NULL;

// These variables are guarded by FullGCALot_lock.
@@ -221,6 +222,7 @@ void Universe::metaspace_pointers_do(MetaspaceClosure* it) {
it->push(&_the_empty_method_array);
it->push(&_the_array_interfaces_array);
it->push(&_the_single_IdentityObject_klass_array);
it->push(&_the_single_PrimitiveObject_klass_array);

_finalizer_register_cache->metaspace_pointers_do(it);
_loader_addClass_cache->metaspace_pointers_do(it);
@@ -272,6 +274,7 @@ void Universe::serialize(SerializeClosure* f) {
f->do_ptr((void**)&_the_empty_klass_array);
f->do_ptr((void**)&_the_empty_instance_klass_array);
f->do_ptr((void**)&_the_single_IdentityObject_klass_array);
f->do_ptr((void**)&_the_single_PrimitiveObject_klass_array);
_finalizer_register_cache->serialize(f);
_loader_addClass_cache->serialize(f);
_throw_illegal_access_error_cache->serialize(f);
@@ -360,6 +363,8 @@ void Universe::genesis(TRAPS) {

assert(_the_single_IdentityObject_klass_array->at(0) ==
vmClasses::IdentityObject_klass(), "u3");
assert(_the_single_PrimitiveObject_klass_array->at(0) ==
vmClasses::PrimitiveObject_klass(), "u3");
} else
#endif
{
@@ -477,7 +482,16 @@ void Universe::initialize_the_single_IdentityObject_klass_array(InstanceKlass* i
Array<InstanceKlass*>* array = MetadataFactory::new_array<InstanceKlass*>(ik->class_loader_data(), 1, NULL, CHECK);
array->at_put(0, ik);
_the_single_IdentityObject_klass_array = array;
}
}

void Universe::initialize_the_single_PrimitiveObject_klass_array(InstanceKlass* ik, TRAPS) {
assert(_the_single_PrimitiveObject_klass_array == NULL, "Must not be initialized twice");
assert(ik->name() == vmSymbols::java_lang_PrimitiveObject(), "Must be");
Array<InstanceKlass*>* array = MetadataFactory::new_array<InstanceKlass*>(ik->class_loader_data(), 1, NULL, CHECK);
array->at_put(0, ik);
_the_single_PrimitiveObject_klass_array = array;
}


void Universe::fixup_mirrors(TRAPS) {
// Bootstrap problem: all classes gets a mirror (java.lang.Class instance) assigned eagerly,
@@ -123,7 +123,8 @@ class Universe: AllStatic {
static Array<u2>* _the_empty_short_array; // Canonicalized short array
static Array<Klass*>* _the_empty_klass_array; // Canonicalized klass array
static Array<InstanceKlass*>* _the_empty_instance_klass_array; // Canonicalized instance klass array
static Array<InstanceKlass*>* _the_single_IdentityObject_klass_array;
static Array<InstanceKlass*>* _the_single_IdentityObject_klass_array; // Common single interface array for IdentityObjects
static Array<InstanceKlass*>* _the_single_PrimitiveObject_klass_array; // Common single interface array for PrimitiveObjects
static Array<Method*>* _the_empty_method_array; // Canonicalized method array

static Array<Klass*>* _the_array_interfaces_array;
@@ -296,6 +297,12 @@ class Universe: AllStatic {
return _the_single_IdentityObject_klass_array;
}
static void initialize_the_single_IdentityObject_klass_array(InstanceKlass* ik, TRAPS);
static Array<InstanceKlass*>* the_single_PrimitiveObject_klass_array() {
assert(_the_single_PrimitiveObject_klass_array != NULL, "Must be initialized before use");
assert(_the_single_PrimitiveObject_klass_array->length() == 1, "Sanity check");
return _the_single_PrimitiveObject_klass_array;
}
static void initialize_the_single_PrimitiveObject_klass_array(InstanceKlass* ik, TRAPS);

// OutOfMemoryError support. Returns an error with the required message. The returned error
// may or may not have a backtrace. If error has a backtrace then the stack trace is already
@@ -633,15 +633,17 @@ void InstanceKlass::deallocate_interfaces(ClassLoaderData* loader_data,
Array<InstanceKlass*>* sti = (super_klass == NULL) ? NULL :
InstanceKlass::cast(super_klass)->transitive_interfaces();
if (ti != sti && ti != NULL && !ti->is_shared() &&
ti != Universe::the_single_IdentityObject_klass_array()) {
ti != Universe::the_single_IdentityObject_klass_array() &&
ti != Universe::the_single_PrimitiveObject_klass_array()) {
MetadataFactory::free_array<InstanceKlass*>(loader_data, ti);
}
}

// local interfaces can be empty
if (local_interfaces != Universe::the_empty_instance_klass_array() &&
local_interfaces != NULL && !local_interfaces->is_shared() &&
local_interfaces != Universe::the_single_IdentityObject_klass_array()) {
local_interfaces != Universe::the_single_IdentityObject_klass_array() &&
local_interfaces != Universe::the_single_PrimitiveObject_klass_array()) {
MetadataFactory::free_array<InstanceKlass*>(loader_data, local_interfaces);
}
}
@@ -292,7 +292,8 @@ class InstanceKlass: public Klass {
_misc_is_declared_atomic = 1 << 19, // implements jl.NonTearable
_misc_invalid_inline_super = 1 << 20, // invalid super type for an inline type
_misc_invalid_identity_super = 1 << 21, // invalid super type for an identity type
_misc_has_injected_identityObject = 1 << 22 // IdentityObject has been injected by the JVM
_misc_has_injected_identityObject = 1 << 22, // IdentityObject has been injected by the JVM
_misc_has_injected_primitiveObject = 1 << 23 // PrimitiveObject has been injected by the JVM
};

// (*) An inline type is considered empty if it contains no non-static fields or
@@ -483,6 +484,14 @@ class InstanceKlass: public Klass {
_misc_flags |= _misc_has_injected_identityObject;
}

bool has_injected_primitiveObject() const {
return (_misc_flags & _misc_has_injected_primitiveObject);
}

void set_has_injected_primitiveObject() {
_misc_flags |= _misc_has_injected_primitiveObject;
}

// field sizes
int nonstatic_field_size() const { return _nonstatic_field_size; }
void set_nonstatic_field_size(int size) { _nonstatic_field_size = size; }
@@ -896,11 +896,14 @@ void JvmtiClassFileReconstituter::write_class_file_format() {
// JVMSpec| u2 interfaces[interfaces_count];
Array<InstanceKlass*>* interfaces = ik()->local_interfaces();
int num_interfaces = interfaces->length();
write_u2(num_interfaces - (ik()->has_injected_identityObject() ? 1 : 0) );
write_u2(num_interfaces -
(ik()->has_injected_identityObject() || ik()->has_injected_primitiveObject() ? 1 : 0));

for (int index = 0; index < num_interfaces; index++) {
HandleMark hm(thread());
InstanceKlass* iik = interfaces->at(index);
if (!ik()->has_injected_identityObject() || iik != vmClasses::IdentityObject_klass()) {
if ( (!ik()->has_injected_identityObject() || iik != vmClasses::IdentityObject_klass()) &&
(!ik()->has_injected_primitiveObject() || iik != vmClasses::PrimitiveObject_klass())) {
write_u2(class_symbol_to_cpool_index(iik->name()));
}
}
@@ -338,6 +338,10 @@ bool VM_RedefineClasses::is_modifiable_class(oop klass_mirror) {
if (k->name() == vmSymbols::java_lang_IdentityObject()) {
return false;
}
// Cannot redefine or retransform interface java.lang.PrimitiveObject.
if (k->name() == vmSymbols::java_lang_PrimitiveObject()) {
return false;
}

// Cannot redefine or retransform a hidden or an unsafe anonymous class.
if (InstanceKlass::cast(k)->is_hidden() ||
@@ -0,0 +1,27 @@
/*
* 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.
*
*/

public abstract class AbstractSpecified implements PrimitiveObject {

}