8227046: compiler implementation for sealed classes

8225056: VM support for sealed classes
8227044: javax.lang.model for sealed classes
8227045: Preview APIs support for sealed classes
8227047: Javadoc for sealed types
8245854: JVM TI Specification for sealed classes

Co-authored-by: Harold Seigel <harold.seigel@oracle.com>
Co-authored-by: Jan Lahoda <jan.lahoda@oracle.com>
Reviewed-by: mcimadamore, forax, darcy, dholmes, jlahoda, lfoltan, mchung, sspitsyn, vromero
This commit is contained in:
Vicente Romero 2020-06-01 17:00:40 -04:00
parent 567692e4ae
commit d42bfef8a4
139 changed files with 6877 additions and 192 deletions

View file

@ -218,6 +218,57 @@ bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const {
return false;
}
// Called to verify that k is a permitted subclass of this class
bool InstanceKlass::has_as_permitted_subclass(const InstanceKlass* k) const {
Thread* THREAD = Thread::current();
assert(k != NULL, "sanity check");
assert(_permitted_subclasses != NULL && _permitted_subclasses != Universe::the_empty_short_array(),
"unexpected empty _permitted_subclasses array");
if (log_is_enabled(Trace, class, sealed)) {
ResourceMark rm(THREAD);
log_trace(class, sealed)("Checking for permitted subclass of %s in %s",
k->external_name(), this->external_name());
}
// Check that the class and its super are in the same module.
if (k->module() != this->module()) {
ResourceMark rm(THREAD);
log_trace(class, sealed)("Check failed for same module of permitted subclass %s and sealed class %s",
k->external_name(), this->external_name());
return false;
}
if (!k->is_public() && !is_same_class_package(k)) {
ResourceMark rm(THREAD);
log_trace(class, sealed)("Check failed, subclass %s not public and not in the same package as sealed class %s",
k->external_name(), this->external_name());
return false;
}
// Check for a resolved cp entry, else fall back to a name check.
// We don't want to resolve any class other than the one being checked.
for (int i = 0; i < _permitted_subclasses->length(); i++) {
int cp_index = _permitted_subclasses->at(i);
if (_constants->tag_at(cp_index).is_klass()) {
Klass* k2 = _constants->klass_at(cp_index, THREAD);
assert(!HAS_PENDING_EXCEPTION, "Unexpected exception");
if (k2 == k) {
log_trace(class, sealed)("- class is listed at permitted_subclasses[%d] => cp[%d]", i, cp_index);
return true;
}
} else {
Symbol* name = _constants->klass_name_at(cp_index);
if (name == k->name()) {
log_trace(class, sealed)("- Found it at permitted_subclasses[%d] => cp[%d]", i, cp_index);
return true;
}
}
}
log_trace(class, sealed)("- class is NOT a permitted subclass!");
return false;
}
// Return nest-host class, resolving, validating and saving it if needed.
// In cases where this is called from a thread that cannot do classloading
// (such as a native JIT thread) then we simply return NULL, which in turn
@ -484,6 +535,7 @@ InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind, Klass
Klass(id),
_nest_members(NULL),
_nest_host(NULL),
_permitted_subclasses(NULL),
_record_components(NULL),
_static_field_size(parser.static_field_size()),
_nonstatic_oop_map_size(nonstatic_oop_map_size(parser.total_oop_map_count())),
@ -665,6 +717,13 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
}
set_nest_members(NULL);
if (permitted_subclasses() != NULL &&
permitted_subclasses() != Universe::the_empty_short_array() &&
!permitted_subclasses()->is_shared()) {
MetadataFactory::free_array<jushort>(loader_data, permitted_subclasses());
}
set_permitted_subclasses(NULL);
// We should deallocate the Annotations instance if it's not in shared spaces.
if (annotations() != NULL && !annotations()->is_shared()) {
MetadataFactory::free_metadata(loader_data, annotations());
@ -676,6 +735,12 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
}
}
bool InstanceKlass::is_sealed() const {
return _permitted_subclasses != NULL &&
_permitted_subclasses != Universe::the_empty_short_array() &&
_permitted_subclasses->length() > 0;
}
bool InstanceKlass::should_be_initialized() const {
return !is_initialized();
}
@ -2414,6 +2479,7 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
}
it->push(&_nest_members);
it->push(&_permitted_subclasses);
it->push(&_record_components);
}
@ -3342,6 +3408,7 @@ void InstanceKlass::print_on(outputStream* st) const {
if (record_components() != NULL) {
st->print(BULLET"record components: "); record_components()->print_value_on(st); st->cr();
}
st->print(BULLET"permitted subclasses: "); permitted_subclasses()->print_value_on(st); st->cr();
if (java_mirror() != NULL) {
st->print(BULLET"java mirror: ");
java_mirror()->print_value_on(st);