Skip to content

Commit 0492736

Browse files
committed
8367564: Fields access in interpreter needs cleanup and refactoring
Reviewed-by: coleenp
1 parent 07a4cb4 commit 0492736

11 files changed

+168
-277
lines changed

src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,16 @@ void InterpreterMacroAssembler::allocate_instance(Register klass, Register new_o
225225
void InterpreterMacroAssembler::read_flat_field(Register entry,
226226
Register field_index, Register field_offset,
227227
Register temp, Register obj) {
228-
Label alloc_failed, done;
228+
Label failed_alloc, slow_path, done;
229229
const Register src = field_offset;
230230
const Register alloc_temp = r10;
231231
const Register dst_temp = field_index;
232232
const Register layout_info = temp;
233-
assert_different_registers(obj, entry, field_index, field_offset, temp, alloc_temp);
233+
assert_different_registers(obj, entry, field_index, field_offset, temp, alloc_temp, rscratch1);
234+
235+
load_unsigned_byte(temp, Address(entry, in_bytes(ResolvedFieldEntry::flags_offset())));
236+
// If the field is nullable, jump to slow path
237+
tbz(temp, ResolvedFieldEntry::is_null_free_inline_type_shift, slow_path);
234238

235239
// Grab the inline field klass
236240
ldr(rscratch1, Address(entry, in_bytes(ResolvedFieldEntry::field_holder_offset())));
@@ -241,7 +245,7 @@ void InterpreterMacroAssembler::read_flat_field(Register entry,
241245

242246
// allocate buffer
243247
push(obj); // save holder
244-
allocate_instance(field_klass, obj, alloc_temp, rscratch2, false, alloc_failed);
248+
allocate_instance(field_klass, obj, alloc_temp, rscratch2, false, failed_alloc);
245249

246250
// Have an oop instance buffer, copy into it
247251
payload_address(obj, dst_temp, field_klass); // danger, uses rscratch1
@@ -253,15 +257,45 @@ void InterpreterMacroAssembler::read_flat_field(Register entry,
253257
pop(obj);
254258
b(done);
255259

256-
bind(alloc_failed);
260+
bind(failed_alloc);
257261
pop(obj);
262+
bind(slow_path);
258263
call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_flat_field),
259264
obj, entry);
260265

261266
bind(done);
262267
membar(Assembler::StoreStore);
263268
}
264269

270+
void InterpreterMacroAssembler::write_flat_field(Register entry, Register field_offset,
271+
Register tmp1, Register tmp2,
272+
Register obj) {
273+
assert_different_registers(entry, field_offset, tmp1, tmp2, obj);
274+
Label slow_path, done;
275+
276+
load_unsigned_byte(tmp1, Address(entry, in_bytes(ResolvedFieldEntry::flags_offset())));
277+
test_field_is_not_null_free_inline_type(tmp1, noreg /* temp */, slow_path);
278+
279+
null_check(r0); // FIXME JDK-8341120
280+
281+
add(obj, obj, field_offset);
282+
283+
load_klass(tmp1, r0);
284+
payload_address(r0, r0, tmp1);
285+
286+
Register layout_info = field_offset;
287+
load_unsigned_short(tmp1, Address(entry, in_bytes(ResolvedFieldEntry::field_index_offset())));
288+
ldr(tmp2, Address(entry, in_bytes(ResolvedFieldEntry::field_holder_offset())));
289+
inline_layout_info(tmp2, tmp1, layout_info);
290+
291+
flat_field_copy(IN_HEAP, r0, obj, layout_info);
292+
b(done);
293+
294+
bind(slow_path);
295+
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_flat_field), obj, r0, entry);
296+
bind(done);
297+
}
298+
265299
// Load object from cpool->resolved_references(index)
266300
void InterpreterMacroAssembler::load_resolved_reference_at_index(
267301
Register result, Register index, Register tmp) {

src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ class InterpreterMacroAssembler: public MacroAssembler {
156156
// - assumes holder_klass and valueKlass field klass have both been resolved
157157
void read_flat_field(Register entry,
158158
Register field_index, Register field_offset,
159-
Register temp, Register obj = r0);
159+
Register temp, Register obj);
160+
161+
void write_flat_field(Register entry, Register field_offset,
162+
Register tmp1, Register tmp2,
163+
Register obj);
160164

161165
// Allocate value buffer in "obj" and read in flat element at the given index
162166
// NOTES:

src/hotspot/cpu/aarch64/templateTable_aarch64.cpp

Lines changed: 36 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -2772,51 +2772,23 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr
27722772
} else { // Valhalla
27732773
if (is_static) {
27742774
__ load_heap_oop(r0, field, rscratch1, rscratch2);
2775-
Label is_null_free_inline_type, uninitialized;
2776-
// Issue below if the static field has not been initialized yet
2777-
__ test_field_is_null_free_inline_type(flags, noreg /*temp*/, is_null_free_inline_type);
2778-
// field is not a null free inline type
2779-
__ push(atos);
2780-
__ b(Done);
2781-
// field is a null free inline type, must not return null even if uninitialized
2782-
__ bind(is_null_free_inline_type);
2783-
__ cbz(r0, uninitialized);
2784-
__ push(atos);
2785-
__ b(Done);
2786-
__ bind(uninitialized);
2787-
__ b(ExternalAddress(Interpreter::_throw_NPE_UninitializedField_entry));
2775+
__ push(atos);
2776+
__ b(Done);
27882777
} else {
2789-
Label is_flat, nonnull, is_inline_type, has_null_marker, rewrite_inline;
2790-
__ test_field_is_null_free_inline_type(flags, noreg /*temp*/, is_inline_type);
2791-
__ test_field_has_null_marker(flags, noreg /*temp*/, has_null_marker);
2792-
// Non-inline field case
2793-
__ load_heap_oop(r0, field, rscratch1, rscratch2);
2778+
Label is_flat, rewrite_inline;
2779+
__ test_field_is_flat(flags, noreg /*temp*/, is_flat);
2780+
__ load_heap_oop(r0, field, rscratch1, rscratch2);
2781+
__ push(atos);
2782+
if (rc == may_rewrite) {
2783+
patch_bytecode(Bytecodes::_fast_agetfield, bc, r1);
2784+
}
2785+
__ b(Done);
2786+
__ bind(is_flat);
2787+
// field is flat (null-free or nullable with a null-marker)
2788+
__ mov(r0, obj);
2789+
__ read_flat_field(cache, field_index, off, inline_klass /* temp */, r0);
2790+
__ verify_oop(r0);
27942791
__ push(atos);
2795-
if (rc == may_rewrite) {
2796-
patch_bytecode(Bytecodes::_fast_agetfield, bc, r1);
2797-
}
2798-
__ b(Done);
2799-
__ bind(is_inline_type);
2800-
__ test_field_is_flat(flags, noreg /* temp */, is_flat);
2801-
// field is not flat
2802-
__ load_heap_oop(r0, field, rscratch1, rscratch2);
2803-
__ cbnz(r0, nonnull);
2804-
__ b(ExternalAddress(Interpreter::_throw_NPE_UninitializedField_entry));
2805-
__ bind(nonnull);
2806-
__ verify_oop(r0);
2807-
__ push(atos);
2808-
__ b(rewrite_inline);
2809-
__ bind(is_flat);
2810-
// field is flat
2811-
__ mov(r0, obj);
2812-
__ read_flat_field(cache, field_index, off, inline_klass /* temp */, r0);
2813-
__ verify_oop(r0);
2814-
__ push(atos);
2815-
__ b(rewrite_inline);
2816-
__ bind(has_null_marker);
2817-
call_VM(r0, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_nullable_flat_field), obj, cache);
2818-
__ verify_oop(r0);
2819-
__ push(atos);
28202792
__ bind(rewrite_inline);
28212793
if (rc == may_rewrite) {
28222794
patch_bytecode(Bytecodes::_fast_vgetfield, bc, r1);
@@ -3057,52 +3029,35 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr
30573029
} else { // Valhalla
30583030
__ pop(atos);
30593031
if (is_static) {
3060-
Label is_inline_type;
3061-
__ test_field_is_not_null_free_inline_type(flags, noreg /* temp */, is_inline_type);
3062-
__ null_check(r0);
3063-
__ bind(is_inline_type);
3032+
Label is_nullable;
3033+
__ test_field_is_not_null_free_inline_type(flags, noreg /* temp */, is_nullable);
3034+
__ null_check(r0); // FIXME JDK-8341120
3035+
__ bind(is_nullable);
30643036
do_oop_store(_masm, field, r0, IN_HEAP);
30653037
__ b(Done);
30663038
} else {
3067-
Label is_inline_type, is_flat, has_null_marker, rewrite_not_inline, rewrite_inline;
3068-
__ test_field_is_null_free_inline_type(flags, noreg /*temp*/, is_inline_type);
3069-
__ test_field_has_null_marker(flags, noreg /*temp*/, has_null_marker);
3070-
// Not an inline type
3039+
Label null_free_reference, is_flat, rewrite_inline;
3040+
__ test_field_is_flat(flags, noreg /*temp*/, is_flat);
3041+
__ test_field_is_null_free_inline_type(flags, noreg /*temp*/, null_free_reference);
30713042
pop_and_check_object(obj);
30723043
// Store into the field
30733044
// Clobbers: r10, r11, r3
30743045
do_oop_store(_masm, field, r0, IN_HEAP);
3075-
__ bind(rewrite_not_inline);
30763046
if (rc == may_rewrite) {
30773047
patch_bytecode(Bytecodes::_fast_aputfield, bc, r19, true, byte_no);
30783048
}
30793049
__ b(Done);
30803050
// Implementation of the inline type semantic
3081-
__ bind(is_inline_type);
3082-
__ null_check(r0);
3083-
__ test_field_is_flat(flags, noreg /*temp*/, is_flat);
3084-
// field is not flat
3051+
__ bind(null_free_reference);
3052+
__ null_check(r0); // FIXME JDK-8341120
30853053
pop_and_check_object(obj);
30863054
// Store into the field
30873055
// Clobbers: r10, r11, r3
30883056
do_oop_store(_masm, field, r0, IN_HEAP);
30893057
__ b(rewrite_inline);
30903058
__ bind(is_flat);
3091-
__ load_field_entry(cache, index); // reload field entry (cache) because it was erased by tos_state
3092-
__ load_unsigned_short(index, Address(cache, in_bytes(ResolvedFieldEntry::field_index_offset())));
3093-
__ ldr(r2, Address(cache, in_bytes(ResolvedFieldEntry::field_holder_offset())));
3094-
__ inline_layout_info(r2, index, r6);
3095-
pop_and_check_object(obj);
3096-
__ load_klass(inline_klass, r0);
3097-
__ payload_address(r0, r0, inline_klass);
3098-
__ add(obj, obj, off);
3099-
// because we use InlineLayoutInfo, we need special value access code specialized for fields (arrays will need a different API)
3100-
__ flat_field_copy(IN_HEAP, r0, obj, r6);
3101-
__ b(rewrite_inline);
3102-
__ bind(has_null_marker);
3103-
assert_different_registers(r0, cache, r19);
3104-
pop_and_check_object(r19);
3105-
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_nullable_flat_field), r19, r0, cache);
3059+
pop_and_check_object(r7);
3060+
__ write_flat_field(cache, off, r3, r6, r7);
31063061
__ bind(rewrite_inline);
31073062
if (rc == may_rewrite) {
31083063
patch_bytecode(Bytecodes::_fast_vputfield, bc, r19, true, byte_no);
@@ -3323,29 +3278,18 @@ void TemplateTable::fast_storefield(TosState state)
33233278
// access field
33243279
switch (bytecode()) {
33253280
case Bytecodes::_fast_vputfield:
3326-
{
3281+
{
33273282
Label is_flat, has_null_marker, done;
3328-
__ test_field_has_null_marker(r5, noreg /* temp */, has_null_marker);
3329-
__ null_check(r0);
33303283
__ test_field_is_flat(r5, noreg /* temp */, is_flat);
3331-
// field is not flat
3284+
__ null_check(r0);
33323285
do_oop_store(_masm, field, r0, IN_HEAP);
33333286
__ b(done);
33343287
__ bind(is_flat);
3335-
// field is flat
33363288
__ load_field_entry(r4, r5);
3337-
__ load_unsigned_short(r5, Address(r4, in_bytes(ResolvedFieldEntry::field_index_offset())));
3338-
__ ldr(r4, Address(r4, in_bytes(ResolvedFieldEntry::field_holder_offset())));
3339-
__ inline_layout_info(r4, r5, r6);
3340-
__ load_klass(r4, r0);
3341-
__ payload_address(r0, r0, r4);
3342-
__ lea(rscratch1, field);
3343-
__ flat_field_copy(IN_HEAP, r0, rscratch1, r6);
3344-
__ b(done);
3345-
__ bind(has_null_marker);
3346-
__ load_field_entry(r4, r1);
3347-
__ mov(r1, r2);
3348-
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_nullable_flat_field), r1, r0, r4);
3289+
// Re-shuffle registers because of VM calls calling convention
3290+
__ mov(r19, r1);
3291+
__ mov(r7, r2);
3292+
__ write_flat_field(r4, r19, r6, r8, r7);
33493293
__ bind(done);
33503294
}
33513295
break;
@@ -3444,27 +3388,11 @@ void TemplateTable::fast_accessfield(TosState state)
34443388
switch (bytecode()) {
34453389
case Bytecodes::_fast_vgetfield:
34463390
{
3447-
Register index = r4, klass = r5, inline_klass = r6, tmp = r7;
3448-
Label is_flat, has_null_marker, nonnull, Done;
3449-
__ test_field_has_null_marker(r3, noreg /*temp*/, has_null_marker);
3450-
__ test_field_is_flat(r3, noreg /* temp */, is_flat);
3451-
// field is not flat
3452-
__ load_heap_oop(r0, field, rscratch1, rscratch2);
3453-
__ cbnz(r0, nonnull);
3454-
__ b(ExternalAddress(Interpreter::_throw_NPE_UninitializedField_entry));
3455-
__ bind(nonnull);
3456-
__ verify_oop(r0);
3457-
__ b(Done);
3458-
__ bind(is_flat);
3391+
Register index = r4, tmp = r7;
34593392
// field is flat
3460-
__ load_unsigned_short(index, Address(r2, in_bytes(ResolvedFieldEntry::field_index_offset())));
3461-
__ read_flat_field(r2, index, r1, tmp /* temp */, r0);
3462-
__ verify_oop(r0);
3463-
__ b(Done);
3464-
__ bind(has_null_marker);
3465-
call_VM(r0, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_nullable_flat_field), r0, r2);
3466-
__ verify_oop(r0);
3467-
__ bind(Done);
3393+
__ load_unsigned_short(index, Address(r2, in_bytes(ResolvedFieldEntry::field_index_offset())));
3394+
__ read_flat_field(r2, index, r1, tmp /* temp */, r0);
3395+
__ verify_oop(r0);
34683396
}
34693397
break;
34703398
case Bytecodes::_fast_agetfield:

src/hotspot/cpu/x86/interp_masm_x86.cpp

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,22 +1081,25 @@ void InterpreterMacroAssembler::allocate_instance(Register klass, Register new_o
10811081
}
10821082

10831083
void InterpreterMacroAssembler::read_flat_field(Register entry, Register tmp1, Register tmp2, Register obj) {
1084-
Label alloc_failed, done;
1084+
Label alloc_failed, slow_path, done;
10851085
const Register alloc_temp = LP64_ONLY(rscratch1) NOT_LP64(rsi);
10861086
const Register dst_temp = LP64_ONLY(rscratch2) NOT_LP64(rdi);
10871087
assert_different_registers(obj, entry, tmp1, tmp2, dst_temp, r8, r9);
10881088

1089-
// FIXME: code below could be re-written to better use InlineLayoutInfo data structure
1090-
// see aarch64 version
1089+
// If the field is nullable, jump to slow path
1090+
load_unsigned_byte(tmp1, Address(entry, in_bytes(ResolvedFieldEntry::flags_offset())));
1091+
testl(tmp1, 1 << ResolvedFieldEntry::is_null_free_inline_type_shift);
1092+
jcc(Assembler::equal, slow_path);
10911093

10921094
// Grap the inline field klass
10931095
const Register field_klass = tmp1;
10941096
load_unsigned_short(tmp2, Address(entry, in_bytes(ResolvedFieldEntry::field_index_offset())));
1097+
10951098
movptr(tmp1, Address(entry, ResolvedFieldEntry::field_holder_offset()));
10961099
get_inline_type_field_klass(tmp1, tmp2, field_klass);
10971100

10981101
// allocate buffer
1099-
push(obj); // push object being read from // FIXME spilling on stack could probably be avoided by using tmp2
1102+
push(obj); // push object being read from
11001103
allocate_instance(field_klass, obj, alloc_temp, dst_temp, false, alloc_failed);
11011104

11021105
// Have an oop instance buffer, copy into it
@@ -1110,19 +1113,51 @@ void InterpreterMacroAssembler::read_flat_field(Register entry, Register tmp1, R
11101113
lea(tmp2, Address(alloc_temp, tmp2));
11111114
// call_VM_leaf, clobbers a few regs, save restore new obj
11121115
push(obj);
1113-
// access_value_copy(IS_DEST_UNINITIALIZED, tmp2, dst_temp, field_klass);
11141116
flat_field_copy(IS_DEST_UNINITIALIZED, tmp2, dst_temp, r8);
11151117
pop(obj);
11161118
jmp(done);
11171119

11181120
bind(alloc_failed);
11191121
pop(obj);
1122+
bind(slow_path);
11201123
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::read_flat_field),
11211124
obj, entry);
11221125
get_vm_result_oop(obj);
11231126
bind(done);
11241127
}
11251128

1129+
void InterpreterMacroAssembler::write_flat_field(Register entry, Register tmp1, Register tmp2,
1130+
Register obj, Register off, Register value) {
1131+
assert_different_registers(entry, tmp1, tmp2, obj, off, value);
1132+
1133+
Label slow_path, done;
1134+
1135+
load_unsigned_byte(tmp2, Address(entry, in_bytes(ResolvedFieldEntry::flags_offset())));
1136+
test_field_is_not_null_free_inline_type(tmp2, tmp1, slow_path);
1137+
1138+
null_check(value); // FIXME JDK-8341120
1139+
1140+
lea(obj, Address(obj, off, Address::times_1));
1141+
1142+
load_klass(tmp2, value, tmp1);
1143+
payload_addr(value, value, tmp2);
1144+
1145+
Register idx = tmp1;
1146+
load_unsigned_short(idx, Address(entry, in_bytes(ResolvedFieldEntry::field_index_offset())));
1147+
movptr(tmp2, Address(entry, in_bytes(ResolvedFieldEntry::field_holder_offset())));
1148+
1149+
Register layout_info = off;
1150+
inline_layout_info(tmp2, idx, layout_info);
1151+
1152+
flat_field_copy(IN_HEAP, value, obj, layout_info);
1153+
jmp(done);
1154+
1155+
bind(slow_path);
1156+
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::write_flat_field), obj, value, entry);
1157+
1158+
bind(done);
1159+
}
1160+
11261161
// Lock object
11271162
//
11281163
// Args:

src/hotspot/cpu/x86/interp_masm_x86.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
215215
void read_flat_field(Register entry,
216216
Register tmp1, Register tmp2,
217217
Register obj = rax);
218+
void write_flat_field(Register entry,
219+
Register tmp1, Register tmp2,
220+
Register obj, Register off, Register value);
218221

219222
// Object locking
220223
void lock_object (Register lock_reg);

0 commit comments

Comments
 (0)