Merge
This commit is contained in:
commit
0772441e15
@ -486,7 +486,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
|||||||
if (ek == _invokespecial_mh) {
|
if (ek == _invokespecial_mh) {
|
||||||
// Must load & check the first argument before entering the target method.
|
// Must load & check the first argument before entering the target method.
|
||||||
__ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch);
|
__ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch);
|
||||||
__ ld_ptr(__ argument_address(O0_argslot), G3_method_handle);
|
__ ld_ptr(__ argument_address(O0_argslot, -1), G3_method_handle);
|
||||||
__ null_check(G3_method_handle);
|
__ null_check(G3_method_handle);
|
||||||
__ verify_oop(G3_method_handle);
|
__ verify_oop(G3_method_handle);
|
||||||
}
|
}
|
||||||
|
@ -3293,8 +3293,6 @@ void TemplateTable::invokedynamic(int byte_no) {
|
|||||||
/*virtual*/ false, /*vfinal*/ false, /*indy*/ true);
|
/*virtual*/ false, /*vfinal*/ false, /*indy*/ true);
|
||||||
__ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
|
__ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
|
||||||
|
|
||||||
__ verify_oop(G5_callsite);
|
|
||||||
|
|
||||||
// profile this call
|
// profile this call
|
||||||
__ profile_call(O4);
|
__ profile_call(O4);
|
||||||
|
|
||||||
@ -3307,8 +3305,10 @@ void TemplateTable::invokedynamic(int byte_no) {
|
|||||||
__ sll(Rret, LogBytesPerWord, Rret);
|
__ sll(Rret, LogBytesPerWord, Rret);
|
||||||
__ ld_ptr(Rtemp, Rret, Rret); // get return address
|
__ ld_ptr(Rtemp, Rret, Rret); // get return address
|
||||||
|
|
||||||
|
__ verify_oop(G5_callsite);
|
||||||
__ load_heap_oop(G5_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, Rscratch), G3_method_handle);
|
__ load_heap_oop(G5_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, Rscratch), G3_method_handle);
|
||||||
__ null_check(G3_method_handle);
|
__ null_check(G3_method_handle);
|
||||||
|
__ verify_oop(G3_method_handle);
|
||||||
|
|
||||||
// Adjust Rret first so Llast_SP can be same as Rret
|
// Adjust Rret first so Llast_SP can be same as Rret
|
||||||
__ add(Rret, -frame::pc_return_offset, O7);
|
__ add(Rret, -frame::pc_return_offset, O7);
|
||||||
|
@ -422,7 +422,7 @@ void TemplateTable::fast_aldc(bool wide) {
|
|||||||
|
|
||||||
Label L_done, L_throw_exception;
|
Label L_done, L_throw_exception;
|
||||||
const Register con_klass_temp = rcx; // same as Rcache
|
const Register con_klass_temp = rcx; // same as Rcache
|
||||||
__ movptr(con_klass_temp, Address(rax, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(con_klass_temp, rax);
|
||||||
__ cmpptr(con_klass_temp, ExternalAddress((address)Universe::systemObjArrayKlassObj_addr()));
|
__ cmpptr(con_klass_temp, ExternalAddress((address)Universe::systemObjArrayKlassObj_addr()));
|
||||||
__ jcc(Assembler::notEqual, L_done);
|
__ jcc(Assembler::notEqual, L_done);
|
||||||
__ cmpl(Address(rax, arrayOopDesc::length_offset_in_bytes()), 0);
|
__ cmpl(Address(rax, arrayOopDesc::length_offset_in_bytes()), 0);
|
||||||
@ -432,7 +432,7 @@ void TemplateTable::fast_aldc(bool wide) {
|
|||||||
|
|
||||||
// Load the exception from the system-array which wraps it:
|
// Load the exception from the system-array which wraps it:
|
||||||
__ bind(L_throw_exception);
|
__ bind(L_throw_exception);
|
||||||
__ movptr(rax, Address(rax, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
__ load_heap_oop(rax, Address(rax, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
||||||
__ jump(ExternalAddress(Interpreter::throw_exception_entry()));
|
__ jump(ExternalAddress(Interpreter::throw_exception_entry()));
|
||||||
|
|
||||||
__ bind(L_done);
|
__ bind(L_done);
|
||||||
@ -946,9 +946,9 @@ void TemplateTable::aastore() {
|
|||||||
__ jcc(Assembler::zero, is_null);
|
__ jcc(Assembler::zero, is_null);
|
||||||
|
|
||||||
// Move subklass into EBX
|
// Move subklass into EBX
|
||||||
__ movptr(rbx, Address(rax, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(rbx, rax);
|
||||||
// Move superklass into EAX
|
// Move superklass into EAX
|
||||||
__ movptr(rax, Address(rdx, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(rax, rdx);
|
||||||
__ movptr(rax, Address(rax, sizeof(oopDesc) + objArrayKlass::element_klass_offset_in_bytes()));
|
__ movptr(rax, Address(rax, sizeof(oopDesc) + objArrayKlass::element_klass_offset_in_bytes()));
|
||||||
// Compress array+index*wordSize+12 into a single register. Frees ECX.
|
// Compress array+index*wordSize+12 into a single register. Frees ECX.
|
||||||
__ lea(rdx, element_address);
|
__ lea(rdx, element_address);
|
||||||
@ -2001,7 +2001,7 @@ void TemplateTable::_return(TosState state) {
|
|||||||
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");
|
||||||
__ movptr(rax, aaddress(0));
|
__ movptr(rax, aaddress(0));
|
||||||
__ movptr(rdi, Address(rax, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(rdi, rax);
|
||||||
__ movl(rdi, Address(rdi, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc)));
|
__ movl(rdi, Address(rdi, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc)));
|
||||||
__ testl(rdi, JVM_ACC_HAS_FINALIZER);
|
__ testl(rdi, JVM_ACC_HAS_FINALIZER);
|
||||||
Label skip_register_finalizer;
|
Label skip_register_finalizer;
|
||||||
@ -2948,7 +2948,7 @@ void TemplateTable::invokevirtual_helper(Register index, Register recv,
|
|||||||
// get receiver klass
|
// get receiver klass
|
||||||
__ null_check(recv, oopDesc::klass_offset_in_bytes());
|
__ null_check(recv, oopDesc::klass_offset_in_bytes());
|
||||||
// Keep recv in rcx for callee expects it there
|
// Keep recv in rcx for callee expects it there
|
||||||
__ movptr(rax, Address(recv, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(rax, recv);
|
||||||
__ verify_oop(rax);
|
__ verify_oop(rax);
|
||||||
|
|
||||||
// profile this call
|
// profile this call
|
||||||
@ -3028,7 +3028,7 @@ void TemplateTable::invokeinterface(int byte_no) {
|
|||||||
|
|
||||||
// Get receiver klass into rdx - also a null check
|
// Get receiver klass into rdx - also a null check
|
||||||
__ restore_locals(); // restore rdi
|
__ restore_locals(); // restore rdi
|
||||||
__ movptr(rdx, Address(rcx, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(rdx, rcx);
|
||||||
__ verify_oop(rdx);
|
__ verify_oop(rdx);
|
||||||
|
|
||||||
// profile this call
|
// profile this call
|
||||||
@ -3083,6 +3083,7 @@ void TemplateTable::invokeinterface(int byte_no) {
|
|||||||
|
|
||||||
void TemplateTable::invokedynamic(int byte_no) {
|
void TemplateTable::invokedynamic(int byte_no) {
|
||||||
transition(vtos, vtos);
|
transition(vtos, vtos);
|
||||||
|
assert(byte_no == f1_oop, "use this argument");
|
||||||
|
|
||||||
if (!EnableInvokeDynamic) {
|
if (!EnableInvokeDynamic) {
|
||||||
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
||||||
@ -3095,7 +3096,6 @@ void TemplateTable::invokedynamic(int byte_no) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(byte_no == f1_oop, "use this argument");
|
|
||||||
prepare_invoke(rax, rbx, byte_no);
|
prepare_invoke(rax, rbx, byte_no);
|
||||||
|
|
||||||
// rax: CallSite object (f1)
|
// rax: CallSite object (f1)
|
||||||
@ -3106,14 +3106,14 @@ void TemplateTable::invokedynamic(int byte_no) {
|
|||||||
Register rax_callsite = rax;
|
Register rax_callsite = rax;
|
||||||
Register rcx_method_handle = rcx;
|
Register rcx_method_handle = rcx;
|
||||||
|
|
||||||
if (ProfileInterpreter) {
|
|
||||||
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
||||||
// profile this call
|
// profile this call
|
||||||
__ profile_call(rsi);
|
__ profile_call(rsi);
|
||||||
}
|
|
||||||
|
|
||||||
__ movptr(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rcx)));
|
__ verify_oop(rax_callsite);
|
||||||
|
__ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rdx)));
|
||||||
__ null_check(rcx_method_handle);
|
__ null_check(rcx_method_handle);
|
||||||
|
__ verify_oop(rcx_method_handle);
|
||||||
__ prepare_to_jump_from_interpreted();
|
__ prepare_to_jump_from_interpreted();
|
||||||
__ jump_to_method_handle_entry(rcx_method_handle, rdx);
|
__ jump_to_method_handle_entry(rcx_method_handle, rdx);
|
||||||
}
|
}
|
||||||
@ -3258,7 +3258,7 @@ void TemplateTable::_new() {
|
|||||||
(int32_t)markOopDesc::prototype()); // header
|
(int32_t)markOopDesc::prototype()); // header
|
||||||
__ pop(rcx); // get saved klass back in the register.
|
__ pop(rcx); // get saved klass back in the register.
|
||||||
}
|
}
|
||||||
__ movptr(Address(rax, oopDesc::klass_offset_in_bytes()), rcx); // klass
|
__ store_klass(rax, rcx); // klass
|
||||||
|
|
||||||
{
|
{
|
||||||
SkipIfEqual skip_if(_masm, &DTraceAllocProbes, 0);
|
SkipIfEqual skip_if(_masm, &DTraceAllocProbes, 0);
|
||||||
@ -3333,7 +3333,7 @@ void TemplateTable::checkcast() {
|
|||||||
__ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(constantPoolOopDesc)));
|
__ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(constantPoolOopDesc)));
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
__ movptr(rbx, Address(rdx, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(rbx, rdx);
|
||||||
|
|
||||||
// Generate subtype check. Blows ECX. Resets EDI. Object in EDX.
|
// Generate subtype check. Blows ECX. Resets EDI. Object in EDX.
|
||||||
// Superklass in EAX. Subklass in EBX.
|
// Superklass in EAX. Subklass in EBX.
|
||||||
@ -3376,12 +3376,12 @@ void TemplateTable::instanceof() {
|
|||||||
__ push(atos);
|
__ push(atos);
|
||||||
call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
|
call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
|
||||||
__ pop_ptr(rdx);
|
__ pop_ptr(rdx);
|
||||||
__ movptr(rdx, Address(rdx, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(rdx, rdx);
|
||||||
__ jmp(resolved);
|
__ jmp(resolved);
|
||||||
|
|
||||||
// Get superklass in EAX and subklass in EDX
|
// Get superklass in EAX and subklass in EDX
|
||||||
__ bind(quicked);
|
__ bind(quicked);
|
||||||
__ movptr(rdx, Address(rax, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(rdx, rax);
|
||||||
__ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(constantPoolOopDesc)));
|
__ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(constantPoolOopDesc)));
|
||||||
|
|
||||||
__ bind(resolved);
|
__ bind(resolved);
|
||||||
|
@ -436,7 +436,7 @@ void TemplateTable::fast_aldc(bool wide) {
|
|||||||
Label L_done, L_throw_exception;
|
Label L_done, L_throw_exception;
|
||||||
const Register con_klass_temp = rcx; // same as cache
|
const Register con_klass_temp = rcx; // same as cache
|
||||||
const Register array_klass_temp = rdx; // same as index
|
const Register array_klass_temp = rdx; // same as index
|
||||||
__ movptr(con_klass_temp, Address(rax, oopDesc::klass_offset_in_bytes()));
|
__ load_klass(con_klass_temp, rax);
|
||||||
__ lea(array_klass_temp, ExternalAddress((address)Universe::systemObjArrayKlassObj_addr()));
|
__ lea(array_klass_temp, ExternalAddress((address)Universe::systemObjArrayKlassObj_addr()));
|
||||||
__ cmpptr(con_klass_temp, Address(array_klass_temp, 0));
|
__ cmpptr(con_klass_temp, Address(array_klass_temp, 0));
|
||||||
__ jcc(Assembler::notEqual, L_done);
|
__ jcc(Assembler::notEqual, L_done);
|
||||||
@ -447,7 +447,7 @@ void TemplateTable::fast_aldc(bool wide) {
|
|||||||
|
|
||||||
// Load the exception from the system-array which wraps it:
|
// Load the exception from the system-array which wraps it:
|
||||||
__ bind(L_throw_exception);
|
__ bind(L_throw_exception);
|
||||||
__ movptr(rax, Address(rax, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
__ load_heap_oop(rax, Address(rax, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
|
||||||
__ jump(ExternalAddress(Interpreter::throw_exception_entry()));
|
__ jump(ExternalAddress(Interpreter::throw_exception_entry()));
|
||||||
|
|
||||||
__ bind(L_done);
|
__ bind(L_done);
|
||||||
@ -3137,7 +3137,6 @@ void TemplateTable::invokedynamic(int byte_no) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(byte_no == f1_oop, "use this argument");
|
|
||||||
prepare_invoke(rax, rbx, byte_no);
|
prepare_invoke(rax, rbx, byte_no);
|
||||||
|
|
||||||
// rax: CallSite object (f1)
|
// rax: CallSite object (f1)
|
||||||
@ -3148,14 +3147,14 @@ void TemplateTable::invokedynamic(int byte_no) {
|
|||||||
Register rax_callsite = rax;
|
Register rax_callsite = rax;
|
||||||
Register rcx_method_handle = rcx;
|
Register rcx_method_handle = rcx;
|
||||||
|
|
||||||
if (ProfileInterpreter) {
|
|
||||||
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
||||||
// profile this call
|
// profile this call
|
||||||
__ profile_call(r13);
|
__ profile_call(r13);
|
||||||
}
|
|
||||||
|
|
||||||
__ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rcx)));
|
__ verify_oop(rax_callsite);
|
||||||
|
__ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rdx)));
|
||||||
__ null_check(rcx_method_handle);
|
__ null_check(rcx_method_handle);
|
||||||
|
__ verify_oop(rcx_method_handle);
|
||||||
__ prepare_to_jump_from_interpreted();
|
__ prepare_to_jump_from_interpreted();
|
||||||
__ jump_to_method_handle_entry(rcx_method_handle, rdx);
|
__ jump_to_method_handle_entry(rcx_method_handle, rdx);
|
||||||
}
|
}
|
||||||
|
@ -441,12 +441,25 @@ void VM_Version::get_processor_features() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// On family 21 processors default is no sw prefetch
|
// some defaults for AMD family 15h
|
||||||
if ( cpu_family() == 21 ) {
|
if ( cpu_family() == 0x15 ) {
|
||||||
|
// On family 15h processors default is no sw prefetch
|
||||||
if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
|
if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
|
||||||
AllocatePrefetchStyle = 0;
|
AllocatePrefetchStyle = 0;
|
||||||
}
|
}
|
||||||
|
// Also, if some other prefetch style is specified, default instruction type is PREFETCHW
|
||||||
|
if (FLAG_IS_DEFAULT(AllocatePrefetchInstr)) {
|
||||||
|
AllocatePrefetchInstr = 3;
|
||||||
}
|
}
|
||||||
|
// On family 15h processors use XMM and UnalignedLoadStores for Array Copy
|
||||||
|
if( FLAG_IS_DEFAULT(UseXMMForArrayCopy) ) {
|
||||||
|
UseXMMForArrayCopy = true;
|
||||||
|
}
|
||||||
|
if( FLAG_IS_DEFAULT(UseUnalignedLoadStores) && UseXMMForArrayCopy ) {
|
||||||
|
UseUnalignedLoadStores = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( is_intel() ) { // Intel cpus specific settings
|
if( is_intel() ) { // Intel cpus specific settings
|
||||||
|
@ -232,14 +232,7 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute size of arguments
|
// compute size of arguments
|
||||||
int arg_size = target->arg_size();
|
int arg_size = target->invoke_arg_size(code);
|
||||||
if (code == Bytecodes::_invokedynamic) {
|
|
||||||
assert(!target->is_static(), "receiver explicit in method");
|
|
||||||
arg_size--; // implicit, not really on stack
|
|
||||||
}
|
|
||||||
if (!target->is_loaded() && code == Bytecodes::_invokestatic) {
|
|
||||||
arg_size--;
|
|
||||||
}
|
|
||||||
int arg_base = MAX2(state._stack_height - arg_size, 0);
|
int arg_base = MAX2(state._stack_height - arg_size, 0);
|
||||||
|
|
||||||
// direct recursive calls are skipped if they can be bound statically without introducing
|
// direct recursive calls are skipped if they can be bound statically without introducing
|
||||||
|
@ -756,7 +756,7 @@ ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
|||||||
assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
|
assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
|
||||||
|
|
||||||
bool is_resolved = cpool->cache()->main_entry_at(index)->is_resolved(bc);
|
bool is_resolved = cpool->cache()->main_entry_at(index)->is_resolved(bc);
|
||||||
if (is_resolved && (oop) cpool->cache()->secondary_entry_at(index)->f1() == NULL)
|
if (is_resolved && cpool->cache()->secondary_entry_at(index)->is_f1_null())
|
||||||
// FIXME: code generation could allow for null (unlinked) call site
|
// FIXME: code generation could allow for null (unlinked) call site
|
||||||
is_resolved = false;
|
is_resolved = false;
|
||||||
|
|
||||||
@ -770,7 +770,7 @@ ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
|||||||
|
|
||||||
// Get the invoker methodOop from the constant pool.
|
// Get the invoker methodOop from the constant pool.
|
||||||
oop f1_value = cpool->cache()->main_entry_at(index)->f1();
|
oop f1_value = cpool->cache()->main_entry_at(index)->f1();
|
||||||
methodOop signature_invoker = methodOop(f1_value);
|
methodOop signature_invoker = (methodOop) f1_value;
|
||||||
assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
|
assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
|
||||||
"correct result from LinkResolver::resolve_invokedynamic");
|
"correct result from LinkResolver::resolve_invokedynamic");
|
||||||
|
|
||||||
|
@ -127,7 +127,24 @@ class ciMethod : public ciObject {
|
|||||||
ciSignature* signature() const { return _signature; }
|
ciSignature* signature() const { return _signature; }
|
||||||
ciType* return_type() const { return _signature->return_type(); }
|
ciType* return_type() const { return _signature->return_type(); }
|
||||||
int arg_size_no_receiver() const { return _signature->size(); }
|
int arg_size_no_receiver() const { return _signature->size(); }
|
||||||
int arg_size() const { return _signature->size() + (_flags.is_static() ? 0 : 1); }
|
// Can only be used on loaded ciMethods
|
||||||
|
int arg_size() const {
|
||||||
|
check_is_loaded();
|
||||||
|
return _signature->size() + (_flags.is_static() ? 0 : 1);
|
||||||
|
}
|
||||||
|
// Report the number of elements on stack when invoking this method.
|
||||||
|
// This is different than the regular arg_size because invokdynamic
|
||||||
|
// has an implicit receiver.
|
||||||
|
int invoke_arg_size(Bytecodes::Code code) const {
|
||||||
|
int arg_size = _signature->size();
|
||||||
|
// Add a receiver argument, maybe:
|
||||||
|
if (code != Bytecodes::_invokestatic &&
|
||||||
|
code != Bytecodes::_invokedynamic) {
|
||||||
|
arg_size++;
|
||||||
|
}
|
||||||
|
return arg_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Method code and related information.
|
// Method code and related information.
|
||||||
address code() { if (_code == NULL) load_code(); return _code; }
|
address code() { if (_code == NULL) load_code(); return _code; }
|
||||||
@ -276,9 +293,9 @@ class ciMethod : public ciObject {
|
|||||||
void print_short_name(outputStream* st = tty);
|
void print_short_name(outputStream* st = tty);
|
||||||
|
|
||||||
methodOop get_method_handle_target() {
|
methodOop get_method_handle_target() {
|
||||||
klassOop receiver_limit_oop = NULL;
|
KlassHandle receiver_limit; int flags = 0;
|
||||||
int flags = 0;
|
methodHandle m = MethodHandles::decode_method(get_oop(), receiver_limit, flags);
|
||||||
return MethodHandles::decode_method(get_oop(), receiver_limit_oop, flags);
|
return m();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -194,6 +194,16 @@ bool ciObject::can_be_constant() {
|
|||||||
// ciObject::should_be_constant()
|
// ciObject::should_be_constant()
|
||||||
bool ciObject::should_be_constant() {
|
bool ciObject::should_be_constant() {
|
||||||
if (ScavengeRootsInCode >= 2) return true; // force everybody to be a constant
|
if (ScavengeRootsInCode >= 2) return true; // force everybody to be a constant
|
||||||
|
if (!JavaObjectsInPerm && !is_null_object()) {
|
||||||
|
// We want Strings and Classes to be embeddable by default since
|
||||||
|
// they used to be in the perm world. Not all Strings used to be
|
||||||
|
// embeddable but there's no easy way to distinguish the interned
|
||||||
|
// from the regulars ones so just treat them all that way.
|
||||||
|
ciEnv* env = CURRENT_ENV;
|
||||||
|
if (klass() == env->String_klass() || klass() == env->Class_klass()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return handle() == NULL || !is_scavengable();
|
return handle() == NULL || !is_scavengable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2011, 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
|
||||||
@ -175,7 +175,7 @@ class VerifyOopClosure: public OopClosure {
|
|||||||
protected:
|
protected:
|
||||||
template <class T> inline void do_oop_work(T* p) {
|
template <class T> inline void do_oop_work(T* p) {
|
||||||
oop obj = oopDesc::load_decode_heap_oop(p);
|
oop obj = oopDesc::load_decode_heap_oop(p);
|
||||||
guarantee(obj->is_oop_or_null(), "invalid oop");
|
guarantee(obj->is_oop_or_null(), err_msg("invalid oop: " INTPTR_FORMAT, obj));
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
virtual void do_oop(oop* p);
|
virtual void do_oop(oop* p);
|
||||||
|
@ -104,7 +104,7 @@ void ConstantPoolCacheEntry::set_f1_if_null_atomic(oop f1) {
|
|||||||
void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL);
|
void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL);
|
||||||
bool success = (result == NULL);
|
bool success = (result == NULL);
|
||||||
if (success) {
|
if (success) {
|
||||||
update_barrier_set(f1_addr, f1);
|
update_barrier_set((void*) f1_addr, f1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,21 +275,23 @@ int ConstantPoolCacheEntry::bootstrap_method_index_in_cache() {
|
|||||||
return (int) bsm_cache_index;
|
return (int) bsm_cache_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site,
|
void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, methodHandle signature_invoker) {
|
||||||
methodHandle signature_invoker) {
|
|
||||||
assert(is_secondary_entry(), "");
|
assert(is_secondary_entry(), "");
|
||||||
|
// NOTE: it's important that all other values are set before f1 is
|
||||||
|
// set since some users short circuit on f1 being set
|
||||||
|
// (i.e. non-null) and that may result in uninitialized values for
|
||||||
|
// other racing threads (e.g. flags).
|
||||||
int param_size = signature_invoker->size_of_parameters();
|
int param_size = signature_invoker->size_of_parameters();
|
||||||
assert(param_size >= 1, "method argument size must include MH.this");
|
assert(param_size >= 1, "method argument size must include MH.this");
|
||||||
param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic
|
param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic
|
||||||
if (Atomic::cmpxchg_ptr(call_site(), &_f1, NULL) == NULL) {
|
|
||||||
// racing threads might be trying to install their own favorites
|
|
||||||
set_f1(call_site());
|
|
||||||
}
|
|
||||||
bool is_final = true;
|
bool is_final = true;
|
||||||
assert(signature_invoker->is_final_method(), "is_final");
|
assert(signature_invoker->is_final_method(), "is_final");
|
||||||
set_flags(as_flags(as_TosState(signature_invoker->result_type()), is_final, false, false, false, true) | param_size);
|
int flags = as_flags(as_TosState(signature_invoker->result_type()), is_final, false, false, false, true) | param_size;
|
||||||
|
assert(_flags == 0 || _flags == flags, "flags should be the same");
|
||||||
|
set_flags(flags);
|
||||||
// do not do set_bytecode on a secondary CP cache entry
|
// do not do set_bytecode on a secondary CP cache entry
|
||||||
//set_bytecode_1(Bytecodes::_invokedynamic);
|
//set_bytecode_1(Bytecodes::_invokedynamic);
|
||||||
|
set_f1_if_null_atomic(call_site()); // This must be the last one to set (see NOTE above)!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1437,7 +1437,10 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
|
|||||||
|
|
||||||
// Update the memory inputs of MemNodes with the value we computed
|
// Update the memory inputs of MemNodes with the value we computed
|
||||||
// in Phase 2 and move stores memory users to corresponding memory slices.
|
// in Phase 2 and move stores memory users to corresponding memory slices.
|
||||||
#ifdef ASSERT
|
|
||||||
|
// Disable memory split verification code until the fix for 6984348.
|
||||||
|
// Currently it produces false negative results since it does not cover all cases.
|
||||||
|
#if 0 // ifdef ASSERT
|
||||||
visited.Reset();
|
visited.Reset();
|
||||||
Node_Stack old_mems(arena, _compile->unique() >> 2);
|
Node_Stack old_mems(arena, _compile->unique() >> 2);
|
||||||
#endif
|
#endif
|
||||||
@ -1447,7 +1450,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
|
|||||||
Node *n = ptnode_adr(i)->_node;
|
Node *n = ptnode_adr(i)->_node;
|
||||||
assert(n != NULL, "sanity");
|
assert(n != NULL, "sanity");
|
||||||
if (n->is_Mem()) {
|
if (n->is_Mem()) {
|
||||||
#ifdef ASSERT
|
#if 0 // ifdef ASSERT
|
||||||
Node* old_mem = n->in(MemNode::Memory);
|
Node* old_mem = n->in(MemNode::Memory);
|
||||||
if (!visited.test_set(old_mem->_idx)) {
|
if (!visited.test_set(old_mem->_idx)) {
|
||||||
old_mems.push(old_mem, old_mem->outcnt());
|
old_mems.push(old_mem, old_mem->outcnt());
|
||||||
@ -1469,13 +1472,13 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef ASSERT
|
#if 0 // ifdef ASSERT
|
||||||
// Verify that memory was split correctly
|
// Verify that memory was split correctly
|
||||||
while (old_mems.is_nonempty()) {
|
while (old_mems.is_nonempty()) {
|
||||||
Node* old_mem = old_mems.node();
|
Node* old_mem = old_mems.node();
|
||||||
uint old_cnt = old_mems.index();
|
uint old_cnt = old_mems.index();
|
||||||
old_mems.pop();
|
old_mems.pop();
|
||||||
assert(old_cnt = old_mem->outcnt(), "old mem could be lost");
|
assert(old_cnt == old_mem->outcnt(), "old mem could be lost");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1033,14 +1033,10 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth) {
|
|||||||
iter.reset_to_bci(bci());
|
iter.reset_to_bci(bci());
|
||||||
iter.next();
|
iter.next();
|
||||||
ciMethod* method = iter.get_method(ignore);
|
ciMethod* method = iter.get_method(ignore);
|
||||||
inputs = method->arg_size_no_receiver();
|
|
||||||
// Add a receiver argument, maybe:
|
|
||||||
if (code != Bytecodes::_invokestatic &&
|
|
||||||
code != Bytecodes::_invokedynamic)
|
|
||||||
inputs += 1;
|
|
||||||
// (Do not use ciMethod::arg_size(), because
|
// (Do not use ciMethod::arg_size(), because
|
||||||
// it might be an unloaded method, which doesn't
|
// it might be an unloaded method, which doesn't
|
||||||
// know whether it is static or not.)
|
// know whether it is static or not.)
|
||||||
|
inputs = method->invoke_arg_size(code);
|
||||||
int size = method->return_type()->size();
|
int size = method->return_type()->size();
|
||||||
depth = size - inputs;
|
depth = size - inputs;
|
||||||
}
|
}
|
||||||
@ -2957,8 +2953,7 @@ static void hook_memory_on_init(GraphKit& kit, int alias_idx,
|
|||||||
|
|
||||||
//---------------------------set_output_for_allocation-------------------------
|
//---------------------------set_output_for_allocation-------------------------
|
||||||
Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
||||||
const TypeOopPtr* oop_type,
|
const TypeOopPtr* oop_type) {
|
||||||
bool raw_mem_only) {
|
|
||||||
int rawidx = Compile::AliasIdxRaw;
|
int rawidx = Compile::AliasIdxRaw;
|
||||||
alloc->set_req( TypeFunc::FramePtr, frameptr() );
|
alloc->set_req( TypeFunc::FramePtr, frameptr() );
|
||||||
add_safepoint_edges(alloc);
|
add_safepoint_edges(alloc);
|
||||||
@ -2982,7 +2977,7 @@ Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
|||||||
rawoop)->as_Initialize();
|
rawoop)->as_Initialize();
|
||||||
assert(alloc->initialization() == init, "2-way macro link must work");
|
assert(alloc->initialization() == init, "2-way macro link must work");
|
||||||
assert(init ->allocation() == alloc, "2-way macro link must work");
|
assert(init ->allocation() == alloc, "2-way macro link must work");
|
||||||
if (ReduceFieldZeroing && !raw_mem_only) {
|
{
|
||||||
// Extract memory strands which may participate in the new object's
|
// Extract memory strands which may participate in the new object's
|
||||||
// initialization, and source them from the new InitializeNode.
|
// initialization, and source them from the new InitializeNode.
|
||||||
// This will allow us to observe initializations when they occur,
|
// This will allow us to observe initializations when they occur,
|
||||||
@ -3043,11 +3038,9 @@ Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
|||||||
// the type to a constant.
|
// the type to a constant.
|
||||||
// The optional arguments are for specialized use by intrinsics:
|
// The optional arguments are for specialized use by intrinsics:
|
||||||
// - If 'extra_slow_test' if not null is an extra condition for the slow-path.
|
// - If 'extra_slow_test' if not null is an extra condition for the slow-path.
|
||||||
// - If 'raw_mem_only', do not cast the result to an oop.
|
|
||||||
// - If 'return_size_val', report the the total object size to the caller.
|
// - If 'return_size_val', report the the total object size to the caller.
|
||||||
Node* GraphKit::new_instance(Node* klass_node,
|
Node* GraphKit::new_instance(Node* klass_node,
|
||||||
Node* extra_slow_test,
|
Node* extra_slow_test,
|
||||||
bool raw_mem_only, // affect only raw memory
|
|
||||||
Node* *return_size_val) {
|
Node* *return_size_val) {
|
||||||
// Compute size in doublewords
|
// Compute size in doublewords
|
||||||
// The size is always an integral number of doublewords, represented
|
// The size is always an integral number of doublewords, represented
|
||||||
@ -3118,7 +3111,7 @@ Node* GraphKit::new_instance(Node* klass_node,
|
|||||||
size, klass_node,
|
size, klass_node,
|
||||||
initial_slow_test);
|
initial_slow_test);
|
||||||
|
|
||||||
return set_output_for_allocation(alloc, oop_type, raw_mem_only);
|
return set_output_for_allocation(alloc, oop_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------new_array-------------------------------------
|
//-------------------------------new_array-------------------------------------
|
||||||
@ -3128,7 +3121,6 @@ Node* GraphKit::new_instance(Node* klass_node,
|
|||||||
Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
||||||
Node* length, // number of array elements
|
Node* length, // number of array elements
|
||||||
int nargs, // number of arguments to push back for uncommon trap
|
int nargs, // number of arguments to push back for uncommon trap
|
||||||
bool raw_mem_only, // affect only raw memory
|
|
||||||
Node* *return_size_val) {
|
Node* *return_size_val) {
|
||||||
jint layout_con = Klass::_lh_neutral_value;
|
jint layout_con = Klass::_lh_neutral_value;
|
||||||
Node* layout_val = get_layout_helper(klass_node, layout_con);
|
Node* layout_val = get_layout_helper(klass_node, layout_con);
|
||||||
@ -3273,7 +3265,7 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
|||||||
ary_type = ary_type->is_aryptr()->cast_to_size(length_type);
|
ary_type = ary_type->is_aryptr()->cast_to_size(length_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* javaoop = set_output_for_allocation(alloc, ary_type, raw_mem_only);
|
Node* javaoop = set_output_for_allocation(alloc, ary_type);
|
||||||
|
|
||||||
// Cast length on remaining path to be as narrow as possible
|
// Cast length on remaining path to be as narrow as possible
|
||||||
if (map()->find_edge(length) >= 0) {
|
if (map()->find_edge(length) >= 0) {
|
||||||
@ -3462,9 +3454,22 @@ void GraphKit::write_barrier_post(Node* oop_store,
|
|||||||
|
|
||||||
// Get the alias_index for raw card-mark memory
|
// Get the alias_index for raw card-mark memory
|
||||||
int adr_type = Compile::AliasIdxRaw;
|
int adr_type = Compile::AliasIdxRaw;
|
||||||
// Smash zero into card
|
Node* zero = __ ConI(0); // Dirty card value
|
||||||
Node* zero = __ ConI(0);
|
|
||||||
BasicType bt = T_BYTE;
|
BasicType bt = T_BYTE;
|
||||||
|
|
||||||
|
if (UseCondCardMark) {
|
||||||
|
// The classic GC reference write barrier is typically implemented
|
||||||
|
// as a store into the global card mark table. Unfortunately
|
||||||
|
// unconditional stores can result in false sharing and excessive
|
||||||
|
// coherence traffic as well as false transactional aborts.
|
||||||
|
// UseCondCardMark enables MP "polite" conditional card mark
|
||||||
|
// stores. In theory we could relax the load from ctrl() to
|
||||||
|
// no_ctrl, but that doesn't buy much latitude.
|
||||||
|
Node* card_val = __ load( __ ctrl(), card_adr, TypeInt::BYTE, bt, adr_type);
|
||||||
|
__ if_then(card_val, BoolTest::ne, zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smash zero into card
|
||||||
if( !UseConcMarkSweepGC ) {
|
if( !UseConcMarkSweepGC ) {
|
||||||
__ store(__ ctrl(), card_adr, zero, bt, adr_type);
|
__ store(__ ctrl(), card_adr, zero, bt, adr_type);
|
||||||
} else {
|
} else {
|
||||||
@ -3472,6 +3477,10 @@ void GraphKit::write_barrier_post(Node* oop_store,
|
|||||||
__ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type);
|
__ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UseCondCardMark) {
|
||||||
|
__ end_if();
|
||||||
|
}
|
||||||
|
|
||||||
// Final sync IdealKit and GraphKit.
|
// Final sync IdealKit and GraphKit.
|
||||||
final_sync(ideal);
|
final_sync(ideal);
|
||||||
}
|
}
|
||||||
|
@ -773,15 +773,13 @@ class GraphKit : public Phase {
|
|||||||
|
|
||||||
// implementation of object creation
|
// implementation of object creation
|
||||||
Node* set_output_for_allocation(AllocateNode* alloc,
|
Node* set_output_for_allocation(AllocateNode* alloc,
|
||||||
const TypeOopPtr* oop_type,
|
const TypeOopPtr* oop_type);
|
||||||
bool raw_mem_only);
|
|
||||||
Node* get_layout_helper(Node* klass_node, jint& constant_value);
|
Node* get_layout_helper(Node* klass_node, jint& constant_value);
|
||||||
Node* new_instance(Node* klass_node,
|
Node* new_instance(Node* klass_node,
|
||||||
Node* slow_test = NULL,
|
Node* slow_test = NULL,
|
||||||
bool raw_mem_only = false,
|
|
||||||
Node* *return_size_val = NULL);
|
Node* *return_size_val = NULL);
|
||||||
Node* new_array(Node* klass_node, Node* count_val, int nargs,
|
Node* new_array(Node* klass_node, Node* count_val, int nargs,
|
||||||
bool raw_mem_only = false, Node* *return_size_val = NULL);
|
Node* *return_size_val = NULL);
|
||||||
|
|
||||||
// Handy for making control flow
|
// Handy for making control flow
|
||||||
IfNode* create_and_map_if(Node* ctrl, Node* tst, float prob, float cnt) {
|
IfNode* create_and_map_if(Node* ctrl, Node* tst, float prob, float cnt) {
|
||||||
|
@ -3527,8 +3527,7 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) {
|
|||||||
Node* orig_tail = _gvn.transform( new(C, 3) SubINode(orig_length, start) );
|
Node* orig_tail = _gvn.transform( new(C, 3) SubINode(orig_length, start) );
|
||||||
Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length);
|
Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length);
|
||||||
|
|
||||||
const bool raw_mem_only = true;
|
newcopy = new_array(klass_node, length, 0);
|
||||||
newcopy = new_array(klass_node, length, 0, raw_mem_only);
|
|
||||||
|
|
||||||
// Generate a direct call to the right arraycopy function(s).
|
// Generate a direct call to the right arraycopy function(s).
|
||||||
// We know the copy is disjoint but we might not know if the
|
// We know the copy is disjoint but we might not know if the
|
||||||
@ -4325,8 +4324,6 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
|||||||
|
|
||||||
const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM;
|
const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM;
|
||||||
int raw_adr_idx = Compile::AliasIdxRaw;
|
int raw_adr_idx = Compile::AliasIdxRaw;
|
||||||
const bool raw_mem_only = true;
|
|
||||||
|
|
||||||
|
|
||||||
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)NULL);
|
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)NULL);
|
||||||
if (array_ctl != NULL) {
|
if (array_ctl != NULL) {
|
||||||
@ -4335,8 +4332,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
|||||||
set_control(array_ctl);
|
set_control(array_ctl);
|
||||||
Node* obj_length = load_array_length(obj);
|
Node* obj_length = load_array_length(obj);
|
||||||
Node* obj_size = NULL;
|
Node* obj_size = NULL;
|
||||||
Node* alloc_obj = new_array(obj_klass, obj_length, 0,
|
Node* alloc_obj = new_array(obj_klass, obj_length, 0, &obj_size);
|
||||||
raw_mem_only, &obj_size);
|
|
||||||
|
|
||||||
if (!use_ReduceInitialCardMarks()) {
|
if (!use_ReduceInitialCardMarks()) {
|
||||||
// If it is an oop array, it requires very special treatment,
|
// If it is an oop array, it requires very special treatment,
|
||||||
@ -4408,7 +4404,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
|||||||
// It's an instance, and it passed the slow-path tests.
|
// It's an instance, and it passed the slow-path tests.
|
||||||
PreserveJVMState pjvms(this);
|
PreserveJVMState pjvms(this);
|
||||||
Node* obj_size = NULL;
|
Node* obj_size = NULL;
|
||||||
Node* alloc_obj = new_instance(obj_klass, NULL, raw_mem_only, &obj_size);
|
Node* alloc_obj = new_instance(obj_klass, NULL, &obj_size);
|
||||||
|
|
||||||
copy_to_clone(obj, alloc_obj, obj_size, false, !use_ReduceInitialCardMarks());
|
copy_to_clone(obj, alloc_obj, obj_size, false, !use_ReduceInitialCardMarks());
|
||||||
|
|
||||||
|
@ -2262,6 +2262,9 @@ bool PhaseIdealLoop::is_valid_clone_loop_form( IdealLoopTree *loop, Node_List& p
|
|||||||
// stmt1
|
// stmt1
|
||||||
// |
|
// |
|
||||||
// v
|
// v
|
||||||
|
// loop predicate
|
||||||
|
// |
|
||||||
|
// v
|
||||||
// stmt2 clone
|
// stmt2 clone
|
||||||
// |
|
// |
|
||||||
// v
|
// v
|
||||||
@ -2272,9 +2275,6 @@ bool PhaseIdealLoop::is_valid_clone_loop_form( IdealLoopTree *loop, Node_List& p
|
|||||||
// : false true
|
// : false true
|
||||||
// : | |
|
// : | |
|
||||||
// : | v
|
// : | v
|
||||||
// : | loop predicate
|
|
||||||
// : | |
|
|
||||||
// : | v
|
|
||||||
// : | newloop<-----+
|
// : | newloop<-----+
|
||||||
// : | | |
|
// : | | |
|
||||||
// : | stmt3 clone |
|
// : | stmt3 clone |
|
||||||
@ -2330,7 +2330,6 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* entry = head->in(LoopNode::EntryControl);
|
|
||||||
int dd = dom_depth(head);
|
int dd = dom_depth(head);
|
||||||
|
|
||||||
// Step 1: find cut point
|
// Step 1: find cut point
|
||||||
@ -2627,8 +2626,6 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
|
|||||||
|
|
||||||
// Backedge of the surviving new_head (the clone) is original last_peel
|
// Backedge of the surviving new_head (the clone) is original last_peel
|
||||||
_igvn.hash_delete(new_head_clone);
|
_igvn.hash_delete(new_head_clone);
|
||||||
Node* new_entry = move_loop_predicates(entry, new_head_clone->in(LoopNode::EntryControl));
|
|
||||||
new_head_clone->set_req(LoopNode::EntryControl, new_entry);
|
|
||||||
new_head_clone->set_req(LoopNode::LoopBackControl, last_peel);
|
new_head_clone->set_req(LoopNode::LoopBackControl, last_peel);
|
||||||
_igvn._worklist.push(new_head_clone);
|
_igvn._worklist.push(new_head_clone);
|
||||||
|
|
||||||
|
@ -221,9 +221,16 @@ void PhaseMacroExpand::eliminate_card_mark(Node* p2x) {
|
|||||||
Node *shift = p2x->unique_out();
|
Node *shift = p2x->unique_out();
|
||||||
Node *addp = shift->unique_out();
|
Node *addp = shift->unique_out();
|
||||||
for (DUIterator_Last jmin, j = addp->last_outs(jmin); j >= jmin; --j) {
|
for (DUIterator_Last jmin, j = addp->last_outs(jmin); j >= jmin; --j) {
|
||||||
Node *st = addp->last_out(j);
|
Node *mem = addp->last_out(j);
|
||||||
assert(st->is_Store(), "store required");
|
if (UseCondCardMark && mem->is_Load()) {
|
||||||
_igvn.replace_node(st, st->in(MemNode::Memory));
|
assert(mem->Opcode() == Op_LoadB, "unexpected code shape");
|
||||||
|
// The load is checking if the card has been written so
|
||||||
|
// replace it with zero to fold the test.
|
||||||
|
_igvn.replace_node(mem, intcon(0));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assert(mem->is_Store(), "store required");
|
||||||
|
_igvn.replace_node(mem, mem->in(MemNode::Memory));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// G1 pre/post barriers
|
// G1 pre/post barriers
|
||||||
|
@ -1260,6 +1260,9 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) {
|
|||||||
}
|
}
|
||||||
uint cnt = mem->req();
|
uint cnt = mem->req();
|
||||||
for (uint i = 1; i < cnt; i++) {
|
for (uint i = 1; i < cnt; i++) {
|
||||||
|
Node* rc = region->in(i);
|
||||||
|
if (rc == NULL || phase->type(rc) == Type::TOP)
|
||||||
|
return NULL; // Wait stable graph
|
||||||
Node *in = mem->in(i);
|
Node *in = mem->in(i);
|
||||||
if (in == NULL) {
|
if (in == NULL) {
|
||||||
return NULL; // Wait stable graph
|
return NULL; // Wait stable graph
|
||||||
@ -1285,14 +1288,13 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Skip the split if the region dominates some control edge of the address.
|
// Skip the split if the region dominates some control edge of the address.
|
||||||
if (cnt == 3 && !MemNode::all_controls_dominate(address, region))
|
if (!MemNode::all_controls_dominate(address, region))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
const Type* this_type = this->bottom_type();
|
const Type* this_type = this->bottom_type();
|
||||||
int this_index = phase->C->get_alias_index(addr_t);
|
int this_index = phase->C->get_alias_index(addr_t);
|
||||||
int this_offset = addr_t->offset();
|
int this_offset = addr_t->offset();
|
||||||
int this_iid = addr_t->is_oopptr()->instance_id();
|
int this_iid = addr_t->is_oopptr()->instance_id();
|
||||||
int wins = 0;
|
|
||||||
PhaseIterGVN *igvn = phase->is_IterGVN();
|
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||||
Node *phi = new (igvn->C, region->req()) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset);
|
Node *phi = new (igvn->C, region->req()) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset);
|
||||||
for (uint i = 1; i < region->req(); i++) {
|
for (uint i = 1; i < region->req(); i++) {
|
||||||
@ -1326,7 +1328,6 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (singleton) {
|
if (singleton) {
|
||||||
wins++;
|
|
||||||
x = igvn->makecon(t);
|
x = igvn->makecon(t);
|
||||||
} else {
|
} else {
|
||||||
// We now call Identity to try to simplify the cloned node.
|
// We now call Identity to try to simplify the cloned node.
|
||||||
@ -1341,12 +1342,10 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) {
|
|||||||
x->raise_bottom_type(t);
|
x->raise_bottom_type(t);
|
||||||
Node *y = x->Identity(igvn);
|
Node *y = x->Identity(igvn);
|
||||||
if (y != x) {
|
if (y != x) {
|
||||||
wins++;
|
|
||||||
x = y;
|
x = y;
|
||||||
} else {
|
} else {
|
||||||
y = igvn->hash_find(x);
|
y = igvn->hash_find(x);
|
||||||
if (y) {
|
if (y) {
|
||||||
wins++;
|
|
||||||
x = y;
|
x = y;
|
||||||
} else {
|
} else {
|
||||||
// Else x is a new node we are keeping
|
// Else x is a new node we are keeping
|
||||||
@ -1360,14 +1359,10 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) {
|
|||||||
igvn->remove_dead_node(the_clone);
|
igvn->remove_dead_node(the_clone);
|
||||||
phi->set_req(i, x);
|
phi->set_req(i, x);
|
||||||
}
|
}
|
||||||
if( wins > 0 ) {
|
|
||||||
// Record Phi
|
// Record Phi
|
||||||
igvn->register_new_node_with_optimizer(phi);
|
igvn->register_new_node_with_optimizer(phi);
|
||||||
return phi;
|
return phi;
|
||||||
}
|
}
|
||||||
igvn->remove_dead_node(phi);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------Ideal------------------------------------------
|
//------------------------------Ideal------------------------------------------
|
||||||
// If the load is from Field memory and the pointer is non-null, we can
|
// If the load is from Field memory and the pointer is non-null, we can
|
||||||
@ -1677,14 +1672,15 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
|
|||||||
// If we are loading from a freshly-allocated object, produce a zero,
|
// If we are loading from a freshly-allocated object, produce a zero,
|
||||||
// if the load is provably beyond the header of the object.
|
// if the load is provably beyond the header of the object.
|
||||||
// (Also allow a variable load from a fresh array to produce zero.)
|
// (Also allow a variable load from a fresh array to produce zero.)
|
||||||
if (ReduceFieldZeroing) {
|
const TypeOopPtr *tinst = tp->isa_oopptr();
|
||||||
|
bool is_instance = (tinst != NULL) && tinst->is_known_instance_field();
|
||||||
|
if (ReduceFieldZeroing || is_instance) {
|
||||||
Node* value = can_see_stored_value(mem,phase);
|
Node* value = can_see_stored_value(mem,phase);
|
||||||
if (value != NULL && value->is_Con())
|
if (value != NULL && value->is_Con())
|
||||||
return value->bottom_type();
|
return value->bottom_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeOopPtr *tinst = tp->isa_oopptr();
|
if (is_instance) {
|
||||||
if (tinst != NULL && tinst->is_known_instance_field()) {
|
|
||||||
// If we have an instance type and our memory input is the
|
// If we have an instance type and our memory input is the
|
||||||
// programs's initial memory state, there is no matching store,
|
// programs's initial memory state, there is no matching store,
|
||||||
// so just return a zero of the appropriate type
|
// so just return a zero of the appropriate type
|
||||||
|
@ -1172,16 +1172,16 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N
|
|||||||
|
|
||||||
Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start) {
|
Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start) {
|
||||||
Node* string = str;
|
Node* string = str;
|
||||||
Node* offset = kit.make_load(NULL,
|
Node* offset = kit.make_load(kit.control(),
|
||||||
kit.basic_plus_adr(string, string, java_lang_String::offset_offset_in_bytes()),
|
kit.basic_plus_adr(string, string, java_lang_String::offset_offset_in_bytes()),
|
||||||
TypeInt::INT, T_INT, offset_field_idx);
|
TypeInt::INT, T_INT, offset_field_idx);
|
||||||
Node* count = kit.make_load(NULL,
|
Node* count = kit.make_load(kit.control(),
|
||||||
kit.basic_plus_adr(string, string, java_lang_String::count_offset_in_bytes()),
|
kit.basic_plus_adr(string, string, java_lang_String::count_offset_in_bytes()),
|
||||||
TypeInt::INT, T_INT, count_field_idx);
|
TypeInt::INT, T_INT, count_field_idx);
|
||||||
const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull,
|
const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull,
|
||||||
TypeAry::make(TypeInt::CHAR,TypeInt::POS),
|
TypeAry::make(TypeInt::CHAR,TypeInt::POS),
|
||||||
ciTypeArrayKlass::make(T_CHAR), true, 0);
|
ciTypeArrayKlass::make(T_CHAR), true, 0);
|
||||||
Node* value = kit.make_load(NULL,
|
Node* value = kit.make_load(kit.control(),
|
||||||
kit.basic_plus_adr(string, string, java_lang_String::value_offset_in_bytes()),
|
kit.basic_plus_adr(string, string, java_lang_String::value_offset_in_bytes()),
|
||||||
value_type, T_OBJECT, value_field_idx);
|
value_type, T_OBJECT, value_field_idx);
|
||||||
|
|
||||||
@ -1342,7 +1342,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
|
|||||||
}
|
}
|
||||||
// Node* offset = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, offset_offset),
|
// Node* offset = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, offset_offset),
|
||||||
// TypeInt::INT, T_INT, offset_field_idx);
|
// TypeInt::INT, T_INT, offset_field_idx);
|
||||||
Node* count = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, java_lang_String::count_offset_in_bytes()),
|
Node* count = kit.make_load(kit.control(), kit.basic_plus_adr(arg, arg, java_lang_String::count_offset_in_bytes()),
|
||||||
TypeInt::INT, T_INT, count_field_idx);
|
TypeInt::INT, T_INT, count_field_idx);
|
||||||
length = __ AddI(length, count);
|
length = __ AddI(length, count);
|
||||||
string_sizes->init_req(argi, NULL);
|
string_sizes->init_req(argi, NULL);
|
||||||
|
@ -82,10 +82,8 @@ void MethodHandleChain::set_method_handle(Handle mh, TRAPS) {
|
|||||||
|
|
||||||
void MethodHandleChain::set_last_method(oop target, TRAPS) {
|
void MethodHandleChain::set_last_method(oop target, TRAPS) {
|
||||||
_is_last = true;
|
_is_last = true;
|
||||||
klassOop receiver_limit_oop = NULL;
|
KlassHandle receiver_limit; int flags = 0;
|
||||||
int flags = 0;
|
_last_method = MethodHandles::decode_method(target, receiver_limit, flags);
|
||||||
methodOop m = MethodHandles::decode_method(target, receiver_limit_oop, flags);
|
|
||||||
_last_method = methodHandle(THREAD, m);
|
|
||||||
if ((flags & MethodHandles::_dmf_has_receiver) == 0)
|
if ((flags & MethodHandles::_dmf_has_receiver) == 0)
|
||||||
_last_invoke = Bytecodes::_invokestatic;
|
_last_invoke = Bytecodes::_invokestatic;
|
||||||
else if ((flags & MethodHandles::_dmf_does_dispatch) == 0)
|
else if ((flags & MethodHandles::_dmf_does_dispatch) == 0)
|
||||||
|
@ -153,9 +153,9 @@ void MethodHandles::set_enabled(bool z) {
|
|||||||
// and local, like parse a data structure. For speed, such methods work on plain
|
// and local, like parse a data structure. For speed, such methods work on plain
|
||||||
// oops, not handles. Trapping methods uniformly operate on handles.
|
// oops, not handles. Trapping methods uniformly operate on handles.
|
||||||
|
|
||||||
methodOop MethodHandles::decode_vmtarget(oop vmtarget, int vmindex, oop mtype,
|
methodHandle MethodHandles::decode_vmtarget(oop vmtarget, int vmindex, oop mtype,
|
||||||
klassOop& receiver_limit_result, int& decode_flags_result) {
|
KlassHandle& receiver_limit_result, int& decode_flags_result) {
|
||||||
if (vmtarget == NULL) return NULL;
|
if (vmtarget == NULL) return methodHandle();
|
||||||
assert(methodOopDesc::nonvirtual_vtable_index < 0, "encoding");
|
assert(methodOopDesc::nonvirtual_vtable_index < 0, "encoding");
|
||||||
if (vmindex < 0) {
|
if (vmindex < 0) {
|
||||||
// this DMH performs no dispatch; it is directly bound to a methodOop
|
// this DMH performs no dispatch; it is directly bound to a methodOop
|
||||||
@ -198,20 +198,20 @@ methodOop MethodHandles::decode_vmtarget(oop vmtarget, int vmindex, oop mtype,
|
|||||||
// MemberName and DirectMethodHandle have the same linkage to the JVM internals.
|
// MemberName and DirectMethodHandle have the same linkage to the JVM internals.
|
||||||
// (MemberName is the non-operational name used for queries and setup.)
|
// (MemberName is the non-operational name used for queries and setup.)
|
||||||
|
|
||||||
methodOop MethodHandles::decode_DirectMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) {
|
methodHandle MethodHandles::decode_DirectMethodHandle(oop mh, KlassHandle& receiver_limit_result, int& decode_flags_result) {
|
||||||
oop vmtarget = java_lang_invoke_DirectMethodHandle::vmtarget(mh);
|
oop vmtarget = java_lang_invoke_DirectMethodHandle::vmtarget(mh);
|
||||||
int vmindex = java_lang_invoke_DirectMethodHandle::vmindex(mh);
|
int vmindex = java_lang_invoke_DirectMethodHandle::vmindex(mh);
|
||||||
oop mtype = java_lang_invoke_DirectMethodHandle::type(mh);
|
oop mtype = java_lang_invoke_DirectMethodHandle::type(mh);
|
||||||
return decode_vmtarget(vmtarget, vmindex, mtype, receiver_limit_result, decode_flags_result);
|
return decode_vmtarget(vmtarget, vmindex, mtype, receiver_limit_result, decode_flags_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) {
|
methodHandle MethodHandles::decode_BoundMethodHandle(oop mh, KlassHandle& receiver_limit_result, int& decode_flags_result) {
|
||||||
assert(java_lang_invoke_BoundMethodHandle::is_instance(mh), "");
|
assert(java_lang_invoke_BoundMethodHandle::is_instance(mh), "");
|
||||||
assert(mh->klass() != SystemDictionary::AdapterMethodHandle_klass(), "");
|
assert(mh->klass() != SystemDictionary::AdapterMethodHandle_klass(), "");
|
||||||
for (oop bmh = mh;;) {
|
for (oop bmh = mh;;) {
|
||||||
// Bound MHs can be stacked to bind several arguments.
|
// Bound MHs can be stacked to bind several arguments.
|
||||||
oop target = java_lang_invoke_MethodHandle::vmtarget(bmh);
|
oop target = java_lang_invoke_MethodHandle::vmtarget(bmh);
|
||||||
if (target == NULL) return NULL;
|
if (target == NULL) return methodHandle();
|
||||||
decode_flags_result |= MethodHandles::_dmf_binds_argument;
|
decode_flags_result |= MethodHandles::_dmf_binds_argument;
|
||||||
klassOop tk = target->klass();
|
klassOop tk = target->klass();
|
||||||
if (tk == SystemDictionary::BoundMethodHandle_klass()) {
|
if (tk == SystemDictionary::BoundMethodHandle_klass()) {
|
||||||
@ -236,14 +236,14 @@ methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_lim
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
methodOop MethodHandles::decode_AdapterMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) {
|
methodHandle MethodHandles::decode_AdapterMethodHandle(oop mh, KlassHandle& receiver_limit_result, int& decode_flags_result) {
|
||||||
assert(mh->klass() == SystemDictionary::AdapterMethodHandle_klass(), "");
|
assert(mh->klass() == SystemDictionary::AdapterMethodHandle_klass(), "");
|
||||||
for (oop amh = mh;;) {
|
for (oop amh = mh;;) {
|
||||||
// Adapter MHs can be stacked to convert several arguments.
|
// Adapter MHs can be stacked to convert several arguments.
|
||||||
int conv_op = adapter_conversion_op(java_lang_invoke_AdapterMethodHandle::conversion(amh));
|
int conv_op = adapter_conversion_op(java_lang_invoke_AdapterMethodHandle::conversion(amh));
|
||||||
decode_flags_result |= (_dmf_adapter_lsb << conv_op) & _DMF_ADAPTER_MASK;
|
decode_flags_result |= (_dmf_adapter_lsb << conv_op) & _DMF_ADAPTER_MASK;
|
||||||
oop target = java_lang_invoke_MethodHandle::vmtarget(amh);
|
oop target = java_lang_invoke_MethodHandle::vmtarget(amh);
|
||||||
if (target == NULL) return NULL;
|
if (target == NULL) return methodHandle();
|
||||||
klassOop tk = target->klass();
|
klassOop tk = target->klass();
|
||||||
if (tk == SystemDictionary::AdapterMethodHandle_klass()) {
|
if (tk == SystemDictionary::AdapterMethodHandle_klass()) {
|
||||||
amh = target;
|
amh = target;
|
||||||
@ -255,8 +255,8 @@ methodOop MethodHandles::decode_AdapterMethodHandle(oop mh, klassOop& receiver_l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
methodOop MethodHandles::decode_MethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) {
|
methodHandle MethodHandles::decode_MethodHandle(oop mh, KlassHandle& receiver_limit_result, int& decode_flags_result) {
|
||||||
if (mh == NULL) return NULL;
|
if (mh == NULL) return methodHandle();
|
||||||
klassOop mhk = mh->klass();
|
klassOop mhk = mh->klass();
|
||||||
assert(java_lang_invoke_MethodHandle::is_subclass(mhk), "must be a MethodHandle");
|
assert(java_lang_invoke_MethodHandle::is_subclass(mhk), "must be a MethodHandle");
|
||||||
if (mhk == SystemDictionary::DirectMethodHandle_klass()) {
|
if (mhk == SystemDictionary::DirectMethodHandle_klass()) {
|
||||||
@ -270,7 +270,7 @@ methodOop MethodHandles::decode_MethodHandle(oop mh, klassOop& receiver_limit_re
|
|||||||
return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result);
|
return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result);
|
||||||
} else {
|
} else {
|
||||||
assert(false, "cannot parse this MH");
|
assert(false, "cannot parse this MH");
|
||||||
return NULL; // random MH?
|
return methodHandle(); // random MH?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,9 +299,9 @@ methodOop MethodHandles::decode_methodOop(methodOop m, int& decode_flags_result)
|
|||||||
|
|
||||||
// A trusted party is handing us a cookie to determine a method.
|
// A trusted party is handing us a cookie to determine a method.
|
||||||
// Let's boil it down to the method oop they really want.
|
// Let's boil it down to the method oop they really want.
|
||||||
methodOop MethodHandles::decode_method(oop x, klassOop& receiver_limit_result, int& decode_flags_result) {
|
methodHandle MethodHandles::decode_method(oop x, KlassHandle& receiver_limit_result, int& decode_flags_result) {
|
||||||
decode_flags_result = 0;
|
decode_flags_result = 0;
|
||||||
receiver_limit_result = NULL;
|
receiver_limit_result = KlassHandle();
|
||||||
klassOop xk = x->klass();
|
klassOop xk = x->klass();
|
||||||
if (xk == Universe::methodKlassObj()) {
|
if (xk == Universe::methodKlassObj()) {
|
||||||
return decode_methodOop((methodOop) x, decode_flags_result);
|
return decode_methodOop((methodOop) x, decode_flags_result);
|
||||||
@ -329,7 +329,7 @@ methodOop MethodHandles::decode_method(oop x, klassOop& receiver_limit_result, i
|
|||||||
assert(!x->is_method(), "already checked");
|
assert(!x->is_method(), "already checked");
|
||||||
assert(!java_lang_invoke_MemberName::is_instance(x), "already checked");
|
assert(!java_lang_invoke_MemberName::is_instance(x), "already checked");
|
||||||
}
|
}
|
||||||
return NULL;
|
return methodHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -389,11 +389,10 @@ void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
|
|||||||
int offset = instanceKlass::cast(k)->offset_from_fields(slot);
|
int offset = instanceKlass::cast(k)->offset_from_fields(slot);
|
||||||
init_MemberName(mname_oop, k, accessFlags_from(mods), offset);
|
init_MemberName(mname_oop, k, accessFlags_from(mods), offset);
|
||||||
} else {
|
} else {
|
||||||
int decode_flags = 0; klassOop receiver_limit = NULL;
|
KlassHandle receiver_limit; int decode_flags = 0;
|
||||||
methodOop m = MethodHandles::decode_method(target_oop,
|
methodHandle m = MethodHandles::decode_method(target_oop, receiver_limit, decode_flags);
|
||||||
receiver_limit, decode_flags);
|
|
||||||
bool do_dispatch = ((decode_flags & MethodHandles::_dmf_does_dispatch) != 0);
|
bool do_dispatch = ((decode_flags & MethodHandles::_dmf_does_dispatch) != 0);
|
||||||
init_MemberName(mname_oop, m, do_dispatch);
|
init_MemberName(mname_oop, m(), do_dispatch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,13 +422,14 @@ void MethodHandles::init_MemberName(oop mname_oop, klassOop field_holder, Access
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
methodOop MethodHandles::decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result) {
|
methodHandle MethodHandles::decode_MemberName(oop mname, KlassHandle& receiver_limit_result, int& decode_flags_result) {
|
||||||
|
methodHandle empty;
|
||||||
int flags = java_lang_invoke_MemberName::flags(mname);
|
int flags = java_lang_invoke_MemberName::flags(mname);
|
||||||
if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) == 0) return NULL; // not invocable
|
if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) == 0) return empty; // not invocable
|
||||||
oop vmtarget = java_lang_invoke_MemberName::vmtarget(mname);
|
oop vmtarget = java_lang_invoke_MemberName::vmtarget(mname);
|
||||||
int vmindex = java_lang_invoke_MemberName::vmindex(mname);
|
int vmindex = java_lang_invoke_MemberName::vmindex(mname);
|
||||||
if (vmindex == VM_INDEX_UNINITIALIZED) return NULL; // not resolved
|
if (vmindex == VM_INDEX_UNINITIALIZED) return empty; // not resolved
|
||||||
methodOop m = decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result);
|
methodHandle m = decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result);
|
||||||
oop clazz = java_lang_invoke_MemberName::clazz(mname);
|
oop clazz = java_lang_invoke_MemberName::clazz(mname);
|
||||||
if (clazz != NULL && java_lang_Class::is_instance(clazz)) {
|
if (clazz != NULL && java_lang_Class::is_instance(clazz)) {
|
||||||
klassOop klass = java_lang_Class::as_klassOop(clazz);
|
klassOop klass = java_lang_Class::as_klassOop(clazz);
|
||||||
@ -439,9 +439,7 @@ methodOop MethodHandles::decode_MemberName(oop mname, klassOop& receiver_limit_r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convert the external string or reflective type to an internal signature
|
// convert the external string or reflective type to an internal signature
|
||||||
Symbol* MethodHandles::convert_to_signature(oop type_str,
|
Symbol* MethodHandles::convert_to_signature(oop type_str, bool polymorphic, TRAPS) {
|
||||||
bool polymorphic,
|
|
||||||
TRAPS) {
|
|
||||||
if (java_lang_invoke_MethodType::is_instance(type_str)) {
|
if (java_lang_invoke_MethodType::is_instance(type_str)) {
|
||||||
return java_lang_invoke_MethodType::as_signature(type_str, polymorphic, CHECK_NULL);
|
return java_lang_invoke_MethodType::as_signature(type_str, polymorphic, CHECK_NULL);
|
||||||
} else if (java_lang_Class::is_instance(type_str)) {
|
} else if (java_lang_Class::is_instance(type_str)) {
|
||||||
@ -474,48 +472,48 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
|
|||||||
#endif
|
#endif
|
||||||
if (java_lang_invoke_MemberName::vmindex(mname()) != VM_INDEX_UNINITIALIZED)
|
if (java_lang_invoke_MemberName::vmindex(mname()) != VM_INDEX_UNINITIALIZED)
|
||||||
return; // already resolved
|
return; // already resolved
|
||||||
oop defc_oop = java_lang_invoke_MemberName::clazz(mname());
|
Handle defc_oop(THREAD, java_lang_invoke_MemberName::clazz(mname()));
|
||||||
oop name_str = java_lang_invoke_MemberName::name(mname());
|
Handle name_str(THREAD, java_lang_invoke_MemberName::name( mname()));
|
||||||
oop type_str = java_lang_invoke_MemberName::type(mname());
|
Handle type_str(THREAD, java_lang_invoke_MemberName::type( mname()));
|
||||||
int flags = java_lang_invoke_MemberName::flags(mname());
|
int flags = java_lang_invoke_MemberName::flags(mname());
|
||||||
|
|
||||||
if (defc_oop == NULL || name_str == NULL || type_str == NULL) {
|
if (defc_oop.is_null() || name_str.is_null() || type_str.is_null()) {
|
||||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to resolve");
|
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to resolve");
|
||||||
}
|
}
|
||||||
klassOop defc_klassOop = java_lang_Class::as_klassOop(defc_oop);
|
|
||||||
defc_oop = NULL; // safety
|
instanceKlassHandle defc;
|
||||||
|
{
|
||||||
|
klassOop defc_klassOop = java_lang_Class::as_klassOop(defc_oop());
|
||||||
if (defc_klassOop == NULL) return; // a primitive; no resolution possible
|
if (defc_klassOop == NULL) return; // a primitive; no resolution possible
|
||||||
if (!Klass::cast(defc_klassOop)->oop_is_instance()) {
|
if (!Klass::cast(defc_klassOop)->oop_is_instance()) {
|
||||||
if (!Klass::cast(defc_klassOop)->oop_is_array()) return;
|
if (!Klass::cast(defc_klassOop)->oop_is_array()) return;
|
||||||
defc_klassOop = SystemDictionary::Object_klass();
|
defc_klassOop = SystemDictionary::Object_klass();
|
||||||
}
|
}
|
||||||
instanceKlassHandle defc(THREAD, defc_klassOop);
|
defc = instanceKlassHandle(THREAD, defc_klassOop);
|
||||||
defc_klassOop = NULL; // safety
|
}
|
||||||
if (defc.is_null()) {
|
if (defc.is_null()) {
|
||||||
THROW_MSG(vmSymbols::java_lang_InternalError(), "primitive class");
|
THROW_MSG(vmSymbols::java_lang_InternalError(), "primitive class");
|
||||||
}
|
}
|
||||||
defc->link_class(CHECK);
|
defc->link_class(CHECK); // possible safepoint
|
||||||
|
|
||||||
// convert the external string name to an internal symbol
|
// convert the external string name to an internal symbol
|
||||||
TempNewSymbol name = java_lang_String::as_symbol_or_null(name_str);
|
TempNewSymbol name = java_lang_String::as_symbol_or_null(name_str());
|
||||||
if (name == NULL) return; // no such name
|
if (name == NULL) return; // no such name
|
||||||
name_str = NULL; // safety
|
|
||||||
|
|
||||||
Handle polymorphic_method_type;
|
Handle polymorphic_method_type;
|
||||||
bool polymorphic_signature = false;
|
bool polymorphic_signature = false;
|
||||||
if ((flags & ALL_KINDS) == IS_METHOD &&
|
if ((flags & ALL_KINDS) == IS_METHOD &&
|
||||||
(defc() == SystemDictionary::MethodHandle_klass() &&
|
(defc() == SystemDictionary::MethodHandle_klass() &&
|
||||||
methodOopDesc::is_method_handle_invoke_name(name)))
|
methodOopDesc::is_method_handle_invoke_name(name))) {
|
||||||
polymorphic_signature = true;
|
polymorphic_signature = true;
|
||||||
|
|
||||||
// convert the external string or reflective type to an internal signature
|
|
||||||
TempNewSymbol type = convert_to_signature(type_str, polymorphic_signature, CHECK);
|
|
||||||
if (java_lang_invoke_MethodType::is_instance(type_str) && polymorphic_signature) {
|
|
||||||
polymorphic_method_type = Handle(THREAD, type_str); //preserve exactly
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert the external string or reflective type to an internal signature
|
||||||
|
TempNewSymbol type = convert_to_signature(type_str(), polymorphic_signature, CHECK);
|
||||||
|
if (java_lang_invoke_MethodType::is_instance(type_str()) && polymorphic_signature) {
|
||||||
|
polymorphic_method_type = type_str; // preserve exactly
|
||||||
|
}
|
||||||
if (type == NULL) return; // no such signature exists in the VM
|
if (type == NULL) return; // no such signature exists in the VM
|
||||||
type_str = NULL; // safety
|
|
||||||
|
|
||||||
// Time to do the lookup.
|
// Time to do the lookup.
|
||||||
switch (flags & ALL_KINDS) {
|
switch (flags & ALL_KINDS) {
|
||||||
@ -560,8 +558,8 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
|
|||||||
java_lang_invoke_MemberName::set_vmtarget(mname(), vmtarget);
|
java_lang_invoke_MemberName::set_vmtarget(mname(), vmtarget);
|
||||||
java_lang_invoke_MemberName::set_vmindex(mname(), vmindex);
|
java_lang_invoke_MemberName::set_vmindex(mname(), vmindex);
|
||||||
java_lang_invoke_MemberName::set_modifiers(mname(), mods);
|
java_lang_invoke_MemberName::set_modifiers(mname(), mods);
|
||||||
DEBUG_ONLY(int junk; klassOop junk2);
|
DEBUG_ONLY(KlassHandle junk1; int junk2);
|
||||||
assert(decode_MemberName(mname(), junk2, junk) == result.resolved_method()(),
|
assert(decode_MemberName(mname(), junk1, junk2) == result.resolved_method(),
|
||||||
"properly stored for later decoding");
|
"properly stored for later decoding");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -589,8 +587,8 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
|
|||||||
java_lang_invoke_MemberName::set_vmtarget(mname(), vmtarget);
|
java_lang_invoke_MemberName::set_vmtarget(mname(), vmtarget);
|
||||||
java_lang_invoke_MemberName::set_vmindex(mname(), vmindex);
|
java_lang_invoke_MemberName::set_vmindex(mname(), vmindex);
|
||||||
java_lang_invoke_MemberName::set_modifiers(mname(), mods);
|
java_lang_invoke_MemberName::set_modifiers(mname(), mods);
|
||||||
DEBUG_ONLY(int junk; klassOop junk2);
|
DEBUG_ONLY(KlassHandle junk1; int junk2);
|
||||||
assert(decode_MemberName(mname(), junk2, junk) == result.resolved_method()(),
|
assert(decode_MemberName(mname(), junk1, junk2) == result.resolved_method(),
|
||||||
"properly stored for later decoding");
|
"properly stored for later decoding");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -677,16 +675,14 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) {
|
|||||||
case IS_METHOD:
|
case IS_METHOD:
|
||||||
case IS_CONSTRUCTOR:
|
case IS_CONSTRUCTOR:
|
||||||
{
|
{
|
||||||
klassOop receiver_limit = NULL;
|
KlassHandle receiver_limit; int decode_flags = 0;
|
||||||
int decode_flags = 0;
|
methodHandle m = decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit, decode_flags);
|
||||||
methodHandle m(THREAD, decode_vmtarget(vmtarget, vmindex, NULL,
|
|
||||||
receiver_limit, decode_flags));
|
|
||||||
if (m.is_null()) break;
|
if (m.is_null()) break;
|
||||||
if (!have_defc) {
|
if (!have_defc) {
|
||||||
klassOop defc = m->method_holder();
|
klassOop defc = m->method_holder();
|
||||||
if (receiver_limit != NULL && receiver_limit != defc
|
if (receiver_limit.not_null() && receiver_limit() != defc
|
||||||
&& Klass::cast(receiver_limit)->is_subtype_of(defc))
|
&& Klass::cast(receiver_limit())->is_subtype_of(defc))
|
||||||
defc = receiver_limit;
|
defc = receiver_limit();
|
||||||
java_lang_invoke_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror());
|
java_lang_invoke_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror());
|
||||||
}
|
}
|
||||||
if (!have_name) {
|
if (!have_name) {
|
||||||
@ -884,10 +880,9 @@ oop MethodHandles::encode_target(Handle mh, int format, TRAPS) {
|
|||||||
// - AMH can have methodOop for static invoke with bound receiver
|
// - AMH can have methodOop for static invoke with bound receiver
|
||||||
// - DMH can have methodOop for static invoke (on variable receiver)
|
// - DMH can have methodOop for static invoke (on variable receiver)
|
||||||
// - DMH can have klassOop for dispatched (non-static) invoke
|
// - DMH can have klassOop for dispatched (non-static) invoke
|
||||||
klassOop receiver_limit = NULL;
|
KlassHandle receiver_limit; int decode_flags = 0;
|
||||||
int decode_flags = 0;
|
methodHandle m = decode_MethodHandle(mh(), receiver_limit, decode_flags);
|
||||||
methodOop m = decode_MethodHandle(mh(), receiver_limit, decode_flags);
|
if (m.is_null()) return NULL;
|
||||||
if (m == NULL) return NULL;
|
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case ETF_REFLECT_METHOD:
|
case ETF_REFLECT_METHOD:
|
||||||
// same as jni_ToReflectedMethod:
|
// same as jni_ToReflectedMethod:
|
||||||
@ -903,10 +898,10 @@ oop MethodHandles::encode_target(Handle mh, int format, TRAPS) {
|
|||||||
if (SystemDictionary::MemberName_klass() == NULL) break;
|
if (SystemDictionary::MemberName_klass() == NULL) break;
|
||||||
instanceKlassHandle mname_klass(THREAD, SystemDictionary::MemberName_klass());
|
instanceKlassHandle mname_klass(THREAD, SystemDictionary::MemberName_klass());
|
||||||
mname_klass->initialize(CHECK_NULL);
|
mname_klass->initialize(CHECK_NULL);
|
||||||
Handle mname = mname_klass->allocate_instance_handle(CHECK_NULL);
|
Handle mname = mname_klass->allocate_instance_handle(CHECK_NULL); // possible safepoint
|
||||||
java_lang_invoke_MemberName::set_vmindex(mname(), VM_INDEX_UNINITIALIZED);
|
java_lang_invoke_MemberName::set_vmindex(mname(), VM_INDEX_UNINITIALIZED);
|
||||||
bool do_dispatch = ((decode_flags & MethodHandles::_dmf_does_dispatch) != 0);
|
bool do_dispatch = ((decode_flags & MethodHandles::_dmf_does_dispatch) != 0);
|
||||||
init_MemberName(mname(), m, do_dispatch);
|
init_MemberName(mname(), m(), do_dispatch);
|
||||||
expand_MemberName(mname, 0, CHECK_NULL);
|
expand_MemberName(mname, 0, CHECK_NULL);
|
||||||
return mname();
|
return mname();
|
||||||
}
|
}
|
||||||
@ -1460,7 +1455,7 @@ void MethodHandles::init_DirectMethodHandle(Handle mh, methodHandle m, bool do_d
|
|||||||
// bits, and will use the same calling sequence code.
|
// bits, and will use the same calling sequence code.
|
||||||
|
|
||||||
int vmindex = methodOopDesc::garbage_vtable_index;
|
int vmindex = methodOopDesc::garbage_vtable_index;
|
||||||
oop vmtarget = NULL;
|
Handle vmtarget;
|
||||||
|
|
||||||
instanceKlass::cast(m->method_holder())->link_class(CHECK);
|
instanceKlass::cast(m->method_holder())->link_class(CHECK);
|
||||||
|
|
||||||
@ -1478,7 +1473,7 @@ void MethodHandles::init_DirectMethodHandle(Handle mh, methodHandle m, bool do_d
|
|||||||
} else if (!do_dispatch || m->can_be_statically_bound()) {
|
} else if (!do_dispatch || m->can_be_statically_bound()) {
|
||||||
// We are simulating an invokestatic or invokespecial instruction.
|
// We are simulating an invokestatic or invokespecial instruction.
|
||||||
// Set up the method pointer, just like ConstantPoolCacheEntry::set_method().
|
// Set up the method pointer, just like ConstantPoolCacheEntry::set_method().
|
||||||
vmtarget = m();
|
vmtarget = m;
|
||||||
// this does not help dispatch, but it will make it possible to parse this MH:
|
// this does not help dispatch, but it will make it possible to parse this MH:
|
||||||
vmindex = methodOopDesc::nonvirtual_vtable_index;
|
vmindex = methodOopDesc::nonvirtual_vtable_index;
|
||||||
assert(vmindex < 0, "(>=0) == do_dispatch");
|
assert(vmindex < 0, "(>=0) == do_dispatch");
|
||||||
@ -1490,7 +1485,7 @@ void MethodHandles::init_DirectMethodHandle(Handle mh, methodHandle m, bool do_d
|
|||||||
// For a DMH, it is done now, when the handle is created.
|
// For a DMH, it is done now, when the handle is created.
|
||||||
Klass* k = Klass::cast(m->method_holder());
|
Klass* k = Klass::cast(m->method_holder());
|
||||||
if (k->should_be_initialized()) {
|
if (k->should_be_initialized()) {
|
||||||
k->initialize(CHECK);
|
k->initialize(CHECK); // possible safepoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1504,10 +1499,10 @@ void MethodHandles::init_DirectMethodHandle(Handle mh, methodHandle m, bool do_d
|
|||||||
|
|
||||||
if (me == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
|
if (me == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
|
||||||
|
|
||||||
java_lang_invoke_DirectMethodHandle::set_vmtarget(mh(), vmtarget);
|
java_lang_invoke_DirectMethodHandle::set_vmtarget(mh(), vmtarget());
|
||||||
java_lang_invoke_DirectMethodHandle::set_vmindex( mh(), vmindex);
|
java_lang_invoke_DirectMethodHandle::set_vmindex( mh(), vmindex);
|
||||||
DEBUG_ONLY(int flags; klassOop rlimit);
|
DEBUG_ONLY(KlassHandle rlimit; int flags);
|
||||||
assert(MethodHandles::decode_method(mh(), rlimit, flags) == m(),
|
assert(MethodHandles::decode_method(mh(), rlimit, flags) == m,
|
||||||
"properly stored for later decoding");
|
"properly stored for later decoding");
|
||||||
DEBUG_ONLY(bool actual_do_dispatch = ((flags & _dmf_does_dispatch) != 0));
|
DEBUG_ONLY(bool actual_do_dispatch = ((flags & _dmf_does_dispatch) != 0));
|
||||||
assert(!(actual_do_dispatch && !do_dispatch),
|
assert(!(actual_do_dispatch && !do_dispatch),
|
||||||
@ -1523,10 +1518,13 @@ void MethodHandles::verify_BoundMethodHandle_with_receiver(Handle mh,
|
|||||||
methodHandle m,
|
methodHandle m,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
// Verify type.
|
// Verify type.
|
||||||
oop receiver = java_lang_invoke_BoundMethodHandle::argument(mh());
|
|
||||||
Handle mtype(THREAD, java_lang_invoke_MethodHandle::type(mh()));
|
|
||||||
KlassHandle bound_recv_type;
|
KlassHandle bound_recv_type;
|
||||||
if (receiver != NULL) bound_recv_type = KlassHandle(THREAD, receiver->klass());
|
{
|
||||||
|
oop receiver = java_lang_invoke_BoundMethodHandle::argument(mh());
|
||||||
|
if (receiver != NULL)
|
||||||
|
bound_recv_type = KlassHandle(THREAD, receiver->klass());
|
||||||
|
}
|
||||||
|
Handle mtype(THREAD, java_lang_invoke_MethodHandle::type(mh()));
|
||||||
verify_method_type(m, mtype, true, bound_recv_type, CHECK);
|
verify_method_type(m, mtype, true, bound_recv_type, CHECK);
|
||||||
|
|
||||||
int receiver_pos = m->size_of_parameters() - 1;
|
int receiver_pos = m->size_of_parameters() - 1;
|
||||||
@ -1573,8 +1571,8 @@ void MethodHandles::init_BoundMethodHandle_with_receiver(Handle mh,
|
|||||||
|
|
||||||
java_lang_invoke_BoundMethodHandle::set_vmtarget(mh(), m());
|
java_lang_invoke_BoundMethodHandle::set_vmtarget(mh(), m());
|
||||||
|
|
||||||
DEBUG_ONLY(int junk; klassOop junk2);
|
DEBUG_ONLY(KlassHandle junk1; int junk2);
|
||||||
assert(MethodHandles::decode_method(mh(), junk2, junk) == m(), "properly stored for later decoding");
|
assert(MethodHandles::decode_method(mh(), junk1, junk2) == m, "properly stored for later decoding");
|
||||||
assert(decode_MethodHandle_stack_pushes(mh()) == 1, "BMH pushes one stack slot");
|
assert(decode_MethodHandle_stack_pushes(mh()) == 1, "BMH pushes one stack slot");
|
||||||
|
|
||||||
// Done!
|
// Done!
|
||||||
@ -1682,8 +1680,11 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get bound type and required slots.
|
// Get bound type and required slots.
|
||||||
|
BasicType ptype;
|
||||||
|
{
|
||||||
oop ptype_oop = java_lang_invoke_MethodType::ptype(java_lang_invoke_MethodHandle::type(target()), argnum);
|
oop ptype_oop = java_lang_invoke_MethodType::ptype(java_lang_invoke_MethodHandle::type(target()), argnum);
|
||||||
BasicType ptype = java_lang_Class::as_BasicType(ptype_oop);
|
ptype = java_lang_Class::as_BasicType(ptype_oop);
|
||||||
|
}
|
||||||
int slots_pushed = type2size[ptype];
|
int slots_pushed = type2size[ptype];
|
||||||
|
|
||||||
// If (a) the target is a direct non-dispatched method handle,
|
// If (a) the target is a direct non-dispatched method handle,
|
||||||
@ -1694,13 +1695,12 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum,
|
|||||||
if (OptimizeMethodHandles &&
|
if (OptimizeMethodHandles &&
|
||||||
target->klass() == SystemDictionary::DirectMethodHandle_klass() &&
|
target->klass() == SystemDictionary::DirectMethodHandle_klass() &&
|
||||||
(argnum == 0 || java_lang_invoke_DirectMethodHandle::vmindex(target()) < 0)) {
|
(argnum == 0 || java_lang_invoke_DirectMethodHandle::vmindex(target()) < 0)) {
|
||||||
int decode_flags = 0; klassOop receiver_limit_oop = NULL;
|
KlassHandle receiver_limit; int decode_flags = 0;
|
||||||
methodHandle m(THREAD, decode_method(target(), receiver_limit_oop, decode_flags));
|
methodHandle m = decode_method(target(), receiver_limit, decode_flags);
|
||||||
if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "DMH failed to decode"); }
|
if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "DMH failed to decode"); }
|
||||||
DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - slots_pushed); // pos. of 1st arg.
|
DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - slots_pushed); // pos. of 1st arg.
|
||||||
assert(java_lang_invoke_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig");
|
assert(java_lang_invoke_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig");
|
||||||
if (argnum == 0 && (decode_flags & _dmf_has_receiver) != 0) {
|
if (argnum == 0 && (decode_flags & _dmf_has_receiver) != 0) {
|
||||||
KlassHandle receiver_limit(THREAD, receiver_limit_oop);
|
|
||||||
init_BoundMethodHandle_with_receiver(mh, m,
|
init_BoundMethodHandle_with_receiver(mh, m,
|
||||||
receiver_limit, decode_flags,
|
receiver_limit, decode_flags,
|
||||||
CHECK);
|
CHECK);
|
||||||
@ -2019,7 +2019,6 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) {
|
void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) {
|
||||||
oop argument = java_lang_invoke_AdapterMethodHandle::argument(mh());
|
|
||||||
int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh());
|
int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh());
|
||||||
jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh());
|
jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh());
|
||||||
jint conv_op = adapter_conversion_op(conversion);
|
jint conv_op = adapter_conversion_op(conversion);
|
||||||
@ -2215,18 +2214,14 @@ JVM_ENTRY(void, MHN_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh,
|
|||||||
|
|
||||||
// which method are we really talking about?
|
// which method are we really talking about?
|
||||||
if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
|
if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
|
||||||
oop target_oop = JNIHandles::resolve_non_null(target_jh);
|
Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
|
||||||
if (java_lang_invoke_MemberName::is_instance(target_oop) &&
|
if (java_lang_invoke_MemberName::is_instance(target()) &&
|
||||||
java_lang_invoke_MemberName::vmindex(target_oop) == VM_INDEX_UNINITIALIZED) {
|
java_lang_invoke_MemberName::vmindex(target()) == VM_INDEX_UNINITIALIZED) {
|
||||||
Handle mname(THREAD, target_oop);
|
MethodHandles::resolve_MemberName(target, CHECK);
|
||||||
MethodHandles::resolve_MemberName(mname, CHECK);
|
|
||||||
target_oop = mname(); // in case of GC
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int decode_flags = 0; klassOop receiver_limit = NULL;
|
KlassHandle receiver_limit; int decode_flags = 0;
|
||||||
methodHandle m(THREAD,
|
methodHandle m = MethodHandles::decode_method(target(), receiver_limit, decode_flags);
|
||||||
MethodHandles::decode_method(target_oop,
|
|
||||||
receiver_limit, decode_flags));
|
|
||||||
if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "no such method"); }
|
if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "no such method"); }
|
||||||
|
|
||||||
// The trusted Java code that calls this method should already have performed
|
// The trusted Java code that calls this method should already have performed
|
||||||
@ -2284,12 +2279,8 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh,
|
|||||||
// Target object is a reflective method. (%%% Do we need this alternate path?)
|
// Target object is a reflective method. (%%% Do we need this alternate path?)
|
||||||
Untested("init_BMH of non-MH");
|
Untested("init_BMH of non-MH");
|
||||||
if (argnum != 0) { THROW(vmSymbols::java_lang_InternalError()); }
|
if (argnum != 0) { THROW(vmSymbols::java_lang_InternalError()); }
|
||||||
int decode_flags = 0; klassOop receiver_limit_oop = NULL;
|
KlassHandle receiver_limit; int decode_flags = 0;
|
||||||
methodHandle m(THREAD,
|
methodHandle m = MethodHandles::decode_method(target(), receiver_limit, decode_flags);
|
||||||
MethodHandles::decode_method(target(),
|
|
||||||
receiver_limit_oop,
|
|
||||||
decode_flags));
|
|
||||||
KlassHandle receiver_limit(THREAD, receiver_limit_oop);
|
|
||||||
MethodHandles::init_BoundMethodHandle_with_receiver(mh, m,
|
MethodHandles::init_BoundMethodHandle_with_receiver(mh, m,
|
||||||
receiver_limit,
|
receiver_limit,
|
||||||
decode_flags,
|
decode_flags,
|
||||||
@ -2424,12 +2415,12 @@ JVM_ENTRY(jint, MHN_getNamedCon(JNIEnv *env, jobject igcls, jint which, jobjectA
|
|||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (which >= 0 && which < con_value_count) {
|
if (which >= 0 && which < con_value_count) {
|
||||||
int con = con_values[which];
|
int con = con_values[which];
|
||||||
objArrayOop box = (objArrayOop) JNIHandles::resolve(box_jh);
|
objArrayHandle box(THREAD, (objArrayOop) JNIHandles::resolve(box_jh));
|
||||||
if (box != NULL && box->klass() == Universe::objectArrayKlassObj() && box->length() > 0) {
|
if (box.not_null() && box->klass() == Universe::objectArrayKlassObj() && box->length() > 0) {
|
||||||
const char* str = &con_names[0];
|
const char* str = &con_names[0];
|
||||||
for (int i = 0; i < which; i++)
|
for (int i = 0; i < which; i++)
|
||||||
str += strlen(str) + 1; // skip name and null
|
str += strlen(str) + 1; // skip name and null
|
||||||
oop name = java_lang_String::create_oop_from_str(str, CHECK_0);
|
oop name = java_lang_String::create_oop_from_str(str, CHECK_0); // possible safepoint
|
||||||
box->obj_at_put(0, name);
|
box->obj_at_put(0, name);
|
||||||
}
|
}
|
||||||
return con;
|
return con;
|
||||||
@ -2486,10 +2477,10 @@ JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls,
|
|||||||
jclass clazz_jh, jstring name_jh, jstring sig_jh,
|
jclass clazz_jh, jstring name_jh, jstring sig_jh,
|
||||||
int mflags, jclass caller_jh, jint skip, jobjectArray results_jh)) {
|
int mflags, jclass caller_jh, jint skip, jobjectArray results_jh)) {
|
||||||
if (clazz_jh == NULL || results_jh == NULL) return -1;
|
if (clazz_jh == NULL || results_jh == NULL) return -1;
|
||||||
klassOop k_oop = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz_jh));
|
KlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz_jh)));
|
||||||
|
|
||||||
objArrayOop results = (objArrayOop) JNIHandles::resolve(results_jh);
|
objArrayHandle results(THREAD, (objArrayOop) JNIHandles::resolve(results_jh));
|
||||||
if (results == NULL || !results->is_objArray()) return -1;
|
if (results.is_null() || !results->is_objArray()) return -1;
|
||||||
|
|
||||||
TempNewSymbol name = NULL;
|
TempNewSymbol name = NULL;
|
||||||
TempNewSymbol sig = NULL;
|
TempNewSymbol sig = NULL;
|
||||||
@ -2502,20 +2493,20 @@ JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls,
|
|||||||
if (sig == NULL) return 0; // a match is not possible
|
if (sig == NULL) return 0; // a match is not possible
|
||||||
}
|
}
|
||||||
|
|
||||||
klassOop caller = NULL;
|
KlassHandle caller;
|
||||||
if (caller_jh != NULL) {
|
if (caller_jh != NULL) {
|
||||||
oop caller_oop = JNIHandles::resolve_non_null(caller_jh);
|
oop caller_oop = JNIHandles::resolve_non_null(caller_jh);
|
||||||
if (!java_lang_Class::is_instance(caller_oop)) return -1;
|
if (!java_lang_Class::is_instance(caller_oop)) return -1;
|
||||||
caller = java_lang_Class::as_klassOop(caller_oop);
|
caller = KlassHandle(THREAD, java_lang_Class::as_klassOop(caller_oop));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != NULL && sig != NULL && results != NULL) {
|
if (name != NULL && sig != NULL && results.not_null()) {
|
||||||
// try a direct resolve
|
// try a direct resolve
|
||||||
// %%% TO DO
|
// %%% TO DO
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = MethodHandles::find_MemberNames(k_oop, name, sig, mflags,
|
int res = MethodHandles::find_MemberNames(k(), name, sig, mflags,
|
||||||
caller, skip, results);
|
caller(), skip, results());
|
||||||
// TO DO: expand at least some of the MemberNames, to avoid massive callbacks
|
// TO DO: expand at least some of the MemberNames, to avoid massive callbacks
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -266,12 +266,12 @@ class MethodHandles: AllStatic {
|
|||||||
|
|
||||||
// helpers for decode_method.
|
// helpers for decode_method.
|
||||||
static methodOop decode_methodOop(methodOop m, int& decode_flags_result);
|
static methodOop decode_methodOop(methodOop m, int& decode_flags_result);
|
||||||
static methodOop decode_vmtarget(oop vmtarget, int vmindex, oop mtype, klassOop& receiver_limit_result, int& decode_flags_result);
|
static methodHandle decode_vmtarget(oop vmtarget, int vmindex, oop mtype, KlassHandle& receiver_limit_result, int& decode_flags_result);
|
||||||
static methodOop decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result);
|
static methodHandle decode_MemberName(oop mname, KlassHandle& receiver_limit_result, int& decode_flags_result);
|
||||||
static methodOop decode_MethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
static methodHandle decode_MethodHandle(oop mh, KlassHandle& receiver_limit_result, int& decode_flags_result);
|
||||||
static methodOop decode_DirectMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
static methodHandle decode_DirectMethodHandle(oop mh, KlassHandle& receiver_limit_result, int& decode_flags_result);
|
||||||
static methodOop decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
static methodHandle decode_BoundMethodHandle(oop mh, KlassHandle& receiver_limit_result, int& decode_flags_result);
|
||||||
static methodOop decode_AdapterMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
static methodHandle decode_AdapterMethodHandle(oop mh, KlassHandle& receiver_limit_result, int& decode_flags_result);
|
||||||
|
|
||||||
// Find out how many stack slots an mh pushes or pops.
|
// Find out how many stack slots an mh pushes or pops.
|
||||||
// The result is *not* reported as a multiple of stack_move_unit();
|
// The result is *not* reported as a multiple of stack_move_unit();
|
||||||
@ -317,7 +317,7 @@ class MethodHandles: AllStatic {
|
|||||||
_dmf_adapter_lsb = 0x20,
|
_dmf_adapter_lsb = 0x20,
|
||||||
_DMF_ADAPTER_MASK = (_dmf_adapter_lsb << CONV_OP_LIMIT) - _dmf_adapter_lsb
|
_DMF_ADAPTER_MASK = (_dmf_adapter_lsb << CONV_OP_LIMIT) - _dmf_adapter_lsb
|
||||||
};
|
};
|
||||||
static methodOop decode_method(oop x, klassOop& receiver_limit_result, int& decode_flags_result);
|
static methodHandle decode_method(oop x, KlassHandle& receiver_limit_result, int& decode_flags_result);
|
||||||
enum {
|
enum {
|
||||||
// format of query to getConstant:
|
// format of query to getConstant:
|
||||||
GC_JVM_PUSH_LIMIT = 0,
|
GC_JVM_PUSH_LIMIT = 0,
|
||||||
|
@ -620,6 +620,9 @@ class CommandLineFlags {
|
|||||||
product(bool, UseSSE42Intrinsics, false, \
|
product(bool, UseSSE42Intrinsics, false, \
|
||||||
"SSE4.2 versions of intrinsics") \
|
"SSE4.2 versions of intrinsics") \
|
||||||
\
|
\
|
||||||
|
product(bool, UseCondCardMark, false, \
|
||||||
|
"Check for already marked card before updating card table") \
|
||||||
|
\
|
||||||
develop(bool, TraceCallFixup, false, \
|
develop(bool, TraceCallFixup, false, \
|
||||||
"traces all call fixups") \
|
"traces all call fixups") \
|
||||||
\
|
\
|
||||||
|
@ -1721,14 +1721,14 @@ char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
|
|||||||
targetArity = ArgumentCount(target->signature()).size();
|
targetArity = ArgumentCount(target->signature()).size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
klassOop kignore; int dmf_flags = 0;
|
KlassHandle kignore; int dmf_flags = 0;
|
||||||
methodOop actual_method = MethodHandles::decode_method(actual, kignore, dmf_flags);
|
methodHandle actual_method = MethodHandles::decode_method(actual, kignore, dmf_flags);
|
||||||
if ((dmf_flags & ~(MethodHandles::_dmf_has_receiver |
|
if ((dmf_flags & ~(MethodHandles::_dmf_has_receiver |
|
||||||
MethodHandles::_dmf_does_dispatch |
|
MethodHandles::_dmf_does_dispatch |
|
||||||
MethodHandles::_dmf_from_interface)) != 0)
|
MethodHandles::_dmf_from_interface)) != 0)
|
||||||
actual_method = NULL; // MH does extra binds, drops, etc.
|
actual_method = methodHandle(); // MH does extra binds, drops, etc.
|
||||||
bool has_receiver = ((dmf_flags & MethodHandles::_dmf_has_receiver) != 0);
|
bool has_receiver = ((dmf_flags & MethodHandles::_dmf_has_receiver) != 0);
|
||||||
if (actual_method != NULL) {
|
if (actual_method.not_null()) {
|
||||||
mhName = actual_method->signature()->as_C_string();
|
mhName = actual_method->signature()->as_C_string();
|
||||||
mhArity = ArgumentCount(actual_method->signature()).size();
|
mhArity = ArgumentCount(actual_method->signature()).size();
|
||||||
if (!actual_method->is_static()) mhArity += 1;
|
if (!actual_method->is_static()) mhArity += 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user