mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8132051: Better byte behavior
Co-authored-by: Roland Westerlin <roland.westerlin@oracle.com> Co-authored-by: Vladimir Kozlov <vladimir.kozlov@oracle.com> Co-authored-by: John Rose <john.r.rose@oracle.com> Reviewed-by: bdelsart, roland, kvn, jrose, ahgross
This commit is contained in:
parent
ed18f94d21
commit
200784d505
40 changed files with 514 additions and 88 deletions
|
@ -344,7 +344,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
|
||||||
length.set_instruction(x->length());
|
length.set_instruction(x->length());
|
||||||
length.load_item();
|
length.load_item();
|
||||||
}
|
}
|
||||||
if (needs_store_check) {
|
if (needs_store_check || x->check_boolean()) {
|
||||||
value.load_item();
|
value.load_item();
|
||||||
} else {
|
} else {
|
||||||
value.load_for_store(x->elt_type());
|
value.load_for_store(x->elt_type());
|
||||||
|
@ -389,7 +389,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
|
||||||
pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
|
pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
|
||||||
true /* do_load */, false /* patch */, NULL);
|
true /* do_load */, false /* patch */, NULL);
|
||||||
}
|
}
|
||||||
__ move(value.result(), array_addr, null_check_info);
|
LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
|
||||||
|
__ move(result, array_addr, null_check_info);
|
||||||
if (obj_store) {
|
if (obj_store) {
|
||||||
// Precise card mark
|
// Precise card mark
|
||||||
post_barrier(LIR_OprFact::address(array_addr), value.result());
|
post_barrier(LIR_OprFact::address(array_addr), value.result());
|
||||||
|
|
|
@ -208,6 +208,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) {
|
||||||
case atos: ld_ptr(oop_addr, Otos_l);
|
case atos: ld_ptr(oop_addr, Otos_l);
|
||||||
st_ptr(G0, oop_addr); break;
|
st_ptr(G0, oop_addr); break;
|
||||||
case btos: // fall through
|
case btos: // fall through
|
||||||
|
case ztos: // fall through
|
||||||
case ctos: // fall through
|
case ctos: // fall through
|
||||||
case stos: // fall through
|
case stos: // fall through
|
||||||
case itos: ld(val_addr, Otos_l1); break;
|
case itos: ld(val_addr, Otos_l1); break;
|
||||||
|
@ -452,9 +453,10 @@ void InterpreterMacroAssembler::push(TosState state) {
|
||||||
interp_verify_oop(Otos_i, state, __FILE__, __LINE__);
|
interp_verify_oop(Otos_i, state, __FILE__, __LINE__);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case atos: push_ptr(); break;
|
case atos: push_ptr(); break;
|
||||||
case btos: push_i(); break;
|
case btos: // fall through
|
||||||
case ctos:
|
case ztos: // fall through
|
||||||
case stos: push_i(); break;
|
case ctos: // fall through
|
||||||
|
case stos: // fall through
|
||||||
case itos: push_i(); break;
|
case itos: push_i(); break;
|
||||||
case ltos: push_l(); break;
|
case ltos: push_l(); break;
|
||||||
case ftos: push_f(); break;
|
case ftos: push_f(); break;
|
||||||
|
@ -468,9 +470,10 @@ void InterpreterMacroAssembler::push(TosState state) {
|
||||||
void InterpreterMacroAssembler::pop(TosState state) {
|
void InterpreterMacroAssembler::pop(TosState state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case atos: pop_ptr(); break;
|
case atos: pop_ptr(); break;
|
||||||
case btos: pop_i(); break;
|
case btos: // fall through
|
||||||
case ctos:
|
case ztos: // fall through
|
||||||
case stos: pop_i(); break;
|
case ctos: // fall through
|
||||||
|
case stos: // fall through
|
||||||
case itos: pop_i(); break;
|
case itos: pop_i(); break;
|
||||||
case ltos: pop_l(); break;
|
case ltos: pop_l(); break;
|
||||||
case ftos: pop_f(); break;
|
case ftos: pop_f(); break;
|
||||||
|
@ -1103,6 +1106,49 @@ void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state,
|
||||||
interp_verify_oop(Otos_i, state, __FILE__, __LINE__);
|
interp_verify_oop(Otos_i, state, __FILE__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterpreterMacroAssembler::narrow(Register result) {
|
||||||
|
|
||||||
|
ld_ptr(Address(Lmethod, Method::const_offset()), G3_scratch);
|
||||||
|
ldub(G3_scratch, in_bytes(ConstMethod::result_type_offset()), G3_scratch);
|
||||||
|
|
||||||
|
Label notBool, notByte, notChar, done;
|
||||||
|
|
||||||
|
// common case first
|
||||||
|
cmp(G3_scratch, T_INT);
|
||||||
|
br(Assembler::equal, true, pn, done);
|
||||||
|
delayed()->nop();
|
||||||
|
|
||||||
|
cmp(G3_scratch, T_BOOLEAN);
|
||||||
|
br(Assembler::notEqual, true, pn, notBool);
|
||||||
|
delayed()->cmp(G3_scratch, T_BYTE);
|
||||||
|
and3(result, 1, result);
|
||||||
|
ba(done);
|
||||||
|
delayed()->nop();
|
||||||
|
|
||||||
|
bind(notBool);
|
||||||
|
// cmp(G3_scratch, T_BYTE);
|
||||||
|
br(Assembler::notEqual, true, pn, notByte);
|
||||||
|
delayed()->cmp(G3_scratch, T_CHAR);
|
||||||
|
sll(result, 24, result);
|
||||||
|
sra(result, 24, result);
|
||||||
|
ba(done);
|
||||||
|
delayed()->nop();
|
||||||
|
|
||||||
|
bind(notByte);
|
||||||
|
// cmp(G3_scratch, T_CHAR);
|
||||||
|
sll(result, 16, result);
|
||||||
|
br(Assembler::notEqual, true, pn, done);
|
||||||
|
delayed()->sra(result, 16, result);
|
||||||
|
// sll(result, 16, result);
|
||||||
|
srl(result, 16, result);
|
||||||
|
|
||||||
|
// bind(notChar);
|
||||||
|
// must be short, instructions already executed in delay slot
|
||||||
|
// sll(result, 16, result);
|
||||||
|
// sra(result, 16, result);
|
||||||
|
|
||||||
|
bind(done);
|
||||||
|
}
|
||||||
|
|
||||||
// remove activation
|
// remove activation
|
||||||
//
|
//
|
||||||
|
@ -1151,6 +1197,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
|
||||||
case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1
|
case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1
|
||||||
#endif
|
#endif
|
||||||
case btos: // fall through
|
case btos: // fall through
|
||||||
|
case ztos: // fall through
|
||||||
case ctos:
|
case ctos:
|
||||||
case stos: // fall through
|
case stos: // fall through
|
||||||
case atos: // fall through
|
case atos: // fall through
|
||||||
|
|
|
@ -103,6 +103,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
void dispatch_via (TosState state, address* table);
|
void dispatch_via (TosState state, address* table);
|
||||||
|
|
||||||
|
|
||||||
|
void narrow(Register result);
|
||||||
|
|
||||||
// Removes the current activation (incl. unlocking of monitors).
|
// Removes the current activation (incl. unlocking of monitors).
|
||||||
// Additionally this code is used for earlyReturn in which case we
|
// Additionally this code is used for earlyReturn in which case we
|
||||||
// want to skip throwing an exception and installing an exception.
|
// want to skip throwing an exception and installing an exception.
|
||||||
|
|
|
@ -165,6 +165,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
|
||||||
switch (bc) {
|
switch (bc) {
|
||||||
case Bytecodes::_fast_aputfield:
|
case Bytecodes::_fast_aputfield:
|
||||||
case Bytecodes::_fast_bputfield:
|
case Bytecodes::_fast_bputfield:
|
||||||
|
case Bytecodes::_fast_zputfield:
|
||||||
case Bytecodes::_fast_cputfield:
|
case Bytecodes::_fast_cputfield:
|
||||||
case Bytecodes::_fast_dputfield:
|
case Bytecodes::_fast_dputfield:
|
||||||
case Bytecodes::_fast_fputfield:
|
case Bytecodes::_fast_fputfield:
|
||||||
|
@ -922,8 +923,20 @@ void TemplateTable::bastore() {
|
||||||
transition(itos, vtos);
|
transition(itos, vtos);
|
||||||
__ pop_i(O2); // index
|
__ pop_i(O2); // index
|
||||||
// Otos_i: val
|
// Otos_i: val
|
||||||
|
// O2: index
|
||||||
// O3: array
|
// O3: array
|
||||||
__ index_check(O3, O2, 0, G3_scratch, O2);
|
__ index_check(O3, O2, 0, G3_scratch, O2);
|
||||||
|
// Need to check whether array is boolean or byte
|
||||||
|
// since both types share the bastore bytecode.
|
||||||
|
__ load_klass(O3, G4_scratch);
|
||||||
|
__ ld(G4_scratch, in_bytes(Klass::layout_helper_offset()), G4_scratch);
|
||||||
|
__ set(Klass::layout_helper_boolean_diffbit(), G3_scratch);
|
||||||
|
__ andcc(G3_scratch, G4_scratch, G0);
|
||||||
|
Label L_skip;
|
||||||
|
__ br(Assembler::zero, false, Assembler::pn, L_skip);
|
||||||
|
__ delayed()->nop();
|
||||||
|
__ and3(Otos_i, 1, Otos_i); // if it is a T_BOOLEAN array, mask the stored value to 0/1
|
||||||
|
__ bind(L_skip);
|
||||||
__ stb(Otos_i, O2, arrayOopDesc::base_offset_in_bytes(T_BYTE));
|
__ stb(Otos_i, O2, arrayOopDesc::base_offset_in_bytes(T_BYTE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2008,6 +2021,12 @@ void TemplateTable::_return(TosState state) {
|
||||||
__ bind(skip_register_finalizer);
|
__ bind(skip_register_finalizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Narrow result if state is itos but result type is smaller.
|
||||||
|
// Need to narrow in the return bytecode rather than in generate_return_entry
|
||||||
|
// since compiled code callers expect the result to already be narrowed.
|
||||||
|
if (state == itos) {
|
||||||
|
__ narrow(Otos_i);
|
||||||
|
}
|
||||||
__ remove_activation(state, /* throw_monitor_exception */ true);
|
__ remove_activation(state, /* throw_monitor_exception */ true);
|
||||||
|
|
||||||
// The caller's SP was adjusted upon method entry to accomodate
|
// The caller's SP was adjusted upon method entry to accomodate
|
||||||
|
@ -2218,7 +2237,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
Label checkVolatile;
|
Label checkVolatile;
|
||||||
|
|
||||||
// compute field type
|
// compute field type
|
||||||
Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj;
|
Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj;
|
||||||
__ srl(Rflags, ConstantPoolCacheEntry::tos_state_shift, Rflags);
|
__ srl(Rflags, ConstantPoolCacheEntry::tos_state_shift, Rflags);
|
||||||
// Make sure we don't need to mask Rflags after the above shift
|
// Make sure we don't need to mask Rflags after the above shift
|
||||||
ConstantPoolCacheEntry::verify_tos_state_shift();
|
ConstantPoolCacheEntry::verify_tos_state_shift();
|
||||||
|
@ -2273,7 +2292,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
|
|
||||||
// cmp(Rflags, btos);
|
// cmp(Rflags, btos);
|
||||||
__ br(Assembler::notEqual, false, Assembler::pt, notByte);
|
__ br(Assembler::notEqual, false, Assembler::pt, notByte);
|
||||||
__ delayed() ->cmp(Rflags, ctos);
|
__ delayed() ->cmp(Rflags, ztos);
|
||||||
|
|
||||||
// btos
|
// btos
|
||||||
__ ldsb(Rclass, Roffset, Otos_i);
|
__ ldsb(Rclass, Roffset, Otos_i);
|
||||||
|
@ -2286,6 +2305,22 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
|
|
||||||
__ bind(notByte);
|
__ bind(notByte);
|
||||||
|
|
||||||
|
// cmp(Rflags, ztos);
|
||||||
|
__ br(Assembler::notEqual, false, Assembler::pt, notBool);
|
||||||
|
__ delayed() ->cmp(Rflags, ctos);
|
||||||
|
|
||||||
|
// ztos
|
||||||
|
__ ldsb(Rclass, Roffset, Otos_i);
|
||||||
|
__ push(itos);
|
||||||
|
if (!is_static && rc == may_rewrite) {
|
||||||
|
// use btos rewriting, no truncating to t/f bit is needed for getfield.
|
||||||
|
patch_bytecode(Bytecodes::_fast_bgetfield, G3_scratch, G4_scratch);
|
||||||
|
}
|
||||||
|
__ ba(checkVolatile);
|
||||||
|
__ delayed()->tst(Lscratch);
|
||||||
|
|
||||||
|
__ bind(notBool);
|
||||||
|
|
||||||
// cmp(Rflags, ctos);
|
// cmp(Rflags, ctos);
|
||||||
__ br(Assembler::notEqual, false, Assembler::pt, notChar);
|
__ br(Assembler::notEqual, false, Assembler::pt, notChar);
|
||||||
__ delayed() ->cmp(Rflags, stos);
|
__ delayed() ->cmp(Rflags, stos);
|
||||||
|
@ -2449,6 +2484,7 @@ void TemplateTable::jvmti_post_fast_field_mod() {
|
||||||
switch (bytecode()) { // save tos values before call_VM() clobbers them
|
switch (bytecode()) { // save tos values before call_VM() clobbers them
|
||||||
case Bytecodes::_fast_aputfield: __ push_ptr(Otos_i); break;
|
case Bytecodes::_fast_aputfield: __ push_ptr(Otos_i); break;
|
||||||
case Bytecodes::_fast_bputfield: // fall through
|
case Bytecodes::_fast_bputfield: // fall through
|
||||||
|
case Bytecodes::_fast_zputfield: // fall through
|
||||||
case Bytecodes::_fast_sputfield: // fall through
|
case Bytecodes::_fast_sputfield: // fall through
|
||||||
case Bytecodes::_fast_cputfield: // fall through
|
case Bytecodes::_fast_cputfield: // fall through
|
||||||
case Bytecodes::_fast_iputfield: __ push_i(Otos_i); break;
|
case Bytecodes::_fast_iputfield: __ push_i(Otos_i); break;
|
||||||
|
@ -2466,6 +2502,7 @@ void TemplateTable::jvmti_post_fast_field_mod() {
|
||||||
switch (bytecode()) { // restore tos values
|
switch (bytecode()) { // restore tos values
|
||||||
case Bytecodes::_fast_aputfield: __ pop_ptr(Otos_i); break;
|
case Bytecodes::_fast_aputfield: __ pop_ptr(Otos_i); break;
|
||||||
case Bytecodes::_fast_bputfield: // fall through
|
case Bytecodes::_fast_bputfield: // fall through
|
||||||
|
case Bytecodes::_fast_zputfield: // fall through
|
||||||
case Bytecodes::_fast_sputfield: // fall through
|
case Bytecodes::_fast_sputfield: // fall through
|
||||||
case Bytecodes::_fast_cputfield: // fall through
|
case Bytecodes::_fast_cputfield: // fall through
|
||||||
case Bytecodes::_fast_iputfield: __ pop_i(Otos_i); break;
|
case Bytecodes::_fast_iputfield: __ pop_i(Otos_i); break;
|
||||||
|
@ -2581,7 +2618,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
ConstantPoolCacheEntry::verify_tos_state_shift();
|
ConstantPoolCacheEntry::verify_tos_state_shift();
|
||||||
|
|
||||||
// compute field type
|
// compute field type
|
||||||
Label notInt, notShort, notChar, notObj, notByte, notLong, notFloat;
|
Label notInt, notShort, notChar, notObj, notByte, notBool, notLong, notFloat;
|
||||||
|
|
||||||
if (is_static) {
|
if (is_static) {
|
||||||
// putstatic with object type most likely, check that first
|
// putstatic with object type most likely, check that first
|
||||||
|
@ -2649,7 +2686,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
|
|
||||||
// cmp(Rflags, btos);
|
// cmp(Rflags, btos);
|
||||||
__ br(Assembler::notEqual, false, Assembler::pt, notByte);
|
__ br(Assembler::notEqual, false, Assembler::pt, notByte);
|
||||||
__ delayed()->cmp(Rflags, ltos);
|
__ delayed()->cmp(Rflags, ztos);
|
||||||
|
|
||||||
// btos
|
// btos
|
||||||
{
|
{
|
||||||
|
@ -2664,6 +2701,25 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
}
|
}
|
||||||
|
|
||||||
__ bind(notByte);
|
__ bind(notByte);
|
||||||
|
|
||||||
|
// cmp(Rflags, btos);
|
||||||
|
__ br(Assembler::notEqual, false, Assembler::pt, notBool);
|
||||||
|
__ delayed()->cmp(Rflags, ltos);
|
||||||
|
|
||||||
|
// ztos
|
||||||
|
{
|
||||||
|
__ pop_i();
|
||||||
|
if (!is_static) pop_and_check_object(Rclass);
|
||||||
|
__ and3(Otos_i, 1, Otos_i);
|
||||||
|
__ stb(Otos_i, Rclass, Roffset);
|
||||||
|
if (!is_static && rc == may_rewrite) {
|
||||||
|
patch_bytecode(Bytecodes::_fast_zputfield, G3_scratch, G4_scratch, true, byte_no);
|
||||||
|
}
|
||||||
|
__ ba(checkVolatile);
|
||||||
|
__ delayed()->tst(Lscratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
__ bind(notBool);
|
||||||
// cmp(Rflags, ltos);
|
// cmp(Rflags, ltos);
|
||||||
__ br(Assembler::notEqual, false, Assembler::pt, notLong);
|
__ br(Assembler::notEqual, false, Assembler::pt, notLong);
|
||||||
__ delayed()->cmp(Rflags, ctos);
|
__ delayed()->cmp(Rflags, ctos);
|
||||||
|
@ -2787,6 +2843,7 @@ void TemplateTable::fast_storefield(TosState state) {
|
||||||
pop_and_check_object(Rclass);
|
pop_and_check_object(Rclass);
|
||||||
|
|
||||||
switch (bytecode()) {
|
switch (bytecode()) {
|
||||||
|
case Bytecodes::_fast_zputfield: __ and3(Otos_i, 1, Otos_i); // fall through to bputfield
|
||||||
case Bytecodes::_fast_bputfield: __ stb(Otos_i, Rclass, Roffset); break;
|
case Bytecodes::_fast_bputfield: __ stb(Otos_i, Rclass, Roffset); break;
|
||||||
case Bytecodes::_fast_cputfield: /* fall through */
|
case Bytecodes::_fast_cputfield: /* fall through */
|
||||||
case Bytecodes::_fast_sputfield: __ sth(Otos_i, Rclass, Roffset); break;
|
case Bytecodes::_fast_sputfield: __ sth(Otos_i, Rclass, Roffset); break;
|
||||||
|
|
|
@ -284,7 +284,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
|
||||||
length.load_item();
|
length.load_item();
|
||||||
|
|
||||||
}
|
}
|
||||||
if (needs_store_check) {
|
if (needs_store_check || x->check_boolean()) {
|
||||||
value.load_item();
|
value.load_item();
|
||||||
} else {
|
} else {
|
||||||
value.load_for_store(x->elt_type());
|
value.load_for_store(x->elt_type());
|
||||||
|
@ -332,7 +332,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
|
||||||
// Seems to be a precise
|
// Seems to be a precise
|
||||||
post_barrier(LIR_OprFact::address(array_addr), value.result());
|
post_barrier(LIR_OprFact::address(array_addr), value.result());
|
||||||
} else {
|
} else {
|
||||||
__ move(value.result(), array_addr, null_check_info);
|
LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
|
||||||
|
__ move(result, array_addr, null_check_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -349,6 +349,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) {
|
||||||
verify_oop(rax, state); break;
|
verify_oop(rax, state); break;
|
||||||
case ltos: movptr(rax, val_addr); break;
|
case ltos: movptr(rax, val_addr); break;
|
||||||
case btos: // fall through
|
case btos: // fall through
|
||||||
|
case ztos: // fall through
|
||||||
case ctos: // fall through
|
case ctos: // fall through
|
||||||
case stos: // fall through
|
case stos: // fall through
|
||||||
case itos: movl(rax, val_addr); break;
|
case itos: movl(rax, val_addr); break;
|
||||||
|
@ -370,6 +371,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) {
|
||||||
case ltos:
|
case ltos:
|
||||||
movl(rdx, val_addr1); // fall through
|
movl(rdx, val_addr1); // fall through
|
||||||
case btos: // fall through
|
case btos: // fall through
|
||||||
|
case ztos: // fall through
|
||||||
case ctos: // fall through
|
case ctos: // fall through
|
||||||
case stos: // fall through
|
case stos: // fall through
|
||||||
case itos: movl(rax, val_addr); break;
|
case itos: movl(rax, val_addr); break;
|
||||||
|
@ -616,6 +618,7 @@ void InterpreterMacroAssembler::pop(TosState state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case atos: pop_ptr(); break;
|
case atos: pop_ptr(); break;
|
||||||
case btos:
|
case btos:
|
||||||
|
case ztos:
|
||||||
case ctos:
|
case ctos:
|
||||||
case stos:
|
case stos:
|
||||||
case itos: pop_i(); break;
|
case itos: pop_i(); break;
|
||||||
|
@ -633,6 +636,7 @@ void InterpreterMacroAssembler::push(TosState state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case atos: push_ptr(); break;
|
case atos: push_ptr(); break;
|
||||||
case btos:
|
case btos:
|
||||||
|
case ztos:
|
||||||
case ctos:
|
case ctos:
|
||||||
case stos:
|
case stos:
|
||||||
case itos: push_i(); break;
|
case itos: push_i(); break;
|
||||||
|
@ -668,6 +672,7 @@ void InterpreterMacroAssembler::pop(TosState state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case atos: pop_ptr(rax); break;
|
case atos: pop_ptr(rax); break;
|
||||||
case btos: // fall through
|
case btos: // fall through
|
||||||
|
case ztos: // fall through
|
||||||
case ctos: // fall through
|
case ctos: // fall through
|
||||||
case stos: // fall through
|
case stos: // fall through
|
||||||
case itos: pop_i(rax); break;
|
case itos: pop_i(rax); break;
|
||||||
|
@ -716,6 +721,7 @@ void InterpreterMacroAssembler::push(TosState state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case atos: push_ptr(rax); break;
|
case atos: push_ptr(rax); break;
|
||||||
case btos: // fall through
|
case btos: // fall through
|
||||||
|
case ztos: // fall through
|
||||||
case ctos: // fall through
|
case ctos: // fall through
|
||||||
case stos: // fall through
|
case stos: // fall through
|
||||||
case itos: push_i(rax); break;
|
case itos: push_i(rax); break;
|
||||||
|
@ -849,6 +855,51 @@ void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) {
|
||||||
dispatch_base(state, table);
|
dispatch_base(state, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterpreterMacroAssembler::narrow(Register result) {
|
||||||
|
|
||||||
|
// Get method->_constMethod->_result_type
|
||||||
|
movptr(rcx, Address(rbp, frame::interpreter_frame_method_offset * wordSize));
|
||||||
|
movptr(rcx, Address(rcx, Method::const_offset()));
|
||||||
|
load_unsigned_byte(rcx, Address(rcx, ConstMethod::result_type_offset()));
|
||||||
|
|
||||||
|
Label done, notBool, notByte, notChar;
|
||||||
|
|
||||||
|
// common case first
|
||||||
|
cmpl(rcx, T_INT);
|
||||||
|
jcc(Assembler::equal, done);
|
||||||
|
|
||||||
|
// mask integer result to narrower return type.
|
||||||
|
cmpl(rcx, T_BOOLEAN);
|
||||||
|
jcc(Assembler::notEqual, notBool);
|
||||||
|
andl(result, 0x1);
|
||||||
|
jmp(done);
|
||||||
|
|
||||||
|
bind(notBool);
|
||||||
|
cmpl(rcx, T_BYTE);
|
||||||
|
jcc(Assembler::notEqual, notByte);
|
||||||
|
LP64_ONLY(movsbl(result, result);)
|
||||||
|
NOT_LP64(shll(result, 24);) // truncate upper 24 bits
|
||||||
|
NOT_LP64(sarl(result, 24);) // and sign-extend byte
|
||||||
|
jmp(done);
|
||||||
|
|
||||||
|
bind(notByte);
|
||||||
|
cmpl(rcx, T_CHAR);
|
||||||
|
jcc(Assembler::notEqual, notChar);
|
||||||
|
LP64_ONLY(movzwl(result, result);)
|
||||||
|
NOT_LP64(andl(result, 0xFFFF);) // truncate upper 16 bits
|
||||||
|
jmp(done);
|
||||||
|
|
||||||
|
bind(notChar);
|
||||||
|
// cmpl(rcx, T_SHORT); // all that's left
|
||||||
|
// jcc(Assembler::notEqual, done);
|
||||||
|
LP64_ONLY(movswl(result, result);)
|
||||||
|
NOT_LP64(shll(result, 16);) // truncate upper 16 bits
|
||||||
|
NOT_LP64(sarl(result, 16);) // and sign-extend short
|
||||||
|
|
||||||
|
// Nothing to do for T_INT
|
||||||
|
bind(done);
|
||||||
|
}
|
||||||
|
|
||||||
// remove activation
|
// remove activation
|
||||||
//
|
//
|
||||||
// Unlock the receiver if this is a synchronized method.
|
// Unlock the receiver if this is a synchronized method.
|
||||||
|
|
|
@ -192,6 +192,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||||
void prepare_to_jump_from_interpreted();
|
void prepare_to_jump_from_interpreted();
|
||||||
void jump_from_interpreted(Register method, Register temp);
|
void jump_from_interpreted(Register method, Register temp);
|
||||||
|
|
||||||
|
// narrow int return value
|
||||||
|
void narrow(Register result);
|
||||||
|
|
||||||
// Returning from interpreted functions
|
// Returning from interpreted functions
|
||||||
//
|
//
|
||||||
// Removes the current activation (incl. unlocking of monitors)
|
// Removes the current activation (incl. unlocking of monitors)
|
||||||
|
|
|
@ -243,6 +243,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
|
||||||
switch (bc) {
|
switch (bc) {
|
||||||
case Bytecodes::_fast_aputfield:
|
case Bytecodes::_fast_aputfield:
|
||||||
case Bytecodes::_fast_bputfield:
|
case Bytecodes::_fast_bputfield:
|
||||||
|
case Bytecodes::_fast_zputfield:
|
||||||
case Bytecodes::_fast_cputfield:
|
case Bytecodes::_fast_cputfield:
|
||||||
case Bytecodes::_fast_dputfield:
|
case Bytecodes::_fast_dputfield:
|
||||||
case Bytecodes::_fast_fputfield:
|
case Bytecodes::_fast_fputfield:
|
||||||
|
@ -1082,6 +1083,16 @@ void TemplateTable::bastore() {
|
||||||
// rbx: index
|
// rbx: index
|
||||||
// rdx: array
|
// rdx: array
|
||||||
index_check(rdx, rbx); // prefer index in rbx
|
index_check(rdx, rbx); // prefer index in rbx
|
||||||
|
// Need to check whether array is boolean or byte
|
||||||
|
// since both types share the bastore bytecode.
|
||||||
|
__ load_klass(rcx, rdx);
|
||||||
|
__ movl(rcx, Address(rcx, Klass::layout_helper_offset()));
|
||||||
|
int diffbit = Klass::layout_helper_boolean_diffbit();
|
||||||
|
__ testl(rcx, diffbit);
|
||||||
|
Label L_skip;
|
||||||
|
__ jccb(Assembler::zero, L_skip);
|
||||||
|
__ andl(rax, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1
|
||||||
|
__ bind(L_skip);
|
||||||
__ movb(Address(rdx, rbx,
|
__ movb(Address(rdx, rbx,
|
||||||
Address::times_1,
|
Address::times_1,
|
||||||
arrayOopDesc::base_offset_in_bytes(T_BYTE)),
|
arrayOopDesc::base_offset_in_bytes(T_BYTE)),
|
||||||
|
@ -2540,13 +2551,12 @@ void TemplateTable::fast_binaryswitch() {
|
||||||
void TemplateTable::_return(TosState state) {
|
void TemplateTable::_return(TosState state) {
|
||||||
transition(state, state);
|
transition(state, state);
|
||||||
|
|
||||||
Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax);
|
|
||||||
|
|
||||||
assert(_desc->calls_vm(),
|
assert(_desc->calls_vm(),
|
||||||
"inconsistent calls_vm information"); // call in remove_activation
|
"inconsistent calls_vm information"); // call in remove_activation
|
||||||
|
|
||||||
if (_desc->bytecode() == Bytecodes::_return_register_finalizer) {
|
if (_desc->bytecode() == Bytecodes::_return_register_finalizer) {
|
||||||
assert(state == vtos, "only valid state");
|
assert(state == vtos, "only valid state");
|
||||||
|
Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax);
|
||||||
__ movptr(robj, aaddress(0));
|
__ movptr(robj, aaddress(0));
|
||||||
__ load_klass(rdi, robj);
|
__ load_klass(rdi, robj);
|
||||||
__ movl(rdi, Address(rdi, Klass::access_flags_offset()));
|
__ movl(rdi, Address(rdi, Klass::access_flags_offset()));
|
||||||
|
@ -2559,7 +2569,14 @@ void TemplateTable::_return(TosState state) {
|
||||||
__ bind(skip_register_finalizer);
|
__ bind(skip_register_finalizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Narrow result if state is itos but result type is smaller.
|
||||||
|
// Need to narrow in the return bytecode rather than in generate_return_entry
|
||||||
|
// since compiled code callers expect the result to already be narrowed.
|
||||||
|
if (state == itos) {
|
||||||
|
__ narrow(rax);
|
||||||
|
}
|
||||||
__ remove_activation(state, rbcp);
|
__ remove_activation(state, rbcp);
|
||||||
|
|
||||||
__ jmp(rbcp);
|
__ jmp(rbcp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2754,7 +2771,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
const Address field(obj, off, Address::times_1, 0*wordSize);
|
const Address field(obj, off, Address::times_1, 0*wordSize);
|
||||||
NOT_LP64(const Address hi(obj, off, Address::times_1, 1*wordSize));
|
NOT_LP64(const Address hi(obj, off, Address::times_1, 1*wordSize));
|
||||||
|
|
||||||
Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble;
|
Label Done, notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble;
|
||||||
|
|
||||||
__ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
|
__ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
|
||||||
// Make sure we don't need to mask edx after the above shift
|
// Make sure we don't need to mask edx after the above shift
|
||||||
|
@ -2773,6 +2790,20 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
__ jmp(Done);
|
__ jmp(Done);
|
||||||
|
|
||||||
__ bind(notByte);
|
__ bind(notByte);
|
||||||
|
__ cmpl(flags, ztos);
|
||||||
|
__ jcc(Assembler::notEqual, notBool);
|
||||||
|
|
||||||
|
// ztos (same code as btos)
|
||||||
|
__ load_signed_byte(rax, field);
|
||||||
|
__ push(ztos);
|
||||||
|
// Rewrite bytecode to be faster
|
||||||
|
if (!is_static && rc == may_rewrite) {
|
||||||
|
// use btos rewriting, no truncating to t/f bit is needed for getfield.
|
||||||
|
patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
|
||||||
|
}
|
||||||
|
__ jmp(Done);
|
||||||
|
|
||||||
|
__ bind(notBool);
|
||||||
__ cmpl(flags, atos);
|
__ cmpl(flags, atos);
|
||||||
__ jcc(Assembler::notEqual, notObj);
|
__ jcc(Assembler::notEqual, notObj);
|
||||||
// atos
|
// atos
|
||||||
|
@ -3006,7 +3037,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
const Address field(obj, off, Address::times_1, 0*wordSize);
|
const Address field(obj, off, Address::times_1, 0*wordSize);
|
||||||
NOT_LP64( const Address hi(obj, off, Address::times_1, 1*wordSize);)
|
NOT_LP64( const Address hi(obj, off, Address::times_1, 1*wordSize);)
|
||||||
|
|
||||||
Label notByte, notInt, notShort, notChar,
|
Label notByte, notBool, notInt, notShort, notChar,
|
||||||
notLong, notFloat, notObj, notDouble;
|
notLong, notFloat, notObj, notDouble;
|
||||||
|
|
||||||
__ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
|
__ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
|
||||||
|
@ -3027,6 +3058,22 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr
|
||||||
}
|
}
|
||||||
|
|
||||||
__ bind(notByte);
|
__ bind(notByte);
|
||||||
|
__ cmpl(flags, ztos);
|
||||||
|
__ jcc(Assembler::notEqual, notBool);
|
||||||
|
|
||||||
|
// ztos
|
||||||
|
{
|
||||||
|
__ pop(ztos);
|
||||||
|
if (!is_static) pop_and_check_object(obj);
|
||||||
|
__ andl(rax, 0x1);
|
||||||
|
__ movb(field, rax);
|
||||||
|
if (!is_static && rc == may_rewrite) {
|
||||||
|
patch_bytecode(Bytecodes::_fast_zputfield, bc, rbx, true, byte_no);
|
||||||
|
}
|
||||||
|
__ jmp(Done);
|
||||||
|
}
|
||||||
|
|
||||||
|
__ bind(notBool);
|
||||||
__ cmpl(flags, atos);
|
__ cmpl(flags, atos);
|
||||||
__ jcc(Assembler::notEqual, notObj);
|
__ jcc(Assembler::notEqual, notObj);
|
||||||
|
|
||||||
|
@ -3214,6 +3261,7 @@ void TemplateTable::jvmti_post_fast_field_mod() {
|
||||||
switch (bytecode()) { // load values into the jvalue object
|
switch (bytecode()) { // load values into the jvalue object
|
||||||
case Bytecodes::_fast_aputfield: __ push_ptr(rax); break;
|
case Bytecodes::_fast_aputfield: __ push_ptr(rax); break;
|
||||||
case Bytecodes::_fast_bputfield: // fall through
|
case Bytecodes::_fast_bputfield: // fall through
|
||||||
|
case Bytecodes::_fast_zputfield: // fall through
|
||||||
case Bytecodes::_fast_sputfield: // fall through
|
case Bytecodes::_fast_sputfield: // fall through
|
||||||
case Bytecodes::_fast_cputfield: // fall through
|
case Bytecodes::_fast_cputfield: // fall through
|
||||||
case Bytecodes::_fast_iputfield: __ push_i(rax); break;
|
case Bytecodes::_fast_iputfield: __ push_i(rax); break;
|
||||||
|
@ -3238,6 +3286,7 @@ void TemplateTable::jvmti_post_fast_field_mod() {
|
||||||
switch (bytecode()) { // restore tos values
|
switch (bytecode()) { // restore tos values
|
||||||
case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break;
|
case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break;
|
||||||
case Bytecodes::_fast_bputfield: // fall through
|
case Bytecodes::_fast_bputfield: // fall through
|
||||||
|
case Bytecodes::_fast_zputfield: // fall through
|
||||||
case Bytecodes::_fast_sputfield: // fall through
|
case Bytecodes::_fast_sputfield: // fall through
|
||||||
case Bytecodes::_fast_cputfield: // fall through
|
case Bytecodes::_fast_cputfield: // fall through
|
||||||
case Bytecodes::_fast_iputfield: __ pop_i(rax); break;
|
case Bytecodes::_fast_iputfield: __ pop_i(rax); break;
|
||||||
|
@ -3297,6 +3346,9 @@ void TemplateTable::fast_storefield(TosState state) {
|
||||||
case Bytecodes::_fast_iputfield:
|
case Bytecodes::_fast_iputfield:
|
||||||
__ movl(field, rax);
|
__ movl(field, rax);
|
||||||
break;
|
break;
|
||||||
|
case Bytecodes::_fast_zputfield:
|
||||||
|
__ andl(rax, 0x1); // boolean is true if LSB is 1
|
||||||
|
// fall through to bputfield
|
||||||
case Bytecodes::_fast_bputfield:
|
case Bytecodes::_fast_bputfield:
|
||||||
__ movb(field, rax);
|
__ movb(field, rax);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -82,6 +82,29 @@ int CppInterpreter::normal_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intptr_t narrow(BasicType type, intptr_t result) {
|
||||||
|
// mask integer result to narrower return type.
|
||||||
|
switch (type) {
|
||||||
|
case T_BOOLEAN:
|
||||||
|
return result&1;
|
||||||
|
case T_BYTE:
|
||||||
|
return (intptr_t)(jbyte)result;
|
||||||
|
case T_CHAR:
|
||||||
|
return (intptr_t)(uintptr_t)(jchar)result;
|
||||||
|
case T_SHORT:
|
||||||
|
return (intptr_t)(jshort)result;
|
||||||
|
case T_OBJECT: // nothing to do fall through
|
||||||
|
case T_LONG:
|
||||||
|
case T_INT:
|
||||||
|
case T_FLOAT:
|
||||||
|
case T_DOUBLE:
|
||||||
|
case T_VOID:
|
||||||
|
return result;
|
||||||
|
default : ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CppInterpreter::main_loop(int recurse, TRAPS) {
|
void CppInterpreter::main_loop(int recurse, TRAPS) {
|
||||||
JavaThread *thread = (JavaThread *) THREAD;
|
JavaThread *thread = (JavaThread *) THREAD;
|
||||||
ZeroStack *stack = thread->zero_stack();
|
ZeroStack *stack = thread->zero_stack();
|
||||||
|
@ -195,8 +218,14 @@ void CppInterpreter::main_loop(int recurse, TRAPS) {
|
||||||
stack->set_sp(stack->sp() + method->max_locals());
|
stack->set_sp(stack->sp() + method->max_locals());
|
||||||
|
|
||||||
// Push our result
|
// Push our result
|
||||||
for (int i = 0; i < result_slots; i++)
|
for (int i = 0; i < result_slots; i++) {
|
||||||
stack->push(result[-i]);
|
// Adjust result to smaller
|
||||||
|
intptr_t res = result[-i];
|
||||||
|
if (result_slots == 1) {
|
||||||
|
res = narrow(result_type_of(method), res);
|
||||||
|
}
|
||||||
|
stack->push(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
||||||
|
@ -532,6 +561,7 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case btos:
|
case btos:
|
||||||
|
case ztos:
|
||||||
SET_LOCALS_INT(object->byte_field_acquire(entry->f2_as_index()), 0);
|
SET_LOCALS_INT(object->byte_field_acquire(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -570,6 +600,7 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case btos:
|
case btos:
|
||||||
|
case ztos:
|
||||||
SET_LOCALS_INT(object->byte_field(entry->f2_as_index()), 0);
|
SET_LOCALS_INT(object->byte_field(entry->f2_as_index()), 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -305,7 +305,8 @@ void Canonicalizer::do_StoreIndexed (StoreIndexed* x) {
|
||||||
// limit this optimization to current block
|
// limit this optimization to current block
|
||||||
if (value != NULL && in_current_block(conv)) {
|
if (value != NULL && in_current_block(conv)) {
|
||||||
set_canonical(new StoreIndexed(x->array(), x->index(), x->length(),
|
set_canonical(new StoreIndexed(x->array(), x->index(), x->length(),
|
||||||
x->elt_type(), value, x->state_before()));
|
x->elt_type(), value, x->state_before(),
|
||||||
|
x->check_boolean()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -976,7 +976,19 @@ void GraphBuilder::store_indexed(BasicType type) {
|
||||||
(array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) {
|
(array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) {
|
||||||
length = append(new ArrayLength(array, state_before));
|
length = append(new ArrayLength(array, state_before));
|
||||||
}
|
}
|
||||||
StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before);
|
ciType* array_type = array->declared_type();
|
||||||
|
bool check_boolean = false;
|
||||||
|
if (array_type != NULL) {
|
||||||
|
if (array_type->is_loaded() &&
|
||||||
|
array_type->as_array_klass()->element_type()->basic_type() == T_BOOLEAN) {
|
||||||
|
assert(type == T_BYTE, "boolean store uses bastore");
|
||||||
|
Value mask = append(new Constant(new IntConstant(1)));
|
||||||
|
value = append(new LogicOp(Bytecodes::_iand, value, mask));
|
||||||
|
}
|
||||||
|
} else if (type == T_BYTE) {
|
||||||
|
check_boolean = true;
|
||||||
|
}
|
||||||
|
StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before, check_boolean);
|
||||||
append(result);
|
append(result);
|
||||||
_memory->store_value(value);
|
_memory->store_value(value);
|
||||||
|
|
||||||
|
@ -1443,6 +1455,36 @@ void GraphBuilder::method_return(Value x) {
|
||||||
need_mem_bar = true;
|
need_mem_bar = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BasicType bt = method()->return_type()->basic_type();
|
||||||
|
switch (bt) {
|
||||||
|
case T_BYTE:
|
||||||
|
{
|
||||||
|
Value shift = append(new Constant(new IntConstant(24)));
|
||||||
|
x = append(new ShiftOp(Bytecodes::_ishl, x, shift));
|
||||||
|
x = append(new ShiftOp(Bytecodes::_ishr, x, shift));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case T_SHORT:
|
||||||
|
{
|
||||||
|
Value shift = append(new Constant(new IntConstant(16)));
|
||||||
|
x = append(new ShiftOp(Bytecodes::_ishl, x, shift));
|
||||||
|
x = append(new ShiftOp(Bytecodes::_ishr, x, shift));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case T_CHAR:
|
||||||
|
{
|
||||||
|
Value mask = append(new Constant(new IntConstant(0xFFFF)));
|
||||||
|
x = append(new LogicOp(Bytecodes::_iand, x, mask));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case T_BOOLEAN:
|
||||||
|
{
|
||||||
|
Value mask = append(new Constant(new IntConstant(1)));
|
||||||
|
x = append(new LogicOp(Bytecodes::_iand, x, mask));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check to see whether we are inlining. If so, Return
|
// Check to see whether we are inlining. If so, Return
|
||||||
// instructions become Gotos to the continuation point.
|
// instructions become Gotos to the continuation point.
|
||||||
if (continuation() != NULL) {
|
if (continuation() != NULL) {
|
||||||
|
@ -1611,6 +1653,10 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
|
||||||
if (state_before == NULL) {
|
if (state_before == NULL) {
|
||||||
state_before = copy_state_for_exception();
|
state_before = copy_state_for_exception();
|
||||||
}
|
}
|
||||||
|
if (field->type()->basic_type() == T_BOOLEAN) {
|
||||||
|
Value mask = append(new Constant(new IntConstant(1)));
|
||||||
|
val = append(new LogicOp(Bytecodes::_iand, val, mask));
|
||||||
|
}
|
||||||
append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching));
|
append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1672,6 +1718,10 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
|
||||||
if (state_before == NULL) {
|
if (state_before == NULL) {
|
||||||
state_before = copy_state_for_exception();
|
state_before = copy_state_for_exception();
|
||||||
}
|
}
|
||||||
|
if (field->type()->basic_type() == T_BOOLEAN) {
|
||||||
|
Value mask = append(new Constant(new IntConstant(1)));
|
||||||
|
val = append(new LogicOp(Bytecodes::_iand, val, mask));
|
||||||
|
}
|
||||||
StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching);
|
StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching);
|
||||||
if (!needs_patching) store = _memory->store(store);
|
if (!needs_patching) store = _memory->store(store);
|
||||||
if (store != NULL) {
|
if (store != NULL) {
|
||||||
|
@ -4134,7 +4184,12 @@ void GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_
|
||||||
#ifndef _LP64
|
#ifndef _LP64
|
||||||
offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
|
offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
|
||||||
#endif
|
#endif
|
||||||
Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile));
|
Value val = args->at(3);
|
||||||
|
if (t == T_BOOLEAN) {
|
||||||
|
Value mask = append(new Constant(new IntConstant(1)));
|
||||||
|
val = append(new LogicOp(Bytecodes::_iand, val, mask));
|
||||||
|
}
|
||||||
|
Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, val, is_volatile));
|
||||||
compilation()->set_has_unsafe_access(true);
|
compilation()->set_has_unsafe_access(true);
|
||||||
kill_all();
|
kill_all();
|
||||||
}
|
}
|
||||||
|
@ -4208,7 +4263,7 @@ void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) {
|
||||||
Value index = args->at(1);
|
Value index = args->at(1);
|
||||||
if (is_store) {
|
if (is_store) {
|
||||||
Value value = args->at(2);
|
Value value = args->at(2);
|
||||||
Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before));
|
Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before, false));
|
||||||
store->set_flag(Instruction::NeedsRangeCheckFlag, false);
|
store->set_flag(Instruction::NeedsRangeCheckFlag, false);
|
||||||
_memory->store_value(value);
|
_memory->store_value(value);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -974,11 +974,13 @@ LEAF(StoreIndexed, AccessIndexed)
|
||||||
|
|
||||||
ciMethod* _profiled_method;
|
ciMethod* _profiled_method;
|
||||||
int _profiled_bci;
|
int _profiled_bci;
|
||||||
|
bool _check_boolean;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// creation
|
// creation
|
||||||
StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before)
|
StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before, bool check_boolean)
|
||||||
: AccessIndexed(array, index, length, elt_type, state_before)
|
: AccessIndexed(array, index, length, elt_type, state_before)
|
||||||
, _value(value), _profiled_method(NULL), _profiled_bci(0)
|
, _value(value), _profiled_method(NULL), _profiled_bci(0), _check_boolean(check_boolean)
|
||||||
{
|
{
|
||||||
set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object()));
|
set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object()));
|
||||||
set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object()));
|
set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object()));
|
||||||
|
@ -990,6 +992,7 @@ LEAF(StoreIndexed, AccessIndexed)
|
||||||
Value value() const { return _value; }
|
Value value() const { return _value; }
|
||||||
bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); }
|
bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); }
|
||||||
bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); }
|
bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); }
|
||||||
|
bool check_boolean() const { return _check_boolean; }
|
||||||
// Helpers for MethodData* profiling
|
// Helpers for MethodData* profiling
|
||||||
void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); }
|
void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); }
|
||||||
void set_profiled_method(ciMethod* method) { _profiled_method = method; }
|
void set_profiled_method(ciMethod* method) { _profiled_method = method; }
|
||||||
|
|
|
@ -3680,3 +3680,26 @@ void LIRGenerator::do_MemBar(MemBar* x) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIR_Opr LIRGenerator::maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) {
|
||||||
|
if (x->check_boolean()) {
|
||||||
|
LIR_Opr value_fixed = rlock_byte(T_BYTE);
|
||||||
|
if (TwoOperandLIRForm) {
|
||||||
|
__ move(value, value_fixed);
|
||||||
|
__ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed);
|
||||||
|
} else {
|
||||||
|
__ logical_and(value, LIR_OprFact::intConst(1), value_fixed);
|
||||||
|
}
|
||||||
|
LIR_Opr klass = new_register(T_METADATA);
|
||||||
|
__ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info);
|
||||||
|
null_check_info = NULL;
|
||||||
|
LIR_Opr layout = new_register(T_INT);
|
||||||
|
__ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout);
|
||||||
|
int diffbit = Klass::layout_helper_boolean_diffbit();
|
||||||
|
__ logical_and(layout, LIR_OprFact::intConst(diffbit), layout);
|
||||||
|
__ cmp(lir_cond_notEqual, layout, LIR_OprFact::intConst(0));
|
||||||
|
__ cmove(lir_cond_notEqual, value_fixed, value, value_fixed, T_BYTE);
|
||||||
|
value = value_fixed;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
|
@ -448,6 +448,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
|
||||||
void profile_arguments(ProfileCall* x);
|
void profile_arguments(ProfileCall* x);
|
||||||
void profile_parameters(Base* x);
|
void profile_parameters(Base* x);
|
||||||
void profile_parameters_at_call(ProfileCall* x);
|
void profile_parameters_at_call(ProfileCall* x);
|
||||||
|
LIR_Opr maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Compilation* compilation() const { return _compilation; }
|
Compilation* compilation() const { return _compilation; }
|
||||||
|
|
|
@ -2713,11 +2713,9 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
|
||||||
m->set_constants(_cp);
|
m->set_constants(_cp);
|
||||||
m->set_name_index(name_index);
|
m->set_name_index(name_index);
|
||||||
m->set_signature_index(signature_index);
|
m->set_signature_index(signature_index);
|
||||||
#ifdef CC_INTERP
|
|
||||||
// hmm is there a gc issue here??
|
|
||||||
ResultTypeFinder rtf(cp->symbol_at(signature_index));
|
ResultTypeFinder rtf(cp->symbol_at(signature_index));
|
||||||
m->set_result_index(rtf.type());
|
m->constMethod()->set_result_type(rtf.type());
|
||||||
#endif
|
|
||||||
|
|
||||||
if (args_size >= 0) {
|
if (args_size >= 0) {
|
||||||
m->set_size_of_parameters(args_size);
|
m->set_size_of_parameters(args_size);
|
||||||
|
|
|
@ -860,10 +860,8 @@ static Method* new_method(
|
||||||
m->set_constants(NULL); // This will get filled in later
|
m->set_constants(NULL); // This will get filled in later
|
||||||
m->set_name_index(cp->utf8(name));
|
m->set_name_index(cp->utf8(name));
|
||||||
m->set_signature_index(cp->utf8(sig));
|
m->set_signature_index(cp->utf8(sig));
|
||||||
#ifdef CC_INTERP
|
|
||||||
ResultTypeFinder rtf(sig);
|
ResultTypeFinder rtf(sig);
|
||||||
m->set_result_index(rtf.type());
|
m->constMethod()->set_result_type(rtf.type());
|
||||||
#endif
|
|
||||||
m->set_size_of_parameters(params);
|
m->set_size_of_parameters(params);
|
||||||
m->set_max_stack(max_stack);
|
m->set_max_stack(max_stack);
|
||||||
m->set_max_locals(params);
|
m->set_max_locals(params);
|
||||||
|
|
|
@ -1767,8 +1767,19 @@ run:
|
||||||
((objArrayOop) arrObj)->obj_at_put(index, rhsObject);
|
((objArrayOop) arrObj)->obj_at_put(index, rhsObject);
|
||||||
UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3);
|
UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3);
|
||||||
}
|
}
|
||||||
CASE(_bastore):
|
CASE(_bastore): {
|
||||||
ARRAY_STOREFROM32(T_BYTE, jbyte, "%d", STACK_INT, 0);
|
ARRAY_INTRO(-3);
|
||||||
|
int item = STACK_INT(-1);
|
||||||
|
// if it is a T_BOOLEAN array, mask the stored value to 0/1
|
||||||
|
if (arrObj->klass() == Universe::boolArrayKlassObj()) {
|
||||||
|
item &= 1;
|
||||||
|
} else {
|
||||||
|
assert(arrObj->klass() == Universe::byteArrayKlassObj(),
|
||||||
|
"should be byte array otherwise");
|
||||||
|
}
|
||||||
|
((typeArrayOop)arrObj)->byte_at_put(index, item);
|
||||||
|
UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3);
|
||||||
|
}
|
||||||
CASE(_castore):
|
CASE(_castore):
|
||||||
ARRAY_STOREFROM32(T_CHAR, jchar, "%d", STACK_INT, 0);
|
ARRAY_STOREFROM32(T_CHAR, jchar, "%d", STACK_INT, 0);
|
||||||
CASE(_sastore):
|
CASE(_sastore):
|
||||||
|
@ -1999,7 +2010,7 @@ run:
|
||||||
} else if (tos_type == ltos) {
|
} else if (tos_type == ltos) {
|
||||||
SET_STACK_LONG(obj->long_field_acquire(field_offset), 0);
|
SET_STACK_LONG(obj->long_field_acquire(field_offset), 0);
|
||||||
MORE_STACK(1);
|
MORE_STACK(1);
|
||||||
} else if (tos_type == btos) {
|
} else if (tos_type == btos || tos_type == ztos) {
|
||||||
SET_STACK_INT(obj->byte_field_acquire(field_offset), -1);
|
SET_STACK_INT(obj->byte_field_acquire(field_offset), -1);
|
||||||
} else if (tos_type == ctos) {
|
} else if (tos_type == ctos) {
|
||||||
SET_STACK_INT(obj->char_field_acquire(field_offset), -1);
|
SET_STACK_INT(obj->char_field_acquire(field_offset), -1);
|
||||||
|
@ -2020,7 +2031,7 @@ run:
|
||||||
} else if (tos_type == ltos) {
|
} else if (tos_type == ltos) {
|
||||||
SET_STACK_LONG(obj->long_field(field_offset), 0);
|
SET_STACK_LONG(obj->long_field(field_offset), 0);
|
||||||
MORE_STACK(1);
|
MORE_STACK(1);
|
||||||
} else if (tos_type == btos) {
|
} else if (tos_type == btos || tos_type == ztos) {
|
||||||
SET_STACK_INT(obj->byte_field(field_offset), -1);
|
SET_STACK_INT(obj->byte_field(field_offset), -1);
|
||||||
} else if (tos_type == ctos) {
|
} else if (tos_type == ctos) {
|
||||||
SET_STACK_INT(obj->char_field(field_offset), -1);
|
SET_STACK_INT(obj->char_field(field_offset), -1);
|
||||||
|
@ -2109,6 +2120,9 @@ run:
|
||||||
obj->release_obj_field_put(field_offset, STACK_OBJECT(-1));
|
obj->release_obj_field_put(field_offset, STACK_OBJECT(-1));
|
||||||
} else if (tos_type == btos) {
|
} else if (tos_type == btos) {
|
||||||
obj->release_byte_field_put(field_offset, STACK_INT(-1));
|
obj->release_byte_field_put(field_offset, STACK_INT(-1));
|
||||||
|
} else if (tos_type == ztos) {
|
||||||
|
int bool_field = STACK_INT(-1); // only store LSB
|
||||||
|
obj->release_byte_field_put(field_offset, (bool_field & 1));
|
||||||
} else if (tos_type == ltos) {
|
} else if (tos_type == ltos) {
|
||||||
obj->release_long_field_put(field_offset, STACK_LONG(-1));
|
obj->release_long_field_put(field_offset, STACK_LONG(-1));
|
||||||
} else if (tos_type == ctos) {
|
} else if (tos_type == ctos) {
|
||||||
|
@ -2129,6 +2143,9 @@ run:
|
||||||
obj->obj_field_put(field_offset, STACK_OBJECT(-1));
|
obj->obj_field_put(field_offset, STACK_OBJECT(-1));
|
||||||
} else if (tos_type == btos) {
|
} else if (tos_type == btos) {
|
||||||
obj->byte_field_put(field_offset, STACK_INT(-1));
|
obj->byte_field_put(field_offset, STACK_INT(-1));
|
||||||
|
} else if (tos_type == ztos) {
|
||||||
|
int bool_field = STACK_INT(-1); // only store LSB
|
||||||
|
obj->byte_field_put(field_offset, (bool_field & 1));
|
||||||
} else if (tos_type == ltos) {
|
} else if (tos_type == ltos) {
|
||||||
obj->long_field_put(field_offset, STACK_LONG(-1));
|
obj->long_field_put(field_offset, STACK_LONG(-1));
|
||||||
} else if (tos_type == ctos) {
|
} else if (tos_type == ctos) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -496,6 +496,7 @@ void Bytecodes::initialize() {
|
||||||
|
|
||||||
def(_fast_aputfield , "fast_aputfield" , "bJJ" , NULL , T_OBJECT , 0, true , _putfield );
|
def(_fast_aputfield , "fast_aputfield" , "bJJ" , NULL , T_OBJECT , 0, true , _putfield );
|
||||||
def(_fast_bputfield , "fast_bputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield );
|
def(_fast_bputfield , "fast_bputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield );
|
||||||
|
def(_fast_zputfield , "fast_zputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield );
|
||||||
def(_fast_cputfield , "fast_cputfield" , "bJJ" , NULL , T_CHAR , 0, true , _putfield );
|
def(_fast_cputfield , "fast_cputfield" , "bJJ" , NULL , T_CHAR , 0, true , _putfield );
|
||||||
def(_fast_dputfield , "fast_dputfield" , "bJJ" , NULL , T_DOUBLE , 0, true , _putfield );
|
def(_fast_dputfield , "fast_dputfield" , "bJJ" , NULL , T_DOUBLE , 0, true , _putfield );
|
||||||
def(_fast_fputfield , "fast_fputfield" , "bJJ" , NULL , T_FLOAT , 0, true , _putfield );
|
def(_fast_fputfield , "fast_fputfield" , "bJJ" , NULL , T_FLOAT , 0, true , _putfield );
|
||||||
|
|
|
@ -257,6 +257,7 @@ class Bytecodes: AllStatic {
|
||||||
|
|
||||||
_fast_aputfield ,
|
_fast_aputfield ,
|
||||||
_fast_bputfield ,
|
_fast_bputfield ,
|
||||||
|
_fast_zputfield ,
|
||||||
_fast_cputfield ,
|
_fast_cputfield ,
|
||||||
_fast_dputfield ,
|
_fast_dputfield ,
|
||||||
_fast_fputfield ,
|
_fast_fputfield ,
|
||||||
|
|
|
@ -1077,7 +1077,8 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread,
|
||||||
char sig_type = '\0';
|
char sig_type = '\0';
|
||||||
|
|
||||||
switch(cp_entry->flag_state()) {
|
switch(cp_entry->flag_state()) {
|
||||||
case btos: sig_type = 'Z'; break;
|
case btos: sig_type = 'B'; break;
|
||||||
|
case ztos: sig_type = 'Z'; break;
|
||||||
case ctos: sig_type = 'C'; break;
|
case ctos: sig_type = 'C'; break;
|
||||||
case stos: sig_type = 'S'; break;
|
case stos: sig_type = 'S'; break;
|
||||||
case itos: sig_type = 'I'; break;
|
case itos: sig_type = 'I'; break;
|
||||||
|
|
|
@ -89,8 +89,9 @@ void TemplateInterpreter::initialize() {
|
||||||
// Implementation of EntryPoint
|
// Implementation of EntryPoint
|
||||||
|
|
||||||
EntryPoint::EntryPoint() {
|
EntryPoint::EntryPoint() {
|
||||||
assert(number_of_states == 9, "check the code below");
|
assert(number_of_states == 10, "check the code below");
|
||||||
_entry[btos] = NULL;
|
_entry[btos] = NULL;
|
||||||
|
_entry[ztos] = NULL;
|
||||||
_entry[ctos] = NULL;
|
_entry[ctos] = NULL;
|
||||||
_entry[stos] = NULL;
|
_entry[stos] = NULL;
|
||||||
_entry[atos] = NULL;
|
_entry[atos] = NULL;
|
||||||
|
@ -102,9 +103,10 @@ EntryPoint::EntryPoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EntryPoint::EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) {
|
EntryPoint::EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) {
|
||||||
assert(number_of_states == 9, "check the code below");
|
assert(number_of_states == 10, "check the code below");
|
||||||
_entry[btos] = bentry;
|
_entry[btos] = bentry;
|
||||||
|
_entry[ztos] = zentry;
|
||||||
_entry[ctos] = centry;
|
_entry[ctos] = centry;
|
||||||
_entry[stos] = sentry;
|
_entry[stos] = sentry;
|
||||||
_entry[atos] = aentry;
|
_entry[atos] = aentry;
|
||||||
|
@ -155,6 +157,7 @@ EntryPoint DispatchTable::entry(int i) const {
|
||||||
return
|
return
|
||||||
EntryPoint(
|
EntryPoint(
|
||||||
_table[btos][i],
|
_table[btos][i],
|
||||||
|
_table[ztos][i],
|
||||||
_table[ctos][i],
|
_table[ctos][i],
|
||||||
_table[stos][i],
|
_table[stos][i],
|
||||||
_table[atos][i],
|
_table[atos][i],
|
||||||
|
@ -169,8 +172,9 @@ EntryPoint DispatchTable::entry(int i) const {
|
||||||
|
|
||||||
void DispatchTable::set_entry(int i, EntryPoint& entry) {
|
void DispatchTable::set_entry(int i, EntryPoint& entry) {
|
||||||
assert(0 <= i && i < length, "index out of bounds");
|
assert(0 <= i && i < length, "index out of bounds");
|
||||||
assert(number_of_states == 9, "check the code below");
|
assert(number_of_states == 10, "check the code below");
|
||||||
_table[btos][i] = entry.entry(btos);
|
_table[btos][i] = entry.entry(btos);
|
||||||
|
_table[ztos][i] = entry.entry(ztos);
|
||||||
_table[ctos][i] = entry.entry(ctos);
|
_table[ctos][i] = entry.entry(ctos);
|
||||||
_table[stos][i] = entry.entry(stos);
|
_table[stos][i] = entry.entry(stos);
|
||||||
_table[atos][i] = entry.entry(atos);
|
_table[atos][i] = entry.entry(atos);
|
||||||
|
|
|
@ -47,7 +47,7 @@ class EntryPoint VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
// Construction
|
// Construction
|
||||||
EntryPoint();
|
EntryPoint();
|
||||||
EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry);
|
EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry);
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
address entry(TosState state) const; // return target address for a given tosca state
|
address entry(TosState state) const; // return target address for a given tosca state
|
||||||
|
|
|
@ -74,6 +74,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||||
Interpreter::_trace_code =
|
Interpreter::_trace_code =
|
||||||
EntryPoint(
|
EntryPoint(
|
||||||
generate_trace_code(btos),
|
generate_trace_code(btos),
|
||||||
|
generate_trace_code(ztos),
|
||||||
generate_trace_code(ctos),
|
generate_trace_code(ctos),
|
||||||
generate_trace_code(stos),
|
generate_trace_code(stos),
|
||||||
generate_trace_code(atos),
|
generate_trace_code(atos),
|
||||||
|
@ -94,6 +95,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||||
generate_return_entry_for(itos, i, index_size),
|
generate_return_entry_for(itos, i, index_size),
|
||||||
generate_return_entry_for(itos, i, index_size),
|
generate_return_entry_for(itos, i, index_size),
|
||||||
generate_return_entry_for(itos, i, index_size),
|
generate_return_entry_for(itos, i, index_size),
|
||||||
|
generate_return_entry_for(itos, i, index_size),
|
||||||
generate_return_entry_for(atos, i, index_size),
|
generate_return_entry_for(atos, i, index_size),
|
||||||
generate_return_entry_for(itos, i, index_size),
|
generate_return_entry_for(itos, i, index_size),
|
||||||
generate_return_entry_for(ltos, i, index_size),
|
generate_return_entry_for(ltos, i, index_size),
|
||||||
|
@ -105,13 +107,16 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{ CodeletMark cm(_masm, "invoke return entry points");
|
{ CodeletMark cm(_masm, "invoke return entry points");
|
||||||
const TosState states[] = {itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos};
|
// These states are in order specified in TosState, except btos/ztos/ctos/stos are
|
||||||
|
// really the same as itos since there is no top of stack optimization for these types
|
||||||
|
const TosState states[] = {itos, itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos, ilgl};
|
||||||
const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic);
|
const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic);
|
||||||
const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface);
|
const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface);
|
||||||
const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic);
|
const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic);
|
||||||
|
|
||||||
for (int i = 0; i < Interpreter::number_of_return_addrs; i++) {
|
for (int i = 0; i < Interpreter::number_of_return_addrs; i++) {
|
||||||
TosState state = states[i];
|
TosState state = states[i];
|
||||||
|
assert(state != ilgl, "states array is wrong above");
|
||||||
Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2));
|
Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2));
|
||||||
Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2));
|
Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2));
|
||||||
Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4));
|
Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4));
|
||||||
|
@ -122,6 +127,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||||
Interpreter::_earlyret_entry =
|
Interpreter::_earlyret_entry =
|
||||||
EntryPoint(
|
EntryPoint(
|
||||||
generate_earlyret_entry_for(btos),
|
generate_earlyret_entry_for(btos),
|
||||||
|
generate_earlyret_entry_for(ztos),
|
||||||
generate_earlyret_entry_for(ctos),
|
generate_earlyret_entry_for(ctos),
|
||||||
generate_earlyret_entry_for(stos),
|
generate_earlyret_entry_for(stos),
|
||||||
generate_earlyret_entry_for(atos),
|
generate_earlyret_entry_for(atos),
|
||||||
|
@ -140,6 +146,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||||
generate_deopt_entry_for(itos, i),
|
generate_deopt_entry_for(itos, i),
|
||||||
generate_deopt_entry_for(itos, i),
|
generate_deopt_entry_for(itos, i),
|
||||||
generate_deopt_entry_for(itos, i),
|
generate_deopt_entry_for(itos, i),
|
||||||
|
generate_deopt_entry_for(itos, i),
|
||||||
generate_deopt_entry_for(atos, i),
|
generate_deopt_entry_for(atos, i),
|
||||||
generate_deopt_entry_for(itos, i),
|
generate_deopt_entry_for(itos, i),
|
||||||
generate_deopt_entry_for(ltos, i),
|
generate_deopt_entry_for(ltos, i),
|
||||||
|
@ -167,6 +174,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||||
Interpreter::_continuation_entry =
|
Interpreter::_continuation_entry =
|
||||||
EntryPoint(
|
EntryPoint(
|
||||||
generate_continuation_for(btos),
|
generate_continuation_for(btos),
|
||||||
|
generate_continuation_for(ztos),
|
||||||
generate_continuation_for(ctos),
|
generate_continuation_for(ctos),
|
||||||
generate_continuation_for(stos),
|
generate_continuation_for(stos),
|
||||||
generate_continuation_for(atos),
|
generate_continuation_for(atos),
|
||||||
|
@ -182,6 +190,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||||
Interpreter::_safept_entry =
|
Interpreter::_safept_entry =
|
||||||
EntryPoint(
|
EntryPoint(
|
||||||
generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),
|
generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),
|
||||||
|
generate_safept_entry_for(ztos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),
|
||||||
generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),
|
generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),
|
||||||
generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),
|
generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),
|
||||||
generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),
|
generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)),
|
||||||
|
@ -301,7 +310,7 @@ void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() {
|
||||||
|
|
||||||
void TemplateInterpreterGenerator::set_unimplemented(int i) {
|
void TemplateInterpreterGenerator::set_unimplemented(int i) {
|
||||||
address e = _unimplemented_bytecode;
|
address e = _unimplemented_bytecode;
|
||||||
EntryPoint entry(e, e, e, e, e, e, e, e, e);
|
EntryPoint entry(e, e, e, e, e, e, e, e, e, e);
|
||||||
Interpreter::_normal_table.set_entry(i, entry);
|
Interpreter::_normal_table.set_entry(i, entry);
|
||||||
Interpreter::_wentry_point[i] = _unimplemented_bytecode;
|
Interpreter::_wentry_point[i] = _unimplemented_bytecode;
|
||||||
}
|
}
|
||||||
|
@ -316,6 +325,7 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) {
|
||||||
assert(_unimplemented_bytecode != NULL, "should have been generated before");
|
assert(_unimplemented_bytecode != NULL, "should have been generated before");
|
||||||
assert(_illegal_bytecode_sequence != NULL, "should have been generated before");
|
assert(_illegal_bytecode_sequence != NULL, "should have been generated before");
|
||||||
address bep = _illegal_bytecode_sequence;
|
address bep = _illegal_bytecode_sequence;
|
||||||
|
address zep = _illegal_bytecode_sequence;
|
||||||
address cep = _illegal_bytecode_sequence;
|
address cep = _illegal_bytecode_sequence;
|
||||||
address sep = _illegal_bytecode_sequence;
|
address sep = _illegal_bytecode_sequence;
|
||||||
address aep = _illegal_bytecode_sequence;
|
address aep = _illegal_bytecode_sequence;
|
||||||
|
@ -337,7 +347,7 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) {
|
||||||
set_wide_entry_point(t, wep);
|
set_wide_entry_point(t, wep);
|
||||||
}
|
}
|
||||||
// set entry points
|
// set entry points
|
||||||
EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep);
|
EntryPoint entry(bep, zep, cep, sep, aep, iep, lep, fep, dep, vep);
|
||||||
Interpreter::_normal_table.set_entry(code, entry);
|
Interpreter::_normal_table.set_entry(code, entry);
|
||||||
Interpreter::_wentry_point[code] = wep;
|
Interpreter::_wentry_point[code] = wep;
|
||||||
CodeCacheExtensions::completed_template_interpreter_entries(_masm, code);
|
CodeCacheExtensions::completed_template_interpreter_entries(_masm, code);
|
||||||
|
@ -355,6 +365,7 @@ void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address&
|
||||||
assert(t->is_valid(), "template must exist");
|
assert(t->is_valid(), "template must exist");
|
||||||
switch (t->tos_in()) {
|
switch (t->tos_in()) {
|
||||||
case btos:
|
case btos:
|
||||||
|
case ztos:
|
||||||
case ctos:
|
case ctos:
|
||||||
case stos:
|
case stos:
|
||||||
ShouldNotReachHere(); // btos/ctos/stos should use itos.
|
ShouldNotReachHere(); // btos/ctos/stos should use itos.
|
||||||
|
|
|
@ -488,6 +488,7 @@ void TemplateTable::initialize() {
|
||||||
|
|
||||||
def(Bytecodes::_fast_aputfield , ubcp|____|____|____, atos, vtos, fast_storefield , atos );
|
def(Bytecodes::_fast_aputfield , ubcp|____|____|____, atos, vtos, fast_storefield , atos );
|
||||||
def(Bytecodes::_fast_bputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );
|
def(Bytecodes::_fast_bputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );
|
||||||
|
def(Bytecodes::_fast_zputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );
|
||||||
def(Bytecodes::_fast_cputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );
|
def(Bytecodes::_fast_cputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos );
|
||||||
def(Bytecodes::_fast_dputfield , ubcp|____|____|____, dtos, vtos, fast_storefield , dtos );
|
def(Bytecodes::_fast_dputfield , ubcp|____|____|____, dtos, vtos, fast_storefield , dtos );
|
||||||
def(Bytecodes::_fast_fputfield , ubcp|____|____|____, ftos, vtos, fast_storefield , ftos );
|
def(Bytecodes::_fast_fputfield , ubcp|____|____|____, ftos, vtos, fast_storefield , ftos );
|
||||||
|
|
|
@ -66,6 +66,7 @@ ConstMethod::ConstMethod(int byte_code_size,
|
||||||
set_max_locals(0);
|
set_max_locals(0);
|
||||||
set_method_idnum(0);
|
set_method_idnum(0);
|
||||||
set_size_of_parameters(0);
|
set_size_of_parameters(0);
|
||||||
|
set_result_type(T_VOID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accessor that copies to metadata.
|
// Accessor that copies to metadata.
|
||||||
|
|
|
@ -210,6 +210,7 @@ private:
|
||||||
|
|
||||||
int _constMethod_size;
|
int _constMethod_size;
|
||||||
u2 _flags;
|
u2 _flags;
|
||||||
|
u1 _result_type; // BasicType of result
|
||||||
|
|
||||||
// Size of Java bytecodes allocated immediately after Method*.
|
// Size of Java bytecodes allocated immediately after Method*.
|
||||||
u2 _code_size;
|
u2 _code_size;
|
||||||
|
@ -494,6 +495,8 @@ public:
|
||||||
static ByteSize size_of_parameters_offset()
|
static ByteSize size_of_parameters_offset()
|
||||||
{ return byte_offset_of(ConstMethod, _size_of_parameters); }
|
{ return byte_offset_of(ConstMethod, _size_of_parameters); }
|
||||||
|
|
||||||
|
static ByteSize result_type_offset()
|
||||||
|
{ return byte_offset_of(ConstMethod, _result_type); }
|
||||||
|
|
||||||
// Unique id for the method
|
// Unique id for the method
|
||||||
static const u2 MAX_IDNUM;
|
static const u2 MAX_IDNUM;
|
||||||
|
@ -516,6 +519,8 @@ public:
|
||||||
int size_of_parameters() const { return _size_of_parameters; }
|
int size_of_parameters() const { return _size_of_parameters; }
|
||||||
void set_size_of_parameters(int size) { _size_of_parameters = size; }
|
void set_size_of_parameters(int size) { _size_of_parameters = size; }
|
||||||
|
|
||||||
|
void set_result_type(BasicType rt) { assert(rt < 16, "result type too large");
|
||||||
|
_result_type = (u1)rt; }
|
||||||
// Deallocation for RedefineClasses
|
// Deallocation for RedefineClasses
|
||||||
void deallocate_contents(ClassLoaderData* loader_data);
|
void deallocate_contents(ClassLoaderData* loader_data);
|
||||||
bool is_klass() const { return false; }
|
bool is_klass() const { return false; }
|
||||||
|
|
|
@ -77,18 +77,19 @@ class PSPromotionManager;
|
||||||
// f2 flag true if f2 contains an oop (e.g., virtual final method)
|
// f2 flag true if f2 contains an oop (e.g., virtual final method)
|
||||||
// fv flag true if invokeinterface used for method in class Object
|
// fv flag true if invokeinterface used for method in class Object
|
||||||
//
|
//
|
||||||
// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 8 with the
|
// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 16 with the
|
||||||
// following mapping to the TosState states:
|
// following mapping to the TosState states:
|
||||||
//
|
//
|
||||||
// btos: 0
|
// btos: 0
|
||||||
// ctos: 1
|
// ztos: 1
|
||||||
// stos: 2
|
// ctos: 2
|
||||||
// itos: 3
|
// stos: 3
|
||||||
// ltos: 4
|
// itos: 4
|
||||||
// ftos: 5
|
// ltos: 5
|
||||||
// dtos: 6
|
// ftos: 6
|
||||||
// atos: 7
|
// dtos: 7
|
||||||
// vtos: 8
|
// atos: 8
|
||||||
|
// vtos: 9
|
||||||
//
|
//
|
||||||
// Entry specific: field entries:
|
// Entry specific: field entries:
|
||||||
// _indices = get (b1 section) and put (b2 section) bytecodes, original constant pool index
|
// _indices = get (b1 section) and put (b2 section) bytecodes, original constant pool index
|
||||||
|
@ -352,14 +353,8 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||||
bool has_method_type() const { return (!is_f1_null()) && (_flags & (1 << has_method_type_shift)) != 0; }
|
bool has_method_type() const { return (!is_f1_null()) && (_flags & (1 << has_method_type_shift)) != 0; }
|
||||||
bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; }
|
bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; }
|
||||||
bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; }
|
bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; }
|
||||||
bool is_byte() const { return flag_state() == btos; }
|
|
||||||
bool is_char() const { return flag_state() == ctos; }
|
|
||||||
bool is_short() const { return flag_state() == stos; }
|
|
||||||
bool is_int() const { return flag_state() == itos; }
|
|
||||||
bool is_long() const { return flag_state() == ltos; }
|
bool is_long() const { return flag_state() == ltos; }
|
||||||
bool is_float() const { return flag_state() == ftos; }
|
|
||||||
bool is_double() const { return flag_state() == dtos; }
|
bool is_double() const { return flag_state() == dtos; }
|
||||||
bool is_object() const { return flag_state() == atos; }
|
|
||||||
TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, "");
|
TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, "");
|
||||||
return (TosState)((_flags >> tos_state_shift) & tos_state_mask); }
|
return (TosState)((_flags >> tos_state_shift) & tos_state_mask); }
|
||||||
|
|
||||||
|
|
|
@ -342,6 +342,21 @@ protected:
|
||||||
assert(btvalue >= T_BOOLEAN && btvalue <= T_OBJECT, "sanity");
|
assert(btvalue >= T_BOOLEAN && btvalue <= T_OBJECT, "sanity");
|
||||||
return (BasicType) btvalue;
|
return (BasicType) btvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Want a pattern to quickly diff against layout header in register
|
||||||
|
// find something less clever!
|
||||||
|
static int layout_helper_boolean_diffbit() {
|
||||||
|
jint zlh = array_layout_helper(T_BOOLEAN);
|
||||||
|
jint blh = array_layout_helper(T_BYTE);
|
||||||
|
assert(zlh != blh, "array layout helpers must differ");
|
||||||
|
int diffbit = 1;
|
||||||
|
while ((diffbit & (zlh ^ blh)) == 0 && (diffbit & zlh) == 0) {
|
||||||
|
diffbit <<= 1;
|
||||||
|
assert(diffbit != 0, "make sure T_BOOLEAN has a different bit than T_BYTE");
|
||||||
|
}
|
||||||
|
return diffbit;
|
||||||
|
}
|
||||||
|
|
||||||
static int layout_helper_log2_element_size(jint lh) {
|
static int layout_helper_log2_element_size(jint lh) {
|
||||||
assert(lh < (jint)_lh_neutral_value, "must be array");
|
assert(lh < (jint)_lh_neutral_value, "must be array");
|
||||||
int l2esz = (lh >> _lh_log2_element_size_shift) & _lh_log2_element_size_mask;
|
int l2esz = (lh >> _lh_log2_element_size_shift) & _lh_log2_element_size_mask;
|
||||||
|
|
|
@ -1220,10 +1220,8 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
|
||||||
m->set_signature_index(_imcp_invoke_signature);
|
m->set_signature_index(_imcp_invoke_signature);
|
||||||
assert(MethodHandles::is_signature_polymorphic_name(m->name()), "");
|
assert(MethodHandles::is_signature_polymorphic_name(m->name()), "");
|
||||||
assert(m->signature() == signature, "");
|
assert(m->signature() == signature, "");
|
||||||
#ifdef CC_INTERP
|
|
||||||
ResultTypeFinder rtf(signature);
|
ResultTypeFinder rtf(signature);
|
||||||
m->set_result_index(rtf.type());
|
m->constMethod()->set_result_type(rtf.type());
|
||||||
#endif
|
|
||||||
m->compute_size_of_parameters(THREAD);
|
m->compute_size_of_parameters(THREAD);
|
||||||
m->init_intrinsic_id();
|
m->init_intrinsic_id();
|
||||||
assert(m->is_method_handle_intrinsic(), "");
|
assert(m->is_method_handle_intrinsic(), "");
|
||||||
|
|
|
@ -443,7 +443,7 @@ jchar oopDesc::char_field(int offset) const { return (jchar) *
|
||||||
void oopDesc::char_field_put(int offset, jchar contents) { *char_field_addr(offset) = (jint) contents; }
|
void oopDesc::char_field_put(int offset, jchar contents) { *char_field_addr(offset) = (jint) contents; }
|
||||||
|
|
||||||
jboolean oopDesc::bool_field(int offset) const { return (jboolean) *bool_field_addr(offset); }
|
jboolean oopDesc::bool_field(int offset) const { return (jboolean) *bool_field_addr(offset); }
|
||||||
void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (jint) contents; }
|
void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (((jint) contents) & 1); }
|
||||||
|
|
||||||
jint oopDesc::int_field(int offset) const { return *int_field_addr(offset); }
|
jint oopDesc::int_field(int offset) const { return *int_field_addr(offset); }
|
||||||
void oopDesc::int_field_put(int offset, jint contents) { *int_field_addr(offset) = contents; }
|
void oopDesc::int_field_put(int offset, jint contents) { *int_field_addr(offset) = contents; }
|
||||||
|
@ -483,7 +483,7 @@ jchar oopDesc::char_field_acquire(int offset) const { return O
|
||||||
void oopDesc::release_char_field_put(int offset, jchar contents) { OrderAccess::release_store(char_field_addr(offset), contents); }
|
void oopDesc::release_char_field_put(int offset, jchar contents) { OrderAccess::release_store(char_field_addr(offset), contents); }
|
||||||
|
|
||||||
jboolean oopDesc::bool_field_acquire(int offset) const { return OrderAccess::load_acquire(bool_field_addr(offset)); }
|
jboolean oopDesc::bool_field_acquire(int offset) const { return OrderAccess::load_acquire(bool_field_addr(offset)); }
|
||||||
void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), contents); }
|
void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), (contents & 1)); }
|
||||||
|
|
||||||
jint oopDesc::int_field_acquire(int offset) const { return OrderAccess::load_acquire(int_field_addr(offset)); }
|
jint oopDesc::int_field_acquire(int offset) const { return OrderAccess::load_acquire(int_field_addr(offset)); }
|
||||||
void oopDesc::release_int_field_put(int offset, jint contents) { OrderAccess::release_store(int_field_addr(offset), contents); }
|
void oopDesc::release_int_field_put(int offset, jint contents) { OrderAccess::release_store(int_field_addr(offset), contents); }
|
||||||
|
|
|
@ -2389,7 +2389,7 @@ StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const
|
||||||
ctl != NULL, "raw memory operations should have control edge");
|
ctl != NULL, "raw memory operations should have control edge");
|
||||||
|
|
||||||
switch (bt) {
|
switch (bt) {
|
||||||
case T_BOOLEAN:
|
case T_BOOLEAN: val = gvn.transform(new AndINode(val, gvn.intcon(0x1))); // Fall through to T_BYTE case
|
||||||
case T_BYTE: return new StoreBNode(ctl, mem, adr, adr_type, val, mo);
|
case T_BYTE: return new StoreBNode(ctl, mem, adr, adr_type, val, mo);
|
||||||
case T_INT: return new StoreINode(ctl, mem, adr, adr_type, val, mo);
|
case T_INT: return new StoreINode(ctl, mem, adr, adr_type, val, mo);
|
||||||
case T_CHAR:
|
case T_CHAR:
|
||||||
|
|
|
@ -730,6 +730,26 @@ void Parse::do_all_blocks() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Node* mask_int_value(Node* v, BasicType bt, PhaseGVN* gvn) {
|
||||||
|
switch (bt) {
|
||||||
|
case T_BYTE:
|
||||||
|
v = gvn->transform(new LShiftINode(v, gvn->intcon(24)));
|
||||||
|
v = gvn->transform(new RShiftINode(v, gvn->intcon(24)));
|
||||||
|
break;
|
||||||
|
case T_SHORT:
|
||||||
|
v = gvn->transform(new LShiftINode(v, gvn->intcon(16)));
|
||||||
|
v = gvn->transform(new RShiftINode(v, gvn->intcon(16)));
|
||||||
|
break;
|
||||||
|
case T_CHAR:
|
||||||
|
v = gvn->transform(new AndINode(v, gvn->intcon(0xFFFF)));
|
||||||
|
break;
|
||||||
|
case T_BOOLEAN:
|
||||||
|
v = gvn->transform(new AndINode(v, gvn->intcon(0x1)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------build_exits----------------------------------
|
//-------------------------------build_exits----------------------------------
|
||||||
// Build normal and exceptional exit merge points.
|
// Build normal and exceptional exit merge points.
|
||||||
void Parse::build_exits() {
|
void Parse::build_exits() {
|
||||||
|
@ -754,6 +774,16 @@ void Parse::build_exits() {
|
||||||
// Add a return value to the exit state. (Do not push it yet.)
|
// Add a return value to the exit state. (Do not push it yet.)
|
||||||
if (tf()->range()->cnt() > TypeFunc::Parms) {
|
if (tf()->range()->cnt() > TypeFunc::Parms) {
|
||||||
const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms);
|
const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms);
|
||||||
|
if (ret_type->isa_int()) {
|
||||||
|
BasicType ret_bt = method()->return_type()->basic_type();
|
||||||
|
if (ret_bt == T_BOOLEAN ||
|
||||||
|
ret_bt == T_CHAR ||
|
||||||
|
ret_bt == T_BYTE ||
|
||||||
|
ret_bt == T_SHORT) {
|
||||||
|
ret_type = TypeInt::INT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Don't "bind" an unloaded return klass to the ret_phi. If the klass
|
// Don't "bind" an unloaded return klass to the ret_phi. If the klass
|
||||||
// becomes loaded during the subsequent parsing, the loaded and unloaded
|
// becomes loaded during the subsequent parsing, the loaded and unloaded
|
||||||
// types will not join when we transform and push in do_exits().
|
// types will not join when we transform and push in do_exits().
|
||||||
|
@ -1014,6 +1044,10 @@ void Parse::do_exits() {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (ret_type->isa_int()) {
|
||||||
|
BasicType ret_bt = method()->return_type()->basic_type();
|
||||||
|
ret_phi = mask_int_value(ret_phi, ret_bt, &_gvn);
|
||||||
|
}
|
||||||
_exits.push_node(ret_type->basic_type(), ret_phi);
|
_exits.push_node(ret_type->basic_type(), ret_phi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,15 @@ void Parse::array_load(BasicType elem_type) {
|
||||||
|
|
||||||
//--------------------------------array_store----------------------------------
|
//--------------------------------array_store----------------------------------
|
||||||
void Parse::array_store(BasicType elem_type) {
|
void Parse::array_store(BasicType elem_type) {
|
||||||
Node* adr = array_addressing(elem_type, 1);
|
const Type* elem = Type::TOP;
|
||||||
|
Node* adr = array_addressing(elem_type, 1, &elem);
|
||||||
if (stopped()) return; // guaranteed null or range check
|
if (stopped()) return; // guaranteed null or range check
|
||||||
Node* val = pop();
|
Node* val = pop();
|
||||||
dec_sp(2); // Pop array and index
|
dec_sp(2); // Pop array and index
|
||||||
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type);
|
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type);
|
||||||
|
if (elem == TypeInt::BOOL) {
|
||||||
|
elem_type = T_BOOLEAN;
|
||||||
|
}
|
||||||
store_to_memory(control(), adr, val, elem_type, adr_type, StoreNode::release_if_reference(elem_type));
|
store_to_memory(control(), adr, val, elem_type, adr_type, StoreNode::release_if_reference(elem_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1820,14 +1820,16 @@ const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig)
|
||||||
break;
|
break;
|
||||||
case T_OBJECT:
|
case T_OBJECT:
|
||||||
case T_ARRAY:
|
case T_ARRAY:
|
||||||
case T_BOOLEAN:
|
|
||||||
case T_CHAR:
|
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
case T_BYTE:
|
|
||||||
case T_SHORT:
|
|
||||||
case T_INT:
|
case T_INT:
|
||||||
field_array[pos++] = get_const_type(type);
|
field_array[pos++] = get_const_type(type);
|
||||||
break;
|
break;
|
||||||
|
case T_BOOLEAN:
|
||||||
|
case T_CHAR:
|
||||||
|
case T_BYTE:
|
||||||
|
case T_SHORT:
|
||||||
|
field_array[pos++] = TypeInt::INT;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2188,6 +2188,7 @@ JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID
|
||||||
field_value.unionType = value; \
|
field_value.unionType = value; \
|
||||||
o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
|
o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
|
||||||
} \
|
} \
|
||||||
|
if (SigType == 'Z') { value = ((jboolean)value) & 1; } \
|
||||||
o->Fieldname##_field_put(offset, value); \
|
o->Fieldname##_field_put(offset, value); \
|
||||||
ReturnProbe; \
|
ReturnProbe; \
|
||||||
JNI_END
|
JNI_END
|
||||||
|
@ -2387,6 +2388,7 @@ JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID
|
||||||
field_value.unionType = value; \
|
field_value.unionType = value; \
|
||||||
JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \
|
JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \
|
||||||
} \
|
} \
|
||||||
|
if (SigType == 'Z') { value = ((jboolean)value) & 1; } \
|
||||||
id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \
|
id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \
|
||||||
ReturnProbe;\
|
ReturnProbe;\
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
|
@ -1354,7 +1354,7 @@ JvmtiEnvBase::check_top_frame(JavaThread* current_thread, JavaThread* java_threa
|
||||||
ResultTypeFinder rtf(signature);
|
ResultTypeFinder rtf(signature);
|
||||||
TosState fr_tos = as_TosState(rtf.type());
|
TosState fr_tos = as_TosState(rtf.type());
|
||||||
if (fr_tos != tos) {
|
if (fr_tos != tos) {
|
||||||
if (tos != itos || (fr_tos != btos && fr_tos != ctos && fr_tos != stos)) {
|
if (tos != itos || (fr_tos != btos && fr_tos != ztos && fr_tos != ctos && fr_tos != stos)) {
|
||||||
return JVMTI_ERROR_TYPE_MISMATCH;
|
return JVMTI_ERROR_TYPE_MISMATCH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1702,7 +1702,7 @@ void JvmtiExport::post_raw_field_modification(JavaThread *thread, Method* method
|
||||||
address location, KlassHandle field_klass, Handle object, jfieldID field,
|
address location, KlassHandle field_klass, Handle object, jfieldID field,
|
||||||
char sig_type, jvalue *value) {
|
char sig_type, jvalue *value) {
|
||||||
|
|
||||||
if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'C' || sig_type == 'S') {
|
if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'B' || sig_type == 'C' || sig_type == 'S') {
|
||||||
// 'I' instructions are used for byte, char, short and int.
|
// 'I' instructions are used for byte, char, short and int.
|
||||||
// determine which it really is, and convert
|
// determine which it really is, and convert
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
|
|
|
@ -133,13 +133,22 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
|
||||||
|
|
||||||
///// Data in the Java heap.
|
///// Data in the Java heap.
|
||||||
|
|
||||||
|
#define truncate_jboolean(x) ((x) & 1)
|
||||||
|
#define truncate_jbyte(x) (x)
|
||||||
|
#define truncate_jshort(x) (x)
|
||||||
|
#define truncate_jchar(x) (x)
|
||||||
|
#define truncate_jint(x) (x)
|
||||||
|
#define truncate_jlong(x) (x)
|
||||||
|
#define truncate_jfloat(x) (x)
|
||||||
|
#define truncate_jdouble(x) (x)
|
||||||
|
|
||||||
#define GET_FIELD(obj, offset, type_name, v) \
|
#define GET_FIELD(obj, offset, type_name, v) \
|
||||||
oop p = JNIHandles::resolve(obj); \
|
oop p = JNIHandles::resolve(obj); \
|
||||||
type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset)
|
type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset)
|
||||||
|
|
||||||
#define SET_FIELD(obj, offset, type_name, x) \
|
#define SET_FIELD(obj, offset, type_name, x) \
|
||||||
oop p = JNIHandles::resolve(obj); \
|
oop p = JNIHandles::resolve(obj); \
|
||||||
*(type_name*)index_oop_from_field_offset_long(p, offset) = x
|
*(type_name*)index_oop_from_field_offset_long(p, offset) = truncate_##type_name(x)
|
||||||
|
|
||||||
#define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
|
#define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
|
||||||
oop p = JNIHandles::resolve(obj); \
|
oop p = JNIHandles::resolve(obj); \
|
||||||
|
@ -150,7 +159,7 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
|
||||||
|
|
||||||
#define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
|
#define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
|
||||||
oop p = JNIHandles::resolve(obj); \
|
oop p = JNIHandles::resolve(obj); \
|
||||||
OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x);
|
OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), truncate_##type_name(x));
|
||||||
|
|
||||||
|
|
||||||
// Get/SetObject must be special-cased, since it works with handles.
|
// Get/SetObject must be special-cased, since it works with handles.
|
||||||
|
|
|
@ -1025,7 +1025,7 @@ static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS) {
|
||||||
static void narrow(jvalue* value, BasicType narrow_type, TRAPS) {
|
static void narrow(jvalue* value, BasicType narrow_type, TRAPS) {
|
||||||
switch (narrow_type) {
|
switch (narrow_type) {
|
||||||
case T_BOOLEAN:
|
case T_BOOLEAN:
|
||||||
value->z = (jboolean)value->i;
|
value->z = (jboolean) (value->i & 1);
|
||||||
return;
|
return;
|
||||||
case T_BYTE:
|
case T_BYTE:
|
||||||
value->b = (jbyte)value->i;
|
value->b = (jbyte)value->i;
|
||||||
|
|
|
@ -846,14 +846,15 @@ class JavaValue {
|
||||||
|
|
||||||
enum TosState { // describes the tos cache contents
|
enum TosState { // describes the tos cache contents
|
||||||
btos = 0, // byte, bool tos cached
|
btos = 0, // byte, bool tos cached
|
||||||
ctos = 1, // char tos cached
|
ztos = 1, // byte, bool tos cached
|
||||||
stos = 2, // short tos cached
|
ctos = 2, // char tos cached
|
||||||
itos = 3, // int tos cached
|
stos = 3, // short tos cached
|
||||||
ltos = 4, // long tos cached
|
itos = 4, // int tos cached
|
||||||
ftos = 5, // float tos cached
|
ltos = 5, // long tos cached
|
||||||
dtos = 6, // double tos cached
|
ftos = 6, // float tos cached
|
||||||
atos = 7, // object cached
|
dtos = 7, // double tos cached
|
||||||
vtos = 8, // tos not cached
|
atos = 8, // object cached
|
||||||
|
vtos = 9, // tos not cached
|
||||||
number_of_states,
|
number_of_states,
|
||||||
ilgl // illegal state: should not occur
|
ilgl // illegal state: should not occur
|
||||||
};
|
};
|
||||||
|
@ -862,7 +863,7 @@ enum TosState { // describes the tos cache contents
|
||||||
inline TosState as_TosState(BasicType type) {
|
inline TosState as_TosState(BasicType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case T_BYTE : return btos;
|
case T_BYTE : return btos;
|
||||||
case T_BOOLEAN: return btos; // FIXME: Add ztos
|
case T_BOOLEAN: return ztos;
|
||||||
case T_CHAR : return ctos;
|
case T_CHAR : return ctos;
|
||||||
case T_SHORT : return stos;
|
case T_SHORT : return stos;
|
||||||
case T_INT : return itos;
|
case T_INT : return itos;
|
||||||
|
@ -878,8 +879,8 @@ inline TosState as_TosState(BasicType type) {
|
||||||
|
|
||||||
inline BasicType as_BasicType(TosState state) {
|
inline BasicType as_BasicType(TosState state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
//case ztos: return T_BOOLEAN;//FIXME
|
|
||||||
case btos : return T_BYTE;
|
case btos : return T_BYTE;
|
||||||
|
case ztos : return T_BOOLEAN;
|
||||||
case ctos : return T_CHAR;
|
case ctos : return T_CHAR;
|
||||||
case stos : return T_SHORT;
|
case stos : return T_SHORT;
|
||||||
case itos : return T_INT;
|
case itos : return T_INT;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue