Skip to content
Permalink
Browse files
Initial runtime arrays support for L or Q type
  • Loading branch information
David Simms committed May 12, 2021
1 parent adff688 commit a6f937bb19739572b305a8380e7feb1b08548c0f
@@ -318,10 +318,14 @@ Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
protection_domain,
CHECK_NULL);
if (k != NULL) {
if ((class_name->is_Q_array_signature() && !k->is_inline_klass())) {
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), "L/Q mismatch on bottom type");
}
k = k->array_klass(ndims, CHECK_NULL);
if (class_name->is_Q_array_signature()) {
if (!k->is_inline_klass()) {
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), "L/Q mismatch on bottom type");
}
k = InlineKlass::cast(k)->null_free_inline_array_klass(ndims, CHECK_NULL);
} else {
k = k->array_klass(ndims, CHECK_NULL);
}
}
} else {
k = Universe::typeArrayKlassObj(t);
@@ -127,10 +127,10 @@ objArrayOop oopFactory::new_objArray(Klass* klass, int length, TRAPS) {
}
}

arrayOop oopFactory::new_flatArray(Klass* klass, int length, TRAPS) {
assert(klass->is_inline_klass(), "Klass must be inline type");
arrayOop oopFactory::new_flatArray(Klass* k, int length, TRAPS) {
InlineKlass* klass = InlineKlass::cast(k);
// Request flattened, but we might not actually get it...either way "null-free" are the aaload/aastore semantics
Klass* array_klass = klass->array_klass(1, CHECK_NULL);
Klass* array_klass = klass->null_free_inline_array_klass(CHECK_NULL);
assert(array_klass->is_null_free_array_klass(), "Expect a null-free array class here");

arrayOop oop;
@@ -100,17 +100,16 @@ ArrayKlass::ArrayKlass(Symbol* name, KlassID id) :
JFR_ONLY(INIT_ID(this);)
}

Symbol* ArrayKlass::create_element_klass_array_name(Klass* element_klass, TRAPS) {
Symbol* ArrayKlass::create_element_klass_array_name(Klass* element_klass, bool qdesc, TRAPS) {
ResourceMark rm(THREAD);
Symbol* name = NULL;
bool is_qtype = element_klass->is_inline_klass();
char *name_str = element_klass->name()->as_C_string();
int len = element_klass->name()->utf8_length();
char *new_str = NEW_RESOURCE_ARRAY(char, len + 4);
int idx = 0;
new_str[idx++] = JVM_SIGNATURE_ARRAY;
if (element_klass->is_instance_klass()) { // it could be an array or simple type
if (is_qtype) {
if (qdesc) {
new_str[idx++] = JVM_SIGNATURE_INLINE_TYPE;
} else {
new_str[idx++] = JVM_SIGNATURE_CLASS;
@@ -56,7 +56,7 @@ class ArrayKlass: public Klass {
ArrayKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for cds"); }

// Create array_name for element klass
static Symbol* create_element_klass_array_name(Klass* element_klass, TRAPS);
static Symbol* create_element_klass_array_name(Klass* element_klass, bool qdesc, TRAPS);

public:
// Instance variables
@@ -84,10 +84,12 @@ void FlatArrayKlass::set_element_klass(Klass* k) {
_element_klass = k;
}

FlatArrayKlass* FlatArrayKlass::allocate_klass(Klass* element_klass, TRAPS) {
FlatArrayKlass* FlatArrayKlass::allocate_klass(Klass* eklass, TRAPS) {
guarantee((!Universe::is_bootstrapping() || vmClasses::Object_klass_loaded()), "Really ?!");
assert(UseFlatArray, "Flatten array required");
assert(InlineKlass::cast(element_klass)->is_naturally_atomic() || (!InlineArrayAtomicAccess), "Atomic by-default");

InlineKlass* element_klass = InlineKlass::cast(eklass);
assert(element_klass->is_naturally_atomic() || (!InlineArrayAtomicAccess), "Atomic by-default");

/*
* MVT->LWorld, now need to allocate secondaries array types, just like objArrayKlass...
@@ -123,13 +125,13 @@ FlatArrayKlass* FlatArrayKlass::allocate_klass(Klass* element_klass, TRAPS) {
elem_super->array_klass(CHECK_NULL);
}
// Now retry from the beginning
ek = element_klass->array_klass(CHECK_NULL);
ek = element_klass->null_free_inline_array_klass(CHECK_NULL);
} // re-lock
return FlatArrayKlass::cast(ek);
}
}

Symbol* name = ArrayKlass::create_element_klass_array_name(element_klass, CHECK_NULL);
Symbol* name = ArrayKlass::create_element_klass_array_name(element_klass, true, CHECK_NULL);
ClassLoaderData* loader_data = element_klass->class_loader_data();
int size = ArrayKlass::static_size(FlatArrayKlass::header_size());
FlatArrayKlass* vak = new (loader_data, size, THREAD) FlatArrayKlass(element_klass, name);
@@ -348,7 +350,7 @@ Klass* FlatArrayKlass::array_klass(int n, TRAPS) {
if (higher_dimension() == NULL) {

// Create multi-dim klass object and link them together
Klass* k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), dim + 1, this, CHECK_NULL);
Klass* k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), dim + 1, this, false, true, CHECK_NULL);
ObjArrayKlass* ak = ObjArrayKlass::cast(k);
ak->set_lower_dimension(this);
// use 'release' to pair with lock-free load
@@ -60,6 +60,7 @@ InlineKlass::InlineKlass(const ClassFileParser& parser)
*((address*)adr_unpack_handler()) = NULL;
assert(pack_handler() == NULL, "pack handler not null");
*((int*)adr_default_value_offset()) = 0;
*((address*)adr_null_free_inline_array_klasses()) = NULL;
set_prototype_header(markWord::inline_type_prototype());
assert(is_inline_type_klass(), "sanity");
assert(prototype_header().is_inline_type(), "sanity");
@@ -164,66 +165,65 @@ bool InlineKlass::flatten_array() {
return true;
}

void InlineKlass::remove_unshareable_info() {
InstanceKlass::remove_unshareable_info();

*((Array<SigEntry>**)adr_extended_sig()) = NULL;
*((Array<VMRegPair>**)adr_return_regs()) = NULL;
*((address*)adr_pack_handler()) = NULL;
*((address*)adr_pack_handler_jobject()) = NULL;
*((address*)adr_unpack_handler()) = NULL;
assert(pack_handler() == NULL, "pack handler not null");
}

void InlineKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, PackageEntry* pkg_entry, TRAPS) {
InstanceKlass::restore_unshareable_info(loader_data, protection_domain, pkg_entry, CHECK);
}

Klass* InlineKlass::array_klass(int n, TRAPS) {
// Need load-acquire for lock-free read
if (array_klasses_acquire() == NULL) {
Klass* InlineKlass::null_free_inline_array_klass(int n, TRAPS) {
if (Atomic::load_acquire(adr_null_free_inline_array_klasses()) == NULL) {
ResourceMark rm(THREAD);
JavaThread *jt = THREAD->as_Java_thread();
{
// Atomic creation of array_klasses
MutexLocker ma(THREAD, MultiArray_lock);

// Check if update has already taken place
if (array_klasses() == NULL) {
if (null_free_inline_array_klasses() == NULL) {
ArrayKlass* k;
if (flatten_array()) {
k = FlatArrayKlass::allocate_klass(this, CHECK_NULL);
} else {
k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), 1, this, CHECK_NULL);
k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), 1, this, true, true, CHECK_NULL);

}
// use 'release' to pair with lock-free load
release_set_array_klasses(k);
Atomic::release_store(adr_null_free_inline_array_klasses(), k);
}
}
}
// array_klasses() will always be set at this point
ArrayKlass* ak = array_klasses();
ArrayKlass* ak = null_free_inline_array_klasses();
return ak->array_klass(n, THREAD);
}

Klass* InlineKlass::array_klass_or_null(int n) {
Klass* InlineKlass::null_free_inline_array_klass_or_null(int n) {
// Need load-acquire for lock-free read
ArrayKlass* ak = array_klasses_acquire();
ArrayKlass* ak = Atomic::load_acquire(adr_null_free_inline_array_klasses());
if (ak == NULL) {
return NULL;
} else {
return ak->array_klass_or_null(n);
}
}

Klass* InlineKlass::array_klass(TRAPS) {
return array_klass(1, THREAD);
Klass* InlineKlass::null_free_inline_array_klass(TRAPS) {
return null_free_inline_array_klass(1, THREAD);
}

Klass* InlineKlass::null_free_inline_array_klass_or_null() {
return null_free_inline_array_klass_or_null(1);
}

Klass* InlineKlass::array_klass_or_null() {
return array_klass_or_null(1);

void InlineKlass::remove_unshareable_info() {
InstanceKlass::remove_unshareable_info();

*((Array<SigEntry>**)adr_extended_sig()) = NULL;
*((Array<VMRegPair>**)adr_return_regs()) = NULL;
*((address*)adr_pack_handler()) = NULL;
*((address*)adr_pack_handler_jobject()) = NULL;
*((address*)adr_unpack_handler()) = NULL;
assert(pack_handler() == NULL, "pack handler not null");
}

void InlineKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, PackageEntry* pkg_entry, TRAPS) {
InstanceKlass::restore_unshareable_info(loader_data, protection_domain, pkg_entry, CHECK);
}

// Inline type arguments are not passed by reference, instead each
// field of the inline type is passed as an argument. This helper
@@ -75,6 +75,15 @@ class InlineKlass: public InstanceKlass {
return ((address)_adr_inlineklass_fixed_block) + in_bytes(default_value_offset_offset());
}

ArrayKlass* volatile* adr_null_free_inline_array_klasses() const {
assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
return (ArrayKlass* volatile*) ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _null_free_inline_array_klasses));
}

ArrayKlass* null_free_inline_array_klasses() const {
return *adr_null_free_inline_array_klasses();
}

address adr_alignment() const {
assert(_adr_inlineklass_fixed_block != NULL, "Should have been initialized");
return ((address)_adr_inlineklass_fixed_block) + in_bytes(byte_offset_of(InlineKlassFixedBlock, _alignment));
@@ -129,15 +138,6 @@ class InlineKlass: public InstanceKlass {
void cleanup_blobs();

public:
// Returns the array class for the n'th dimension
virtual Klass* array_klass(int n, TRAPS);
virtual Klass* array_klass_or_null(int n);

// Returns the array class with this class as element type
virtual Klass* array_klass(TRAPS);
virtual Klass* array_klass_or_null();


// Type testing
bool is_inline_klass_slow() const { return true; }

@@ -168,6 +168,19 @@ class InlineKlass: public InstanceKlass {
bool contains_oops() const { return nonstatic_oop_map_count() > 0; }
int nonstatic_oop_count();

// null free inline arrays...
//

// null free inline array klass, akin to InstanceKlass::array_klass()
// Returns the array class for the n'th dimension
Klass* null_free_inline_array_klass(int n, TRAPS);
Klass* null_free_inline_array_klass_or_null(int n);

// Returns the array class with this class as element type
Klass* null_free_inline_array_klass(TRAPS);
Klass* null_free_inline_array_klass_or_null();


// General store methods
//
// Normally loads and store methods would be found in *Oops classes, but since values can be
@@ -1574,7 +1574,8 @@ Klass* InstanceKlass::array_klass(int n, TRAPS) {

// Check if update has already taken place
if (array_klasses() == NULL) {
ObjArrayKlass* k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), 1, this, CHECK_NULL);
ObjArrayKlass* k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), 1, this,
false, false, CHECK_NULL);
// use 'release' to pair with lock-free load
release_set_array_klasses(k);
}
@@ -142,6 +142,7 @@ class InlineKlassFixedBlock {
address* _pack_handler_jobject;
address* _unpack_handler;
int* _default_value_offset;
ArrayKlass** _null_free_inline_array_klasses;
int _alignment;
int _first_field_offset;
int _exact_size_in_bytes;
@@ -46,17 +46,21 @@
#include "runtime/mutexLocker.hpp"
#include "utilities/macros.hpp"

ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS) {
ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n,
Klass* k, Symbol* name, bool null_free,
TRAPS) {
assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(),
"array klasses must be same size as InstanceKlass");

int size = ArrayKlass::static_size(ObjArrayKlass::header_size());

return new (loader_data, size, THREAD) ObjArrayKlass(n, k, name);
return new (loader_data, size, THREAD) ObjArrayKlass(n, k, name, null_free);
}

ObjArrayKlass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data,
int n, Klass* element_klass, TRAPS) {
int n, Klass* element_klass,
bool null_free, bool qdesc, TRAPS) {
assert(!null_free || (n == 1 && element_klass->is_inline_klass() && qdesc), "null-free unsupported");

// Eagerly allocate the direct array supertype.
Klass* super_klass = NULL;
@@ -87,7 +91,11 @@ ObjArrayKlass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_da
elem_super->array_klass(CHECK_NULL);
}
// Now retry from the beginning
ek = element_klass->array_klass(n, CHECK_NULL);
if (null_free) {
ek = InlineKlass::cast(element_klass)->null_free_inline_array_klass(CHECK_NULL);
} else {
ek = element_klass->array_klass(n, CHECK_NULL);
}
} // re-lock
return ObjArrayKlass::cast(ek);
}
@@ -98,10 +106,10 @@ ObjArrayKlass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_da
}

// Create type name for klass.
Symbol* name = ArrayKlass::create_element_klass_array_name(element_klass, CHECK_NULL);
Symbol* name = ArrayKlass::create_element_klass_array_name(element_klass, qdesc, CHECK_NULL);

// Initialize instance variables
ObjArrayKlass* oak = ObjArrayKlass::allocate(loader_data, n, element_klass, name, CHECK_NULL);
ObjArrayKlass* oak = ObjArrayKlass::allocate(loader_data, n, element_klass, name, null_free, CHECK_NULL);

ModuleEntry* module = oak->module();
assert(module != NULL, "No module entry for array");
@@ -119,7 +127,7 @@ ObjArrayKlass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_da
return oak;
}

ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name, ID) {
ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name, bool null_free) : ArrayKlass(name, ID) {
set_dimension(n);
set_element_klass(element_klass);

@@ -135,8 +143,9 @@ ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayK
set_bottom_klass(bk);
set_class_loader_data(bk->class_loader_data());

jint lh = array_layout_helper(T_OBJECT);
if (element_klass->is_inline_klass()) {
int lh = array_layout_helper(T_OBJECT);
if (null_free) {
assert(n == 1, "Bytecode does not support null-free multi-dim");
lh = layout_helper_set_null_free(lh);
set_prototype_header(markWord::nullfree_array_prototype());
assert(prototype_header().is_nullfree_array(), "sanity");
@@ -176,7 +185,7 @@ objArrayOop ObjArrayKlass::allocate(int length, TRAPS) {
oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
int length = *sizes;
if (rank == 1) { // last dim may be flatArray, check if we have any special storage requirements
if (element_klass()->is_inline_klass()) {
if (name()->is_Q_array_signature()) {
return oopFactory::new_flatArray(element_klass(), length, CHECK_NULL);
} else {
return oopFactory::new_objArray(element_klass(), length, CHECK_NULL);
@@ -338,7 +347,8 @@ Klass* ObjArrayKlass::array_klass(int n, TRAPS) {
if (higher_dimension() == NULL) {

// Create multi-dim klass object and link them together
Klass* k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), dim + 1, this, CHECK_NULL);
Klass* k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), dim + 1, this,
false, this->name()->is_Q_array_signature(), CHECK_NULL);
ObjArrayKlass* ak = ObjArrayKlass::cast(k);
ak->set_lower_dimension(this);
// use 'release' to pair with lock-free load
@@ -45,8 +45,8 @@ class ObjArrayKlass : public ArrayKlass {
Klass* _bottom_klass; // The one-dimensional type (InstanceKlass or TypeArrayKlass)

// Constructor
ObjArrayKlass(int n, Klass* element_klass, Symbol* name);
static ObjArrayKlass* allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS);
ObjArrayKlass(int n, Klass* element_klass, Symbol* name, bool null_free);
static ObjArrayKlass* allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, bool null_free, TRAPS);
public:
// For dummy objects
ObjArrayKlass() {}
@@ -67,7 +67,8 @@ class ObjArrayKlass : public ArrayKlass {

// Allocation
static ObjArrayKlass* allocate_objArray_klass(ClassLoaderData* loader_data,
int n, Klass* element_klass, TRAPS);
int n, Klass* element_klass,
bool null_free, bool qdesc, TRAPS);

objArrayOop allocate(int length, TRAPS);
oop multi_allocate(int rank, jint* sizes, TRAPS);
@@ -187,7 +187,7 @@ Klass* TypeArrayKlass::array_klass(int n, TRAPS) {

if (higher_dimension() == NULL) {
Klass* oak = ObjArrayKlass::allocate_objArray_klass(
class_loader_data(), dim + 1, this, CHECK_NULL);
class_loader_data(), dim + 1, this, false, false, CHECK_NULL);
ObjArrayKlass* h_ak = ObjArrayKlass::cast(oak);
h_ak->set_lower_dimension(this);
// use 'release' to pair with lock-free load

0 comments on commit a6f937b

Please sign in to comment.