Skip to content

Commit defdd12

Browse files
committed
8142984: Zero: fast accessors should handle both getters and setters
Reviewed-by: andrew, coleenp
1 parent 1718aba commit defdd12

File tree

7 files changed

+164
-105
lines changed

7 files changed

+164
-105
lines changed

src/hotspot/cpu/zero/zeroInterpreter_zero.cpp

Lines changed: 132 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -547,38 +547,23 @@ int ZeroInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) {
547547
return 0;
548548
}
549549

550-
int ZeroInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
551-
JavaThread *thread = THREAD->as_Java_thread();
552-
ZeroStack *stack = thread->zero_stack();
553-
intptr_t *locals = stack->sp();
554-
550+
int ZeroInterpreter::getter_entry(Method* method, intptr_t UNUSED, TRAPS) {
555551
// Drop into the slow path if we need a safepoint check
556552
if (SafepointMechanism::should_process(THREAD)) {
557553
return normal_entry(method, 0, THREAD);
558554
}
559555

560-
// Load the object pointer and drop into the slow path
561-
// if we have a NullPointerException
562-
oop object = LOCALS_OBJECT(0);
563-
if (object == NULL) {
564-
return normal_entry(method, 0, THREAD);
565-
}
566-
567-
// Read the field index from the bytecode, which looks like this:
556+
// Read the field index from the bytecode:
568557
// 0: aload_0
569558
// 1: getfield
570559
// 2: index
571560
// 3: index
572-
// 4: ireturn/areturn/freturn/lreturn/dreturn
561+
// 4: return
562+
//
573563
// NB this is not raw bytecode: index is in machine order
574-
u1 *code = method->code_base();
575-
assert(code[0] == Bytecodes::_aload_0 &&
576-
code[1] == Bytecodes::_getfield &&
577-
(code[4] == Bytecodes::_ireturn ||
578-
code[4] == Bytecodes::_freturn ||
579-
code[4] == Bytecodes::_lreturn ||
580-
code[4] == Bytecodes::_dreturn ||
581-
code[4] == Bytecodes::_areturn), "should do");
564+
565+
assert(method->is_getter(), "Expect the particular bytecode shape");
566+
u1* code = method->code_base();
582567
u2 index = Bytes::get_native_u2(&code[2]);
583568

584569
// Get the entry from the constant pool cache, and drop into
@@ -589,96 +574,154 @@ int ZeroInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
589574
return normal_entry(method, 0, THREAD);
590575
}
591576

592-
// Get the result and push it onto the stack
577+
JavaThread* thread = THREAD->as_Java_thread();
578+
ZeroStack* stack = thread->zero_stack();
579+
intptr_t* topOfStack = stack->sp();
580+
581+
// Load the object pointer and drop into the slow path
582+
// if we have a NullPointerException
583+
oop object = STACK_OBJECT(0);
584+
if (object == NULL) {
585+
return normal_entry(method, 0, THREAD);
586+
}
587+
588+
// If needed, allocate additional slot on stack: we already have one
589+
// for receiver, and double/long need another one.
593590
switch (entry->flag_state()) {
594-
case ltos:
595-
case dtos:
596-
stack->overflow_check(1, CHECK_0);
597-
stack->alloc(wordSize);
598-
break;
591+
case ltos:
592+
case dtos:
593+
stack->overflow_check(1, CHECK_0);
594+
stack->alloc(wordSize);
595+
topOfStack = stack->sp();
596+
break;
599597
}
598+
599+
// Read the field to stack(0)
600+
int offset = entry->f2_as_index();
600601
if (entry->is_volatile()) {
601602
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
602603
OrderAccess::fence();
603604
}
604605
switch (entry->flag_state()) {
605-
case ctos:
606-
SET_LOCALS_INT(object->char_field_acquire(entry->f2_as_index()), 0);
607-
break;
608-
609-
case btos:
610-
case ztos:
611-
SET_LOCALS_INT(object->byte_field_acquire(entry->f2_as_index()), 0);
612-
break;
613-
614-
case stos:
615-
SET_LOCALS_INT(object->short_field_acquire(entry->f2_as_index()), 0);
616-
break;
617-
618-
case itos:
619-
SET_LOCALS_INT(object->int_field_acquire(entry->f2_as_index()), 0);
620-
break;
606+
case btos:
607+
case ztos: SET_STACK_INT(object->byte_field_acquire(offset), 0); break;
608+
case ctos: SET_STACK_INT(object->char_field_acquire(offset), 0); break;
609+
case stos: SET_STACK_INT(object->short_field_acquire(offset), 0); break;
610+
case itos: SET_STACK_INT(object->int_field_acquire(offset), 0); break;
611+
case ltos: SET_STACK_LONG(object->long_field_acquire(offset), 0); break;
612+
case ftos: SET_STACK_FLOAT(object->float_field_acquire(offset), 0); break;
613+
case dtos: SET_STACK_DOUBLE(object->double_field_acquire(offset), 0); break;
614+
case atos: SET_STACK_OBJECT(object->obj_field_acquire(offset), 0); break;
615+
default:
616+
ShouldNotReachHere();
617+
}
618+
} else {
619+
switch (entry->flag_state()) {
620+
case btos:
621+
case ztos: SET_STACK_INT(object->byte_field(offset), 0); break;
622+
case ctos: SET_STACK_INT(object->char_field(offset), 0); break;
623+
case stos: SET_STACK_INT(object->short_field(offset), 0); break;
624+
case itos: SET_STACK_INT(object->int_field(offset), 0); break;
625+
case ltos: SET_STACK_LONG(object->long_field(offset), 0); break;
626+
case ftos: SET_STACK_FLOAT(object->float_field(offset), 0); break;
627+
case dtos: SET_STACK_DOUBLE(object->double_field(offset), 0); break;
628+
case atos: SET_STACK_OBJECT(object->obj_field(offset), 0); break;
629+
default:
630+
ShouldNotReachHere();
631+
}
632+
}
621633

622-
case ltos:
623-
SET_LOCALS_LONG(object->long_field_acquire(entry->f2_as_index()), 0);
624-
break;
634+
// No deoptimized frames on the stack
635+
return 0;
636+
}
625637

626-
case ftos:
627-
SET_LOCALS_FLOAT(object->float_field_acquire(entry->f2_as_index()), 0);
628-
break;
638+
int ZeroInterpreter::setter_entry(Method* method, intptr_t UNUSED, TRAPS) {
639+
// Drop into the slow path if we need a safepoint check
640+
if (SafepointMechanism::should_process(THREAD)) {
641+
return normal_entry(method, 0, THREAD);
642+
}
629643

630-
case dtos:
631-
SET_LOCALS_DOUBLE(object->double_field_acquire(entry->f2_as_index()), 0);
632-
break;
644+
// Read the field index from the bytecode:
645+
// 0: aload_0
646+
// 1: *load_1
647+
// 2: putfield
648+
// 3: index
649+
// 4: index
650+
// 5: return
651+
//
652+
// NB this is not raw bytecode: index is in machine order
633653

634-
case atos:
635-
SET_LOCALS_OBJECT(object->obj_field_acquire(entry->f2_as_index()), 0);
636-
break;
654+
assert(method->is_setter(), "Expect the particular bytecode shape");
655+
u1* code = method->code_base();
656+
u2 index = Bytes::get_native_u2(&code[3]);
637657

638-
default:
639-
ShouldNotReachHere();
640-
}
658+
// Get the entry from the constant pool cache, and drop into
659+
// the slow path if it has not been resolved
660+
ConstantPoolCache* cache = method->constants()->cache();
661+
ConstantPoolCacheEntry* entry = cache->entry_at(index);
662+
if (!entry->is_resolved(Bytecodes::_putfield)) {
663+
return normal_entry(method, 0, THREAD);
641664
}
642-
else {
643-
switch (entry->flag_state()) {
644-
case ctos:
645-
SET_LOCALS_INT(object->char_field(entry->f2_as_index()), 0);
646-
break;
647665

648-
case btos:
649-
case ztos:
650-
SET_LOCALS_INT(object->byte_field(entry->f2_as_index()), 0);
651-
break;
652-
653-
case stos:
654-
SET_LOCALS_INT(object->short_field(entry->f2_as_index()), 0);
655-
break;
656-
657-
case itos:
658-
SET_LOCALS_INT(object->int_field(entry->f2_as_index()), 0);
659-
break;
666+
JavaThread* thread = THREAD->as_Java_thread();
667+
ZeroStack* stack = thread->zero_stack();
668+
intptr_t* topOfStack = stack->sp();
660669

670+
// Figure out where the receiver is. If there is a long/double
671+
// operand on stack top, then receiver is two slots down.
672+
oop object = NULL;
673+
switch (entry->flag_state()) {
661674
case ltos:
662-
SET_LOCALS_LONG(object->long_field(entry->f2_as_index()), 0);
663-
break;
664-
665-
case ftos:
666-
SET_LOCALS_FLOAT(object->float_field(entry->f2_as_index()), 0);
667-
break;
668-
669675
case dtos:
670-
SET_LOCALS_DOUBLE(object->double_field(entry->f2_as_index()), 0);
676+
object = STACK_OBJECT(-2);
671677
break;
672-
673-
case atos:
674-
SET_LOCALS_OBJECT(object->obj_field(entry->f2_as_index()), 0);
678+
default:
679+
object = STACK_OBJECT(-1);
675680
break;
681+
}
676682

677-
default:
678-
ShouldNotReachHere();
683+
// Load the receiver pointer and drop into the slow path
684+
// if we have a NullPointerException
685+
if (object == NULL) {
686+
return normal_entry(method, 0, THREAD);
687+
}
688+
689+
// Store the stack(0) to field
690+
int offset = entry->f2_as_index();
691+
if (entry->is_volatile()) {
692+
switch (entry->flag_state()) {
693+
case btos: object->release_byte_field_put(offset, STACK_INT(0)); break;
694+
case ztos: object->release_byte_field_put(offset, STACK_INT(0) & 1); break; // only store LSB
695+
case ctos: object->release_char_field_put(offset, STACK_INT(0)); break;
696+
case stos: object->release_short_field_put(offset, STACK_INT(0)); break;
697+
case itos: object->release_int_field_put(offset, STACK_INT(0)); break;
698+
case ltos: object->release_long_field_put(offset, STACK_LONG(0)); break;
699+
case ftos: object->release_float_field_put(offset, STACK_FLOAT(0)); break;
700+
case dtos: object->release_double_field_put(offset, STACK_DOUBLE(0)); break;
701+
case atos: object->release_obj_field_put(offset, STACK_OBJECT(0)); break;
702+
default:
703+
ShouldNotReachHere();
704+
}
705+
OrderAccess::storeload();
706+
} else {
707+
switch (entry->flag_state()) {
708+
case btos: object->byte_field_put(offset, STACK_INT(0)); break;
709+
case ztos: object->byte_field_put(offset, STACK_INT(0) & 1); break; // only store LSB
710+
case ctos: object->char_field_put(offset, STACK_INT(0)); break;
711+
case stos: object->short_field_put(offset, STACK_INT(0)); break;
712+
case itos: object->int_field_put(offset, STACK_INT(0)); break;
713+
case ltos: object->long_field_put(offset, STACK_LONG(0)); break;
714+
case ftos: object->float_field_put(offset, STACK_FLOAT(0)); break;
715+
case dtos: object->double_field_put(offset, STACK_DOUBLE(0)); break;
716+
case atos: object->obj_field_put(offset, STACK_OBJECT(0)); break;
717+
default:
718+
ShouldNotReachHere();
679719
}
680720
}
681721

722+
// Nothing is returned, pop out parameters
723+
stack->set_sp(stack->sp() + method->size_of_parameters());
724+
682725
// No deoptimized frames on the stack
683726
return 0;
684727
}

src/hotspot/cpu/zero/zeroInterpreter_zero.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
// Method entries
3535
static int normal_entry(Method* method, intptr_t UNUSED, TRAPS);
3636
static int native_entry(Method* method, intptr_t UNUSED, TRAPS);
37-
static int accessor_entry(Method* method, intptr_t UNUSED, TRAPS);
37+
static int getter_entry(Method* method, intptr_t UNUSED, TRAPS);
38+
static int setter_entry(Method* method, intptr_t UNUSED, TRAPS);
3839
static int empty_entry(Method* method, intptr_t UNUSED, TRAPS);
3940

4041
public:

src/hotspot/share/interpreter/abstractInterpreter.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,14 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan
185185
default : break;
186186
}
187187

188-
// Accessor method?
188+
// Getter method?
189189
if (m->is_getter()) {
190-
// TODO: We should have used ::is_accessor above, but fast accessors in Zero expect only getters.
191-
// See ZeroInterpreter::accessor_entry in zeroInterpreter_zero.cpp. This should be fixed in Zero,
192-
// then the call above updated to ::is_accessor
193-
assert(m->size_of_parameters() == 1, "fast code for accessors assumes parameter size = 1");
194-
return accessor;
190+
return getter;
191+
}
192+
193+
// Setter method?
194+
if (m->is_setter()) {
195+
return setter;
195196
}
196197

197198
// Note: for now: zero locals for all non-empty methods
@@ -300,7 +301,8 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) {
300301
case native : tty->print("native" ); break;
301302
case native_synchronized : tty->print("native_synchronized" ); break;
302303
case empty : tty->print("empty" ); break;
303-
case accessor : tty->print("accessor" ); break;
304+
case getter : tty->print("getter" ); break;
305+
case setter : tty->print("setter" ); break;
304306
case abstract : tty->print("abstract" ); break;
305307
case java_lang_math_sin : tty->print("java_lang_math_sin" ); break;
306308
case java_lang_math_cos : tty->print("java_lang_math_cos" ); break;

src/hotspot/share/interpreter/abstractInterpreter.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ class AbstractInterpreter: AllStatic {
6060
native, // native method
6161
native_synchronized, // native method & is synchronized
6262
empty, // empty method (code: _return)
63-
accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return)
63+
getter, // getter method
64+
setter, // setter method
6465
abstract, // abstract method (throws an AbstractMethodException)
6566
method_handle_invoke_FIRST, // java.lang.invoke.MethodHandles::invokeExact, etc.
6667
method_handle_invoke_LAST = (method_handle_invoke_FIRST

src/hotspot/share/interpreter/templateInterpreterGenerator.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ void TemplateInterpreterGenerator::generate_all() {
188188
method_entry(zerolocals)
189189
method_entry(zerolocals_synchronized)
190190
method_entry(empty)
191-
method_entry(accessor)
191+
method_entry(getter)
192+
method_entry(setter)
192193
method_entry(abstract)
193194
method_entry(java_lang_math_sin )
194195
method_entry(java_lang_math_cos )
@@ -406,7 +407,8 @@ address TemplateInterpreterGenerator::generate_method_entry(
406407
case Interpreter::native : native = true; break;
407408
case Interpreter::native_synchronized : native = true; synchronized = true; break;
408409
case Interpreter::empty : break;
409-
case Interpreter::accessor : break;
410+
case Interpreter::getter : break;
411+
case Interpreter::setter : break;
410412
case Interpreter::abstract : entry_point = generate_abstract_entry(); break;
411413

412414
case Interpreter::java_lang_math_sin : // fall thru

src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ void ZeroInterpreterGenerator::generate_all() {
5050
method_entry(zerolocals);
5151
method_entry(zerolocals_synchronized);
5252
method_entry(empty);
53-
method_entry(accessor);
53+
method_entry(getter);
54+
method_entry(setter);
5455
method_entry(abstract);
5556
method_entry(java_lang_math_sin );
5657
method_entry(java_lang_math_cos );
@@ -90,7 +91,8 @@ address ZeroInterpreterGenerator::generate_method_entry(
9091
case Interpreter::native : native = true; break;
9192
case Interpreter::native_synchronized : native = true; synchronized = true; break;
9293
case Interpreter::empty : entry_point = generate_empty_entry(); break;
93-
case Interpreter::accessor : entry_point = generate_accessor_entry(); break;
94+
case Interpreter::getter : entry_point = generate_getter_entry(); break;
95+
case Interpreter::setter : entry_point = generate_setter_entry(); break;
9496
case Interpreter::abstract : entry_point = generate_abstract_entry(); break;
9597

9698
case Interpreter::java_lang_math_sin : // fall thru
@@ -156,11 +158,18 @@ address ZeroInterpreterGenerator::generate_empty_entry() {
156158
return generate_entry((address) ZeroInterpreter::empty_entry);
157159
}
158160

159-
address ZeroInterpreterGenerator::generate_accessor_entry() {
161+
address ZeroInterpreterGenerator::generate_getter_entry() {
160162
if (!UseFastAccessorMethods)
161163
return NULL;
162164

163-
return generate_entry((address) ZeroInterpreter::accessor_entry);
165+
return generate_entry((address) ZeroInterpreter::getter_entry);
166+
}
167+
168+
address ZeroInterpreterGenerator::generate_setter_entry() {
169+
if (!UseFastAccessorMethods)
170+
return NULL;
171+
172+
return generate_entry((address) ZeroInterpreter::setter_entry);
164173
}
165174

166175
address ZeroInterpreterGenerator::generate_Reference_get_entry(void) {

src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class ZeroInterpreterGenerator: public AbstractInterpreterGenerator {
4444
address generate_abstract_entry();
4545
address generate_math_entry(AbstractInterpreter::MethodKind kind);
4646
address generate_empty_entry();
47-
address generate_accessor_entry();
47+
address generate_getter_entry();
48+
address generate_setter_entry();
4849
address generate_Reference_get_entry();
4950

5051
public:

0 commit comments

Comments
 (0)