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

Initial runtime arrays support for L or Q type #411

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
@@ -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