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

JDK-8269023 [lworld] L/Q<type> support #453

Closed
wants to merge 24 commits into from
Closed
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4de6a48
Merge lworld
May 10, 2021
adff688
First set of changes to initiate the transition to the L/Q model
fparain May 10, 2021
a6f937b
Initial runtime arrays support for L or Q type
May 12, 2021
ac1feac
8266931: [lworld] [lw3] Test InlineTypeArrays.java fails because of i…
fparain May 17, 2021
671a346
CDS support for InlineKlass::null_free_array_klasses() & corrected mo…
May 19, 2021
6841917
Rename nullfree to null_free
May 19, 2021
4aa22fb
L/Q again, step two
fparain May 19, 2021
375479e
More C1 fixes
fparain May 20, 2021
bca447b
Merge lworld
May 25, 2021
477ecf5
8267846: [lworld] JIT support for the L/Q model (step 1)
TobiHartmann May 31, 2021
d9d96e8
8267948: [lword] Core reflection and method handles support for L/Q m…
Jun 7, 2021
8807adf
8268389: [lworld] Tests must be update after core reflection changes …
fparain Jun 8, 2021
3552074
8268399: [BACKOUT] [lworld] Tests must be update after core reflectio…
fparain Jun 9, 2021
31e9967
8268418: [lworld] VM assert illegal mirror klass when calling Class::…
Jun 9, 2021
d23562e
8267597: [lworld] Withdraw all support for bifurcated class generatio…
Jun 10, 2021
64ec4ec
8268584: [lqagain] Javac tests should not needlessly hardcode toStrin…
Jun 11, 2021
569dd54
8268358: [lworld] toString for primitive class should return `ClassNa…
Jun 11, 2021
fa11596
8268656: [lqagain] A few code chunks dealing with dual class scheme s…
Jun 14, 2021
52ee195
8268908: Update test/jdk/valhalla/valuetypes tests to prepare for jtr…
Jun 16, 2021
70a2405
Merge lworld
Jun 17, 2021
3b3e4d4
8268980: [lword] Fix Class::descriptorString to return L-descriptor f…
Jun 17, 2021
521bed2
8268981: [lworld] UnifiedPrimitiveClassNestHostTest.java should test …
Jun 17, 2021
2a7e977
8218159: ValueBootstrapMethods.isSubstitutable should not filter synt…
Jun 18, 2021
9579e93
Merge branch 'lworld' of https://git.openjdk.java.net/valhalla into c…
MrSimms Jun 21, 2021
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -255,12 +255,12 @@ void NewTypeArrayStub::emit_code(LIR_Assembler* ce) {
// Implementation of NewObjectArrayStub

NewObjectArrayStub::NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result,
CodeEmitInfo* info, bool is_inline_type) {
CodeEmitInfo* info, bool is_null_free) {
_klass_reg = klass_reg;
_result = result;
_length = length;
_info = new CodeEmitInfo(info);
_is_inline_type = is_inline_type;
_is_null_free = is_null_free;
}


@@ -270,7 +270,7 @@ void NewObjectArrayStub::emit_code(LIR_Assembler* ce) {
assert(_length->as_register() == r19, "length must in r19,");
assert(_klass_reg->as_register() == r3, "klass_reg must in r3");

if (_is_inline_type) {
if (_is_null_free) {
__ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_flat_array_id)));
} else {
__ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_object_array_id)));
@@ -511,10 +511,8 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) {
assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == r0, "word returns are in r0,");

ciMethod* method = compilation()->method();

ciType* return_type = method->return_type();
if (InlineTypeReturnedAsFields && return_type->is_inlinetype()) {
ciInlineKlass* vk = return_type->as_inline_klass();
if (InlineTypeReturnedAsFields && method->signature()->returns_null_free_inline_type()) {
ciInlineKlass* vk = method->return_type()->as_inline_klass();
if (vk->can_be_returned_as_fields()) {
address unpack_handler = vk->unpack_handler();
assert(unpack_handler != NULL, "must be");
@@ -1629,7 +1627,7 @@ void LIR_Assembler::emit_opNullFreeArrayCheck(LIR_OpNullFreeArrayCheck* op) {
__ br(Assembler::NE, test_mark_word);
__ load_prototype_header(tmp, op->array()->as_register());
__ bind(test_mark_word);
__ tst(tmp, markWord::nullfree_array_bit_in_place);
__ tst(tmp, markWord::null_free_array_bit_in_place);
} else {
Register klass = op->tmp()->as_register();
__ load_klass(klass, op->array()->as_register());
@@ -1599,11 +1599,11 @@ void MacroAssembler::test_non_flattened_array_oop(Register oop, Register temp_re
}

void MacroAssembler::test_null_free_array_oop(Register oop, Register temp_reg, Label& is_null_free_array) {
test_oop_prototype_bit(oop, temp_reg, markWord::nullfree_array_bit_in_place, true, is_null_free_array);
test_oop_prototype_bit(oop, temp_reg, markWord::null_free_array_bit_in_place, true, is_null_free_array);
}

void MacroAssembler::test_non_null_free_array_oop(Register oop, Register temp_reg, Label&is_non_null_free_array) {
test_oop_prototype_bit(oop, temp_reg, markWord::nullfree_array_bit_in_place, false, is_non_null_free_array);
test_oop_prototype_bit(oop, temp_reg, markWord::null_free_array_bit_in_place, false, is_non_null_free_array);
}

void MacroAssembler::test_flattened_array_layout(Register lh, Label& is_flattened_array) {
@@ -310,12 +310,12 @@ void NewTypeArrayStub::emit_code(LIR_Assembler* ce) {
// Implementation of NewObjectArrayStub

NewObjectArrayStub::NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result,
CodeEmitInfo* info, bool is_inline_type) {
CodeEmitInfo* info, bool is_null_free) {
_klass_reg = klass_reg;
_result = result;
_length = length;
_info = new CodeEmitInfo(info);
_is_inline_type = is_inline_type;
_is_null_free = is_null_free;
}


@@ -324,7 +324,7 @@ void NewObjectArrayStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
assert(_length->as_register() == rbx, "length must in rbx,");
assert(_klass_reg->as_register() == rdx, "klass_reg must in rdx");
if (_is_inline_type) {
if (_is_null_free) {
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_flat_array_id)));
} else {
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_object_array_id)));
@@ -531,9 +531,8 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) {
}

ciMethod* method = compilation()->method();
ciType* return_type = method->return_type();
if (InlineTypeReturnedAsFields && return_type->is_inlinetype()) {
ciInlineKlass* vk = return_type->as_inline_klass();
if (InlineTypeReturnedAsFields && method->signature()->returns_null_free_inline_type()) {
ciInlineKlass* vk = method->return_type()->as_inline_klass();
if (vk->can_be_returned_as_fields()) {
#ifndef _LP64
Unimplemented();
@@ -2030,7 +2029,7 @@ void LIR_Assembler::emit_opNullFreeArrayCheck(LIR_OpNullFreeArrayCheck* op) {
__ jccb(Assembler::notZero, test_mark_word);
__ load_prototype_header(tmp, op->array()->as_register(), rscratch1);
__ bind(test_mark_word);
__ testl(tmp, markWord::nullfree_array_bit_in_place);
__ testl(tmp, markWord::null_free_array_bit_in_place);
} else {
Register tmp_load_klass = LP64_ONLY(rscratch1) NOT_LP64(noreg);
Register klass = op->tmp()->as_register();
@@ -2954,20 +2954,20 @@ void MacroAssembler::test_klass_is_empty_inline_type(Register klass, Register te
jcc(Assembler::notZero, is_empty_inline_type);
}

void MacroAssembler::test_field_is_inline_type(Register flags, Register temp_reg, Label& is_inline_type) {
void MacroAssembler::test_field_is_null_free_inline_type(Register flags, Register temp_reg, Label& is_null_free_inline_type) {
movl(temp_reg, flags);
shrl(temp_reg, ConstantPoolCacheEntry::is_inline_type_shift);
shrl(temp_reg, ConstantPoolCacheEntry::is_null_free_inline_type_shift);
andl(temp_reg, 0x1);
testl(temp_reg, temp_reg);
jcc(Assembler::notZero, is_inline_type);
jcc(Assembler::notZero, is_null_free_inline_type);
}

void MacroAssembler::test_field_is_not_inline_type(Register flags, Register temp_reg, Label& not_inline_type) {
void MacroAssembler::test_field_is_not_null_free_inline_type(Register flags, Register temp_reg, Label& not_null_free_inline_type) {
movl(temp_reg, flags);
shrl(temp_reg, ConstantPoolCacheEntry::is_inline_type_shift);
shrl(temp_reg, ConstantPoolCacheEntry::is_null_free_inline_type_shift);
andl(temp_reg, 0x1);
testl(temp_reg, temp_reg);
jcc(Assembler::zero, not_inline_type);
jcc(Assembler::zero, not_null_free_inline_type);
}

void MacroAssembler::test_field_is_inlined(Register flags, Register temp_reg, Label& is_inlined) {
@@ -3019,7 +3019,7 @@ void MacroAssembler::test_non_flattened_array_oop(Register oop, Register temp_re

void MacroAssembler::test_null_free_array_oop(Register oop, Register temp_reg, Label&is_null_free_array) {
#ifdef _LP64
test_oop_prototype_bit(oop, temp_reg, markWord::nullfree_array_bit_in_place, true, is_null_free_array);
test_oop_prototype_bit(oop, temp_reg, markWord::null_free_array_bit_in_place, true, is_null_free_array);
#else
load_klass(temp_reg, oop, noreg);
movl(temp_reg, Address(temp_reg, Klass::layout_helper_offset()));
@@ -3029,7 +3029,7 @@ void MacroAssembler::test_null_free_array_oop(Register oop, Register temp_reg, L

void MacroAssembler::test_non_null_free_array_oop(Register oop, Register temp_reg, Label&is_non_null_free_array) {
#ifdef _LP64
test_oop_prototype_bit(oop, temp_reg, markWord::nullfree_array_bit_in_place, false, is_non_null_free_array);
test_oop_prototype_bit(oop, temp_reg, markWord::null_free_array_bit_in_place, false, is_non_null_free_array);
#else
load_klass(temp_reg, oop, noreg);
movl(temp_reg, Address(temp_reg, Klass::layout_helper_offset()));
@@ -118,8 +118,8 @@ class MacroAssembler: public Assembler {
// get_default_value_oop with extra assertion for empty inline klass
void get_empty_inline_type_oop(Register inline_klass, Register temp_reg, Register obj);

void test_field_is_inline_type(Register flags, Register temp_reg, Label& is_inline);
void test_field_is_not_inline_type(Register flags, Register temp_reg, Label& not_inline);
void test_field_is_null_free_inline_type(Register flags, Register temp_reg, Label& is_null_free);
void test_field_is_not_null_free_inline_type(Register flags, Register temp_reg, Label& not_null_free);
void test_field_is_inlined(Register flags, Register temp_reg, Label& is_inlined);

// Check oops for special arrays, i.e. flattened and/or null-free
@@ -2992,14 +2992,14 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr
if (is_static) {
__ load_heap_oop(rax, field);
if (EnableValhalla) {
Label is_inline_type, uninitialized;
Label is_null_free_inline_type, uninitialized;
// Issue below if the static field has not been initialized yet
__ test_field_is_inline_type(flags2, rscratch1, is_inline_type);
// field is not an inline type
__ test_field_is_null_free_inline_type(flags2, rscratch1, is_null_free_inline_type);
// field is not a null free inline type
__ push(atos);
__ jmp(Done);
// field is an inline type, must not return null even if uninitialized
__ bind(is_inline_type);
// field is a null free inline type, must not return null even if uninitialized
__ bind(is_null_free_inline_type);
__ testptr(rax, rax);
__ jcc(Assembler::zero, uninitialized);
__ push(atos);
@@ -3026,9 +3026,9 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr
} else {
Label is_inlined, nonnull, is_inline_type, rewrite_inline;
if (EnableValhalla) {
__ test_field_is_inline_type(flags2, rscratch1, is_inline_type);
__ test_field_is_null_free_inline_type(flags2, rscratch1, is_inline_type);
}
// field is not an inline type
// field is not a null free inline type
pop_and_check_object(obj);
__ load_heap_oop(rax, field);
__ push(atos);
@@ -3379,7 +3379,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri
if (is_static) {
Label is_inline_type;
if (EnableValhalla) {
__ test_field_is_not_inline_type(flags2, rscratch1, is_inline_type);
__ test_field_is_not_null_free_inline_type(flags2, rscratch1, is_inline_type);
__ null_check(rax);
__ bind(is_inline_type);
}
@@ -3388,7 +3388,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri
} else {
Label is_inline_type, is_inlined, rewrite_not_inline, rewrite_inline;
if (EnableValhalla) {
__ test_field_is_inline_type(flags2, rscratch1, is_inline_type);
__ test_field_is_null_free_inline_type(flags2, rscratch1, is_inline_type);
}
// Not an inline type
pop_and_check_object(obj);
@@ -676,14 +676,14 @@ void Canonicalizer::do_CheckCast (CheckCast* x) {
klass->as_instance_klass()->is_interface();
// Interface casts can't be statically optimized away since verifier doesn't
// enforce interface types in bytecode.
if (!is_interface && klass->is_subtype_of(x->klass())) {
if (!is_interface && klass->is_subtype_of(x->klass()) && (!x->is_null_free() || obj->is_null_free())) {
assert(!x->klass()->is_inlinetype() || x->klass() == klass, "Inline klasses can't have subtypes");
set_canonical(obj);
return;
}
}
// checkcast of null returns null for non-inline klasses
if (!x->klass()->is_inlinetype() && obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) {
// checkcast of null returns null for non null-free klasses
if (!x->is_null_free() && obj->is_null_obj()) {
set_canonical(obj);
}
}
@@ -697,7 +697,7 @@ void Canonicalizer::do_InstanceOf (InstanceOf* x) {
return;
}
// instanceof null returns false
if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) {
if (obj->as_Constant() && obj->is_null_obj()) {
set_constant(0);
}
}
@@ -384,9 +384,9 @@ class NewObjectArrayStub: public CodeStub {
LIR_Opr _length;
LIR_Opr _result;
CodeEmitInfo* _info;
bool _is_inline_type;
bool _is_null_free;
public:
NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info, bool is_inline_type);
NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info, bool is_null_free);
virtual void emit_code(LIR_Assembler* e);
virtual CodeEmitInfo* info() const { return _info; }
virtual void visit(LIR_OpVisitState* visitor) {
@@ -1840,7 +1840,7 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
assert(!field->is_stable() || !field_value.is_null_or_zero(),
"stable static w/ default value shouldn't be a constant");
constant = make_constant(field_value, field);
} else if (field_type == T_INLINE_TYPE && field->type()->as_inline_klass()->is_empty()) {
} else if (field->is_null_free() && field->type()->is_loaded() && field->type()->as_inline_klass()->is_empty()) {
// Loading from a field of an empty inline type. Just return the default instance.
constant = new Constant(new InstanceConstant(field->type()->as_inline_klass()->default_instance()));
}
@@ -1865,7 +1865,7 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
Value mask = append(new Constant(new IntConstant(1)));
val = append(new LogicOp(Bytecodes::_iand, val, mask));
}
if (field_type == T_INLINE_TYPE && field->type()->as_inline_klass()->is_empty()) {
if (field->is_null_free() && field->type()->is_loaded() && field->type()->as_inline_klass()->is_empty()) {
// Storing to a field of an empty inline type. Ignore.
break;
}
@@ -1883,7 +1883,7 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
if (!has_pending_field_access() && !has_pending_load_indexed()) {
obj = apop();
ObjectType* obj_type = obj->type()->as_ObjectType();
if (field_type == T_INLINE_TYPE && field->type()->as_inline_klass()->is_empty()) {
if (field->is_null_free() && field->type()->is_loaded() && field->type()->as_inline_klass()->is_empty()) {
// Loading from a field of an empty inline type. Just return the default instance.
null_check(obj);
constant = new Constant(new InstanceConstant(field->type()->as_inline_klass()->default_instance()));
@@ -1892,7 +1892,7 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
if (!const_oop->is_null_object() && const_oop->is_loaded()) {
ciConstant field_value = field->constant_value_of(const_oop);
if (field_value.is_valid()) {
if (field->signature()->is_Q_signature() && field_value.is_null_or_zero()) {
if (field->is_null_free() && field_value.is_null_or_zero()) {
// Non-flattened inline type field. Replace null by the default value.
constant = new Constant(new InstanceConstant(field->type()->as_inline_klass()->default_instance()));
} else {
@@ -2038,7 +2038,7 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
Value mask = append(new Constant(new IntConstant(1)));
val = append(new LogicOp(Bytecodes::_iand, val, mask));
}
if (field_type == T_INLINE_TYPE && field->type()->as_inline_klass()->is_empty()) {
if (field->is_null_free() && field->type()->is_loaded() && field->type()->as_inline_klass()->is_empty()) {
// Storing to a field of an empty inline type. Ignore.
null_check(obj);
} else if (!field->is_flattened()) {
@@ -2470,7 +2470,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
}

Invoke* result = new Invoke(code, result_type, recv, args, target, state_before,
declared_signature->return_type()->is_inlinetype());
declared_signature->returns_null_free_inline_type());
// push result
append_split(result);

@@ -2514,7 +2514,7 @@ void GraphBuilder::new_type_array() {
void GraphBuilder::new_object_array() {
bool will_link;
ciKlass* klass = stream()->get_klass(will_link);
bool null_free = stream()->is_inline_klass();
bool null_free = stream()->has_Q_signature();
ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling();
NewArray* n = new NewObjectArray(klass, ipop(), state_before, null_free);
apush(append_split(n));
@@ -2541,7 +2541,7 @@ bool GraphBuilder::direct_compare(ciKlass* k) {
void GraphBuilder::check_cast(int klass_index) {
bool will_link;
ciKlass* klass = stream()->get_klass(will_link);
bool null_free = stream()->is_inline_klass();
bool null_free = stream()->has_Q_signature();
ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_for_exception();
CheckCast* c = new CheckCast(klass, apop(), state_before, null_free);
apush(append_split(c));
@@ -3569,7 +3569,7 @@ ValueStack* GraphBuilder::state_at_entry() {
// don't allow T_ARRAY to propagate into locals types
if (is_reference_type(basic_type)) basic_type = T_OBJECT;
ValueType* vt = as_ValueType(basic_type);
state->store_local(idx, new Local(type, vt, idx, false, type->is_inlinetype()));
state->store_local(idx, new Local(type, vt, idx, false, sig->is_null_free_at(i)));
idx += type->size();
}

@@ -108,7 +108,7 @@ void Instruction::state_values_do(ValueVisitor* f) {
}

ciType* Instruction::exact_type() const {
ciType* t = declared_type();
ciType* t = declared_type();
if (t != NULL && t->is_klass()) {
return t->as_klass()->exact_klass();
}
@@ -138,15 +138,13 @@ bool Instruction::maybe_flattened_array() {
if (UseFlatArray) {
ciType* type = declared_type();
if (type != NULL) {
if (type->is_obj_array_klass()) {
// Due to array covariance, the runtime type might be a flattened array.
if (type->is_obj_array_klass() && !type->as_obj_array_klass()->is_elem_null_free()) {
// The runtime type of [LMyValue might be [QMyValue due to [QMyValue <: [LMyValue.
ciKlass* element_klass = type->as_obj_array_klass()->element_klass();
if (element_klass->can_be_inline_klass() && (!element_klass->is_inlinetype() || element_klass->as_inline_klass()->flatten_array())) {
return true;
}
} else if (type->is_flat_array_klass()) {
ciKlass* element_klass = type->as_flat_array_klass()->element_klass();
assert(!element_klass->is_loaded() || element_klass->flatten_array(), "must be flattened");
return true;
} else if (type->is_klass() && type->as_klass()->is_java_lang_Object()) {
// This can happen as a parameter to System.arraycopy()
@@ -166,8 +164,7 @@ bool Instruction::maybe_null_free_array() {
if (type != NULL) {
if (type->is_obj_array_klass()) {
// Due to array covariance, the runtime type might be a null-free array.
ciKlass* element_klass = type->as_obj_array_klass()->element_klass();
if (element_klass->can_be_inline_klass()) {
if (type->as_obj_array_klass()->can_be_inline_array_klass()) {
return true;
}
}
@@ -290,7 +287,7 @@ ciType* NewTypeArray::exact_type() const {
}

ciType* NewObjectArray::exact_type() const {
return ciArrayKlass::make(klass());
return ciArrayKlass::make(klass(), is_null_free());
}

ciType* NewMultiArray::exact_type() const {
@@ -861,7 +861,7 @@ LEAF(LoadField, AccessField)
ciInlineKlass* inline_klass = NULL, Value default_value = NULL )
: AccessField(obj, offset, field, is_static, state_before, needs_patching)
{
set_null_free(field->signature()->is_Q_signature());
set_null_free(field->is_null_free());
}

ciType* declared_type() const;