Merge
This commit is contained in:
commit
5bec0d60ab
@ -63,12 +63,12 @@ public class SystemDictionary {
|
||||
javaSystemLoaderField = type.getOopField("_java_system_loader");
|
||||
nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue();
|
||||
|
||||
objectKlassField = type.getOopField(WK_KLASS("object_klass"));
|
||||
classLoaderKlassField = type.getOopField(WK_KLASS("classloader_klass"));
|
||||
stringKlassField = type.getOopField(WK_KLASS("string_klass"));
|
||||
systemKlassField = type.getOopField(WK_KLASS("system_klass"));
|
||||
threadKlassField = type.getOopField(WK_KLASS("thread_klass"));
|
||||
threadGroupKlassField = type.getOopField(WK_KLASS("threadGroup_klass"));
|
||||
objectKlassField = type.getOopField(WK_KLASS("Object_klass"));
|
||||
classLoaderKlassField = type.getOopField(WK_KLASS("ClassLoader_klass"));
|
||||
stringKlassField = type.getOopField(WK_KLASS("String_klass"));
|
||||
systemKlassField = type.getOopField(WK_KLASS("System_klass"));
|
||||
threadKlassField = type.getOopField(WK_KLASS("Thread_klass"));
|
||||
threadGroupKlassField = type.getOopField(WK_KLASS("ThreadGroup_klass"));
|
||||
}
|
||||
|
||||
// This WK functions must follow the definitions in systemDictionary.hpp:
|
||||
|
@ -1885,6 +1885,10 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
|
||||
|
@ -330,6 +330,14 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
||||
// This is the sp before any possible extension (adapter/locals).
|
||||
intptr_t* unextended_sp = interpreter_frame_sender_sp();
|
||||
|
||||
address sender_pc = this->sender_pc();
|
||||
CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc);
|
||||
assert(sender_cb, "sanity");
|
||||
nmethod* sender_nm = sender_cb->as_nmethod_or_null();
|
||||
if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) {
|
||||
unextended_sp = (intptr_t*) at(link_offset);
|
||||
}
|
||||
|
||||
// The interpreter and compiler(s) always save EBP/RBP in a known
|
||||
// location on entry. We must record where that location is
|
||||
// so this if EBP/RBP was live on callout from c2 we can find
|
||||
@ -352,7 +360,7 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
||||
#endif // AMD64
|
||||
}
|
||||
#endif /* COMPILER2 */
|
||||
return frame(sp, unextended_sp, link(), sender_pc());
|
||||
return frame(sp, unextended_sp, link(), sender_pc);
|
||||
}
|
||||
|
||||
|
||||
@ -375,6 +383,18 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
||||
|
||||
intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset);
|
||||
|
||||
intptr_t* unextended_sp = sender_sp;
|
||||
// If we are returning to a compiled method handle call site,
|
||||
// the saved_fp will in fact be a saved value of the unextended SP.
|
||||
// The simplest way to tell whether we are returning to such a call
|
||||
// site is as follows:
|
||||
CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc);
|
||||
assert(sender_cb, "sanity");
|
||||
nmethod* sender_nm = sender_cb->as_nmethod_or_null();
|
||||
if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) {
|
||||
unextended_sp = saved_fp;
|
||||
}
|
||||
|
||||
if (map->update_map()) {
|
||||
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
||||
// For C1, the runtime stub might not have oop maps, so set this flag
|
||||
@ -399,7 +419,7 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {
|
||||
}
|
||||
|
||||
assert(sender_sp != sp(), "must have changed");
|
||||
return frame(sender_sp, saved_fp, sender_pc);
|
||||
return frame(sender_sp, unextended_sp, saved_fp, sender_pc);
|
||||
}
|
||||
|
||||
frame frame::sender(RegisterMap* map) const {
|
||||
|
@ -225,11 +225,12 @@ inline methodOop* frame::interpreter_frame_method_addr() const {
|
||||
// top of expression stack
|
||||
inline intptr_t* frame::interpreter_frame_tos_address() const {
|
||||
intptr_t* last_sp = interpreter_frame_last_sp();
|
||||
if (last_sp == NULL ) {
|
||||
if (last_sp == NULL) {
|
||||
return sp();
|
||||
} else {
|
||||
// sp() may have been extended by an adapter
|
||||
assert(last_sp < fp() && last_sp >= sp(), "bad tos");
|
||||
// sp() may have been extended or shrunk by an adapter. At least
|
||||
// check that we don't fall behind the legal region.
|
||||
assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(), "bad tos");
|
||||
return last_sp;
|
||||
}
|
||||
}
|
||||
|
@ -65,9 +65,9 @@ static void verify_argslot(MacroAssembler* _masm, Register rax_argslot,
|
||||
// Verify that argslot lies within (rsp, rbp].
|
||||
Label L_ok, L_bad;
|
||||
__ cmpptr(rax_argslot, rbp);
|
||||
__ jcc(Assembler::above, L_bad);
|
||||
__ jccb(Assembler::above, L_bad);
|
||||
__ cmpptr(rsp, rax_argslot);
|
||||
__ jcc(Assembler::below, L_ok);
|
||||
__ jccb(Assembler::below, L_ok);
|
||||
__ bind(L_bad);
|
||||
__ stop(error_message);
|
||||
__ bind(L_ok);
|
||||
@ -136,9 +136,9 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
|
||||
if (arg_slots.is_register()) {
|
||||
Label L_ok, L_bad;
|
||||
__ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
|
||||
__ jcc(Assembler::greater, L_bad);
|
||||
__ jccb(Assembler::greater, L_bad);
|
||||
__ testl(arg_slots.as_register(), -stack_move_unit() - 1);
|
||||
__ jcc(Assembler::zero, L_ok);
|
||||
__ jccb(Assembler::zero, L_ok);
|
||||
__ bind(L_bad);
|
||||
__ stop("assert arg_slots <= 0 and clear low bits");
|
||||
__ bind(L_ok);
|
||||
@ -173,7 +173,7 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
|
||||
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
||||
__ addptr(rdx_temp, wordSize);
|
||||
__ cmpptr(rdx_temp, rax_argslot);
|
||||
__ jcc(Assembler::less, loop);
|
||||
__ jccb(Assembler::less, loop);
|
||||
}
|
||||
|
||||
// Now move the argslot down, to point to the opened-up space.
|
||||
@ -211,9 +211,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
||||
Label L_ok, L_bad;
|
||||
__ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
|
||||
__ cmpptr(rbx_temp, rbp);
|
||||
__ jcc(Assembler::above, L_bad);
|
||||
__ jccb(Assembler::above, L_bad);
|
||||
__ cmpptr(rsp, rax_argslot);
|
||||
__ jcc(Assembler::below, L_ok);
|
||||
__ jccb(Assembler::below, L_ok);
|
||||
__ bind(L_bad);
|
||||
__ stop("deleted argument(s) must fall within current frame");
|
||||
__ bind(L_ok);
|
||||
@ -221,9 +221,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
||||
if (arg_slots.is_register()) {
|
||||
Label L_ok, L_bad;
|
||||
__ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
|
||||
__ jcc(Assembler::less, L_bad);
|
||||
__ jccb(Assembler::less, L_bad);
|
||||
__ testl(arg_slots.as_register(), -stack_move_unit() - 1);
|
||||
__ jcc(Assembler::zero, L_ok);
|
||||
__ jccb(Assembler::zero, L_ok);
|
||||
__ bind(L_bad);
|
||||
__ stop("assert arg_slots >= 0 and clear low bits");
|
||||
__ bind(L_ok);
|
||||
@ -258,7 +258,7 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
||||
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
||||
__ addptr(rdx_temp, -wordSize);
|
||||
__ cmpptr(rdx_temp, rsp);
|
||||
__ jcc(Assembler::greaterEqual, loop);
|
||||
__ jccb(Assembler::greaterEqual, loop);
|
||||
}
|
||||
|
||||
// Now move the argslot up, to point to the just-copied block.
|
||||
@ -268,8 +268,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
extern "C" void print_method_handle(oop mh);
|
||||
void trace_method_handle_stub(const char* adaptername,
|
||||
oopDesc* mh,
|
||||
oop mh,
|
||||
intptr_t* entry_sp,
|
||||
intptr_t* saved_sp,
|
||||
intptr_t* saved_bp) {
|
||||
@ -280,6 +281,7 @@ void trace_method_handle_stub(const char* adaptername,
|
||||
adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);
|
||||
if (last_sp != saved_sp)
|
||||
printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
|
||||
if (Verbose) print_method_handle(mh);
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
@ -382,11 +384,11 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
// FIXME: fill in _raise_exception_method with a suitable sun.dyn method
|
||||
__ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
|
||||
__ testptr(rbx_method, rbx_method);
|
||||
__ jcc(Assembler::zero, no_method);
|
||||
__ jccb(Assembler::zero, no_method);
|
||||
int jobject_oop_offset = 0;
|
||||
__ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject
|
||||
__ testptr(rbx_method, rbx_method);
|
||||
__ jcc(Assembler::zero, no_method);
|
||||
__ jccb(Assembler::zero, no_method);
|
||||
__ verify_oop(rbx_method);
|
||||
__ push(rdi_pc); // and restore caller PC
|
||||
__ jmp(rbx_method_fie);
|
||||
@ -533,16 +535,15 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
if (arg_type == T_OBJECT) {
|
||||
__ movptr(Address(rax_argslot, 0), rbx_temp);
|
||||
} else {
|
||||
__ load_sized_value(rbx_temp, prim_value_addr,
|
||||
__ load_sized_value(rdx_temp, prim_value_addr,
|
||||
type2aelembytes(arg_type), is_signed_subword_type(arg_type));
|
||||
__ movptr(Address(rax_argslot, 0), rbx_temp);
|
||||
__ movptr(Address(rax_argslot, 0), rdx_temp);
|
||||
#ifndef _LP64
|
||||
if (arg_slots == 2) {
|
||||
__ movl(rbx_temp, prim_value_addr.plus_disp(wordSize));
|
||||
__ movl(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp);
|
||||
__ movl(rdx_temp, prim_value_addr.plus_disp(wordSize));
|
||||
__ movl(Address(rax_argslot, Interpreter::stackElementSize()), rdx_temp);
|
||||
}
|
||||
#endif //_LP64
|
||||
break;
|
||||
}
|
||||
|
||||
if (direct_to_method) {
|
||||
@ -584,7 +585,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
Label done;
|
||||
__ movptr(rdx_temp, vmarg);
|
||||
__ testl(rdx_temp, rdx_temp);
|
||||
__ jcc(Assembler::zero, done); // no cast if null
|
||||
__ jccb(Assembler::zero, done); // no cast if null
|
||||
__ load_klass(rdx_temp, rdx_temp);
|
||||
|
||||
// live at this point:
|
||||
@ -675,24 +676,24 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
// (now we are done with the old MH)
|
||||
|
||||
// original 32-bit vmdata word must be of this form:
|
||||
// | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
|
||||
__ xchgl(rcx, rbx_vminfo); // free rcx for shifts
|
||||
// | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
|
||||
__ xchgptr(rcx, rbx_vminfo); // free rcx for shifts
|
||||
__ shll(rdx_temp /*, rcx*/);
|
||||
Label zero_extend, done;
|
||||
__ testl(rcx, CONV_VMINFO_SIGN_FLAG);
|
||||
__ jcc(Assembler::zero, zero_extend);
|
||||
__ jccb(Assembler::zero, zero_extend);
|
||||
|
||||
// this path is taken for int->byte, int->short
|
||||
__ sarl(rdx_temp /*, rcx*/);
|
||||
__ jmp(done);
|
||||
__ jmpb(done);
|
||||
|
||||
__ bind(zero_extend);
|
||||
// this is taken for int->char
|
||||
__ shrl(rdx_temp /*, rcx*/);
|
||||
|
||||
__ bind(done);
|
||||
__ movptr(vmarg, rdx_temp);
|
||||
__ xchgl(rcx, rbx_vminfo); // restore rcx_recv
|
||||
__ movl(vmarg, rdx_temp);
|
||||
__ xchgptr(rcx, rbx_vminfo); // restore rcx_recv
|
||||
|
||||
__ jump_to_method_handle_entry(rcx_recv, rdx_temp);
|
||||
}
|
||||
@ -861,7 +862,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
// Verify that argslot > destslot, by at least swap_bytes.
|
||||
Label L_ok;
|
||||
__ cmpptr(rax_argslot, rbx_destslot);
|
||||
__ jcc(Assembler::aboveEqual, L_ok);
|
||||
__ jccb(Assembler::aboveEqual, L_ok);
|
||||
__ stop("source must be above destination (upward rotation)");
|
||||
__ bind(L_ok);
|
||||
}
|
||||
@ -877,7 +878,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
__ movptr(Address(rax_argslot, swap_bytes), rdx_temp);
|
||||
__ addptr(rax_argslot, -wordSize);
|
||||
__ cmpptr(rax_argslot, rbx_destslot);
|
||||
__ jcc(Assembler::aboveEqual, loop);
|
||||
__ jccb(Assembler::aboveEqual, loop);
|
||||
} else {
|
||||
__ addptr(rax_argslot, swap_bytes);
|
||||
#ifdef ASSERT
|
||||
@ -885,7 +886,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
// Verify that argslot < destslot, by at least swap_bytes.
|
||||
Label L_ok;
|
||||
__ cmpptr(rax_argslot, rbx_destslot);
|
||||
__ jcc(Assembler::belowEqual, L_ok);
|
||||
__ jccb(Assembler::belowEqual, L_ok);
|
||||
__ stop("source must be below destination (downward rotation)");
|
||||
__ bind(L_ok);
|
||||
}
|
||||
@ -901,7 +902,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
__ movptr(Address(rax_argslot, -swap_bytes), rdx_temp);
|
||||
__ addptr(rax_argslot, wordSize);
|
||||
__ cmpptr(rax_argslot, rbx_destslot);
|
||||
__ jcc(Assembler::belowEqual, loop);
|
||||
__ jccb(Assembler::belowEqual, loop);
|
||||
}
|
||||
|
||||
// pop the original first chunk into the destination slot, now free
|
||||
@ -967,7 +968,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
__ addptr(rax_argslot, wordSize);
|
||||
__ addptr(rdx_newarg, wordSize);
|
||||
__ cmpptr(rdx_newarg, rbx_oldarg);
|
||||
__ jcc(Assembler::less, loop);
|
||||
__ jccb(Assembler::less, loop);
|
||||
|
||||
__ pop(rdi); // restore temp
|
||||
|
||||
@ -1119,7 +1120,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
||||
}
|
||||
__ addptr(rax_argslot, Interpreter::stackElementSize());
|
||||
__ cmpptr(rax_argslot, rdx_argslot_limit);
|
||||
__ jcc(Assembler::less, loop);
|
||||
__ jccb(Assembler::less, loop);
|
||||
} else if (length_constant == 0) {
|
||||
__ bind(skip_array_check);
|
||||
// nothing to copy
|
||||
|
@ -43,11 +43,11 @@ ExceptionBlob* OptoRuntime::_exception_blob;
|
||||
// This code is entered with a jmp.
|
||||
//
|
||||
// Arguments:
|
||||
// rax,: exception oop
|
||||
// rax: exception oop
|
||||
// rdx: exception pc
|
||||
//
|
||||
// Results:
|
||||
// rax,: exception oop
|
||||
// rax: exception oop
|
||||
// rdx: exception pc in caller or ???
|
||||
// destination: exception handler of caller
|
||||
//
|
||||
@ -113,17 +113,17 @@ void OptoRuntime::generate_exception_blob() {
|
||||
__ addptr(rsp, return_off * wordSize); // Epilog!
|
||||
__ pop(rdx); // Exception pc
|
||||
|
||||
// rax: exception handler for given <exception oop/exception pc>
|
||||
|
||||
// rax,: exception handler for given <exception oop/exception pc>
|
||||
// Restore SP from BP if the exception PC is a MethodHandle call.
|
||||
__ cmpl(Address(rcx, JavaThread::is_method_handle_exception_offset()), 0);
|
||||
__ cmovptr(Assembler::notEqual, rsp, rbp);
|
||||
|
||||
// We have a handler in rax, (could be deopt blob)
|
||||
// rdx - throwing pc, deopt blob will need it.
|
||||
|
||||
__ push(rax);
|
||||
|
||||
// rcx contains handler address
|
||||
|
||||
__ get_thread(rcx); // TLS
|
||||
// Get the exception
|
||||
__ movptr(rax, Address(rcx, JavaThread::exception_oop_offset()));
|
||||
// Get the exception pc in case we are deoptimized
|
||||
@ -137,7 +137,7 @@ void OptoRuntime::generate_exception_blob() {
|
||||
|
||||
__ pop(rcx);
|
||||
|
||||
// rax,: exception oop
|
||||
// rax: exception oop
|
||||
// rcx: exception handler
|
||||
// rdx: exception pc
|
||||
__ jmp (rcx);
|
||||
|
@ -638,6 +638,10 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||
|
||||
__ movptr(rax, Address(rsp, 0));
|
||||
|
||||
// Must preserve original SP for loading incoming arguments because
|
||||
// we need to align the outgoing SP for compiled code.
|
||||
__ movptr(r11, rsp);
|
||||
|
||||
// Cut-out for having no stack args. Since up to 2 int/oop args are passed
|
||||
// in registers, we will occasionally have no stack args.
|
||||
int comp_words_on_stack = 0;
|
||||
@ -661,6 +665,10 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||
// as far as the placement of the call instruction
|
||||
__ push(rax);
|
||||
|
||||
// Put saved SP in another register
|
||||
const Register saved_sp = rax;
|
||||
__ movptr(saved_sp, r11);
|
||||
|
||||
// Will jump to the compiled code just as if compiled code was doing it.
|
||||
// Pre-load the register-jump target early, to schedule it better.
|
||||
__ movptr(r11, Address(rbx, in_bytes(methodOopDesc::from_compiled_offset())));
|
||||
@ -680,11 +688,7 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||
assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(),
|
||||
"scrambled load targets?");
|
||||
// Load in argument order going down.
|
||||
// int ld_off = (total_args_passed + comp_words_on_stack -i)*wordSize;
|
||||
// base ld_off on r13 (sender_sp) as the stack alignment makes offsets from rsp
|
||||
// unpredictable
|
||||
int ld_off = ((total_args_passed - 1) - i)*Interpreter::stackElementSize();
|
||||
|
||||
int ld_off = (total_args_passed - i)*Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes();
|
||||
// Point to interpreter value (vs. tag)
|
||||
int next_off = ld_off - Interpreter::stackElementSize();
|
||||
//
|
||||
@ -699,10 +703,14 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||
if (r_1->is_stack()) {
|
||||
// Convert stack slot to an SP offset (+ wordSize to account for return address )
|
||||
int st_off = regs[i].first()->reg2stack()*VMRegImpl::stack_slot_size + wordSize;
|
||||
|
||||
// We can use r13 as a temp here because compiled code doesn't need r13 as an input
|
||||
// and if we end up going thru a c2i because of a miss a reasonable value of r13
|
||||
// will be generated.
|
||||
if (!r_2->is_valid()) {
|
||||
// sign extend???
|
||||
__ movl(rax, Address(r13, ld_off));
|
||||
__ movptr(Address(rsp, st_off), rax);
|
||||
__ movl(r13, Address(saved_sp, ld_off));
|
||||
__ movptr(Address(rsp, st_off), r13);
|
||||
} else {
|
||||
//
|
||||
// We are using two optoregs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE
|
||||
@ -715,9 +723,9 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||
// ld_off is MSW so get LSW
|
||||
const int offset = (sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)?
|
||||
next_off : ld_off;
|
||||
__ movq(rax, Address(r13, offset));
|
||||
__ movq(r13, Address(saved_sp, offset));
|
||||
// st_off is LSW (i.e. reg.first())
|
||||
__ movq(Address(rsp, st_off), rax);
|
||||
__ movq(Address(rsp, st_off), r13);
|
||||
}
|
||||
} else if (r_1->is_Register()) { // Register argument
|
||||
Register r = r_1->as_Register();
|
||||
@ -732,16 +740,16 @@ static void gen_i2c_adapter(MacroAssembler *masm,
|
||||
next_off : ld_off;
|
||||
|
||||
// this can be a misaligned move
|
||||
__ movq(r, Address(r13, offset));
|
||||
__ movq(r, Address(saved_sp, offset));
|
||||
} else {
|
||||
// sign extend and use a full word?
|
||||
__ movl(r, Address(r13, ld_off));
|
||||
__ movl(r, Address(saved_sp, ld_off));
|
||||
}
|
||||
} else {
|
||||
if (!r_2->is_valid()) {
|
||||
__ movflt(r_1->as_XMMRegister(), Address(r13, ld_off));
|
||||
__ movflt(r_1->as_XMMRegister(), Address(saved_sp, ld_off));
|
||||
} else {
|
||||
__ movdbl(r_1->as_XMMRegister(), Address(r13, next_off));
|
||||
__ movdbl(r_1->as_XMMRegister(), Address(saved_sp, next_off));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3319,6 +3327,10 @@ void OptoRuntime::generate_exception_blob() {
|
||||
|
||||
// rax: exception handler
|
||||
|
||||
// Restore SP from BP if the exception PC is a MethodHandle call.
|
||||
__ cmpl(Address(r15_thread, JavaThread::is_method_handle_exception_offset()), 0);
|
||||
__ cmovptr(Assembler::notEqual, rsp, rbp);
|
||||
|
||||
// We have a handler in rax (could be deopt blob).
|
||||
__ mov(r8, rax);
|
||||
|
||||
|
@ -1488,7 +1488,10 @@ int AbstractInterpreter::layout_activation(methodOop method,
|
||||
|
||||
if (interpreter_frame != NULL) {
|
||||
#ifdef ASSERT
|
||||
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
|
||||
if (!EnableMethodHandles)
|
||||
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
|
||||
// Probably, since deoptimization doesn't work yet.
|
||||
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
|
||||
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
|
||||
#endif
|
||||
|
||||
|
@ -449,8 +449,12 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
|
||||
__ addptr(rax, stack_base);
|
||||
__ subptr(rax, stack_size);
|
||||
|
||||
// Use the maximum number of pages we might bang.
|
||||
const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages) ? StackShadowPages :
|
||||
(StackRedPages+StackYellowPages);
|
||||
|
||||
// add in the red and yellow zone sizes
|
||||
__ addptr(rax, (StackRedPages + StackYellowPages) * page_size);
|
||||
__ addptr(rax, max_pages * page_size);
|
||||
|
||||
// check against the current stack bottom
|
||||
__ cmpptr(rsp, rax);
|
||||
@ -1502,8 +1506,10 @@ int AbstractInterpreter::layout_activation(methodOop method,
|
||||
tempcount* Interpreter::stackElementWords() + popframe_extra_args;
|
||||
if (interpreter_frame != NULL) {
|
||||
#ifdef ASSERT
|
||||
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(),
|
||||
"Frame not properly walkable");
|
||||
if (!EnableMethodHandles)
|
||||
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
|
||||
// Probably, since deoptimization doesn't work yet.
|
||||
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
|
||||
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
|
||||
#endif
|
||||
|
||||
|
@ -268,22 +268,36 @@ static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CON
|
||||
static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000));
|
||||
static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
|
||||
|
||||
// Offset hacking within calls.
|
||||
static int pre_call_FPU_size() {
|
||||
if (Compile::current()->in_24_bit_fp_mode())
|
||||
return 6; // fldcw
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int preserve_SP_size() {
|
||||
return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg)
|
||||
}
|
||||
|
||||
// !!!!! Special hack to get all type of calls to specify the byte offset
|
||||
// from the start of the call to the point where the return address
|
||||
// will point.
|
||||
int MachCallStaticJavaNode::ret_addr_offset() {
|
||||
return 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 5 bytes from start of call to where return address points
|
||||
int offset = 5 + pre_call_FPU_size(); // 5 bytes from start of call to where return address points
|
||||
if (_method_handle_invoke)
|
||||
offset += preserve_SP_size();
|
||||
return offset;
|
||||
}
|
||||
|
||||
int MachCallDynamicJavaNode::ret_addr_offset() {
|
||||
return 10 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 10 bytes from start of call to where return address points
|
||||
return 10 + pre_call_FPU_size(); // 10 bytes from start of call to where return address points
|
||||
}
|
||||
|
||||
static int sizeof_FFree_Float_Stack_All = -1;
|
||||
|
||||
int MachCallRuntimeNode::ret_addr_offset() {
|
||||
assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already");
|
||||
return sizeof_FFree_Float_Stack_All + 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0);
|
||||
return sizeof_FFree_Float_Stack_All + 5 + pre_call_FPU_size();
|
||||
}
|
||||
|
||||
// Indicate if the safepoint node needs the polling page as an input.
|
||||
@ -299,8 +313,16 @@ bool SafePointNode::needs_polling_address_input() {
|
||||
// The address of the call instruction needs to be 4-byte aligned to
|
||||
// ensure that it does not span a cache line so that it can be patched.
|
||||
int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
|
||||
if (Compile::current()->in_24_bit_fp_mode())
|
||||
current_offset += 6; // skip fldcw in pre_call_FPU, if any
|
||||
current_offset += pre_call_FPU_size(); // skip fldcw, if any
|
||||
current_offset += 1; // skip call opcode byte
|
||||
return round_to(current_offset, alignment_required()) - current_offset;
|
||||
}
|
||||
|
||||
// The address of the call instruction needs to be 4-byte aligned to
|
||||
// ensure that it does not span a cache line so that it can be patched.
|
||||
int CallStaticJavaHandleNode::compute_padding(int current_offset) const {
|
||||
current_offset += pre_call_FPU_size(); // skip fldcw, if any
|
||||
current_offset += preserve_SP_size(); // skip mov rbp, rsp
|
||||
current_offset += 1; // skip call opcode byte
|
||||
return round_to(current_offset, alignment_required()) - current_offset;
|
||||
}
|
||||
@ -308,8 +330,7 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
|
||||
// The address of the call instruction needs to be 4-byte aligned to
|
||||
// ensure that it does not span a cache line so that it can be patched.
|
||||
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const {
|
||||
if (Compile::current()->in_24_bit_fp_mode())
|
||||
current_offset += 6; // skip fldcw in pre_call_FPU, if any
|
||||
current_offset += pre_call_FPU_size(); // skip fldcw, if any
|
||||
current_offset += 5; // skip MOV instruction
|
||||
current_offset += 1; // skip call opcode byte
|
||||
return round_to(current_offset, alignment_required()) - current_offset;
|
||||
@ -1460,6 +1481,10 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return EBP_REG_mask;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
//----------ENCODING BLOCK-----------------------------------------------------
|
||||
@ -1772,10 +1797,13 @@ encode %{
|
||||
|
||||
enc_class pre_call_FPU %{
|
||||
// If method sets FPU control word restore it here
|
||||
debug_only(int off0 = cbuf.code_size());
|
||||
if( Compile::current()->in_24_bit_fp_mode() ) {
|
||||
MacroAssembler masm(&cbuf);
|
||||
masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
|
||||
}
|
||||
debug_only(int off1 = cbuf.code_size());
|
||||
assert(off1 - off0 == pre_call_FPU_size(), "correct size prediction");
|
||||
%}
|
||||
|
||||
enc_class post_call_FPU %{
|
||||
@ -1786,6 +1814,21 @@ encode %{
|
||||
}
|
||||
%}
|
||||
|
||||
enc_class preserve_SP %{
|
||||
debug_only(int off0 = cbuf.code_size());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
// RBP is preserved across all calls, even compiled calls.
|
||||
// Use it to preserve RSP in places where the callee might change the SP.
|
||||
__ movptr(rbp, rsp);
|
||||
debug_only(int off1 = cbuf.code_size());
|
||||
assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
|
||||
%}
|
||||
|
||||
enc_class restore_SP %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ movptr(rsp, rbp);
|
||||
%}
|
||||
|
||||
enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL
|
||||
// CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
|
||||
// who we intended to call.
|
||||
@ -13406,6 +13449,7 @@ instruct cmovXX_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regX dst,
|
||||
// compute_padding() functions will have to be adjusted.
|
||||
instruct CallStaticJavaDirect(method meth) %{
|
||||
match(CallStaticJava);
|
||||
predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
|
||||
effect(USE meth);
|
||||
|
||||
ins_cost(300);
|
||||
@ -13420,6 +13464,30 @@ instruct CallStaticJavaDirect(method meth) %{
|
||||
ins_alignment(4);
|
||||
%}
|
||||
|
||||
// Call Java Static Instruction (method handle version)
|
||||
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||
// compute_padding() functions will have to be adjusted.
|
||||
instruct CallStaticJavaHandle(method meth, eBPRegP ebp) %{
|
||||
match(CallStaticJava);
|
||||
predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
|
||||
effect(USE meth);
|
||||
// EBP is saved by all callees (for interpreter stack correction).
|
||||
// We use it here for a similar purpose, in {preserve,restore}_SP.
|
||||
|
||||
ins_cost(300);
|
||||
format %{ "CALL,static/MethodHandle " %}
|
||||
opcode(0xE8); /* E8 cd */
|
||||
ins_encode( pre_call_FPU,
|
||||
preserve_SP,
|
||||
Java_Static_Call( meth ),
|
||||
restore_SP,
|
||||
call_epilog,
|
||||
post_call_FPU );
|
||||
ins_pipe( pipe_slow );
|
||||
ins_pc_relative(1);
|
||||
ins_alignment(4);
|
||||
%}
|
||||
|
||||
// Call Java Dynamic Instruction
|
||||
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||
// compute_padding() functions will have to be adjusted.
|
||||
|
@ -551,12 +551,19 @@ source %{
|
||||
|
||||
#define __ _masm.
|
||||
|
||||
static int preserve_SP_size() {
|
||||
return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg)
|
||||
}
|
||||
|
||||
// !!!!! Special hack to get all types of calls to specify the byte offset
|
||||
// from the start of the call to the point where the return address
|
||||
// will point.
|
||||
int MachCallStaticJavaNode::ret_addr_offset()
|
||||
{
|
||||
return 5; // 5 bytes from start of call to where return address points
|
||||
int offset = 5; // 5 bytes from start of call to where return address points
|
||||
if (_method_handle_invoke)
|
||||
offset += preserve_SP_size();
|
||||
return offset;
|
||||
}
|
||||
|
||||
int MachCallDynamicJavaNode::ret_addr_offset()
|
||||
@ -587,6 +594,15 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const
|
||||
return round_to(current_offset, alignment_required()) - current_offset;
|
||||
}
|
||||
|
||||
// The address of the call instruction needs to be 4-byte aligned to
|
||||
// ensure that it does not span a cache line so that it can be patched.
|
||||
int CallStaticJavaHandleNode::compute_padding(int current_offset) const
|
||||
{
|
||||
current_offset += preserve_SP_size(); // skip mov rbp, rsp
|
||||
current_offset += 1; // skip call opcode byte
|
||||
return round_to(current_offset, alignment_required()) - current_offset;
|
||||
}
|
||||
|
||||
// The address of the call instruction needs to be 4-byte aligned to
|
||||
// ensure that it does not span a cache line so that it can be patched.
|
||||
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
|
||||
@ -2113,6 +2129,10 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return LONG_RDX_REG_mask;
|
||||
}
|
||||
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return PTR_RBP_REG_mask;
|
||||
}
|
||||
|
||||
static Address build_address(int b, int i, int s, int d) {
|
||||
Register index = as_Register(i);
|
||||
Address::ScaleFactor scale = (Address::ScaleFactor)s;
|
||||
@ -2608,6 +2628,21 @@ encode %{
|
||||
RELOC_DISP32);
|
||||
%}
|
||||
|
||||
enc_class preserve_SP %{
|
||||
debug_only(int off0 = cbuf.code_size());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
// RBP is preserved across all calls, even compiled calls.
|
||||
// Use it to preserve RSP in places where the callee might change the SP.
|
||||
__ movptr(rbp, rsp);
|
||||
debug_only(int off1 = cbuf.code_size());
|
||||
assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
|
||||
%}
|
||||
|
||||
enc_class restore_SP %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ movptr(rsp, rbp);
|
||||
%}
|
||||
|
||||
enc_class Java_Static_Call(method meth)
|
||||
%{
|
||||
// JAVA STATIC CALL
|
||||
@ -12526,9 +12561,9 @@ instruct safePoint_poll(rFlagsReg cr)
|
||||
// Call Java Static Instruction
|
||||
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||
// compute_padding() functions will have to be adjusted.
|
||||
instruct CallStaticJavaDirect(method meth)
|
||||
%{
|
||||
instruct CallStaticJavaDirect(method meth) %{
|
||||
match(CallStaticJava);
|
||||
predicate(!((CallStaticJavaNode*) n)->is_method_handle_invoke());
|
||||
effect(USE meth);
|
||||
|
||||
ins_cost(300);
|
||||
@ -12540,6 +12575,28 @@ instruct CallStaticJavaDirect(method meth)
|
||||
ins_alignment(4);
|
||||
%}
|
||||
|
||||
// Call Java Static Instruction (method handle version)
|
||||
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||
// compute_padding() functions will have to be adjusted.
|
||||
instruct CallStaticJavaHandle(method meth, rbp_RegP rbp) %{
|
||||
match(CallStaticJava);
|
||||
predicate(((CallStaticJavaNode*) n)->is_method_handle_invoke());
|
||||
effect(USE meth);
|
||||
// RBP is saved by all callees (for interpreter stack correction).
|
||||
// We use it here for a similar purpose, in {preserve,restore}_SP.
|
||||
|
||||
ins_cost(300);
|
||||
format %{ "call,static/MethodHandle " %}
|
||||
opcode(0xE8); /* E8 cd */
|
||||
ins_encode(preserve_SP,
|
||||
Java_Static_Call(meth),
|
||||
restore_SP,
|
||||
call_epilog);
|
||||
ins_pipe(pipe_slow);
|
||||
ins_pc_relative(1);
|
||||
ins_alignment(4);
|
||||
%}
|
||||
|
||||
// Call Java Dynamic Instruction
|
||||
// Note: If this code changes, the corresponding ret_addr_offset() and
|
||||
// compute_padding() functions will have to be adjusted.
|
||||
|
@ -245,7 +245,7 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
|
||||
if (handlerAddr == NULL) {
|
||||
CALL_VM_NOCHECK(InterpreterRuntime::prepare_native_call(thread, method));
|
||||
if (HAS_PENDING_EXCEPTION)
|
||||
goto unwind_and_return;
|
||||
goto unlock_unwind_and_return;
|
||||
|
||||
handlerAddr = method->signature_handler();
|
||||
assert(handlerAddr != NULL, "eh?");
|
||||
@ -254,7 +254,7 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
|
||||
CALL_VM_NOCHECK(handlerAddr =
|
||||
InterpreterRuntime::slow_signature_handler(thread, method, NULL,NULL));
|
||||
if (HAS_PENDING_EXCEPTION)
|
||||
goto unwind_and_return;
|
||||
goto unlock_unwind_and_return;
|
||||
}
|
||||
handler = \
|
||||
InterpreterRuntime::SignatureHandler::from_handlerAddr(handlerAddr);
|
||||
@ -365,10 +365,10 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
|
||||
// Reset handle block
|
||||
thread->active_handles()->clear();
|
||||
|
||||
// Unlock if necessary. It seems totally wrong that this
|
||||
// is skipped in the event of an exception but apparently
|
||||
// the template interpreter does this so we do too.
|
||||
if (monitor && !HAS_PENDING_EXCEPTION) {
|
||||
unlock_unwind_and_return:
|
||||
|
||||
// Unlock if necessary
|
||||
if (monitor) {
|
||||
BasicLock *lock = monitor->lock();
|
||||
markOop header = lock->displaced_header();
|
||||
oop rcvr = monitor->obj();
|
||||
|
@ -251,8 +251,9 @@ class IRScopeDebugInfo: public CompilationResourceObj {
|
||||
DebugToken* expvals = recorder->create_scope_values(expressions());
|
||||
DebugToken* monvals = recorder->create_monitor_values(monitors());
|
||||
// reexecute allowed only for the topmost frame
|
||||
bool reexecute = topmost ? should_reexecute() : false;
|
||||
recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, locvals, expvals, monvals);
|
||||
bool reexecute = topmost ? should_reexecute() : false;
|
||||
bool is_method_handle_invoke = false;
|
||||
recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, locvals, expvals, monvals);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -425,7 +425,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
|
||||
assert(exception.not_null(), "NULL exceptions should be handled by throw_exception");
|
||||
assert(exception->is_oop(), "just checking");
|
||||
// Check that exception is a subclass of Throwable, otherwise we have a VerifyError
|
||||
if (!(exception->is_a(SystemDictionary::throwable_klass()))) {
|
||||
if (!(exception->is_a(SystemDictionary::Throwable_klass()))) {
|
||||
if (ExitVMOnVerifyError) vm_exit(-1);
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
49
hotspot/src/share/vm/ci/ciCPCache.cpp
Normal file
49
hotspot/src/share/vm/ci/ciCPCache.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "incls/_precompiled.incl"
|
||||
#include "incls/_ciCPCache.cpp.incl"
|
||||
|
||||
// ciCPCache
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciCPCache::get_f1_offset
|
||||
size_t ciCPCache::get_f1_offset(int index) {
|
||||
// Calculate the offset from the constantPoolCacheOop to the f1
|
||||
// field.
|
||||
ByteSize f1_offset =
|
||||
constantPoolCacheOopDesc::entry_offset(index) +
|
||||
ConstantPoolCacheEntry::f1_offset();
|
||||
|
||||
return in_bytes(f1_offset);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciCPCache::print
|
||||
//
|
||||
// Print debugging information about the cache.
|
||||
void ciCPCache::print() {
|
||||
Unimplemented();
|
||||
}
|
43
hotspot/src/share/vm/ci/ciCPCache.hpp
Normal file
43
hotspot/src/share/vm/ci/ciCPCache.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
// ciCPCache
|
||||
//
|
||||
// This class represents a constant pool cache.
|
||||
//
|
||||
// Note: This class is called ciCPCache as ciConstantPoolCache is used
|
||||
// for something different.
|
||||
class ciCPCache : public ciObject {
|
||||
public:
|
||||
ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {}
|
||||
|
||||
// What kind of ciObject is this?
|
||||
bool is_cpcache() const { return true; }
|
||||
|
||||
// Get the offset in bytes from the oop to the f1 field of the
|
||||
// requested entry.
|
||||
size_t get_f1_offset(int index);
|
||||
|
||||
void print();
|
||||
};
|
46
hotspot/src/share/vm/ci/ciCallSite.cpp
Normal file
46
hotspot/src/share/vm/ci/ciCallSite.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "incls/_precompiled.incl"
|
||||
#include "incls/_ciCallSite.cpp.incl"
|
||||
|
||||
// ciCallSite
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciCallSite::get_target
|
||||
//
|
||||
// Return the target MethodHandle of this CallSite.
|
||||
ciMethodHandle* ciCallSite::get_target() const {
|
||||
VM_ENTRY_MARK;
|
||||
oop method_handle_oop = java_dyn_CallSite::target(get_oop());
|
||||
return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciCallSite::print
|
||||
//
|
||||
// Print debugging information about the CallSite.
|
||||
void ciCallSite::print() {
|
||||
Unimplemented();
|
||||
}
|
39
hotspot/src/share/vm/ci/ciCallSite.hpp
Normal file
39
hotspot/src/share/vm/ci/ciCallSite.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
// ciCallSite
|
||||
//
|
||||
// The class represents a java.dyn.CallSite object.
|
||||
class ciCallSite : public ciInstance {
|
||||
public:
|
||||
ciCallSite(instanceHandle h_i) : ciInstance(h_i) {}
|
||||
|
||||
// What kind of ciObject is this?
|
||||
bool is_call_site() const { return true; }
|
||||
|
||||
// Return the target MethodHandle of this CallSite.
|
||||
ciMethodHandle* get_target() const;
|
||||
|
||||
void print();
|
||||
};
|
@ -25,6 +25,7 @@
|
||||
class ciEnv;
|
||||
class ciObjectFactory;
|
||||
class ciConstantPoolCache;
|
||||
class ciCPCache;
|
||||
|
||||
class ciField;
|
||||
class ciConstant;
|
||||
@ -42,6 +43,8 @@ class ciTypeFlow;
|
||||
class ciObject;
|
||||
class ciNullObject;
|
||||
class ciInstance;
|
||||
class ciCallSite;
|
||||
class ciMethodHandle;
|
||||
class ciMethod;
|
||||
class ciMethodData;
|
||||
class ciReceiverTypeData; // part of ciMethodData
|
||||
@ -78,6 +81,7 @@ friend class ciObjectFactory;
|
||||
// Any more access must be given explicitly.
|
||||
#define CI_PACKAGE_ACCESS_TO \
|
||||
friend class ciObjectFactory; \
|
||||
friend class ciCallSite; \
|
||||
friend class ciConstantPoolCache; \
|
||||
friend class ciField; \
|
||||
friend class ciConstant; \
|
||||
@ -93,6 +97,7 @@ friend class ciNullObject; \
|
||||
friend class ciInstance; \
|
||||
friend class ciMethod; \
|
||||
friend class ciMethodData; \
|
||||
friend class ciMethodHandle; \
|
||||
friend class ciReceiverTypeData; \
|
||||
friend class ciSymbol; \
|
||||
friend class ciArray; \
|
||||
|
@ -38,17 +38,9 @@ ciInstanceKlassKlass* ciEnv::_instance_klass_klass_instance;
|
||||
ciTypeArrayKlassKlass* ciEnv::_type_array_klass_klass_instance;
|
||||
ciObjArrayKlassKlass* ciEnv::_obj_array_klass_klass_instance;
|
||||
|
||||
ciInstanceKlass* ciEnv::_ArrayStoreException;
|
||||
ciInstanceKlass* ciEnv::_Class;
|
||||
ciInstanceKlass* ciEnv::_ClassCastException;
|
||||
ciInstanceKlass* ciEnv::_Object;
|
||||
ciInstanceKlass* ciEnv::_Throwable;
|
||||
ciInstanceKlass* ciEnv::_Thread;
|
||||
ciInstanceKlass* ciEnv::_OutOfMemoryError;
|
||||
ciInstanceKlass* ciEnv::_String;
|
||||
ciInstanceKlass* ciEnv::_StringBuffer;
|
||||
ciInstanceKlass* ciEnv::_StringBuilder;
|
||||
ciInstanceKlass* ciEnv::_Integer;
|
||||
#define WK_KLASS_DEFN(name, ignore_s, ignore_o) ciInstanceKlass* ciEnv::_##name = NULL;
|
||||
WK_KLASSES_DO(WK_KLASS_DEFN)
|
||||
#undef WK_KLASS_DEFN
|
||||
|
||||
ciSymbol* ciEnv::_unloaded_cisymbol = NULL;
|
||||
ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = NULL;
|
||||
@ -442,12 +434,11 @@ ciKlass* ciEnv::get_klass_by_name(ciKlass* accessing_klass,
|
||||
// ciEnv::get_klass_by_index_impl
|
||||
//
|
||||
// Implementation of get_klass_by_index.
|
||||
ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor,
|
||||
ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool,
|
||||
int index,
|
||||
bool& is_accessible) {
|
||||
assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
|
||||
bool& is_accessible,
|
||||
ciInstanceKlass* accessor) {
|
||||
EXCEPTION_CONTEXT;
|
||||
constantPoolHandle cpool(THREAD, accessor->get_instanceKlass()->constants());
|
||||
KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index));
|
||||
symbolHandle klass_name;
|
||||
if (klass.is_null()) {
|
||||
@ -509,22 +500,21 @@ ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor,
|
||||
// ciEnv::get_klass_by_index
|
||||
//
|
||||
// Get a klass from the constant pool.
|
||||
ciKlass* ciEnv::get_klass_by_index(ciInstanceKlass* accessor,
|
||||
ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool,
|
||||
int index,
|
||||
bool& is_accessible) {
|
||||
GUARDED_VM_ENTRY(return get_klass_by_index_impl(accessor, index, is_accessible);)
|
||||
bool& is_accessible,
|
||||
ciInstanceKlass* accessor) {
|
||||
GUARDED_VM_ENTRY(return get_klass_by_index_impl(cpool, index, is_accessible, accessor);)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciEnv::get_constant_by_index_impl
|
||||
//
|
||||
// Implementation of get_constant_by_index().
|
||||
ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
|
||||
int index) {
|
||||
ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
|
||||
int index,
|
||||
ciInstanceKlass* accessor) {
|
||||
EXCEPTION_CONTEXT;
|
||||
instanceKlass* ik_accessor = accessor->get_instanceKlass();
|
||||
assert(ik_accessor->is_linked(), "must be linked before accessing constant pool");
|
||||
constantPoolOop cpool = ik_accessor->constants();
|
||||
constantTag tag = cpool->tag_at(index);
|
||||
if (tag.is_int()) {
|
||||
return ciConstant(T_INT, (jint)cpool->int_at(index));
|
||||
@ -552,7 +542,7 @@ ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
|
||||
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
|
||||
// 4881222: allow ldc to take a class type
|
||||
bool ignore;
|
||||
ciKlass* klass = get_klass_by_index_impl(accessor, index, ignore);
|
||||
ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
record_out_of_memory_failure();
|
||||
@ -561,6 +551,11 @@ ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
|
||||
assert (klass->is_instance_klass() || klass->is_array_klass(),
|
||||
"must be an instance or array klass ");
|
||||
return ciConstant(T_OBJECT, klass);
|
||||
} else if (tag.is_object()) {
|
||||
oop obj = cpool->object_at(index);
|
||||
assert(obj->is_instance(), "must be an instance");
|
||||
ciObject* ciobj = get_object(obj);
|
||||
return ciConstant(T_OBJECT, ciobj);
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
return ciConstant();
|
||||
@ -597,9 +592,10 @@ bool ciEnv::is_unresolved_klass_impl(instanceKlass* accessor, int index) const {
|
||||
// Pull a constant out of the constant pool. How appropriate.
|
||||
//
|
||||
// Implementation note: this query is currently in no way cached.
|
||||
ciConstant ciEnv::get_constant_by_index(ciInstanceKlass* accessor,
|
||||
int index) {
|
||||
GUARDED_VM_ENTRY(return get_constant_by_index_impl(accessor, index); )
|
||||
ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
|
||||
int index,
|
||||
ciInstanceKlass* accessor) {
|
||||
GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, index, accessor);)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -609,7 +605,7 @@ ciConstant ciEnv::get_constant_by_index(ciInstanceKlass* accessor,
|
||||
//
|
||||
// Implementation note: this query is currently in no way cached.
|
||||
bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor,
|
||||
int index) const {
|
||||
int index) const {
|
||||
GUARDED_VM_ENTRY(return is_unresolved_string_impl(accessor->get_instanceKlass(), index); )
|
||||
}
|
||||
|
||||
@ -620,7 +616,7 @@ bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor,
|
||||
//
|
||||
// Implementation note: this query is currently in no way cached.
|
||||
bool ciEnv::is_unresolved_klass(ciInstanceKlass* accessor,
|
||||
int index) const {
|
||||
int index) const {
|
||||
GUARDED_VM_ENTRY(return is_unresolved_klass_impl(accessor->get_instanceKlass(), index); )
|
||||
}
|
||||
|
||||
@ -701,15 +697,12 @@ methodOop ciEnv::lookup_method(instanceKlass* accessor,
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciEnv::get_method_by_index_impl
|
||||
ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor,
|
||||
int index, Bytecodes::Code bc) {
|
||||
// Get the method's declared holder.
|
||||
|
||||
assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
|
||||
constantPoolHandle cpool = accessor->get_instanceKlass()->constants();
|
||||
ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
|
||||
int index, Bytecodes::Code bc,
|
||||
ciInstanceKlass* accessor) {
|
||||
int holder_index = cpool->klass_ref_index_at(index);
|
||||
bool holder_is_accessible;
|
||||
ciKlass* holder = get_klass_by_index_impl(accessor, holder_index, holder_is_accessible);
|
||||
ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
|
||||
ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
|
||||
|
||||
// Get the method's name and signature.
|
||||
@ -735,6 +728,33 @@ ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor,
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciEnv::get_fake_invokedynamic_method_impl
|
||||
ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
||||
int index, Bytecodes::Code bc) {
|
||||
assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
|
||||
|
||||
// Get the CallSite from the constant pool cache.
|
||||
ConstantPoolCacheEntry* cpc_entry = cpool->cache()->secondary_entry_at(index);
|
||||
assert(cpc_entry != NULL && cpc_entry->is_secondary_entry(), "sanity");
|
||||
Handle call_site = cpc_entry->f1();
|
||||
|
||||
// Call site might not be linked yet.
|
||||
if (call_site.is_null()) {
|
||||
ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass();
|
||||
ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol();
|
||||
return get_unloaded_method(mh_klass, ciSymbol::invoke_name(), sig_sym);
|
||||
}
|
||||
|
||||
// Get the methodOop from the CallSite.
|
||||
methodOop method_oop = (methodOop) java_dyn_CallSite::vmmethod(call_site());
|
||||
assert(method_oop != NULL, "sanity");
|
||||
assert(method_oop->is_method_handle_invoke(), "consistent");
|
||||
|
||||
return get_object(method_oop)->as_method();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciEnv::get_instance_klass_for_declared_method_holder
|
||||
ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* method_holder) {
|
||||
@ -757,15 +777,19 @@ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* m
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciEnv::get_method_by_index
|
||||
ciMethod* ciEnv::get_method_by_index(ciInstanceKlass* accessor,
|
||||
int index, Bytecodes::Code bc) {
|
||||
GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, bc);)
|
||||
ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool,
|
||||
int index, Bytecodes::Code bc,
|
||||
ciInstanceKlass* accessor) {
|
||||
if (bc == Bytecodes::_invokedynamic) {
|
||||
GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc);)
|
||||
} else {
|
||||
GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciEnv::name_buffer
|
||||
char *ciEnv::name_buffer(int req_len) {
|
||||
|
@ -74,17 +74,9 @@ private:
|
||||
static ciTypeArrayKlassKlass* _type_array_klass_klass_instance;
|
||||
static ciObjArrayKlassKlass* _obj_array_klass_klass_instance;
|
||||
|
||||
static ciInstanceKlass* _ArrayStoreException;
|
||||
static ciInstanceKlass* _Class;
|
||||
static ciInstanceKlass* _ClassCastException;
|
||||
static ciInstanceKlass* _Object;
|
||||
static ciInstanceKlass* _Throwable;
|
||||
static ciInstanceKlass* _Thread;
|
||||
static ciInstanceKlass* _OutOfMemoryError;
|
||||
static ciInstanceKlass* _String;
|
||||
static ciInstanceKlass* _StringBuffer;
|
||||
static ciInstanceKlass* _StringBuilder;
|
||||
static ciInstanceKlass* _Integer;
|
||||
#define WK_KLASS_DECL(name, ignore_s, ignore_o) static ciInstanceKlass* _##name;
|
||||
WK_KLASSES_DO(WK_KLASS_DECL)
|
||||
#undef WK_KLASS_DECL
|
||||
|
||||
static ciSymbol* _unloaded_cisymbol;
|
||||
static ciInstanceKlass* _unloaded_ciinstance_klass;
|
||||
@ -120,37 +112,45 @@ private:
|
||||
bool require_local);
|
||||
|
||||
// Constant pool access.
|
||||
ciKlass* get_klass_by_index(ciInstanceKlass* loading_klass,
|
||||
ciKlass* get_klass_by_index(constantPoolHandle cpool,
|
||||
int klass_index,
|
||||
bool& is_accessible);
|
||||
ciConstant get_constant_by_index(ciInstanceKlass* loading_klass,
|
||||
int constant_index);
|
||||
bool& is_accessible,
|
||||
ciInstanceKlass* loading_klass);
|
||||
ciConstant get_constant_by_index(constantPoolHandle cpool,
|
||||
int constant_index,
|
||||
ciInstanceKlass* accessor);
|
||||
bool is_unresolved_string(ciInstanceKlass* loading_klass,
|
||||
int constant_index) const;
|
||||
bool is_unresolved_klass(ciInstanceKlass* loading_klass,
|
||||
int constant_index) const;
|
||||
ciField* get_field_by_index(ciInstanceKlass* loading_klass,
|
||||
int field_index);
|
||||
ciMethod* get_method_by_index(ciInstanceKlass* loading_klass,
|
||||
int method_index, Bytecodes::Code bc);
|
||||
ciMethod* get_method_by_index(constantPoolHandle cpool,
|
||||
int method_index, Bytecodes::Code bc,
|
||||
ciInstanceKlass* loading_klass);
|
||||
|
||||
// Implementation methods for loading and constant pool access.
|
||||
ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass,
|
||||
ciSymbol* klass_name,
|
||||
bool require_local);
|
||||
ciKlass* get_klass_by_index_impl(ciInstanceKlass* loading_klass,
|
||||
ciKlass* get_klass_by_index_impl(constantPoolHandle cpool,
|
||||
int klass_index,
|
||||
bool& is_accessible);
|
||||
ciConstant get_constant_by_index_impl(ciInstanceKlass* loading_klass,
|
||||
int constant_index);
|
||||
bool& is_accessible,
|
||||
ciInstanceKlass* loading_klass);
|
||||
ciConstant get_constant_by_index_impl(constantPoolHandle cpool,
|
||||
int constant_index,
|
||||
ciInstanceKlass* loading_klass);
|
||||
bool is_unresolved_string_impl (instanceKlass* loading_klass,
|
||||
int constant_index) const;
|
||||
bool is_unresolved_klass_impl (instanceKlass* loading_klass,
|
||||
int constant_index) const;
|
||||
ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass,
|
||||
int field_index);
|
||||
ciMethod* get_method_by_index_impl(ciInstanceKlass* loading_klass,
|
||||
int method_index, Bytecodes::Code bc);
|
||||
ciMethod* get_method_by_index_impl(constantPoolHandle cpool,
|
||||
int method_index, Bytecodes::Code bc,
|
||||
ciInstanceKlass* loading_klass);
|
||||
ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
||||
int index, Bytecodes::Code bc);
|
||||
|
||||
// Helper methods
|
||||
bool check_klass_accessibility(ciKlass* accessing_klass,
|
||||
@ -292,39 +292,13 @@ public:
|
||||
|
||||
|
||||
// Access to certain well known ciObjects.
|
||||
ciInstanceKlass* ArrayStoreException_klass() {
|
||||
return _ArrayStoreException;
|
||||
}
|
||||
ciInstanceKlass* Class_klass() {
|
||||
return _Class;
|
||||
}
|
||||
ciInstanceKlass* ClassCastException_klass() {
|
||||
return _ClassCastException;
|
||||
}
|
||||
ciInstanceKlass* Object_klass() {
|
||||
return _Object;
|
||||
}
|
||||
ciInstanceKlass* Throwable_klass() {
|
||||
return _Throwable;
|
||||
}
|
||||
ciInstanceKlass* Thread_klass() {
|
||||
return _Thread;
|
||||
}
|
||||
ciInstanceKlass* OutOfMemoryError_klass() {
|
||||
return _OutOfMemoryError;
|
||||
}
|
||||
ciInstanceKlass* String_klass() {
|
||||
return _String;
|
||||
}
|
||||
ciInstanceKlass* StringBuilder_klass() {
|
||||
return _StringBuilder;
|
||||
}
|
||||
ciInstanceKlass* StringBuffer_klass() {
|
||||
return _StringBuffer;
|
||||
}
|
||||
ciInstanceKlass* Integer_klass() {
|
||||
return _Integer;
|
||||
#define WK_KLASS_FUNC(name, ignore_s, ignore_o) \
|
||||
ciInstanceKlass* name() { \
|
||||
return _##name;\
|
||||
}
|
||||
WK_KLASSES_DO(WK_KLASS_FUNC)
|
||||
#undef WK_KLASS_FUNC
|
||||
|
||||
ciInstance* NullPointerException_instance() {
|
||||
assert(_NullPointerException_instance != NULL, "initialization problem");
|
||||
return _NullPointerException_instance;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,12 +34,16 @@
|
||||
//
|
||||
// Get the exception klass that this handler catches.
|
||||
ciInstanceKlass* ciExceptionHandler::catch_klass() {
|
||||
VM_ENTRY_MARK;
|
||||
assert(!is_catch_all(), "bad index");
|
||||
if (_catch_klass == NULL) {
|
||||
bool will_link;
|
||||
ciKlass* k = CURRENT_ENV->get_klass_by_index(_loading_klass,
|
||||
assert(_loading_klass->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
|
||||
constantPoolHandle cpool(_loading_klass->get_instanceKlass()->constants());
|
||||
ciKlass* k = CURRENT_ENV->get_klass_by_index(cpool,
|
||||
_catch_klass_index,
|
||||
will_link);
|
||||
will_link,
|
||||
_loading_klass);
|
||||
if (!will_link && k->is_loaded()) {
|
||||
GUARDED_VM_ENTRY(
|
||||
k = CURRENT_ENV->get_unloaded_klass(_loading_klass, k->name());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -86,7 +86,7 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with(NULL) {
|
||||
bool ignore;
|
||||
// This is not really a class reference; the index always refers to the
|
||||
// field's type signature, as a symbol. Linkage checks do not apply.
|
||||
_type = ciEnv::current(thread)->get_klass_by_index(klass, sig_index, ignore);
|
||||
_type = ciEnv::current(thread)->get_klass_by_index(cpool, sig_index, ignore, klass);
|
||||
} else {
|
||||
_type = ciType::make(field_type);
|
||||
}
|
||||
@ -100,9 +100,9 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with(NULL) {
|
||||
int holder_index = cpool->klass_ref_index_at(index);
|
||||
bool holder_is_accessible;
|
||||
ciInstanceKlass* declared_holder =
|
||||
ciEnv::current(thread)->get_klass_by_index(klass, holder_index,
|
||||
holder_is_accessible)
|
||||
->as_instance_klass();
|
||||
ciEnv::current(thread)->get_klass_by_index(cpool, holder_index,
|
||||
holder_is_accessible,
|
||||
klass)->as_instance_klass();
|
||||
|
||||
// The declared holder of this field may not have been loaded.
|
||||
// Bail out with partial field information.
|
||||
@ -168,8 +168,18 @@ void ciField::initialize_from(fieldDescriptor* fd) {
|
||||
_holder = CURRENT_ENV->get_object(fd->field_holder())->as_instance_klass();
|
||||
|
||||
// Check to see if the field is constant.
|
||||
if (_holder->is_initialized() &&
|
||||
this->is_final() && this->is_static()) {
|
||||
if (_holder->is_initialized() && this->is_final()) {
|
||||
if (!this->is_static()) {
|
||||
// A field can be constant if it's a final static field or if it's
|
||||
// a final non-static field of a trusted class ({java,sun}.dyn).
|
||||
if (_holder->is_in_package("java/dyn") || _holder->is_in_package("sun/dyn")) {
|
||||
_is_constant = true;
|
||||
return;
|
||||
}
|
||||
_is_constant = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// This field just may be constant. The only cases where it will
|
||||
// not be constant are:
|
||||
//
|
||||
@ -182,8 +192,8 @@ void ciField::initialize_from(fieldDescriptor* fd) {
|
||||
// java.lang.System.out, and java.lang.System.err.
|
||||
|
||||
klassOop k = _holder->get_klassOop();
|
||||
assert( SystemDictionary::system_klass() != NULL, "Check once per vm");
|
||||
if( k == SystemDictionary::system_klass() ) {
|
||||
assert( SystemDictionary::System_klass() != NULL, "Check once per vm");
|
||||
if( k == SystemDictionary::System_klass() ) {
|
||||
// Check offsets for case 2: System.in, System.out, or System.err
|
||||
if( _offset == java_lang_System::in_offset_in_bytes() ||
|
||||
_offset == java_lang_System::out_offset_in_bytes() ||
|
||||
|
@ -138,10 +138,18 @@ public:
|
||||
|
||||
// Get the constant value of this field.
|
||||
ciConstant constant_value() {
|
||||
assert(is_constant(), "illegal call to constant_value()");
|
||||
assert(is_static() && is_constant(), "illegal call to constant_value()");
|
||||
return _constant_value;
|
||||
}
|
||||
|
||||
// Get the constant value of non-static final field in the given
|
||||
// object.
|
||||
ciConstant constant_value_of(ciObject* object) {
|
||||
assert(!is_static() && is_constant(), "only if field is non-static constant");
|
||||
assert(object->is_instance(), "must be instance");
|
||||
return object->as_instance()->field_value(this);
|
||||
}
|
||||
|
||||
// Check for link time errors. Accessing a field from a
|
||||
// certain class via a certain bytecode may or may not be legal.
|
||||
// This call checks to see if an exception may be raised by
|
||||
|
@ -36,7 +36,7 @@ ciType* ciInstance::java_mirror_type() {
|
||||
VM_ENTRY_MARK;
|
||||
oop m = get_oop();
|
||||
// Return NULL if it is not java.lang.Class.
|
||||
if (m == NULL || m->klass() != SystemDictionary::class_klass()) {
|
||||
if (m == NULL || m->klass() != SystemDictionary::Class_klass()) {
|
||||
return NULL;
|
||||
}
|
||||
// Return either a primitive type or a klass.
|
||||
|
@ -75,7 +75,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
|
||||
_java_mirror = NULL;
|
||||
|
||||
if (is_shared()) {
|
||||
if (h_k() != SystemDictionary::object_klass()) {
|
||||
if (h_k() != SystemDictionary::Object_klass()) {
|
||||
super();
|
||||
}
|
||||
java_mirror();
|
||||
@ -232,8 +232,48 @@ bool ciInstanceKlass::is_java_lang_Object() {
|
||||
// ------------------------------------------------------------------
|
||||
// ciInstanceKlass::uses_default_loader
|
||||
bool ciInstanceKlass::uses_default_loader() {
|
||||
VM_ENTRY_MARK;
|
||||
return loader() == NULL;
|
||||
// Note: We do not need to resolve the handle or enter the VM
|
||||
// in order to test null-ness.
|
||||
return _loader == NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciInstanceKlass::is_in_package
|
||||
//
|
||||
// Is this klass in the given package?
|
||||
bool ciInstanceKlass::is_in_package(const char* packagename, int len) {
|
||||
// To avoid class loader mischief, this test always rejects application classes.
|
||||
if (!uses_default_loader())
|
||||
return false;
|
||||
GUARDED_VM_ENTRY(
|
||||
return is_in_package_impl(packagename, len);
|
||||
)
|
||||
}
|
||||
|
||||
bool ciInstanceKlass::is_in_package_impl(const char* packagename, int len) {
|
||||
ASSERT_IN_VM;
|
||||
|
||||
// If packagename contains trailing '/' exclude it from the
|
||||
// prefix-test since we test for it explicitly.
|
||||
if (packagename[len - 1] == '/')
|
||||
len--;
|
||||
|
||||
if (!name()->starts_with(packagename, len))
|
||||
return false;
|
||||
|
||||
// Test if the class name is something like "java/lang".
|
||||
if ((len + 1) > name()->utf8_length())
|
||||
return false;
|
||||
|
||||
// Test for trailing '/'
|
||||
if ((char) name()->byte_at(len) != '/')
|
||||
return false;
|
||||
|
||||
// Make sure it's not actually in a subpackage:
|
||||
if (name()->index_of_at(len+1, "/", 1) >= 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
@ -29,10 +29,11 @@
|
||||
// be loaded.
|
||||
class ciInstanceKlass : public ciKlass {
|
||||
CI_PACKAGE_ACCESS
|
||||
friend class ciBytecodeStream;
|
||||
friend class ciEnv;
|
||||
friend class ciExceptionHandler;
|
||||
friend class ciMethod;
|
||||
friend class ciField;
|
||||
friend class ciBytecodeStream;
|
||||
|
||||
private:
|
||||
jobject _loader;
|
||||
@ -78,6 +79,8 @@ protected:
|
||||
|
||||
const char* type_string() { return "ciInstanceKlass"; }
|
||||
|
||||
bool is_in_package_impl(const char* packagename, int len);
|
||||
|
||||
void print_impl(outputStream* st);
|
||||
|
||||
ciConstantPoolCache* field_cache();
|
||||
@ -196,6 +199,12 @@ public:
|
||||
|
||||
bool is_java_lang_Object();
|
||||
|
||||
// Is this klass in the given package?
|
||||
bool is_in_package(const char* packagename) {
|
||||
return is_in_package(packagename, (int) strlen(packagename));
|
||||
}
|
||||
bool is_in_package(const char* packagename, int len);
|
||||
|
||||
// What kind of ciObject is this?
|
||||
bool is_instance_klass() { return true; }
|
||||
bool is_java_klass() { return true; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -69,7 +69,7 @@ public:
|
||||
ciKlass(KlassHandle k_h);
|
||||
|
||||
// What is the name of this klass?
|
||||
ciSymbol* name() { return _name; }
|
||||
ciSymbol* name() const { return _name; }
|
||||
|
||||
// What is its layout helper value?
|
||||
jint layout_helper() { return _layout_helper; }
|
||||
|
@ -687,7 +687,7 @@ int ciMethod::scale_count(int count, float prof_factor) {
|
||||
// ------------------------------------------------------------------
|
||||
// invokedynamic support
|
||||
//
|
||||
bool ciMethod::is_method_handle_invoke() {
|
||||
bool ciMethod::is_method_handle_invoke() const {
|
||||
check_is_loaded();
|
||||
bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
|
||||
#ifdef ASSERT
|
||||
|
@ -38,6 +38,8 @@ class ciMethod : public ciObject {
|
||||
CI_PACKAGE_ACCESS
|
||||
friend class ciEnv;
|
||||
friend class ciExceptionHandlerStream;
|
||||
friend class ciBytecodeStream;
|
||||
friend class ciMethodHandle;
|
||||
|
||||
private:
|
||||
// General method information.
|
||||
@ -213,7 +215,7 @@ class ciMethod : public ciObject {
|
||||
bool check_call(int refinfo_index, bool is_static) const;
|
||||
void build_method_data(); // make sure it exists in the VM also
|
||||
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
|
||||
bool is_method_handle_invoke();
|
||||
bool is_method_handle_invoke() const;
|
||||
ciInstance* method_handle_type();
|
||||
|
||||
// What kind of ciObject is this?
|
||||
@ -251,4 +253,10 @@ class ciMethod : public ciObject {
|
||||
// Print the name of this method in various incarnations.
|
||||
void print_name(outputStream* st = tty);
|
||||
void print_short_name(outputStream* st = tty);
|
||||
|
||||
methodOop get_method_handle_target() {
|
||||
klassOop receiver_limit_oop = NULL;
|
||||
int flags = 0;
|
||||
return MethodHandles::decode_method(get_oop(), receiver_limit_oop, flags);
|
||||
}
|
||||
};
|
||||
|
52
hotspot/src/share/vm/ci/ciMethodHandle.cpp
Normal file
52
hotspot/src/share/vm/ci/ciMethodHandle.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "incls/_precompiled.incl"
|
||||
#include "incls/_ciMethodHandle.cpp.incl"
|
||||
|
||||
// ciMethodHandle
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethodHandle::get_adapter
|
||||
//
|
||||
// Return an adapter for this MethodHandle.
|
||||
ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
|
||||
VM_ENTRY_MARK;
|
||||
|
||||
Handle h(get_oop());
|
||||
methodHandle callee(_callee->get_methodOop());
|
||||
MethodHandleCompiler mhc(h, callee, is_invokedynamic, THREAD);
|
||||
methodHandle m = mhc.compile(CHECK_NULL);
|
||||
return CURRENT_ENV->get_object(m())->as_method();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethodHandle::print_impl
|
||||
//
|
||||
// Implementation of the print method.
|
||||
void ciMethodHandle::print_impl(outputStream* st) {
|
||||
st->print(" type=");
|
||||
get_oop()->print();
|
||||
}
|
56
hotspot/src/share/vm/ci/ciMethodHandle.hpp
Normal file
56
hotspot/src/share/vm/ci/ciMethodHandle.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
// ciMethodHandle
|
||||
//
|
||||
// The class represents a java.dyn.MethodHandle object.
|
||||
class ciMethodHandle : public ciInstance {
|
||||
private:
|
||||
ciMethod* _callee;
|
||||
|
||||
// Return an adapter for this MethodHandle.
|
||||
ciMethod* get_adapter(bool is_invokedynamic) const;
|
||||
|
||||
protected:
|
||||
void print_impl(outputStream* st);
|
||||
|
||||
public:
|
||||
ciMethodHandle(instanceHandle h_i) : ciInstance(h_i) {};
|
||||
|
||||
// What kind of ciObject is this?
|
||||
bool is_method_handle() const { return true; }
|
||||
|
||||
ciMethod* callee() const { return _callee; }
|
||||
void set_callee(ciMethod* m) { _callee = m; }
|
||||
|
||||
// Return an adapter for a MethodHandle call.
|
||||
ciMethod* get_method_handle_adapter() const {
|
||||
return get_adapter(false);
|
||||
}
|
||||
|
||||
// Return an adapter for an invokedynamic call.
|
||||
ciMethod* get_invokedynamic_adapter() const {
|
||||
return get_adapter(true);
|
||||
}
|
||||
};
|
@ -131,9 +131,12 @@ public:
|
||||
|
||||
// What kind of ciObject is this?
|
||||
virtual bool is_null_object() const { return false; }
|
||||
virtual bool is_call_site() const { return false; }
|
||||
virtual bool is_cpcache() const { return false; }
|
||||
virtual bool is_instance() { return false; }
|
||||
virtual bool is_method() { return false; }
|
||||
virtual bool is_method_data() { return false; }
|
||||
virtual bool is_method_handle() const { return false; }
|
||||
virtual bool is_array() { return false; }
|
||||
virtual bool is_obj_array() { return false; }
|
||||
virtual bool is_type_array() { return false; }
|
||||
@ -185,6 +188,14 @@ public:
|
||||
assert(is_null_object(), "bad cast");
|
||||
return (ciNullObject*)this;
|
||||
}
|
||||
ciCallSite* as_call_site() {
|
||||
assert(is_call_site(), "bad cast");
|
||||
return (ciCallSite*) this;
|
||||
}
|
||||
ciCPCache* as_cpcache() {
|
||||
assert(is_cpcache(), "bad cast");
|
||||
return (ciCPCache*) this;
|
||||
}
|
||||
ciInstance* as_instance() {
|
||||
assert(is_instance(), "bad cast");
|
||||
return (ciInstance*)this;
|
||||
@ -197,6 +208,10 @@ public:
|
||||
assert(is_method_data(), "bad cast");
|
||||
return (ciMethodData*)this;
|
||||
}
|
||||
ciMethodHandle* as_method_handle() {
|
||||
assert(is_method_handle(), "bad cast");
|
||||
return (ciMethodHandle*) this;
|
||||
}
|
||||
ciArray* as_array() {
|
||||
assert(is_array(), "bad cast");
|
||||
return (ciArray*)this;
|
||||
|
@ -144,39 +144,13 @@ void ciObjectFactory::init_shared_objects() {
|
||||
ciEnv::_obj_array_klass_klass_instance =
|
||||
get(Universe::objArrayKlassKlassObj())
|
||||
->as_obj_array_klass_klass();
|
||||
ciEnv::_ArrayStoreException =
|
||||
get(SystemDictionary::ArrayStoreException_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_Class =
|
||||
get(SystemDictionary::class_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_ClassCastException =
|
||||
get(SystemDictionary::ClassCastException_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_Object =
|
||||
get(SystemDictionary::object_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_Throwable =
|
||||
get(SystemDictionary::throwable_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_Thread =
|
||||
get(SystemDictionary::thread_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_OutOfMemoryError =
|
||||
get(SystemDictionary::OutOfMemoryError_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_String =
|
||||
get(SystemDictionary::string_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_StringBuffer =
|
||||
get(SystemDictionary::stringBuffer_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_StringBuilder =
|
||||
get(SystemDictionary::StringBuilder_klass())
|
||||
->as_instance_klass();
|
||||
ciEnv::_Integer =
|
||||
get(SystemDictionary::int_klass())
|
||||
->as_instance_klass();
|
||||
|
||||
#define WK_KLASS_DEFN(name, ignore_s, opt) \
|
||||
if (SystemDictionary::name() != NULL) \
|
||||
ciEnv::_##name = get(SystemDictionary::name())->as_instance_klass();
|
||||
|
||||
WK_KLASSES_DO(WK_KLASS_DEFN)
|
||||
#undef WK_KLASS_DEFN
|
||||
|
||||
for (int len = -1; len != _ci_objects->length(); ) {
|
||||
len = _ci_objects->length();
|
||||
@ -333,13 +307,21 @@ ciObject* ciObjectFactory::create_new_object(oop o) {
|
||||
return new (arena()) ciMethodData(h_md);
|
||||
} else if (o->is_instance()) {
|
||||
instanceHandle h_i(THREAD, (instanceOop)o);
|
||||
return new (arena()) ciInstance(h_i);
|
||||
if (java_dyn_CallSite::is_instance(o))
|
||||
return new (arena()) ciCallSite(h_i);
|
||||
else if (java_dyn_MethodHandle::is_instance(o))
|
||||
return new (arena()) ciMethodHandle(h_i);
|
||||
else
|
||||
return new (arena()) ciInstance(h_i);
|
||||
} else if (o->is_objArray()) {
|
||||
objArrayHandle h_oa(THREAD, (objArrayOop)o);
|
||||
return new (arena()) ciObjArray(h_oa);
|
||||
} else if (o->is_typeArray()) {
|
||||
typeArrayHandle h_ta(THREAD, (typeArrayOop)o);
|
||||
return new (arena()) ciTypeArray(h_ta);
|
||||
} else if (o->is_constantPoolCache()) {
|
||||
constantPoolCacheHandle h_cpc(THREAD, (constantPoolCacheOop) o);
|
||||
return new (arena()) ciCPCache(h_cpc);
|
||||
}
|
||||
|
||||
// The oop is of some type not supported by the compiler interface.
|
||||
@ -576,7 +558,7 @@ ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) {
|
||||
if (key->is_perm() && _non_perm_count == 0) {
|
||||
return emptyBucket;
|
||||
} else if (key->is_instance()) {
|
||||
if (key->klass() == SystemDictionary::class_klass()) {
|
||||
if (key->klass() == SystemDictionary::Class_klass()) {
|
||||
// class mirror instances are always perm
|
||||
return emptyBucket;
|
||||
}
|
||||
|
@ -186,8 +186,9 @@ int ciBytecodeStream::get_klass_index() const {
|
||||
// If this bytecode is a new, newarray, multianewarray, instanceof,
|
||||
// or checkcast, get the referenced klass.
|
||||
ciKlass* ciBytecodeStream::get_klass(bool& will_link) {
|
||||
return CURRENT_ENV->get_klass_by_index(_holder, get_klass_index(),
|
||||
will_link);
|
||||
VM_ENTRY_MARK;
|
||||
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||
return CURRENT_ENV->get_klass_by_index(cpool, get_klass_index(), will_link, _holder);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -213,7 +214,9 @@ int ciBytecodeStream::get_constant_index() const {
|
||||
// If this bytecode is one of the ldc variants, get the referenced
|
||||
// constant.
|
||||
ciConstant ciBytecodeStream::get_constant() {
|
||||
return CURRENT_ENV->get_constant_by_index(_holder, get_constant_index());
|
||||
VM_ENTRY_MARK;
|
||||
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||
return CURRENT_ENV->get_constant_by_index(cpool, get_constant_index(), _holder);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -264,9 +267,11 @@ ciField* ciBytecodeStream::get_field(bool& will_link) {
|
||||
// There is no "will_link" result passed back. The user is responsible
|
||||
// for checking linkability when retrieving the associated field.
|
||||
ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() {
|
||||
VM_ENTRY_MARK;
|
||||
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||
int holder_index = get_field_holder_index();
|
||||
bool ignore;
|
||||
return CURRENT_ENV->get_klass_by_index(_holder, holder_index, ignore)
|
||||
return CURRENT_ENV->get_klass_by_index(cpool, holder_index, ignore, _holder)
|
||||
->as_instance_klass();
|
||||
}
|
||||
|
||||
@ -277,9 +282,10 @@ ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() {
|
||||
// referenced by the current bytecode. Used for generating
|
||||
// deoptimization information.
|
||||
int ciBytecodeStream::get_field_holder_index() {
|
||||
VM_ENTRY_MARK;
|
||||
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
||||
return cpool->klass_ref_index_at(get_field_index());
|
||||
GUARDED_VM_ENTRY(
|
||||
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
||||
return cpool->klass_ref_index_at(get_field_index());
|
||||
)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -321,7 +327,9 @@ int ciBytecodeStream::get_method_index() {
|
||||
//
|
||||
// If this is a method invocation bytecode, get the invoked method.
|
||||
ciMethod* ciBytecodeStream::get_method(bool& will_link) {
|
||||
ciMethod* m = CURRENT_ENV->get_method_by_index(_holder, get_method_index(),cur_bc());
|
||||
VM_ENTRY_MARK;
|
||||
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||
ciMethod* m = CURRENT_ENV->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
|
||||
will_link = m->is_loaded();
|
||||
return m;
|
||||
}
|
||||
@ -338,11 +346,13 @@ ciMethod* ciBytecodeStream::get_method(bool& will_link) {
|
||||
// There is no "will_link" result passed back. The user is responsible
|
||||
// for checking linkability when retrieving the associated method.
|
||||
ciKlass* ciBytecodeStream::get_declared_method_holder() {
|
||||
VM_ENTRY_MARK;
|
||||
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||
bool ignore;
|
||||
// report as Dynamic for invokedynamic, which is syntactically classless
|
||||
// report as InvokeDynamic for invokedynamic, which is syntactically classless
|
||||
if (cur_bc() == Bytecodes::_invokedynamic)
|
||||
return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_Dynamic(), false);
|
||||
return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore);
|
||||
return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false);
|
||||
return CURRENT_ENV->get_klass_by_index(cpool, get_method_holder_index(), ignore, _holder);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -352,8 +362,7 @@ ciKlass* ciBytecodeStream::get_declared_method_holder() {
|
||||
// referenced by the current bytecode. Used for generating
|
||||
// deoptimization information.
|
||||
int ciBytecodeStream::get_method_holder_index() {
|
||||
VM_ENTRY_MARK;
|
||||
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
||||
constantPoolOop cpool = _method->get_methodOop()->constants();
|
||||
return cpool->klass_ref_index_at(get_method_index());
|
||||
}
|
||||
|
||||
@ -370,3 +379,31 @@ int ciBytecodeStream::get_method_signature_index() {
|
||||
int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
|
||||
return cpool->signature_ref_index_at(name_and_type_index);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciBytecodeStream::get_cpcache
|
||||
ciCPCache* ciBytecodeStream::get_cpcache() {
|
||||
VM_ENTRY_MARK;
|
||||
// Get the constant pool.
|
||||
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
||||
constantPoolCacheOop cpcache = cpool->cache();
|
||||
|
||||
return CURRENT_ENV->get_object(cpcache)->as_cpcache();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciBytecodeStream::get_call_site
|
||||
ciCallSite* ciBytecodeStream::get_call_site() {
|
||||
VM_ENTRY_MARK;
|
||||
// Get the constant pool.
|
||||
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
||||
constantPoolCacheOop cpcache = cpool->cache();
|
||||
|
||||
// Get the CallSite from the constant pool cache.
|
||||
int method_index = get_method_index();
|
||||
ConstantPoolCacheEntry* cpcache_entry = cpcache->secondary_entry_at(method_index);
|
||||
oop call_site_oop = cpcache_entry->f1();
|
||||
|
||||
// Create a CallSite object and return it.
|
||||
return CURRENT_ENV->get_object(call_site_oop)->as_call_site();
|
||||
}
|
||||
|
@ -232,6 +232,9 @@ public:
|
||||
int get_method_holder_index();
|
||||
int get_method_signature_index();
|
||||
|
||||
ciCPCache* get_cpcache();
|
||||
ciCallSite* get_call_site();
|
||||
|
||||
private:
|
||||
void assert_index_size(int required_size) const {
|
||||
#ifdef ASSERT
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -59,6 +59,22 @@ int ciSymbol::byte_at(int i) {
|
||||
GUARDED_VM_ENTRY(return get_symbolOop()->byte_at(i);)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciSymbol::starts_with
|
||||
//
|
||||
// Tests if the symbol starts with the given prefix.
|
||||
bool ciSymbol::starts_with(const char* prefix, int len) const {
|
||||
GUARDED_VM_ENTRY(return get_symbolOop()->starts_with(prefix, len);)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciSymbol::index_of
|
||||
//
|
||||
// Determines where the symbol contains the given substring.
|
||||
int ciSymbol::index_of_at(int i, const char* str, int len) const {
|
||||
GUARDED_VM_ENTRY(return get_symbolOop()->index_of_at(i, str, len);)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciSymbol::utf8_length
|
||||
int ciSymbol::utf8_length() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,6 +28,7 @@
|
||||
// machine.
|
||||
class ciSymbol : public ciObject {
|
||||
CI_PACKAGE_ACCESS
|
||||
// These friends all make direct use of get_symbolOop:
|
||||
friend class ciEnv;
|
||||
friend class ciInstanceKlass;
|
||||
friend class ciSignature;
|
||||
@ -38,13 +39,13 @@ private:
|
||||
ciSymbol(symbolOop s) : ciObject(s) {}
|
||||
ciSymbol(symbolHandle s); // for use with vmSymbolHandles
|
||||
|
||||
symbolOop get_symbolOop() { return (symbolOop)get_oop(); }
|
||||
symbolOop get_symbolOop() const { return (symbolOop)get_oop(); }
|
||||
|
||||
const char* type_string() { return "ciSymbol"; }
|
||||
|
||||
void print_impl(outputStream* st);
|
||||
|
||||
int byte_at(int i);
|
||||
// This is public in symbolOop but private here, because the base can move:
|
||||
jbyte* base();
|
||||
|
||||
// Make a ciSymbol from a C string (implementation).
|
||||
@ -55,6 +56,15 @@ public:
|
||||
const char* as_utf8();
|
||||
int utf8_length();
|
||||
|
||||
// Return the i-th utf8 byte, where i < utf8_length
|
||||
int byte_at(int i);
|
||||
|
||||
// Tests if the symbol starts with the given prefix.
|
||||
bool starts_with(const char* prefix, int len) const;
|
||||
|
||||
// Determines where the symbol contains the given substring.
|
||||
int index_of_at(int i, const char* str, int len) const;
|
||||
|
||||
// What kind of ciObject is this?
|
||||
bool is_symbol() { return true; }
|
||||
|
||||
|
@ -111,7 +111,7 @@ ciType* ciType::make(BasicType t) {
|
||||
// short, etc.
|
||||
// Note: Bare T_ADDRESS means a raw pointer type, not a return_address.
|
||||
assert((uint)t < T_CONFLICT+1, "range check");
|
||||
if (t == T_OBJECT) return ciEnv::_Object; // java/lang/Object
|
||||
if (t == T_OBJECT) return ciEnv::_Object_klass; // java/lang/Object
|
||||
assert(_basic_types[t] != NULL, "domain check");
|
||||
return _basic_types[t];
|
||||
}
|
||||
|
@ -635,8 +635,15 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str,
|
||||
ciMethod* method = str->get_method(will_link);
|
||||
if (!will_link) {
|
||||
// We weren't able to find the method.
|
||||
ciKlass* unloaded_holder = method->holder();
|
||||
trap(str, unloaded_holder, str->get_method_holder_index());
|
||||
if (str->cur_bc() == Bytecodes::_invokedynamic) {
|
||||
trap(str, NULL,
|
||||
Deoptimization::make_trap_request
|
||||
(Deoptimization::Reason_uninitialized,
|
||||
Deoptimization::Action_reinterpret));
|
||||
} else {
|
||||
ciKlass* unloaded_holder = method->holder();
|
||||
trap(str, unloaded_holder, str->get_method_holder_index());
|
||||
}
|
||||
} else {
|
||||
ciSignature* signature = method->signature();
|
||||
ciSignatureStream sigstr(signature);
|
||||
@ -1292,8 +1299,8 @@ bool ciTypeFlow::StateVector::apply_one_bytecode(ciBytecodeStream* str) {
|
||||
case Bytecodes::_invokeinterface: do_invoke(str, true); break;
|
||||
case Bytecodes::_invokespecial: do_invoke(str, true); break;
|
||||
case Bytecodes::_invokestatic: do_invoke(str, false); break;
|
||||
|
||||
case Bytecodes::_invokevirtual: do_invoke(str, true); break;
|
||||
case Bytecodes::_invokedynamic: do_invoke(str, false); break;
|
||||
|
||||
case Bytecodes::_istore: store_local_int(str->get_index()); break;
|
||||
case Bytecodes::_istore_0: store_local_int(0); break;
|
||||
|
@ -79,7 +79,7 @@
|
||||
THREAD); \
|
||||
if (HAS_PENDING_EXCEPTION) { \
|
||||
if (PENDING_EXCEPTION->klass() == \
|
||||
SystemDictionary::threaddeath_klass()) { \
|
||||
SystemDictionary::ThreadDeath_klass()) { \
|
||||
/* Kill the compilation. */ \
|
||||
fatal("unhandled ci exception"); \
|
||||
return (result); \
|
||||
|
@ -430,7 +430,7 @@ void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Hand
|
||||
case JVM_CONSTANT_UnresolvedClass :
|
||||
// Patching a class means pre-resolving it.
|
||||
// The name in the constant pool is ignored.
|
||||
if (patch->klass() == SystemDictionary::class_klass()) { // %%% java_lang_Class::is_instance
|
||||
if (patch->klass() == SystemDictionary::Class_klass()) { // %%% java_lang_Class::is_instance
|
||||
guarantee_property(!java_lang_Class::is_primitive(patch()),
|
||||
"Illegal class patch at %d in class file %s",
|
||||
index, CHECK);
|
||||
@ -643,7 +643,7 @@ void ClassFileParser::verify_constantvalue(int constantvalue_index, int signatur
|
||||
guarantee_property(value_type.is_int(), "Inconsistent constant value type in class file %s", CHECK);
|
||||
break;
|
||||
case T_OBJECT:
|
||||
guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;", 18)
|
||||
guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;")
|
||||
&& (value_type.is_string() || value_type.is_unresolved_string())),
|
||||
"Bad string initial value in class file %s", CHECK);
|
||||
break;
|
||||
@ -1718,9 +1718,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||
m->set_exception_table(exception_handlers());
|
||||
|
||||
// Copy byte codes
|
||||
if (code_length > 0) {
|
||||
memcpy(m->code_base(), code_start, code_length);
|
||||
}
|
||||
m->set_code(code_start);
|
||||
|
||||
// Copy line number table
|
||||
if (linenumber_table != NULL) {
|
||||
@ -3471,8 +3469,8 @@ void ClassFileParser::set_precomputed_flags(instanceKlassHandle k) {
|
||||
#endif
|
||||
|
||||
// Check if this klass supports the java.lang.Cloneable interface
|
||||
if (SystemDictionary::cloneable_klass_loaded()) {
|
||||
if (k->is_subtype_of(SystemDictionary::cloneable_klass())) {
|
||||
if (SystemDictionary::Cloneable_klass_loaded()) {
|
||||
if (k->is_subtype_of(SystemDictionary::Cloneable_klass())) {
|
||||
k->set_is_cloneable();
|
||||
}
|
||||
}
|
||||
@ -4178,7 +4176,7 @@ char* ClassFileParser::skip_over_field_name(char* name, bool slash_ok, unsigned
|
||||
// Check if ch is Java identifier start or is Java identifier part
|
||||
// 4672820: call java.lang.Character methods directly without generating separate tables.
|
||||
EXCEPTION_MARK;
|
||||
instanceKlassHandle klass (THREAD, SystemDictionary::char_klass());
|
||||
instanceKlassHandle klass (THREAD, SystemDictionary::Character_klass());
|
||||
|
||||
// return value
|
||||
JavaValue result(T_BOOLEAN);
|
||||
|
@ -819,7 +819,7 @@ objArrayOop ClassLoader::get_system_packages(TRAPS) {
|
||||
_package_hash_table->copy_pkgnames(packages);
|
||||
}
|
||||
// Allocate objArray and fill with java.lang.String
|
||||
objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(),
|
||||
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
|
||||
nof_entries, CHECK_0);
|
||||
objArrayHandle result(THREAD, r);
|
||||
for (int i = 0; i < nof_entries; i++) {
|
||||
|
@ -95,14 +95,14 @@ oop JavaAssertions::createAssertionStatusDirectives(TRAPS) {
|
||||
int len;
|
||||
typeArrayOop t;
|
||||
len = OptionList::count(_packages);
|
||||
objArrayOop pn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL);
|
||||
objArrayOop pn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL);
|
||||
objArrayHandle pkgNames (THREAD, pn);
|
||||
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
|
||||
typeArrayHandle pkgEnabled(THREAD, t);
|
||||
fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL);
|
||||
|
||||
len = OptionList::count(_classes);
|
||||
objArrayOop cn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL);
|
||||
objArrayOop cn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL);
|
||||
objArrayHandle classNames (THREAD, cn);
|
||||
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
|
||||
typeArrayHandle classEnabled(THREAD, t);
|
||||
|
@ -68,9 +68,9 @@ Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
|
||||
// and the char array it points to end up in the same cache line.
|
||||
oop obj;
|
||||
if (tenured) {
|
||||
obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_permanent_instance(CHECK_NH);
|
||||
obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_permanent_instance(CHECK_NH);
|
||||
} else {
|
||||
obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_instance(CHECK_NH);
|
||||
obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_instance(CHECK_NH);
|
||||
}
|
||||
|
||||
// Create the char array. The String object must be handlized here
|
||||
@ -293,7 +293,7 @@ char* java_lang_String::as_utf8_string(oop java_string, int start, int len) {
|
||||
|
||||
bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
|
||||
assert(SharedSkipVerify ||
|
||||
java_string->klass() == SystemDictionary::string_klass(),
|
||||
java_string->klass() == SystemDictionary::String_klass(),
|
||||
"must be java_string");
|
||||
typeArrayOop value = java_lang_String::value(java_string);
|
||||
int offset = java_lang_String::offset(java_string);
|
||||
@ -311,7 +311,7 @@ bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
|
||||
|
||||
void java_lang_String::print(Handle java_string, outputStream* st) {
|
||||
oop obj = java_string();
|
||||
assert(obj->klass() == SystemDictionary::string_klass(), "must be java_string");
|
||||
assert(obj->klass() == SystemDictionary::String_klass(), "must be java_string");
|
||||
typeArrayOop value = java_lang_String::value(obj);
|
||||
int offset = java_lang_String::offset(obj);
|
||||
int length = java_lang_String::length(obj);
|
||||
@ -339,9 +339,9 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
|
||||
// class is put into the system dictionary.
|
||||
int computed_modifiers = k->compute_modifier_flags(CHECK_0);
|
||||
k->set_modifier_flags(computed_modifiers);
|
||||
if (SystemDictionary::class_klass_loaded()) {
|
||||
if (SystemDictionary::Class_klass_loaded()) {
|
||||
// Allocate mirror (java.lang.Class instance)
|
||||
Handle mirror = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0);
|
||||
Handle mirror = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0);
|
||||
// Setup indirections
|
||||
mirror->obj_field_put(klass_offset, k());
|
||||
k->set_java_mirror(mirror());
|
||||
@ -378,7 +378,7 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
|
||||
oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
|
||||
// This should be improved by adding a field at the Java level or by
|
||||
// introducing a new VM klass (see comment in ClassFileParser)
|
||||
oop java_class = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0);
|
||||
oop java_class = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0);
|
||||
if (type != T_VOID) {
|
||||
klassOop aklass = Universe::typeArrayKlassObj(type);
|
||||
assert(aklass != NULL, "correct bootstrap");
|
||||
@ -502,7 +502,7 @@ BasicType java_lang_Class::as_BasicType(oop java_class, klassOop* reference_klas
|
||||
|
||||
oop java_lang_Class::primitive_mirror(BasicType t) {
|
||||
oop mirror = Universe::java_mirror(t);
|
||||
assert(mirror != NULL && mirror->is_a(SystemDictionary::class_klass()), "must be a Class");
|
||||
assert(mirror != NULL && mirror->is_a(SystemDictionary::Class_klass()), "must be a Class");
|
||||
assert(java_lang_Class::is_primitive(mirror), "must be primitive");
|
||||
return mirror;
|
||||
}
|
||||
@ -515,14 +515,14 @@ void java_lang_Class::compute_offsets() {
|
||||
assert(!offsets_computed, "offsets should be initialized only once");
|
||||
offsets_computed = true;
|
||||
|
||||
klassOop k = SystemDictionary::class_klass();
|
||||
klassOop k = SystemDictionary::Class_klass();
|
||||
// The classRedefinedCount field is only present starting in 1.5,
|
||||
// so don't go fatal.
|
||||
compute_optional_offset(classRedefinedCount_offset,
|
||||
k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
|
||||
|
||||
// The field indicating parallelCapable (parallelLockMap) is only present starting in 7,
|
||||
klassOop k1 = SystemDictionary::classloader_klass();
|
||||
klassOop k1 = SystemDictionary::ClassLoader_klass();
|
||||
compute_optional_offset(parallelCapable_offset,
|
||||
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
|
||||
}
|
||||
@ -588,7 +588,7 @@ int java_lang_Thread::_park_event_offset = 0 ;
|
||||
void java_lang_Thread::compute_offsets() {
|
||||
assert(_group_offset == 0, "offsets should be initialized only once");
|
||||
|
||||
klassOop k = SystemDictionary::thread_klass();
|
||||
klassOop k = SystemDictionary::Thread_klass();
|
||||
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::char_array_signature());
|
||||
compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature());
|
||||
compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature());
|
||||
@ -847,7 +847,7 @@ bool java_lang_ThreadGroup::is_vmAllowSuspension(oop java_thread_group) {
|
||||
void java_lang_ThreadGroup::compute_offsets() {
|
||||
assert(_parent_offset == 0, "offsets should be initialized only once");
|
||||
|
||||
klassOop k = SystemDictionary::threadGroup_klass();
|
||||
klassOop k = SystemDictionary::ThreadGroup_klass();
|
||||
|
||||
compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature());
|
||||
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||
@ -1344,7 +1344,7 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t
|
||||
// No-op if stack trace is disabled
|
||||
if (!StackTraceInThrowable) return;
|
||||
|
||||
assert(throwable->is_a(SystemDictionary::throwable_klass()), "sanity check");
|
||||
assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check");
|
||||
|
||||
oop backtrace = java_lang_Throwable::backtrace(throwable());
|
||||
assert(backtrace != NULL, "backtrace not preallocated");
|
||||
@ -1449,7 +1449,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
|
||||
assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4");
|
||||
|
||||
// Allocate java.lang.StackTraceElement instance
|
||||
klassOop k = SystemDictionary::stackTraceElement_klass();
|
||||
klassOop k = SystemDictionary::StackTraceElement_klass();
|
||||
assert(k != NULL, "must be loaded in 1.4+");
|
||||
instanceKlassHandle ik (THREAD, k);
|
||||
if (ik->should_be_initialized()) {
|
||||
@ -1487,7 +1487,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
|
||||
|
||||
|
||||
void java_lang_reflect_AccessibleObject::compute_offsets() {
|
||||
klassOop k = SystemDictionary::reflect_accessible_object_klass();
|
||||
klassOop k = SystemDictionary::reflect_AccessibleObject_klass();
|
||||
compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature());
|
||||
}
|
||||
|
||||
@ -1502,7 +1502,7 @@ void java_lang_reflect_AccessibleObject::set_override(oop reflect, jboolean valu
|
||||
}
|
||||
|
||||
void java_lang_reflect_Method::compute_offsets() {
|
||||
klassOop k = SystemDictionary::reflect_method_klass();
|
||||
klassOop k = SystemDictionary::reflect_Method_klass();
|
||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||
compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature());
|
||||
@ -1523,7 +1523,7 @@ void java_lang_reflect_Method::compute_offsets() {
|
||||
|
||||
Handle java_lang_reflect_Method::create(TRAPS) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
klassOop klass = SystemDictionary::reflect_method_klass();
|
||||
klassOop klass = SystemDictionary::reflect_Method_klass();
|
||||
// This class is eagerly initialized during VM initialization, since we keep a refence
|
||||
// to one of the methods
|
||||
assert(instanceKlass::cast(klass)->is_initialized(), "must be initialized");
|
||||
@ -1665,7 +1665,7 @@ void java_lang_reflect_Method::set_annotation_default(oop method, oop value) {
|
||||
}
|
||||
|
||||
void java_lang_reflect_Constructor::compute_offsets() {
|
||||
klassOop k = SystemDictionary::reflect_constructor_klass();
|
||||
klassOop k = SystemDictionary::reflect_Constructor_klass();
|
||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||
compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature());
|
||||
compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature());
|
||||
@ -1789,7 +1789,7 @@ void java_lang_reflect_Constructor::set_parameter_annotations(oop method, oop va
|
||||
}
|
||||
|
||||
void java_lang_reflect_Field::compute_offsets() {
|
||||
klassOop k = SystemDictionary::reflect_field_klass();
|
||||
klassOop k = SystemDictionary::reflect_Field_klass();
|
||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||
compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature());
|
||||
@ -1896,7 +1896,7 @@ void java_lang_reflect_Field::set_annotations(oop field, oop value) {
|
||||
|
||||
|
||||
void sun_reflect_ConstantPool::compute_offsets() {
|
||||
klassOop k = SystemDictionary::reflect_constant_pool_klass();
|
||||
klassOop k = SystemDictionary::reflect_ConstantPool_klass();
|
||||
// This null test can be removed post beta
|
||||
if (k != NULL) {
|
||||
compute_offset(_cp_oop_offset, k, vmSymbols::constantPoolOop_name(), vmSymbols::object_signature());
|
||||
@ -1906,7 +1906,7 @@ void sun_reflect_ConstantPool::compute_offsets() {
|
||||
|
||||
Handle sun_reflect_ConstantPool::create(TRAPS) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
klassOop k = SystemDictionary::reflect_constant_pool_klass();
|
||||
klassOop k = SystemDictionary::reflect_ConstantPool_klass();
|
||||
instanceKlassHandle klass (THREAD, k);
|
||||
// Ensure it is initialized
|
||||
klass->initialize(CHECK_NH);
|
||||
@ -1926,7 +1926,7 @@ void sun_reflect_ConstantPool::set_cp_oop(oop reflect, oop value) {
|
||||
}
|
||||
|
||||
void sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() {
|
||||
klassOop k = SystemDictionary::reflect_unsafe_static_field_accessor_impl_klass();
|
||||
klassOop k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass();
|
||||
// This null test can be removed post beta
|
||||
if (k != NULL) {
|
||||
compute_offset(_base_offset, k,
|
||||
@ -2072,7 +2072,7 @@ void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream*
|
||||
|
||||
// Support for java_lang_ref_Reference
|
||||
oop java_lang_ref_Reference::pending_list_lock() {
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass());
|
||||
char *addr = (((char *)ik->start_of_static_fields()) + static_lock_offset);
|
||||
if (UseCompressedOops) {
|
||||
return oopDesc::load_decode_heap_oop((narrowOop *)addr);
|
||||
@ -2082,7 +2082,7 @@ oop java_lang_ref_Reference::pending_list_lock() {
|
||||
}
|
||||
|
||||
HeapWord *java_lang_ref_Reference::pending_list_addr() {
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass());
|
||||
char *addr = (((char *)ik->start_of_static_fields()) + static_pending_offset);
|
||||
// XXX This might not be HeapWord aligned, almost rather be char *.
|
||||
return (HeapWord*)addr;
|
||||
@ -2105,17 +2105,17 @@ jlong java_lang_ref_SoftReference::timestamp(oop ref) {
|
||||
}
|
||||
|
||||
jlong java_lang_ref_SoftReference::clock() {
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass());
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass());
|
||||
int offset = ik->offset_of_static_fields() + static_clock_offset;
|
||||
|
||||
return SystemDictionary::soft_reference_klass()->long_field(offset);
|
||||
return SystemDictionary::SoftReference_klass()->long_field(offset);
|
||||
}
|
||||
|
||||
void java_lang_ref_SoftReference::set_clock(jlong value) {
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass());
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass());
|
||||
int offset = ik->offset_of_static_fields() + static_clock_offset;
|
||||
|
||||
SystemDictionary::soft_reference_klass()->long_field_put(offset, value);
|
||||
SystemDictionary::SoftReference_klass()->long_field_put(offset, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2403,6 +2403,10 @@ oop java_dyn_MethodType::ptype(oop mt, int idx) {
|
||||
return ptypes(mt)->obj_at(idx);
|
||||
}
|
||||
|
||||
int java_dyn_MethodType::ptype_count(oop mt) {
|
||||
return ptypes(mt)->length();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Support for java_dyn_MethodTypeForm
|
||||
@ -2534,7 +2538,7 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
|
||||
// the generated bytecodes for reflection, and if so, "magically"
|
||||
// delegate to its parent to prevent class loading from occurring
|
||||
// in places where applications using reflection didn't expect it.
|
||||
klassOop delegating_cl_class = SystemDictionary::reflect_delegating_classloader_klass();
|
||||
klassOop delegating_cl_class = SystemDictionary::reflect_DelegatingClassLoader_klass();
|
||||
// This might be null in non-1.4 JDKs
|
||||
if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) {
|
||||
return parent(loader);
|
||||
@ -2549,7 +2553,7 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
|
||||
void java_lang_System::compute_offsets() {
|
||||
assert(offset_of_static_fields == 0, "offsets should be initialized only once");
|
||||
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::system_klass());
|
||||
instanceKlass* ik = instanceKlass::cast(SystemDictionary::System_klass());
|
||||
offset_of_static_fields = ik->offset_of_static_fields();
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ class java_lang_String : AllStatic {
|
||||
|
||||
// Testers
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && obj->klass() == SystemDictionary::string_klass();
|
||||
return obj != NULL && obj->klass() == SystemDictionary::String_klass();
|
||||
}
|
||||
|
||||
// Debugging
|
||||
@ -161,7 +161,7 @@ class java_lang_Class : AllStatic {
|
||||
static void print_signature(oop java_class, outputStream *st);
|
||||
// Testing
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && obj->klass() == SystemDictionary::class_klass();
|
||||
return obj != NULL && obj->klass() == SystemDictionary::Class_klass();
|
||||
}
|
||||
static bool is_primitive(oop java_class);
|
||||
static BasicType primitive_type(oop java_class);
|
||||
@ -1027,6 +1027,7 @@ class java_dyn_MethodType: AllStatic {
|
||||
static oop form(oop mt);
|
||||
|
||||
static oop ptype(oop mt, int index);
|
||||
static int ptype_count(oop mt);
|
||||
|
||||
static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS);
|
||||
static void print_signature(oop mt, outputStream* st);
|
||||
@ -1083,6 +1084,14 @@ public:
|
||||
static oop vmmethod(oop site);
|
||||
static void set_vmmethod(oop site, oop ref);
|
||||
|
||||
// Testers
|
||||
static bool is_subclass(klassOop klass) {
|
||||
return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass());
|
||||
}
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
|
||||
// Accessors for code generation:
|
||||
static int target_offset_in_bytes() { return _target_offset; }
|
||||
static int type_offset_in_bytes() { return _type_offset; }
|
||||
|
@ -60,10 +60,10 @@ oop SystemDictionary::java_system_loader() {
|
||||
}
|
||||
|
||||
void SystemDictionary::compute_java_system_loader(TRAPS) {
|
||||
KlassHandle system_klass(THREAD, WK_KLASS(classloader_klass));
|
||||
KlassHandle system_klass(THREAD, WK_KLASS(ClassLoader_klass));
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
KlassHandle(THREAD, WK_KLASS(classloader_klass)),
|
||||
KlassHandle(THREAD, WK_KLASS(ClassLoader_klass)),
|
||||
vmSymbolHandles::getSystemClassLoader_name(),
|
||||
vmSymbolHandles::void_classloader_signature(),
|
||||
CHECK);
|
||||
@ -128,7 +128,7 @@ klassOop SystemDictionary::handle_resolution_exception(symbolHandle class_name,
|
||||
// in which case we have to check whether the pending exception is a ClassNotFoundException,
|
||||
// and if so convert it to a NoClassDefFoundError
|
||||
// And chain the original ClassNotFoundException
|
||||
if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass())) {
|
||||
if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass())) {
|
||||
ResourceMark rm(THREAD);
|
||||
assert(klass_h() == NULL, "Should not have result with exception pending");
|
||||
Handle e(THREAD, PENDING_EXCEPTION);
|
||||
@ -359,7 +359,7 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass,
|
||||
|
||||
assert(class_loader() != NULL, "should not have non-null protection domain for null classloader");
|
||||
|
||||
KlassHandle system_loader(THREAD, SystemDictionary::classloader_klass());
|
||||
KlassHandle system_loader(THREAD, SystemDictionary::ClassLoader_klass());
|
||||
JavaCalls::call_special(&result,
|
||||
class_loader,
|
||||
system_loader,
|
||||
@ -743,7 +743,7 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam
|
||||
// Bootstrap goes through here to allow for an extra guarantee check
|
||||
if (UnsyncloadClass || (class_loader.is_null())) {
|
||||
if (k.is_null() && HAS_PENDING_EXCEPTION
|
||||
&& PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) {
|
||||
&& PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
klassOop check = find_class(d_index, d_hash, name, class_loader);
|
||||
if (check != NULL) {
|
||||
@ -1367,7 +1367,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_nam
|
||||
|
||||
JavaValue result(T_OBJECT);
|
||||
|
||||
KlassHandle spec_klass (THREAD, SystemDictionary::classloader_klass());
|
||||
KlassHandle spec_klass (THREAD, SystemDictionary::ClassLoader_klass());
|
||||
|
||||
// Call public unsynchronized loadClass(String) directly for all class loaders
|
||||
// for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will
|
||||
@ -1944,13 +1944,13 @@ void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id
|
||||
|
||||
|
||||
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
assert(WK_KLASS(object_klass) == NULL, "preloaded classes should only be initialized once");
|
||||
assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
|
||||
// Preload commonly used klasses
|
||||
WKID scan = FIRST_WKID;
|
||||
// first do Object, String, Class
|
||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(class_klass), scan, CHECK);
|
||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK);
|
||||
|
||||
debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(class_klass)));
|
||||
debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(Class_klass)));
|
||||
|
||||
// Fixup mirrors for classes loaded before java.lang.Class.
|
||||
// These calls iterate over the objects currently in the perm gen
|
||||
@ -1961,17 +1961,17 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
Universe::fixup_mirrors(CHECK);
|
||||
|
||||
// do a bunch more:
|
||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(reference_klass), scan, CHECK);
|
||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Reference_klass), scan, CHECK);
|
||||
|
||||
// Preload ref klasses and set reference types
|
||||
instanceKlass::cast(WK_KLASS(reference_klass))->set_reference_type(REF_OTHER);
|
||||
instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(reference_klass));
|
||||
instanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
|
||||
instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass));
|
||||
|
||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(phantom_reference_klass), scan, CHECK);
|
||||
instanceKlass::cast(WK_KLASS(soft_reference_klass))->set_reference_type(REF_SOFT);
|
||||
instanceKlass::cast(WK_KLASS(weak_reference_klass))->set_reference_type(REF_WEAK);
|
||||
instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
|
||||
instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
|
||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK);
|
||||
instanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
|
||||
instanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK);
|
||||
instanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
|
||||
instanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
|
||||
|
||||
WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
|
||||
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
|
||||
@ -1984,7 +1984,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
scan = WKID(meth_group_end+1);
|
||||
}
|
||||
WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
|
||||
WKID indy_group_end = WK_KLASS_ENUM_NAME(Dynamic_klass);
|
||||
WKID indy_group_end = WK_KLASS_ENUM_NAME(InvokeDynamic_klass);
|
||||
initialize_wk_klasses_until(indy_group_start, scan, CHECK);
|
||||
if (EnableInvokeDynamic) {
|
||||
initialize_wk_klasses_through(indy_group_end, scan, CHECK);
|
||||
@ -1996,14 +1996,14 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
|
||||
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
|
||||
|
||||
_box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass);
|
||||
_box_klasses[T_CHAR] = WK_KLASS(char_klass);
|
||||
_box_klasses[T_FLOAT] = WK_KLASS(float_klass);
|
||||
_box_klasses[T_DOUBLE] = WK_KLASS(double_klass);
|
||||
_box_klasses[T_BYTE] = WK_KLASS(byte_klass);
|
||||
_box_klasses[T_SHORT] = WK_KLASS(short_klass);
|
||||
_box_klasses[T_INT] = WK_KLASS(int_klass);
|
||||
_box_klasses[T_LONG] = WK_KLASS(long_klass);
|
||||
_box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
|
||||
_box_klasses[T_CHAR] = WK_KLASS(Character_klass);
|
||||
_box_klasses[T_FLOAT] = WK_KLASS(Float_klass);
|
||||
_box_klasses[T_DOUBLE] = WK_KLASS(Double_klass);
|
||||
_box_klasses[T_BYTE] = WK_KLASS(Byte_klass);
|
||||
_box_klasses[T_SHORT] = WK_KLASS(Short_klass);
|
||||
_box_klasses[T_INT] = WK_KLASS(Integer_klass);
|
||||
_box_klasses[T_LONG] = WK_KLASS(Long_klass);
|
||||
//_box_klasses[T_OBJECT] = WK_KLASS(object_klass);
|
||||
//_box_klasses[T_ARRAY] = WK_KLASS(object_klass);
|
||||
|
||||
@ -2014,11 +2014,11 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
#endif // KERNEL
|
||||
|
||||
{ // Compute whether we should use loadClass or loadClassInternal when loading classes.
|
||||
methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature());
|
||||
methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature());
|
||||
_has_loadClassInternal = (method != NULL);
|
||||
}
|
||||
{ // Compute whether we should use checkPackageAccess or NOT
|
||||
methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature());
|
||||
methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature());
|
||||
_has_checkPackageAccess = (method != NULL);
|
||||
}
|
||||
}
|
||||
@ -2340,6 +2340,8 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
|
||||
SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
|
||||
if (spe == NULL || spe->property_oop() == NULL) {
|
||||
// Must create lots of stuff here, but outside of the SystemDictionary lock.
|
||||
if (THREAD->is_Compiler_thread())
|
||||
return NULL; // do not attempt from within compiler
|
||||
Handle mt = compute_method_handle_type(signature(),
|
||||
class_loader, protection_domain,
|
||||
CHECK_NULL);
|
||||
@ -2372,7 +2374,7 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
|
||||
TRAPS) {
|
||||
Handle empty;
|
||||
int npts = ArgumentCount(signature()).size();
|
||||
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty));
|
||||
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty));
|
||||
int arg = 0;
|
||||
Handle rt; // the return type from the signature
|
||||
for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {
|
||||
|
@ -82,55 +82,55 @@ class SymbolPropertyTable;
|
||||
|
||||
#define WK_KLASSES_DO(template) \
|
||||
/* well-known classes */ \
|
||||
template(object_klass, java_lang_Object, Pre) \
|
||||
template(string_klass, java_lang_String, Pre) \
|
||||
template(class_klass, java_lang_Class, Pre) \
|
||||
template(cloneable_klass, java_lang_Cloneable, Pre) \
|
||||
template(classloader_klass, java_lang_ClassLoader, Pre) \
|
||||
template(serializable_klass, java_io_Serializable, Pre) \
|
||||
template(system_klass, java_lang_System, Pre) \
|
||||
template(throwable_klass, java_lang_Throwable, Pre) \
|
||||
template(error_klass, java_lang_Error, Pre) \
|
||||
template(threaddeath_klass, java_lang_ThreadDeath, Pre) \
|
||||
template(exception_klass, java_lang_Exception, Pre) \
|
||||
template(runtime_exception_klass, java_lang_RuntimeException, Pre) \
|
||||
template(protectionDomain_klass, java_security_ProtectionDomain, Pre) \
|
||||
template(Object_klass, java_lang_Object, Pre) \
|
||||
template(String_klass, java_lang_String, Pre) \
|
||||
template(Class_klass, java_lang_Class, Pre) \
|
||||
template(Cloneable_klass, java_lang_Cloneable, Pre) \
|
||||
template(ClassLoader_klass, java_lang_ClassLoader, Pre) \
|
||||
template(Serializable_klass, java_io_Serializable, Pre) \
|
||||
template(System_klass, java_lang_System, Pre) \
|
||||
template(Throwable_klass, java_lang_Throwable, Pre) \
|
||||
template(Error_klass, java_lang_Error, Pre) \
|
||||
template(ThreadDeath_klass, java_lang_ThreadDeath, Pre) \
|
||||
template(Exception_klass, java_lang_Exception, Pre) \
|
||||
template(RuntimeException_klass, java_lang_RuntimeException, Pre) \
|
||||
template(ProtectionDomain_klass, java_security_ProtectionDomain, Pre) \
|
||||
template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \
|
||||
template(classNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \
|
||||
template(noClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \
|
||||
template(linkageError_klass, java_lang_LinkageError, Pre) \
|
||||
template(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \
|
||||
template(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \
|
||||
template(LinkageError_klass, java_lang_LinkageError, Pre) \
|
||||
template(ClassCastException_klass, java_lang_ClassCastException, Pre) \
|
||||
template(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre) \
|
||||
template(virtualMachineError_klass, java_lang_VirtualMachineError, Pre) \
|
||||
template(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre) \
|
||||
template(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre) \
|
||||
template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \
|
||||
template(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre) \
|
||||
template(reference_klass, java_lang_ref_Reference, Pre) \
|
||||
template(Reference_klass, java_lang_ref_Reference, Pre) \
|
||||
\
|
||||
/* Preload ref klasses and set reference types */ \
|
||||
template(soft_reference_klass, java_lang_ref_SoftReference, Pre) \
|
||||
template(weak_reference_klass, java_lang_ref_WeakReference, Pre) \
|
||||
template(final_reference_klass, java_lang_ref_FinalReference, Pre) \
|
||||
template(phantom_reference_klass, java_lang_ref_PhantomReference, Pre) \
|
||||
template(finalizer_klass, java_lang_ref_Finalizer, Pre) \
|
||||
template(SoftReference_klass, java_lang_ref_SoftReference, Pre) \
|
||||
template(WeakReference_klass, java_lang_ref_WeakReference, Pre) \
|
||||
template(FinalReference_klass, java_lang_ref_FinalReference, Pre) \
|
||||
template(PhantomReference_klass, java_lang_ref_PhantomReference, Pre) \
|
||||
template(Finalizer_klass, java_lang_ref_Finalizer, Pre) \
|
||||
\
|
||||
template(thread_klass, java_lang_Thread, Pre) \
|
||||
template(threadGroup_klass, java_lang_ThreadGroup, Pre) \
|
||||
template(properties_klass, java_util_Properties, Pre) \
|
||||
template(reflect_accessible_object_klass, java_lang_reflect_AccessibleObject, Pre) \
|
||||
template(reflect_field_klass, java_lang_reflect_Field, Pre) \
|
||||
template(reflect_method_klass, java_lang_reflect_Method, Pre) \
|
||||
template(reflect_constructor_klass, java_lang_reflect_Constructor, Pre) \
|
||||
template(Thread_klass, java_lang_Thread, Pre) \
|
||||
template(ThreadGroup_klass, java_lang_ThreadGroup, Pre) \
|
||||
template(Properties_klass, java_util_Properties, Pre) \
|
||||
template(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre) \
|
||||
template(reflect_Field_klass, java_lang_reflect_Field, Pre) \
|
||||
template(reflect_Method_klass, java_lang_reflect_Method, Pre) \
|
||||
template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \
|
||||
\
|
||||
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
|
||||
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
|
||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||
template(reflect_magic_klass, sun_reflect_MagicAccessorImpl, Opt) \
|
||||
template(reflect_method_accessor_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
template(reflect_constructor_accessor_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
template(reflect_delegating_classloader_klass, sun_reflect_DelegatingClassLoader, Opt) \
|
||||
template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
|
||||
template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
|
||||
template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \
|
||||
template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \
|
||||
template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
|
||||
template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
|
||||
\
|
||||
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
||||
template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \
|
||||
@ -144,16 +144,14 @@ class SymbolPropertyTable;
|
||||
template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
|
||||
template(Linkage_klass, java_dyn_Linkage, Opt) \
|
||||
template(CallSite_klass, java_dyn_CallSite, Opt) \
|
||||
template(Dynamic_klass, java_dyn_Dynamic, Opt) \
|
||||
template(InvokeDynamic_klass, java_dyn_InvokeDynamic, Opt) \
|
||||
/* Note: MethodHandle must be first, and Dynamic last in group */ \
|
||||
\
|
||||
template(vector_klass, java_util_Vector, Pre) \
|
||||
template(hashtable_klass, java_util_Hashtable, Pre) \
|
||||
template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
|
||||
template(StringBuffer_klass, java_lang_StringBuffer, Pre) \
|
||||
template(StringBuilder_klass, java_lang_StringBuilder, Pre) \
|
||||
\
|
||||
/* It's NULL in non-1.4 JDKs. */ \
|
||||
template(stackTraceElement_klass, java_lang_StackTraceElement, Opt) \
|
||||
template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \
|
||||
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
|
||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||
template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \
|
||||
@ -164,14 +162,14 @@ class SymbolPropertyTable;
|
||||
template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
|
||||
\
|
||||
/* Preload boxing klasses */ \
|
||||
template(boolean_klass, java_lang_Boolean, Pre) \
|
||||
template(char_klass, java_lang_Character, Pre) \
|
||||
template(float_klass, java_lang_Float, Pre) \
|
||||
template(double_klass, java_lang_Double, Pre) \
|
||||
template(byte_klass, java_lang_Byte, Pre) \
|
||||
template(short_klass, java_lang_Short, Pre) \
|
||||
template(int_klass, java_lang_Integer, Pre) \
|
||||
template(long_klass, java_lang_Long, Pre) \
|
||||
template(Boolean_klass, java_lang_Boolean, Pre) \
|
||||
template(Character_klass, java_lang_Character, Pre) \
|
||||
template(Float_klass, java_lang_Float, Pre) \
|
||||
template(Double_klass, java_lang_Double, Pre) \
|
||||
template(Byte_klass, java_lang_Byte, Pre) \
|
||||
template(Short_klass, java_lang_Short, Pre) \
|
||||
template(Integer_klass, java_lang_Integer, Pre) \
|
||||
template(Long_klass, java_lang_Long, Pre) \
|
||||
/*end*/
|
||||
|
||||
|
||||
@ -438,8 +436,8 @@ public:
|
||||
// Tells whether ClassLoader.checkPackageAccess is present
|
||||
static bool has_checkPackageAccess() { return _has_checkPackageAccess; }
|
||||
|
||||
static bool class_klass_loaded() { return WK_KLASS(class_klass) != NULL; }
|
||||
static bool cloneable_klass_loaded() { return WK_KLASS(cloneable_klass) != NULL; }
|
||||
static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; }
|
||||
static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; }
|
||||
|
||||
// Returns default system loader
|
||||
static oop java_system_loader();
|
||||
|
@ -143,7 +143,7 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul
|
||||
|
||||
bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) {
|
||||
symbolOop name = klass->name();
|
||||
klassOop refl_magic_klass = SystemDictionary::reflect_magic_klass();
|
||||
klassOop refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass();
|
||||
|
||||
return (should_verify_for(klass->class_loader(), should_verify_class) &&
|
||||
// return if the class is a bootstrapping class
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -70,6 +70,7 @@ static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGN
|
||||
void vmSymbols::initialize(TRAPS) {
|
||||
assert((int)SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield");
|
||||
assert((int)SID_LIMIT*5 > (1<<log2_SID_LIMIT), "make the bitfield smaller, please");
|
||||
assert(vmIntrinsics::FLAG_LIMIT <= (1 << vmIntrinsics::log2_FLAG_LIMIT), "must fit in this bitfield");
|
||||
|
||||
if (!UseSharedSpaces) {
|
||||
const char* string = &vm_symbol_bodies[0];
|
||||
@ -271,6 +272,58 @@ vmSymbols::SID vmSymbols::find_sid(symbolOop symbol) {
|
||||
return sid;
|
||||
}
|
||||
|
||||
static vmIntrinsics::ID wrapper_intrinsic(BasicType type, bool unboxing) {
|
||||
#define TYPE2(type, unboxing) ((int)(type)*2 + ((unboxing) ? 1 : 0))
|
||||
switch (TYPE2(type, unboxing)) {
|
||||
#define BASIC_TYPE_CASE(type, box, unbox) \
|
||||
case TYPE2(type, false): return vmIntrinsics::box; \
|
||||
case TYPE2(type, true): return vmIntrinsics::unbox
|
||||
BASIC_TYPE_CASE(T_BOOLEAN, _Boolean_valueOf, _booleanValue);
|
||||
BASIC_TYPE_CASE(T_BYTE, _Byte_valueOf, _byteValue);
|
||||
BASIC_TYPE_CASE(T_CHAR, _Character_valueOf, _charValue);
|
||||
BASIC_TYPE_CASE(T_SHORT, _Short_valueOf, _shortValue);
|
||||
BASIC_TYPE_CASE(T_INT, _Integer_valueOf, _intValue);
|
||||
BASIC_TYPE_CASE(T_LONG, _Long_valueOf, _longValue);
|
||||
BASIC_TYPE_CASE(T_FLOAT, _Float_valueOf, _floatValue);
|
||||
BASIC_TYPE_CASE(T_DOUBLE, _Double_valueOf, _doubleValue);
|
||||
#undef BASIC_TYPE_CASE
|
||||
}
|
||||
#undef TYPE2
|
||||
return vmIntrinsics::_none;
|
||||
}
|
||||
|
||||
vmIntrinsics::ID vmIntrinsics::for_boxing(BasicType type) {
|
||||
return wrapper_intrinsic(type, false);
|
||||
}
|
||||
vmIntrinsics::ID vmIntrinsics::for_unboxing(BasicType type) {
|
||||
return wrapper_intrinsic(type, true);
|
||||
}
|
||||
|
||||
vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest) {
|
||||
#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d))
|
||||
switch (SRC_DEST(src, dest)) {
|
||||
case SRC_DEST(T_INT, T_FLOAT): return vmIntrinsics::_intBitsToFloat;
|
||||
case SRC_DEST(T_FLOAT, T_INT): return vmIntrinsics::_floatToRawIntBits;
|
||||
|
||||
case SRC_DEST(T_LONG, T_DOUBLE): return vmIntrinsics::_longBitsToDouble;
|
||||
case SRC_DEST(T_DOUBLE, T_LONG): return vmIntrinsics::_doubleToRawLongBits;
|
||||
}
|
||||
#undef SRC_DEST
|
||||
|
||||
return vmIntrinsics::_none;
|
||||
}
|
||||
|
||||
methodOop vmIntrinsics::method_for(vmIntrinsics::ID id) {
|
||||
if (id == _none) return NULL;
|
||||
symbolOop cname = vmSymbols::symbol_at(class_for(id));
|
||||
symbolOop mname = vmSymbols::symbol_at(name_for(id));
|
||||
symbolOop msig = vmSymbols::symbol_at(signature_for(id));
|
||||
if (cname == NULL || mname == NULL || msig == NULL) return NULL;
|
||||
klassOop k = SystemDictionary::find_well_known_klass(cname);
|
||||
if (k == NULL) return NULL;
|
||||
return instanceKlass::cast(k)->find_method(mname, msig);
|
||||
}
|
||||
|
||||
|
||||
#define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0"
|
||||
static const char* vm_intrinsic_name_bodies =
|
||||
@ -330,15 +383,15 @@ inline bool match_F_RNY(jshort flags) {
|
||||
}
|
||||
|
||||
// These are for forming case labels:
|
||||
#define ID3(x, y, z) (( jint)(z) + \
|
||||
((jint)(y) << vmSymbols::log2_SID_LIMIT) + \
|
||||
((jint)(x) << (2*vmSymbols::log2_SID_LIMIT)) )
|
||||
#define ID3(x, y, z) (( jlong)(z) + \
|
||||
((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \
|
||||
((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) )
|
||||
#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n)
|
||||
|
||||
vmIntrinsics::ID vmIntrinsics::find_id(vmSymbols::SID holder,
|
||||
vmSymbols::SID name,
|
||||
vmSymbols::SID sig,
|
||||
jshort flags) {
|
||||
vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder,
|
||||
vmSymbols::SID name,
|
||||
vmSymbols::SID sig,
|
||||
jshort flags) {
|
||||
assert((int)vmSymbols::SID_LIMIT <= (1<<vmSymbols::log2_SID_LIMIT), "must fit");
|
||||
|
||||
// Let the C compiler build the decision tree.
|
||||
@ -383,62 +436,50 @@ const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf,
|
||||
}
|
||||
|
||||
|
||||
// These are for friendly printouts of intrinsics:
|
||||
// These are to get information about intrinsics.
|
||||
|
||||
#define ID4(x, y, z, f) ((ID3(x, y, z) << vmIntrinsics::log2_FLAG_LIMIT) | (jlong) (f))
|
||||
|
||||
static const jlong intrinsic_info_array[vmIntrinsics::ID_LIMIT+1] = {
|
||||
#define VM_INTRINSIC_INFO(ignore_id, klass, name, sig, fcode) \
|
||||
ID4(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig), vmIntrinsics::fcode),
|
||||
|
||||
0, VM_INTRINSICS_DO(VM_INTRINSIC_INFO,
|
||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE)
|
||||
0
|
||||
#undef VM_INTRINSIC_INFO
|
||||
};
|
||||
|
||||
inline jlong intrinsic_info(vmIntrinsics::ID id) {
|
||||
return intrinsic_info_array[vmIntrinsics::ID_from((int)id)];
|
||||
}
|
||||
|
||||
vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) {
|
||||
#ifndef PRODUCT
|
||||
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
|
||||
case id: return SID_ENUM(klass);
|
||||
|
||||
switch (id) {
|
||||
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
|
||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
|
||||
}
|
||||
#undef VM_INTRINSIC_CASE
|
||||
#endif //PRODUCT
|
||||
return vmSymbols::NO_SID;
|
||||
jlong info = intrinsic_info(id);
|
||||
int shift = 2*vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
|
||||
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1021, "");
|
||||
return vmSymbols::SID( (info >> shift) & mask );
|
||||
}
|
||||
|
||||
vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) {
|
||||
#ifndef PRODUCT
|
||||
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
|
||||
case id: return SID_ENUM(name);
|
||||
|
||||
switch (id) {
|
||||
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
|
||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
|
||||
}
|
||||
#undef VM_INTRINSIC_CASE
|
||||
#endif //PRODUCT
|
||||
return vmSymbols::NO_SID;
|
||||
jlong info = intrinsic_info(id);
|
||||
int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
|
||||
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, "");
|
||||
return vmSymbols::SID( (info >> shift) & mask );
|
||||
}
|
||||
|
||||
vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) {
|
||||
#ifndef PRODUCT
|
||||
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
|
||||
case id: return SID_ENUM(sig);
|
||||
|
||||
switch (id) {
|
||||
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
|
||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
|
||||
}
|
||||
#undef VM_INTRINSIC_CASE
|
||||
#endif //PRODUCT
|
||||
return vmSymbols::NO_SID;
|
||||
jlong info = intrinsic_info(id);
|
||||
int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
|
||||
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, "");
|
||||
return vmSymbols::SID( (info >> shift) & mask );
|
||||
}
|
||||
|
||||
vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) {
|
||||
#ifndef PRODUCT
|
||||
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
|
||||
case id: return fcode;
|
||||
|
||||
switch (id) {
|
||||
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
|
||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
|
||||
}
|
||||
#undef VM_INTRINSIC_CASE
|
||||
#endif //PRODUCT
|
||||
return F_none;
|
||||
jlong info = intrinsic_info(id);
|
||||
int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT);
|
||||
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, "");
|
||||
return Flags( (info >> shift) & mask );
|
||||
}
|
||||
|
||||
|
||||
|
@ -219,7 +219,7 @@
|
||||
template(base_name, "base") \
|
||||
\
|
||||
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
|
||||
template(java_dyn_Dynamic, "java/dyn/Dynamic") \
|
||||
template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") \
|
||||
template(java_dyn_Linkage, "java/dyn/Linkage") \
|
||||
template(java_dyn_CallSite, "java/dyn/CallSite") \
|
||||
template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
|
||||
@ -347,9 +347,14 @@
|
||||
\
|
||||
/* common signatures names */ \
|
||||
template(void_method_signature, "()V") \
|
||||
template(void_boolean_signature, "()Z") \
|
||||
template(void_byte_signature, "()B") \
|
||||
template(void_char_signature, "()C") \
|
||||
template(void_short_signature, "()S") \
|
||||
template(void_int_signature, "()I") \
|
||||
template(void_long_signature, "()J") \
|
||||
template(void_boolean_signature, "()Z") \
|
||||
template(void_float_signature, "()F") \
|
||||
template(void_double_signature, "()D") \
|
||||
template(int_void_signature, "(I)V") \
|
||||
template(int_int_signature, "(I)I") \
|
||||
template(int_bool_signature, "(I)Z") \
|
||||
@ -854,6 +859,46 @@
|
||||
\
|
||||
do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
|
||||
/* (symbols invoke_name and invoke_signature defined above) */ \
|
||||
do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \
|
||||
do_name( checkSpreadArgument_name, "checkSpreadArgument") \
|
||||
do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \
|
||||
\
|
||||
/* unboxing methods: */ \
|
||||
do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \
|
||||
do_name( booleanValue_name, "booleanValue") \
|
||||
do_intrinsic(_byteValue, java_lang_Byte, byteValue_name, void_byte_signature, F_R) \
|
||||
do_name( byteValue_name, "byteValue") \
|
||||
do_intrinsic(_charValue, java_lang_Character, charValue_name, void_char_signature, F_R) \
|
||||
do_name( charValue_name, "charValue") \
|
||||
do_intrinsic(_shortValue, java_lang_Short, shortValue_name, void_short_signature, F_R) \
|
||||
do_name( shortValue_name, "shortValue") \
|
||||
do_intrinsic(_intValue, java_lang_Integer, intValue_name, void_int_signature, F_R) \
|
||||
do_name( intValue_name, "intValue") \
|
||||
do_intrinsic(_longValue, java_lang_Long, longValue_name, void_long_signature, F_R) \
|
||||
do_name( longValue_name, "longValue") \
|
||||
do_intrinsic(_floatValue, java_lang_Float, floatValue_name, void_float_signature, F_R) \
|
||||
do_name( floatValue_name, "floatValue") \
|
||||
do_intrinsic(_doubleValue, java_lang_Double, doubleValue_name, void_double_signature, F_R) \
|
||||
do_name( doubleValue_name, "doubleValue") \
|
||||
\
|
||||
/* boxing methods: */ \
|
||||
do_name( valueOf_name, "valueOf") \
|
||||
do_intrinsic(_Boolean_valueOf, java_lang_Boolean, valueOf_name, Boolean_valueOf_signature, F_S) \
|
||||
do_name( Boolean_valueOf_signature, "(Z)Ljava/lang/Boolean;") \
|
||||
do_intrinsic(_Byte_valueOf, java_lang_Byte, valueOf_name, Byte_valueOf_signature, F_S) \
|
||||
do_name( Byte_valueOf_signature, "(B)Ljava/lang/Byte;") \
|
||||
do_intrinsic(_Character_valueOf, java_lang_Character, valueOf_name, Character_valueOf_signature, F_S) \
|
||||
do_name( Character_valueOf_signature, "(C)Ljava/lang/Character;") \
|
||||
do_intrinsic(_Short_valueOf, java_lang_Short, valueOf_name, Short_valueOf_signature, F_S) \
|
||||
do_name( Short_valueOf_signature, "(S)Ljava/lang/Short;") \
|
||||
do_intrinsic(_Integer_valueOf, java_lang_Integer, valueOf_name, Integer_valueOf_signature, F_S) \
|
||||
do_name( Integer_valueOf_signature, "(I)Ljava/lang/Integer;") \
|
||||
do_intrinsic(_Long_valueOf, java_lang_Long, valueOf_name, Long_valueOf_signature, F_S) \
|
||||
do_name( Long_valueOf_signature, "(J)Ljava/lang/Long;") \
|
||||
do_intrinsic(_Float_valueOf, java_lang_Float, valueOf_name, Float_valueOf_signature, F_S) \
|
||||
do_name( Float_valueOf_signature, "(F)Ljava/lang/Float;") \
|
||||
do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \
|
||||
do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \
|
||||
\
|
||||
/*end*/
|
||||
|
||||
@ -984,7 +1029,12 @@ class vmIntrinsics: AllStatic {
|
||||
F_Y, // !static ?native synchronized
|
||||
F_RN, // !static native !synchronized
|
||||
F_SN, // static native !synchronized
|
||||
F_RNY // !static native synchronized
|
||||
F_RNY, // !static native synchronized
|
||||
|
||||
FLAG_LIMIT
|
||||
};
|
||||
enum {
|
||||
log2_FLAG_LIMIT = 4 // checked by an assert at start-up
|
||||
};
|
||||
|
||||
public:
|
||||
@ -996,15 +1046,32 @@ public:
|
||||
|
||||
static const char* name_at(ID id);
|
||||
|
||||
private:
|
||||
static ID find_id_impl(vmSymbols::SID holder,
|
||||
vmSymbols::SID name,
|
||||
vmSymbols::SID sig,
|
||||
jshort flags);
|
||||
|
||||
public:
|
||||
// Given a method's class, name, signature, and access flags, report its ID.
|
||||
static ID find_id(vmSymbols::SID holder,
|
||||
vmSymbols::SID name,
|
||||
vmSymbols::SID sig,
|
||||
jshort flags);
|
||||
jshort flags) {
|
||||
ID id = find_id_impl(holder, name, sig, flags);
|
||||
#ifdef ASSERT
|
||||
// ID _none does not hold the following asserts.
|
||||
if (id == _none) return id;
|
||||
#endif
|
||||
assert( class_for(id) == holder, "correct id");
|
||||
assert( name_for(id) == name, "correct id");
|
||||
assert(signature_for(id) == sig, "correct id");
|
||||
return id;
|
||||
}
|
||||
|
||||
static void verify_method(ID actual_id, methodOop m) PRODUCT_RETURN;
|
||||
|
||||
// No need for these in the product:
|
||||
// Find out the symbols behind an intrinsic:
|
||||
static vmSymbols::SID class_for(ID id);
|
||||
static vmSymbols::SID name_for(ID id);
|
||||
static vmSymbols::SID signature_for(ID id);
|
||||
@ -1014,4 +1081,11 @@ public:
|
||||
|
||||
// Access to intrinsic methods:
|
||||
static methodOop method_for(ID id);
|
||||
|
||||
// Wrapper object methods:
|
||||
static ID for_boxing(BasicType type);
|
||||
static ID for_unboxing(BasicType type);
|
||||
|
||||
// Raw conversion:
|
||||
static ID for_raw_conversion(BasicType src, BasicType dest);
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -102,6 +102,9 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
||||
virtual bool is_compiled_by_c2() const { return false; }
|
||||
virtual bool is_compiled_by_c1() const { return false; }
|
||||
|
||||
// Casting
|
||||
nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
|
||||
|
||||
// Boundaries
|
||||
address header_begin() const { return (address) this; }
|
||||
address header_end() const { return ((address) this) + _header_size; };
|
||||
|
@ -281,6 +281,7 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
|
||||
ciMethod* method,
|
||||
int bci,
|
||||
bool reexecute,
|
||||
bool is_method_handle_invoke,
|
||||
DebugToken* locals,
|
||||
DebugToken* expressions,
|
||||
DebugToken* monitors) {
|
||||
@ -292,8 +293,9 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
|
||||
int stream_offset = stream()->position();
|
||||
last_pd->set_scope_decode_offset(stream_offset);
|
||||
|
||||
// Record reexecute bit into pcDesc
|
||||
// Record flags into pcDesc.
|
||||
last_pd->set_should_reexecute(reexecute);
|
||||
last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
|
||||
|
||||
// serialize sender stream offest
|
||||
stream()->write_int(sender_stream_offset);
|
||||
|
@ -88,6 +88,7 @@ class DebugInformationRecorder: public ResourceObj {
|
||||
ciMethod* method,
|
||||
int bci,
|
||||
bool reexecute,
|
||||
bool is_method_handle_invoke = false,
|
||||
DebugToken* locals = NULL,
|
||||
DebugToken* expressions = NULL,
|
||||
DebugToken* monitors = NULL);
|
||||
|
@ -1170,7 +1170,7 @@ void nmethod::log_state_change() const {
|
||||
}
|
||||
|
||||
// Common functionality for both make_not_entrant and make_zombie
|
||||
bool nmethod::make_not_entrant_or_zombie(int state) {
|
||||
bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
||||
assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
|
||||
|
||||
// If the method is already zombie there is nothing to do
|
||||
@ -1724,9 +1724,9 @@ void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map
|
||||
if (!method()->is_native()) {
|
||||
SimpleScopeDesc ssd(this, fr.pc());
|
||||
Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci());
|
||||
bool is_static = call->is_invokestatic();
|
||||
bool has_receiver = call->has_receiver();
|
||||
symbolOop signature = call->signature();
|
||||
fr.oops_compiled_arguments_do(signature, is_static, reg_map, f);
|
||||
fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1763,6 +1763,14 @@ void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) {
|
||||
"must end with a sentinel");
|
||||
#endif //ASSERT
|
||||
|
||||
// Search for MethodHandle invokes and tag the nmethod.
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (pcs[i].is_method_handle_invoke()) {
|
||||
set_has_method_handle_invokes(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int size = count * sizeof(PcDesc);
|
||||
assert(scopes_pcs_size() >= size, "oob");
|
||||
memcpy(scopes_pcs_begin(), pcs, size);
|
||||
@ -2029,6 +2037,18 @@ bool nmethod::is_deopt_pc(address pc) {
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// MethodHandle
|
||||
|
||||
bool nmethod::is_method_handle_return(address return_pc) {
|
||||
if (!has_method_handle_invokes()) return false;
|
||||
PcDesc* pd = pc_desc_at(return_pc);
|
||||
if (pd == NULL)
|
||||
return false;
|
||||
return pd->is_method_handle_invoke();
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Verification
|
||||
|
||||
|
@ -81,18 +81,19 @@ class PcDescCache VALUE_OBJ_CLASS_SPEC {
|
||||
|
||||
struct nmFlags {
|
||||
friend class VMStructs;
|
||||
unsigned int version:8; // version number (0 = first version)
|
||||
unsigned int level:4; // optimization level
|
||||
unsigned int age:4; // age (in # of sweep steps)
|
||||
unsigned int version:8; // version number (0 = first version)
|
||||
unsigned int level:4; // optimization level
|
||||
unsigned int age:4; // age (in # of sweep steps)
|
||||
|
||||
unsigned int state:2; // {alive, zombie, unloaded)
|
||||
unsigned int state:2; // {alive, zombie, unloaded)
|
||||
|
||||
unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap?
|
||||
unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures
|
||||
unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies
|
||||
unsigned int markedForReclamation:1; // Used by NMethodSweeper
|
||||
unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap?
|
||||
unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures
|
||||
unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies
|
||||
unsigned int markedForReclamation:1; // Used by NMethodSweeper
|
||||
|
||||
unsigned int has_unsafe_access:1; // May fault due to unsafe access.
|
||||
unsigned int has_unsafe_access:1; // May fault due to unsafe access.
|
||||
unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes?
|
||||
|
||||
void clear();
|
||||
};
|
||||
@ -254,7 +255,7 @@ class nmethod : public CodeBlob {
|
||||
const char* reloc_string_for(u_char* begin, u_char* end);
|
||||
// Returns true if this thread changed the state of the nmethod or
|
||||
// false if another thread performed the transition.
|
||||
bool make_not_entrant_or_zombie(int state);
|
||||
bool make_not_entrant_or_zombie(unsigned int state);
|
||||
void inc_decompile_count();
|
||||
|
||||
// used to check that writes to nmFlags are done consistently.
|
||||
@ -409,6 +410,9 @@ class nmethod : public CodeBlob {
|
||||
bool has_unsafe_access() const { return flags.has_unsafe_access; }
|
||||
void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; }
|
||||
|
||||
bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; }
|
||||
void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; }
|
||||
|
||||
int level() const { return flags.level; }
|
||||
void set_level(int newLevel) { check_safepoint(); flags.level = newLevel; }
|
||||
|
||||
@ -541,6 +545,9 @@ class nmethod : public CodeBlob {
|
||||
address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
|
||||
void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
|
||||
|
||||
// MethodHandle
|
||||
bool is_method_handle_return(address return_pc);
|
||||
|
||||
// jvmti support:
|
||||
void post_compiled_method_load_event();
|
||||
|
||||
|
@ -38,6 +38,7 @@ class PcDesc VALUE_OBJ_CLASS_SPEC {
|
||||
int word;
|
||||
struct {
|
||||
unsigned int reexecute: 1;
|
||||
unsigned int is_method_handle_invoke: 1;
|
||||
} bits;
|
||||
bool operator ==(const PcDescFlags& other) { return word == other.word; }
|
||||
} _flags;
|
||||
@ -72,6 +73,9 @@ class PcDesc VALUE_OBJ_CLASS_SPEC {
|
||||
_flags == pd->_flags;
|
||||
}
|
||||
|
||||
bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; }
|
||||
void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; }
|
||||
|
||||
// Returns the real pc
|
||||
address real_pc(const nmethod* code) const;
|
||||
|
||||
|
@ -1820,9 +1820,11 @@ void CompileBroker::print_times() {
|
||||
CompileBroker::_t_standard_compilation.seconds(),
|
||||
CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count);
|
||||
tty->print_cr(" On stack replacement : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count);
|
||||
compiler(CompLevel_fast_compile)->print_timers();
|
||||
if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier)) {
|
||||
compiler(CompLevel_highest_tier)->print_timers();
|
||||
|
||||
if (compiler(CompLevel_fast_compile)) {
|
||||
compiler(CompLevel_fast_compile)->print_timers();
|
||||
if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier))
|
||||
compiler(CompLevel_highest_tier)->print_timers();
|
||||
}
|
||||
|
||||
tty->cr();
|
||||
|
@ -782,6 +782,7 @@ void MethodLiveness::BasicBlock::compute_gen_kill_single(ciBytecodeStream *instr
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokeinterface:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_newarray:
|
||||
case Bytecodes::_anewarray:
|
||||
case Bytecodes::_checkcast:
|
||||
|
@ -274,7 +274,7 @@ CollectedHeap::fill_with_object_impl(HeapWord* start, size_t words)
|
||||
fill_with_array(start, words);
|
||||
} else if (words > 0) {
|
||||
assert(words == min_fill_size(), "unaligned size");
|
||||
post_allocation_setup_common(SystemDictionary::object_klass(), start,
|
||||
post_allocation_setup_common(SystemDictionary::Object_klass(), start,
|
||||
words);
|
||||
}
|
||||
}
|
||||
|
@ -155,6 +155,9 @@ callGenerator.cpp callnode.hpp
|
||||
callGenerator.cpp cfgnode.hpp
|
||||
callGenerator.cpp compileLog.hpp
|
||||
callGenerator.cpp connode.hpp
|
||||
callGenerator.cpp ciCPCache.hpp
|
||||
callGenerator.cpp ciMethodHandle.hpp
|
||||
callGenerator.cpp javaClasses.hpp
|
||||
callGenerator.cpp parse.hpp
|
||||
callGenerator.cpp rootnode.hpp
|
||||
callGenerator.cpp runtime.hpp
|
||||
@ -391,6 +394,9 @@ divnode.hpp type.hpp
|
||||
|
||||
doCall.cpp addnode.hpp
|
||||
doCall.cpp callGenerator.hpp
|
||||
doCall.cpp ciCallSite.hpp
|
||||
doCall.cpp ciCPCache.hpp
|
||||
doCall.cpp ciMethodHandle.hpp
|
||||
doCall.cpp cfgnode.hpp
|
||||
doCall.cpp compileLog.hpp
|
||||
doCall.cpp linkResolver.hpp
|
||||
|
@ -516,6 +516,11 @@ ciArrayKlassKlass.hpp ciKlassKlass.hpp
|
||||
|
||||
ciCallProfile.hpp ciClassList.hpp
|
||||
|
||||
ciCallSite.cpp ciCallSite.hpp
|
||||
ciCallSite.cpp ciUtilities.hpp
|
||||
|
||||
ciCallSite.hpp ciInstance.hpp
|
||||
|
||||
ciConstant.cpp allocation.hpp
|
||||
ciConstant.cpp allocation.inline.hpp
|
||||
ciConstant.cpp ciConstant.hpp
|
||||
@ -532,6 +537,12 @@ ciConstantPoolCache.cpp ciUtilities.hpp
|
||||
ciConstantPoolCache.hpp growableArray.hpp
|
||||
ciConstantPoolCache.hpp resourceArea.hpp
|
||||
|
||||
ciCPCache.cpp cpCacheOop.hpp
|
||||
ciCPCache.cpp ciCPCache.hpp
|
||||
|
||||
ciCPCache.hpp ciClassList.hpp
|
||||
ciCPCache.hpp ciObject.hpp
|
||||
|
||||
ciEnv.cpp allocation.inline.hpp
|
||||
ciEnv.cpp ciConstant.hpp
|
||||
ciEnv.cpp ciEnv.hpp
|
||||
@ -593,6 +604,7 @@ ciField.cpp universe.inline.hpp
|
||||
ciField.hpp ciClassList.hpp
|
||||
ciField.hpp ciConstant.hpp
|
||||
ciField.hpp ciFlags.hpp
|
||||
ciField.hpp ciInstance.hpp
|
||||
|
||||
ciFlags.cpp ciFlags.hpp
|
||||
|
||||
@ -679,6 +691,7 @@ ciMethod.hpp ciFlags.hpp
|
||||
ciMethod.hpp ciInstanceKlass.hpp
|
||||
ciMethod.hpp ciObject.hpp
|
||||
ciMethod.hpp ciSignature.hpp
|
||||
ciMethod.hpp methodHandles.hpp
|
||||
ciMethod.hpp methodLiveness.hpp
|
||||
|
||||
ciMethodBlocks.cpp bytecode.hpp
|
||||
@ -710,6 +723,15 @@ ciMethodKlass.cpp ciUtilities.hpp
|
||||
ciMethodKlass.hpp ciKlass.hpp
|
||||
ciMethodKlass.hpp ciSymbol.hpp
|
||||
|
||||
ciMethodHandle.cpp ciClassList.hpp
|
||||
ciMethodHandle.cpp ciInstance.hpp
|
||||
ciMethodHandle.cpp ciMethodHandle.hpp
|
||||
ciMethodHandle.cpp ciUtilities.hpp
|
||||
ciMethodHandle.cpp methodHandles.hpp
|
||||
ciMethodHandle.cpp methodHandleWalk.hpp
|
||||
|
||||
ciMethodHandle.hpp methodHandles.hpp
|
||||
|
||||
ciNullObject.cpp ciNullObject.hpp
|
||||
|
||||
ciNullObject.hpp ciClassList.hpp
|
||||
@ -755,11 +777,14 @@ ciObject.hpp handles.hpp
|
||||
ciObject.hpp jniHandles.hpp
|
||||
|
||||
ciObjectFactory.cpp allocation.inline.hpp
|
||||
ciObjectFactory.cpp ciCallSite.hpp
|
||||
ciObjectFactory.cpp ciCPCache.hpp
|
||||
ciObjectFactory.cpp ciInstance.hpp
|
||||
ciObjectFactory.cpp ciInstanceKlass.hpp
|
||||
ciObjectFactory.cpp ciInstanceKlassKlass.hpp
|
||||
ciObjectFactory.cpp ciMethod.hpp
|
||||
ciObjectFactory.cpp ciMethodData.hpp
|
||||
ciObjectFactory.cpp ciMethodHandle.hpp
|
||||
ciObjectFactory.cpp ciMethodKlass.hpp
|
||||
ciObjectFactory.cpp ciNullObject.hpp
|
||||
ciObjectFactory.cpp ciObjArray.hpp
|
||||
@ -793,6 +818,7 @@ ciSignature.hpp ciSymbol.hpp
|
||||
ciSignature.hpp globalDefinitions.hpp
|
||||
ciSignature.hpp growableArray.hpp
|
||||
|
||||
ciStreams.cpp ciCallSite.hpp
|
||||
ciStreams.cpp ciConstant.hpp
|
||||
ciStreams.cpp ciField.hpp
|
||||
ciStreams.cpp ciStreams.hpp
|
||||
@ -2814,6 +2840,12 @@ methodDataOop.hpp oop.hpp
|
||||
methodDataOop.hpp orderAccess.hpp
|
||||
methodDataOop.hpp universe.hpp
|
||||
|
||||
methodHandleWalk.hpp methodHandles.hpp
|
||||
|
||||
methodHandleWalk.cpp methodHandleWalk.hpp
|
||||
methodHandleWalk.cpp oopFactory.hpp
|
||||
methodHandleWalk.cpp rewriter.hpp
|
||||
|
||||
methodHandles.hpp frame.inline.hpp
|
||||
methodHandles.hpp globals.hpp
|
||||
methodHandles.hpp interfaceSupport.hpp
|
||||
|
@ -102,7 +102,9 @@ methodHandle Bytecode_invoke::static_target(TRAPS) {
|
||||
KlassHandle resolved_klass;
|
||||
constantPoolHandle constants(THREAD, _method->constants());
|
||||
|
||||
if (adjusted_invoke_code() != Bytecodes::_invokeinterface) {
|
||||
if (adjusted_invoke_code() == Bytecodes::_invokedynamic) {
|
||||
LinkResolver::resolve_dynamic_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
|
||||
} else if (adjusted_invoke_code() != Bytecodes::_invokeinterface) {
|
||||
LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
|
||||
} else {
|
||||
LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
|
||||
|
@ -205,12 +205,14 @@ class Bytecode_invoke: public ResourceObj {
|
||||
bool is_invokespecial() const { return adjusted_invoke_code() == Bytecodes::_invokespecial; }
|
||||
bool is_invokedynamic() const { return adjusted_invoke_code() == Bytecodes::_invokedynamic; }
|
||||
|
||||
bool has_receiver() const { return !is_invokestatic() && !is_invokedynamic(); }
|
||||
bool has_giant_index() const { return is_invokedynamic(); }
|
||||
|
||||
bool is_valid() const { return is_invokeinterface() ||
|
||||
is_invokevirtual() ||
|
||||
is_invokestatic() ||
|
||||
is_invokespecial(); }
|
||||
is_invokespecial() ||
|
||||
is_invokedynamic(); }
|
||||
|
||||
// Creation
|
||||
inline friend Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci);
|
||||
|
@ -270,6 +270,8 @@ void BytecodePrinter::print_constant(int i, outputStream* st) {
|
||||
st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name());
|
||||
} else if (tag.is_unresolved_klass()) {
|
||||
st->print_cr(" <unresolved klass at %d>", i);
|
||||
} else if (tag.is_object()) {
|
||||
st->print_cr(" " PTR_FORMAT, constants->object_at(i));
|
||||
} else {
|
||||
st->print_cr(" bad tag=%d at %d", tag.value(), i);
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ void Bytecodes::initialize() {
|
||||
def(_invokespecial , "invokespecial" , "bjj" , NULL , T_ILLEGAL, -1, true);
|
||||
def(_invokestatic , "invokestatic" , "bjj" , NULL , T_ILLEGAL, 0, true);
|
||||
def(_invokeinterface , "invokeinterface" , "bjj__", NULL , T_ILLEGAL, -1, true);
|
||||
def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, -1, true );
|
||||
def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, 0, true );
|
||||
def(_new , "new" , "bii" , NULL , T_OBJECT , 1, true );
|
||||
def(_newarray , "newarray" , "bc" , NULL , T_OBJECT , 0, true );
|
||||
def(_anewarray , "anewarray" , "bii" , NULL , T_OBJECT , 0, true );
|
||||
|
@ -323,7 +323,7 @@ address AbstractInterpreter::deopt_continue_after_entry(methodOop method, addres
|
||||
// (NOT needed for the old calling convension)
|
||||
if (!is_top_frame) {
|
||||
int index = Bytes::get_native_u4(bcp+1);
|
||||
method->constants()->cache()->entry_at(index)->set_parameter_size(callee_parameters);
|
||||
method->constants()->cache()->secondary_entry_at(index)->set_parameter_size(callee_parameters);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
|
||||
assert(h_exception.not_null(), "NULL exceptions should be handled by athrow");
|
||||
assert(h_exception->is_oop(), "just checking");
|
||||
// Check that exception is a subclass of Throwable, otherwise we have a VerifyError
|
||||
if (!(h_exception->is_a(SystemDictionary::throwable_klass()))) {
|
||||
if (!(h_exception->is_a(SystemDictionary::Throwable_klass()))) {
|
||||
if (ExitVMOnVerifyError) vm_exit(-1);
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
@ -585,7 +585,7 @@ IRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThre
|
||||
Handle exception(thread, thread->vm_result());
|
||||
assert(exception() != NULL, "vm result should be set");
|
||||
thread->set_vm_result(NULL); // clear vm result before continuing (may cause memory leaks and assert failures)
|
||||
if (!exception->is_a(SystemDictionary::threaddeath_klass())) {
|
||||
if (!exception->is_a(SystemDictionary::ThreadDeath_klass())) {
|
||||
exception = get_preinitialized_exception(
|
||||
SystemDictionary::IllegalMonitorStateException_klass(),
|
||||
CATCH);
|
||||
@ -660,7 +660,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes
|
||||
tty->print_cr("Resolving: klass: %s to method: %s", info.resolved_klass()->name()->as_C_string(), info.resolved_method()->name()->as_C_string());
|
||||
}
|
||||
if (info.resolved_method()->method_holder() ==
|
||||
SystemDictionary::object_klass()) {
|
||||
SystemDictionary::Object_klass()) {
|
||||
// NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec
|
||||
// (see also cpCacheOop.cpp for details)
|
||||
methodHandle rm = info.resolved_method();
|
||||
@ -1250,7 +1250,7 @@ IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* threa
|
||||
methodHandle mh(thread, fr.interpreter_frame_method());
|
||||
Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci);
|
||||
ArgumentSizeComputer asc(invoke->signature());
|
||||
int size_of_arguments = (asc.size() + (invoke->is_invokestatic() ? 0 : 1)); // receiver
|
||||
int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver
|
||||
Copy::conjoint_bytes(src_address, dest_address,
|
||||
size_of_arguments * Interpreter::stackElementSize());
|
||||
IRT_END
|
||||
|
@ -55,7 +55,7 @@ void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_kl
|
||||
// we should pick the vtable index from the resolved method.
|
||||
// Other than that case, there is no valid vtable index to specify.
|
||||
int vtable_index = methodOopDesc::invalid_vtable_index;
|
||||
if (resolved_method->method_holder() == SystemDictionary::object_klass()) {
|
||||
if (resolved_method->method_holder() == SystemDictionary::Object_klass()) {
|
||||
assert(resolved_method->vtable_index() == selected_method->vtable_index(), "sanity check");
|
||||
vtable_index = resolved_method->vtable_index();
|
||||
}
|
||||
@ -75,6 +75,8 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass
|
||||
_selected_method = selected_method;
|
||||
_vtable_index = vtable_index;
|
||||
if (CompilationPolicy::mustBeCompiled(selected_method)) {
|
||||
// This path is unusual, mostly used by the '-Xcomp' stress test mode.
|
||||
|
||||
// Note: with several active threads, the mustBeCompiled may be true
|
||||
// while canBeCompiled is false; remove assert
|
||||
// assert(CompilationPolicy::canBeCompiled(selected_method), "cannot compile");
|
||||
@ -82,6 +84,16 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass
|
||||
// don't force compilation, resolve was on behalf of compiler
|
||||
return;
|
||||
}
|
||||
if (instanceKlass::cast(selected_method->method_holder())->is_not_initialized()) {
|
||||
// 'is_not_initialized' means not only '!is_initialized', but also that
|
||||
// initialization has not been started yet ('!being_initialized')
|
||||
// Do not force compilation of methods in uninitialized classes.
|
||||
// Note that doing this would throw an assert later,
|
||||
// in CompileBroker::compile_method.
|
||||
// We sometimes use the link resolver to do reflective lookups
|
||||
// even before classes are initialized.
|
||||
return;
|
||||
}
|
||||
CompileBroker::compile_method(selected_method, InvocationEntryBci,
|
||||
methodHandle(), 0, "mustBeCompiled", CHECK);
|
||||
}
|
||||
@ -181,7 +193,7 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass,
|
||||
// We'll check for the method name first, as that's most likely
|
||||
// to be false (so we'll short-circuit out of these tests).
|
||||
if (sel_method->name() == vmSymbols::clone_name() &&
|
||||
sel_klass() == SystemDictionary::object_klass() &&
|
||||
sel_klass() == SystemDictionary::Object_klass() &&
|
||||
resolved_klass->oop_is_array()) {
|
||||
// We need to change "protected" to "public".
|
||||
assert(flags.is_protected(), "clone not protected?");
|
||||
@ -223,6 +235,18 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle& re
|
||||
resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
|
||||
}
|
||||
|
||||
void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) {
|
||||
// The class is java.dyn.MethodHandle
|
||||
resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
|
||||
|
||||
symbolHandle method_name = vmSymbolHandles::invoke_name();
|
||||
|
||||
symbolHandle method_signature(THREAD, pool->signature_ref_at(index));
|
||||
KlassHandle current_klass (THREAD, pool->pool_holder());
|
||||
|
||||
resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
|
||||
}
|
||||
|
||||
void LinkResolver::resolve_interface_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) {
|
||||
|
||||
// resolve klass
|
||||
|
@ -133,6 +133,7 @@ class LinkResolver: AllStatic {
|
||||
|
||||
// static resolving for all calls except interface calls
|
||||
static void resolve_method (methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_dynamic_method (methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_interface_method(methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS);
|
||||
|
||||
// runtime/static resolving for fields
|
||||
|
@ -247,15 +247,22 @@ methodHandle Rewriter::rewrite_jsrs(methodHandle method, TRAPS) {
|
||||
|
||||
void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) {
|
||||
ResourceMark rm(THREAD);
|
||||
Rewriter rw(klass, CHECK);
|
||||
Rewriter rw(klass, klass->constants(), klass->methods(), CHECK);
|
||||
// (That's all, folks.)
|
||||
}
|
||||
|
||||
Rewriter::Rewriter(instanceKlassHandle klass, TRAPS)
|
||||
|
||||
void Rewriter::rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS) {
|
||||
ResourceMark rm(THREAD);
|
||||
Rewriter rw(klass, cpool, methods, CHECK);
|
||||
// (That's all, folks.)
|
||||
}
|
||||
|
||||
|
||||
Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS)
|
||||
: _klass(klass),
|
||||
// gather starting points
|
||||
_pool( THREAD, klass->constants()),
|
||||
_methods(THREAD, klass->methods())
|
||||
_pool(cpool),
|
||||
_methods(methods)
|
||||
{
|
||||
assert(_pool->cache() == NULL, "constant pool cache must not be set yet");
|
||||
|
||||
|
@ -57,7 +57,7 @@ class Rewriter: public StackObj {
|
||||
}
|
||||
|
||||
// All the work goes in here:
|
||||
Rewriter(instanceKlassHandle klass, TRAPS);
|
||||
Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS);
|
||||
|
||||
void compute_index_maps();
|
||||
void make_constant_pool_cache(TRAPS);
|
||||
@ -70,6 +70,7 @@ class Rewriter: public StackObj {
|
||||
public:
|
||||
// Driver routine:
|
||||
static void rewrite(instanceKlassHandle klass, TRAPS);
|
||||
static void rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS);
|
||||
|
||||
enum {
|
||||
_secondary_entry_tag = nth_bit(30)
|
||||
|
@ -49,7 +49,7 @@ object_type ClassifyObjectClosure::classify_object(oop obj, bool count) {
|
||||
|
||||
Klass* k = obj->blueprint();
|
||||
|
||||
if (k->as_klassOop() == SystemDictionary::object_klass()) {
|
||||
if (k->as_klassOop() == SystemDictionary::Object_klass()) {
|
||||
tty->print_cr("Found the class!");
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
void do_oop(oop* p) {
|
||||
if (p != NULL) {
|
||||
oop obj = *p;
|
||||
if (obj->klass() == SystemDictionary::string_klass()) {
|
||||
if (obj->klass() == SystemDictionary::String_klass()) {
|
||||
|
||||
int hash;
|
||||
typeArrayOop value = java_lang_String::value(obj);
|
||||
@ -625,11 +625,11 @@ public:
|
||||
|
||||
if (obj->is_klass() || obj->is_instance()) {
|
||||
if (obj->is_klass() ||
|
||||
obj->is_a(SystemDictionary::class_klass()) ||
|
||||
obj->is_a(SystemDictionary::throwable_klass())) {
|
||||
obj->is_a(SystemDictionary::Class_klass()) ||
|
||||
obj->is_a(SystemDictionary::Throwable_klass())) {
|
||||
// Do nothing
|
||||
}
|
||||
else if (obj->is_a(SystemDictionary::string_klass())) {
|
||||
else if (obj->is_a(SystemDictionary::String_klass())) {
|
||||
// immutable objects.
|
||||
} else {
|
||||
// someone added an object we hadn't accounted for.
|
||||
|
@ -71,7 +71,7 @@ void ReferenceProcessor::init_statics() {
|
||||
assert(_sentinelRef == NULL, "should be initialized precisely once");
|
||||
EXCEPTION_MARK;
|
||||
_sentinelRef = instanceKlass::cast(
|
||||
SystemDictionary::reference_klass())->
|
||||
SystemDictionary::Reference_klass())->
|
||||
allocate_permanent_instance(THREAD);
|
||||
|
||||
// Initialize the master soft ref clock.
|
||||
|
@ -876,7 +876,7 @@ void ContiguousSpace::allocate_temporary_filler(int factor) {
|
||||
instanceOop obj = (instanceOop) allocate(size);
|
||||
obj->set_mark(markOopDesc::prototype());
|
||||
obj->set_klass_gap(0);
|
||||
obj->set_klass(SystemDictionary::object_klass());
|
||||
obj->set_klass(SystemDictionary::Object_klass());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +291,7 @@ void Universe::genesis(TRAPS) {
|
||||
|
||||
SystemDictionary::initialize(CHECK);
|
||||
|
||||
klassOop ok = SystemDictionary::object_klass();
|
||||
klassOop ok = SystemDictionary::Object_klass();
|
||||
|
||||
_the_null_string = StringTable::intern("null", CHECK);
|
||||
_the_min_jint_string = StringTable::intern("-2147483648", CHECK);
|
||||
@ -299,9 +299,9 @@ void Universe::genesis(TRAPS) {
|
||||
if (UseSharedSpaces) {
|
||||
// Verify shared interfaces array.
|
||||
assert(_the_array_interfaces_array->obj_at(0) ==
|
||||
SystemDictionary::cloneable_klass(), "u3");
|
||||
SystemDictionary::Cloneable_klass(), "u3");
|
||||
assert(_the_array_interfaces_array->obj_at(1) ==
|
||||
SystemDictionary::serializable_klass(), "u3");
|
||||
SystemDictionary::Serializable_klass(), "u3");
|
||||
|
||||
// Verify element klass for system obj array klass
|
||||
assert(objArrayKlass::cast(_systemObjArrayKlassObj)->element_klass() == ok, "u1");
|
||||
@ -320,8 +320,8 @@ void Universe::genesis(TRAPS) {
|
||||
assert(Klass::cast(systemObjArrayKlassObj())->super() == ok, "u3");
|
||||
} else {
|
||||
// Set up shared interfaces array. (Do this before supers are set up.)
|
||||
_the_array_interfaces_array->obj_at_put(0, SystemDictionary::cloneable_klass());
|
||||
_the_array_interfaces_array->obj_at_put(1, SystemDictionary::serializable_klass());
|
||||
_the_array_interfaces_array->obj_at_put(0, SystemDictionary::Cloneable_klass());
|
||||
_the_array_interfaces_array->obj_at_put(1, SystemDictionary::Serializable_klass());
|
||||
|
||||
// Set element klass for system obj array klass
|
||||
objArrayKlass::cast(_systemObjArrayKlassObj)->set_element_klass(ok);
|
||||
@ -365,7 +365,7 @@ void Universe::genesis(TRAPS) {
|
||||
// Initialize _objectArrayKlass after core bootstraping to make
|
||||
// sure the super class is set up properly for _objectArrayKlass.
|
||||
_objectArrayKlassObj = instanceKlass::
|
||||
cast(SystemDictionary::object_klass())->array_klass(1, CHECK);
|
||||
cast(SystemDictionary::Object_klass())->array_klass(1, CHECK);
|
||||
// Add the class to the class hierarchy manually to make sure that
|
||||
// its vtable is initialized after core bootstrapping is completed.
|
||||
Klass::cast(_objectArrayKlassObj)->append_to_sibling_list();
|
||||
@ -426,11 +426,11 @@ void Universe::genesis(TRAPS) {
|
||||
while (i < size) {
|
||||
if (!UseConcMarkSweepGC) {
|
||||
// Allocate dummy in old generation
|
||||
oop dummy = instanceKlass::cast(SystemDictionary::object_klass())->allocate_instance(CHECK);
|
||||
oop dummy = instanceKlass::cast(SystemDictionary::Object_klass())->allocate_instance(CHECK);
|
||||
dummy_array->obj_at_put(i++, dummy);
|
||||
}
|
||||
// Allocate dummy in permanent generation
|
||||
oop dummy = instanceKlass::cast(SystemDictionary::object_klass())->allocate_permanent_instance(CHECK);
|
||||
oop dummy = instanceKlass::cast(SystemDictionary::Object_klass())->allocate_permanent_instance(CHECK);
|
||||
dummy_array->obj_at_put(i++, dummy);
|
||||
}
|
||||
{
|
||||
@ -540,7 +540,7 @@ void Universe::fixup_mirrors(TRAPS) {
|
||||
// but we cannot do that for classes created before java.lang.Class is loaded. Here we simply
|
||||
// walk over permanent objects created so far (mostly classes) and fixup their mirrors. Note
|
||||
// that the number of objects allocated at this point is very small.
|
||||
assert(SystemDictionary::class_klass_loaded(), "java.lang.Class should be loaded");
|
||||
assert(SystemDictionary::Class_klass_loaded(), "java.lang.Class should be loaded");
|
||||
FixupMirrorClosure blk;
|
||||
Universe::heap()->permanent_object_iterate(&blk);
|
||||
}
|
||||
@ -556,7 +556,7 @@ void Universe::run_finalizers_on_exit() {
|
||||
if (TraceReferenceGC) tty->print_cr("Callback to run finalizers on exit");
|
||||
{
|
||||
PRESERVE_EXCEPTION_MARK;
|
||||
KlassHandle finalizer_klass(THREAD, SystemDictionary::finalizer_klass());
|
||||
KlassHandle finalizer_klass(THREAD, SystemDictionary::Finalizer_klass());
|
||||
JavaValue result(T_VOID);
|
||||
JavaCalls::call_static(
|
||||
&result,
|
||||
@ -950,7 +950,7 @@ bool universe_post_init() {
|
||||
{ ResourceMark rm;
|
||||
Interpreter::initialize(); // needed for interpreter entry points
|
||||
if (!UseSharedSpaces) {
|
||||
KlassHandle ok_h(THREAD, SystemDictionary::object_klass());
|
||||
KlassHandle ok_h(THREAD, SystemDictionary::Object_klass());
|
||||
Universe::reinitialize_vtable_of(ok_h, CHECK_false);
|
||||
Universe::reinitialize_itables(CHECK_false);
|
||||
}
|
||||
@ -960,7 +960,7 @@ bool universe_post_init() {
|
||||
instanceKlassHandle k_h;
|
||||
if (!UseSharedSpaces) {
|
||||
// Setup preallocated empty java.lang.Class array
|
||||
Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_false);
|
||||
Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false);
|
||||
// Setup preallocated OutOfMemoryError errors
|
||||
k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_OutOfMemoryError(), true, CHECK_false);
|
||||
k_h = instanceKlassHandle(THREAD, k);
|
||||
@ -1027,8 +1027,8 @@ bool universe_post_init() {
|
||||
// Setup static method for registering finalizers
|
||||
// The finalizer klass must be linked before looking up the method, in
|
||||
// case it needs to get rewritten.
|
||||
instanceKlass::cast(SystemDictionary::finalizer_klass())->link_class(CHECK_false);
|
||||
methodOop m = instanceKlass::cast(SystemDictionary::finalizer_klass())->find_method(
|
||||
instanceKlass::cast(SystemDictionary::Finalizer_klass())->link_class(CHECK_false);
|
||||
methodOop m = instanceKlass::cast(SystemDictionary::Finalizer_klass())->find_method(
|
||||
vmSymbols::register_method_name(),
|
||||
vmSymbols::register_method_signature());
|
||||
if (m == NULL || !m->is_static()) {
|
||||
@ -1036,7 +1036,7 @@ bool universe_post_init() {
|
||||
"java.lang.ref.Finalizer.register", false);
|
||||
}
|
||||
Universe::_finalizer_register_cache->init(
|
||||
SystemDictionary::finalizer_klass(), m, CHECK_false);
|
||||
SystemDictionary::Finalizer_klass(), m, CHECK_false);
|
||||
|
||||
// Resolve on first use and initialize class.
|
||||
// Note: No race-condition here, since a resolve will always return the same result
|
||||
@ -1053,14 +1053,14 @@ bool universe_post_init() {
|
||||
Universe::_reflect_invoke_cache->init(k_h(), m, CHECK_false);
|
||||
|
||||
// Setup method for registering loaded classes in class loader vector
|
||||
instanceKlass::cast(SystemDictionary::classloader_klass())->link_class(CHECK_false);
|
||||
m = instanceKlass::cast(SystemDictionary::classloader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature());
|
||||
instanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false);
|
||||
m = instanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature());
|
||||
if (m == NULL || m->is_static()) {
|
||||
THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(),
|
||||
"java.lang.ClassLoader.addClass", false);
|
||||
}
|
||||
Universe::_loader_addClass_cache->init(
|
||||
SystemDictionary::classloader_klass(), m, CHECK_false);
|
||||
SystemDictionary::ClassLoader_klass(), m, CHECK_false);
|
||||
|
||||
// The folowing is initializing converter functions for serialization in
|
||||
// JVM.cpp. If we clean up the StrictMath code above we may want to find
|
||||
|
@ -43,7 +43,7 @@ klassOop arrayKlass::java_super() const {
|
||||
if (super() == NULL) return NULL; // bootstrap case
|
||||
// Array klasses have primary supertypes which are not reported to Java.
|
||||
// Example super chain: String[][] -> Object[][] -> Object[] -> Object
|
||||
return SystemDictionary::object_klass();
|
||||
return SystemDictionary::Object_klass();
|
||||
}
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ const Klass_vtbl& cplusplus_vtbl, int header_size, KlassHandle klass, TRAPS) {
|
||||
k = arrayKlassHandle(THREAD, base_klass());
|
||||
|
||||
assert(!k()->is_parsable(), "not expecting parsability yet.");
|
||||
k->set_super(Universe::is_bootstrapping() ? (klassOop)NULL : SystemDictionary::object_klass());
|
||||
k->set_super(Universe::is_bootstrapping() ? (klassOop)NULL : SystemDictionary::Object_klass());
|
||||
k->set_layout_helper(Klass::_lh_neutral_value);
|
||||
k->set_dimension(1);
|
||||
k->set_higher_dimension(NULL);
|
||||
@ -117,9 +117,9 @@ objArrayOop arrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS) {
|
||||
|
||||
bool arrayKlass::compute_is_subtype_of(klassOop k) {
|
||||
// An array is a subtype of Serializable, Clonable, and Object
|
||||
return k == SystemDictionary::object_klass()
|
||||
|| k == SystemDictionary::cloneable_klass()
|
||||
|| k == SystemDictionary::serializable_klass();
|
||||
return k == SystemDictionary::Object_klass()
|
||||
|| k == SystemDictionary::Cloneable_klass()
|
||||
|| k == SystemDictionary::Serializable_klass();
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,7 +67,7 @@ class arrayKlass: public Klass {
|
||||
// Compiler/Interpreter offset
|
||||
static ByteSize component_mirror_offset() { return byte_offset_of(arrayKlass, _component_mirror); }
|
||||
|
||||
virtual klassOop java_super() const;//{ return SystemDictionary::object_klass(); }
|
||||
virtual klassOop java_super() const;//{ return SystemDictionary::Object_klass(); }
|
||||
|
||||
// Allocation
|
||||
// Sizes points to the first dimension of the array, subsequent dimensions
|
||||
|
@ -258,6 +258,11 @@ public:
|
||||
LocalVariableTableElement* localvariable_table_start() const;
|
||||
|
||||
// byte codes
|
||||
void set_code(address code) {
|
||||
if (code_size() > 0) {
|
||||
memcpy(code_base(), code, code_size());
|
||||
}
|
||||
}
|
||||
address code_base() const { return (address) (this+1); }
|
||||
address code_end() const { return code_base() + code_size(); }
|
||||
bool contains(address bcp) const { return code_base() <= bcp
|
||||
|
@ -110,7 +110,7 @@ klassOop constantPoolOopDesc::klass_at_impl(constantPoolHandle this_oop, int whi
|
||||
}
|
||||
|
||||
if (!PENDING_EXCEPTION->
|
||||
is_a(SystemDictionary::linkageError_klass())) {
|
||||
is_a(SystemDictionary::LinkageError_klass())) {
|
||||
// Just throw the exception and don't prevent these classes from
|
||||
// being loaded due to virtual machine errors like StackOverflow
|
||||
// and OutOfMemoryError, etc, or if the thread was hit by stop()
|
||||
|
@ -191,6 +191,16 @@ class constantPoolOopDesc : public oopDesc {
|
||||
}
|
||||
}
|
||||
|
||||
void object_at_put(int which, oop str) {
|
||||
oop_store((volatile oop*) obj_at_addr(which), str);
|
||||
release_tag_at_put(which, JVM_CONSTANT_Object);
|
||||
if (UseConcMarkSweepGC) {
|
||||
// In case the earlier card-mark was consumed by a concurrent
|
||||
// marking thread before the tag was updated, redirty the card.
|
||||
oop_store_without_check((volatile oop*) obj_at_addr(which), str);
|
||||
}
|
||||
}
|
||||
|
||||
// For temporary use while constructing constant pool
|
||||
void string_index_at_put(int which, int string_index) {
|
||||
tag_at_put(which, JVM_CONSTANT_StringIndex);
|
||||
@ -228,7 +238,8 @@ class constantPoolOopDesc : public oopDesc {
|
||||
tag.is_unresolved_klass() ||
|
||||
tag.is_symbol() ||
|
||||
tag.is_unresolved_string() ||
|
||||
tag.is_string();
|
||||
tag.is_string() ||
|
||||
tag.is_object();
|
||||
}
|
||||
|
||||
// Fetching constants
|
||||
@ -291,6 +302,11 @@ class constantPoolOopDesc : public oopDesc {
|
||||
return string_at_impl(h_this, which, CHECK_NULL);
|
||||
}
|
||||
|
||||
oop object_at(int which) {
|
||||
assert(tag_at(which).is_object(), "Corrupted constant pool");
|
||||
return *obj_at_addr(which);
|
||||
}
|
||||
|
||||
// A "pseudo-string" is an non-string oop that has found is way into
|
||||
// a String entry.
|
||||
// Under AnonymousClasses this can happen if the user patches a live
|
||||
|
@ -1556,13 +1556,13 @@ void GenerateOopMap::interp1(BytecodeStream *itr) {
|
||||
case Bytecodes::_getfield: do_field(true, false, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_putfield: do_field(false, false, itr->get_index_big(), itr->bci()); break;
|
||||
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_invokedynamic: do_method(true, false, itr->get_index_int(), itr->bci()); break;
|
||||
case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_newarray:
|
||||
case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break;
|
||||
case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_newarray:
|
||||
case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break;
|
||||
case Bytecodes::_checkcast: do_checkcast(); break;
|
||||
case Bytecodes::_arraylength:
|
||||
case Bytecodes::_instanceof: pp(rCTS, vCTS); break;
|
||||
@ -1830,12 +1830,8 @@ void GenerateOopMap::do_jsr(int targ_bci) {
|
||||
|
||||
|
||||
void GenerateOopMap::do_ldc(int idx, int bci) {
|
||||
constantPoolOop cp = method()->constants();
|
||||
constantTag tag = cp->tag_at(idx);
|
||||
|
||||
CellTypeState cts = (tag.is_string() || tag.is_unresolved_string() ||
|
||||
tag.is_klass() || tag.is_unresolved_klass())
|
||||
? CellTypeState::make_line_ref(bci) : valCTS;
|
||||
constantPoolOop cp = method()->constants();
|
||||
CellTypeState cts = cp->is_pointer_entry(idx) ? CellTypeState::make_line_ref(bci) : valCTS;
|
||||
ppush1(cts);
|
||||
}
|
||||
|
||||
|
@ -383,7 +383,7 @@ void instanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
|
||||
this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
|
||||
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below
|
||||
}
|
||||
if (e->is_a(SystemDictionary::error_klass())) {
|
||||
if (e->is_a(SystemDictionary::Error_klass())) {
|
||||
THROW_OOP(e());
|
||||
} else {
|
||||
JavaCallArguments args(e);
|
||||
@ -568,7 +568,7 @@ void instanceKlass::check_valid_for_instantiation(bool throwError, TRAPS) {
|
||||
THROW_MSG(throwError ? vmSymbols::java_lang_InstantiationError()
|
||||
: vmSymbols::java_lang_InstantiationException(), external_name());
|
||||
}
|
||||
if (as_klassOop() == SystemDictionary::class_klass()) {
|
||||
if (as_klassOop() == SystemDictionary::Class_klass()) {
|
||||
ResourceMark rm(THREAD);
|
||||
THROW_MSG(throwError ? vmSymbols::java_lang_IllegalAccessError()
|
||||
: vmSymbols::java_lang_IllegalAccessException(), external_name());
|
||||
@ -2225,7 +2225,7 @@ void FieldPrinter::do_field(fieldDescriptor* fd) {
|
||||
void instanceKlass::oop_print_on(oop obj, outputStream* st) {
|
||||
Klass::oop_print_on(obj, st);
|
||||
|
||||
if (as_klassOop() == SystemDictionary::string_klass()) {
|
||||
if (as_klassOop() == SystemDictionary::String_klass()) {
|
||||
typeArrayOop value = java_lang_String::value(obj);
|
||||
juint offset = java_lang_String::offset(obj);
|
||||
juint length = java_lang_String::length(obj);
|
||||
@ -2245,7 +2245,7 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) {
|
||||
FieldPrinter print_nonstatic_field(st, obj);
|
||||
do_nonstatic_fields(&print_nonstatic_field);
|
||||
|
||||
if (as_klassOop() == SystemDictionary::class_klass()) {
|
||||
if (as_klassOop() == SystemDictionary::Class_klass()) {
|
||||
st->print(BULLET"signature: ");
|
||||
java_lang_Class::print_signature(obj, st);
|
||||
st->cr();
|
||||
@ -2272,7 +2272,7 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) {
|
||||
st->print("a ");
|
||||
name()->print_value_on(st);
|
||||
obj->print_address_on(st);
|
||||
if (as_klassOop() == SystemDictionary::string_klass()
|
||||
if (as_klassOop() == SystemDictionary::String_klass()
|
||||
&& java_lang_String::value(obj) != NULL) {
|
||||
ResourceMark rm;
|
||||
int len = java_lang_String::length(obj);
|
||||
@ -2281,7 +2281,7 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) {
|
||||
st->print(" = \"%s\"", str);
|
||||
if (len > plen)
|
||||
st->print("...[%d]", len);
|
||||
} else if (as_klassOop() == SystemDictionary::class_klass()) {
|
||||
} else if (as_klassOop() == SystemDictionary::Class_klass()) {
|
||||
klassOop k = java_lang_Class::as_klassOop(obj);
|
||||
st->print(" = ");
|
||||
if (k != NULL) {
|
||||
@ -2348,7 +2348,7 @@ void instanceKlass::verify_class_klass_nonstatic_oop_maps(klassOop k) {
|
||||
|
||||
// Check that we have the right class
|
||||
static bool first_time = true;
|
||||
guarantee(k == SystemDictionary::class_klass() && first_time, "Invalid verify of maps");
|
||||
guarantee(k == SystemDictionary::Class_klass() && first_time, "Invalid verify of maps");
|
||||
first_time = false;
|
||||
const int extra = java_lang_Class::number_of_fake_oop_fields;
|
||||
guarantee(ik->nonstatic_field_size() == extra, "just checking");
|
||||
|
@ -397,7 +397,7 @@ void instanceRefKlass::update_nonstatic_oop_maps(klassOop k) {
|
||||
|
||||
// Check that we have the right class
|
||||
debug_only(static bool first_time = true);
|
||||
assert(k == SystemDictionary::reference_klass() && first_time,
|
||||
assert(k == SystemDictionary::Reference_klass() && first_time,
|
||||
"Invalid update of maps");
|
||||
debug_only(first_time = false);
|
||||
assert(ik->nonstatic_oop_map_count() == 1, "just checking");
|
||||
|
@ -217,8 +217,8 @@ void Klass::initialize_supers(klassOop k, TRAPS) {
|
||||
set_super(NULL);
|
||||
oop_store_without_check((oop*) &_primary_supers[0], (oop) this->as_klassOop());
|
||||
assert(super_depth() == 0, "Object must already be initialized properly");
|
||||
} else if (k != super() || k == SystemDictionary::object_klass()) {
|
||||
assert(super() == NULL || super() == SystemDictionary::object_klass(),
|
||||
} else if (k != super() || k == SystemDictionary::Object_klass()) {
|
||||
assert(super() == NULL || super() == SystemDictionary::Object_klass(),
|
||||
"initialize this only once to a non-trivial value");
|
||||
set_super(k);
|
||||
Klass* sup = k->klass_part();
|
||||
@ -370,7 +370,7 @@ void Klass::append_to_sibling_list() {
|
||||
void Klass::remove_from_sibling_list() {
|
||||
// remove receiver from sibling list
|
||||
instanceKlass* super = superklass();
|
||||
assert(super != NULL || as_klassOop() == SystemDictionary::object_klass(), "should have super");
|
||||
assert(super != NULL || as_klassOop() == SystemDictionary::Object_klass(), "should have super");
|
||||
if (super == NULL) return; // special case: class Object
|
||||
if (super->subklass() == this) {
|
||||
// first subklass
|
||||
|
@ -456,12 +456,12 @@ objArrayHandle methodOopDesc::resolved_checked_exceptions_impl(methodOop this_oo
|
||||
return objArrayHandle(THREAD, Universe::the_empty_class_klass_array());
|
||||
} else {
|
||||
methodHandle h_this(THREAD, this_oop);
|
||||
objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::class_klass(), length, CHECK_(objArrayHandle()));
|
||||
objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::Class_klass(), length, CHECK_(objArrayHandle()));
|
||||
objArrayHandle mirrors (THREAD, m_oop);
|
||||
for (int i = 0; i < length; i++) {
|
||||
CheckedExceptionElement* table = h_this->checked_exceptions_start(); // recompute on each iteration, not gc safe
|
||||
klassOop k = h_this->constants()->klass_at(table[i].class_cp_index, CHECK_(objArrayHandle()));
|
||||
assert(Klass::cast(k)->is_subclass_of(SystemDictionary::throwable_klass()), "invalid exception class");
|
||||
assert(Klass::cast(k)->is_subclass_of(SystemDictionary::Throwable_klass()), "invalid exception class");
|
||||
mirrors->obj_at_put(i, Klass::cast(k)->java_mirror());
|
||||
}
|
||||
return mirrors;
|
||||
@ -1032,8 +1032,8 @@ bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) {
|
||||
// We are loading classes eagerly. If a ClassNotFoundException or
|
||||
// a LinkageError was generated, be sure to ignore it.
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
if (PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass()) ||
|
||||
PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) {
|
||||
if (PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass()) ||
|
||||
PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -365,6 +365,7 @@ class methodOopDesc : public oopDesc {
|
||||
#endif
|
||||
|
||||
// byte codes
|
||||
void set_code(address code) { return constMethod()->set_code(code); }
|
||||
address code_base() const { return constMethod()->code_base(); }
|
||||
bool contains(address bcp) const { return constMethod()->contains(bcp); }
|
||||
|
||||
|
@ -246,8 +246,8 @@ objArrayOop objArrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS)
|
||||
} else {
|
||||
objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL);
|
||||
objArrayHandle secondaries(THREAD, sec_oop);
|
||||
secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::cloneable_klass());
|
||||
secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::serializable_klass());
|
||||
secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::Cloneable_klass());
|
||||
secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::Serializable_klass());
|
||||
for (int i = 0; i < num_elem_supers; i++) {
|
||||
klassOop elem_super = (klassOop) elem_supers->obj_at(i);
|
||||
klassOop array_super = elem_super->klass_part()->array_klass_or_null();
|
||||
|
@ -99,7 +99,7 @@ klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHand
|
||||
}
|
||||
} else {
|
||||
// The element type is already Object. Object[] has direct super of Object.
|
||||
super_klass = KlassHandle(THREAD, SystemDictionary::object_klass());
|
||||
super_klass = KlassHandle(THREAD, SystemDictionary::Object_klass());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,11 @@
|
||||
# include "incls/_precompiled.incl"
|
||||
# include "incls/_symbolOop.cpp.incl"
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// symbolOopDesc::equals
|
||||
//
|
||||
// Compares the symbol with a string of the given length.
|
||||
bool symbolOopDesc::equals(const char* str, int len) const {
|
||||
int l = utf8_length();
|
||||
if (l != len) return false;
|
||||
@ -36,6 +41,48 @@ bool symbolOopDesc::equals(const char* str, int len) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// symbolOopDesc::starts_with
|
||||
//
|
||||
// Tests if the symbol starts with the specified prefix of the given
|
||||
// length.
|
||||
bool symbolOopDesc::starts_with(const char* prefix, int len) const {
|
||||
if (len > utf8_length()) return false;
|
||||
while (len-- > 0) {
|
||||
if (prefix[len] != (char) byte_at(len))
|
||||
return false;
|
||||
}
|
||||
assert(len == -1, "we should be at the beginning");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// symbolOopDesc::index_of
|
||||
//
|
||||
// Finds if the given string is a substring of this symbol's utf8 bytes.
|
||||
// Return -1 on failure. Otherwise return the first index where str occurs.
|
||||
int symbolOopDesc::index_of_at(int i, const char* str, int len) const {
|
||||
assert(i >= 0 && i <= utf8_length(), "oob");
|
||||
if (len <= 0) return 0;
|
||||
char first_char = str[0];
|
||||
address bytes = (address) ((symbolOopDesc*)this)->base();
|
||||
address limit = bytes + utf8_length() - len; // inclusive limit
|
||||
address scan = bytes + i;
|
||||
if (scan > limit)
|
||||
return -1;
|
||||
for (;;) {
|
||||
scan = (address) memchr(scan, first_char, (limit + 1 - scan));
|
||||
if (scan == NULL)
|
||||
return -1; // not found
|
||||
assert(scan >= bytes+i && scan <= limit, "scan oob");
|
||||
if (memcmp(scan, str, len) == 0)
|
||||
return (int)(scan - bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char* symbolOopDesc::as_C_string(char* buf, int size) const {
|
||||
if (size > 0) {
|
||||
int len = MIN2(size - 1, utf8_length());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -70,8 +70,21 @@ class symbolOopDesc : public oopDesc {
|
||||
|
||||
void set_utf8_length(int len) { _length = len; }
|
||||
|
||||
// Compares the symbol with a string
|
||||
// Compares the symbol with a string.
|
||||
bool equals(const char* str, int len) const;
|
||||
bool equals(const char* str) const { return equals(str, (int) strlen(str)); }
|
||||
|
||||
// Tests if the symbol starts with the given prefix.
|
||||
bool starts_with(const char* prefix, int len) const;
|
||||
bool starts_with(const char* prefix) const {
|
||||
return starts_with(prefix, (int) strlen(prefix));
|
||||
}
|
||||
|
||||
// Tests if the symbol starts with the given prefix.
|
||||
int index_of_at(int i, const char* str, int len) const;
|
||||
int index_of_at(int i, const char* str) const {
|
||||
return index_of_at(i, str, (int) strlen(str));
|
||||
}
|
||||
|
||||
// Three-way compare for sorting; returns -1/0/1 if receiver is </==/> than arg
|
||||
// note that the ordering is not alfabetical
|
||||
|
@ -180,6 +180,10 @@ const char* InlineTree::shouldNotInline(ciMethod *callee_method, ciMethod* calle
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Always inline MethodHandle methods.
|
||||
if (callee_method->is_method_handle_invoke())
|
||||
return NULL;
|
||||
|
||||
// First check all inlining restrictions which are required for correctness
|
||||
if (callee_method->is_abstract()) return "abstract method";
|
||||
// note: we allow ik->is_abstract()
|
||||
@ -322,14 +326,17 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call
|
||||
// stricter than callee_holder->is_initialized()
|
||||
ciBytecodeStream iter(caller_method);
|
||||
iter.force_bci(caller_bci);
|
||||
int index = iter.get_index_int();
|
||||
if( !caller_method->is_klass_loaded(index, true) ) {
|
||||
return false;
|
||||
}
|
||||
// Try to do constant pool resolution if running Xcomp
|
||||
Bytecodes::Code call_bc = iter.cur_bc();
|
||||
if( !caller_method->check_call(index, call_bc == Bytecodes::_invokestatic) ) {
|
||||
return false;
|
||||
// An invokedynamic instruction does not have a klass.
|
||||
if (call_bc != Bytecodes::_invokedynamic) {
|
||||
int index = iter.get_index_int();
|
||||
if (!caller_method->is_klass_loaded(index, true)) {
|
||||
return false;
|
||||
}
|
||||
// Try to do constant pool resolution if running Xcomp
|
||||
if( !caller_method->check_call(index, call_bc == Bytecodes::_invokestatic) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// We will attempt to see if a class/field/etc got properly loaded. If it
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -136,6 +136,8 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) {
|
||||
}
|
||||
// Mark the call node as virtual, sort of:
|
||||
call->set_optimized_virtual(true);
|
||||
if (method()->is_method_handle_invoke())
|
||||
call->set_method_handle_invoke(true);
|
||||
}
|
||||
kit.set_arguments_for_java_call(call);
|
||||
kit.set_edges_for_java_call(call, false, _separate_io_proj);
|
||||
@ -145,6 +147,71 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) {
|
||||
return kit.transfer_exceptions_into_jvms();
|
||||
}
|
||||
|
||||
//---------------------------DynamicCallGenerator-----------------------------
|
||||
// Internal class which handles all out-of-line invokedynamic calls.
|
||||
class DynamicCallGenerator : public CallGenerator {
|
||||
public:
|
||||
DynamicCallGenerator(ciMethod* method)
|
||||
: CallGenerator(method)
|
||||
{
|
||||
}
|
||||
virtual JVMState* generate(JVMState* jvms);
|
||||
};
|
||||
|
||||
JVMState* DynamicCallGenerator::generate(JVMState* jvms) {
|
||||
GraphKit kit(jvms);
|
||||
|
||||
if (kit.C->log() != NULL) {
|
||||
kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci());
|
||||
}
|
||||
|
||||
// Get the constant pool cache from the caller class.
|
||||
ciMethod* caller_method = jvms->method();
|
||||
ciBytecodeStream str(caller_method);
|
||||
str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
|
||||
assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!");
|
||||
ciCPCache* cpcache = str.get_cpcache();
|
||||
|
||||
// Get the offset of the CallSite from the constant pool cache
|
||||
// pointer.
|
||||
int index = str.get_method_index();
|
||||
size_t call_site_offset = cpcache->get_f1_offset(index);
|
||||
|
||||
// Load the CallSite object from the constant pool cache.
|
||||
const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
|
||||
Node* cpcache_adr = kit.makecon(cpcache_ptr);
|
||||
Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
|
||||
Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
|
||||
|
||||
// Load the target MethodHandle from the CallSite object.
|
||||
Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
|
||||
Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT);
|
||||
|
||||
address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub();
|
||||
|
||||
CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci());
|
||||
// invokedynamic is treated as an optimized invokevirtual.
|
||||
call->set_optimized_virtual(true);
|
||||
// Take extra care (in the presence of argument motion) not to trash the SP:
|
||||
call->set_method_handle_invoke(true);
|
||||
|
||||
// Pass the target MethodHandle as first argument and shift the
|
||||
// other arguments.
|
||||
call->init_req(0 + TypeFunc::Parms, target_mh);
|
||||
uint nargs = call->method()->arg_size();
|
||||
for (uint i = 1; i < nargs; i++) {
|
||||
Node* arg = kit.argument(i - 1);
|
||||
call->init_req(i + TypeFunc::Parms, arg);
|
||||
}
|
||||
|
||||
kit.set_edges_for_java_call(call);
|
||||
Node* ret = kit.set_results_for_java_call(call);
|
||||
kit.push_node(method()->return_type()->basic_type(), ret);
|
||||
return kit.transfer_exceptions_into_jvms();
|
||||
}
|
||||
|
||||
//--------------------------VirtualCallGenerator------------------------------
|
||||
// Internal class which handles all out-of-line calls checking receiver type.
|
||||
class VirtualCallGenerator : public CallGenerator {
|
||||
private:
|
||||
int _vtable_index;
|
||||
@ -159,8 +226,6 @@ public:
|
||||
virtual JVMState* generate(JVMState* jvms);
|
||||
};
|
||||
|
||||
//--------------------------VirtualCallGenerator------------------------------
|
||||
// Internal class which handles all out-of-line calls checking receiver type.
|
||||
JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
|
||||
GraphKit kit(jvms);
|
||||
Node* receiver = kit.argument(0);
|
||||
@ -253,8 +318,14 @@ CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj
|
||||
return new DirectCallGenerator(m, separate_io_proj);
|
||||
}
|
||||
|
||||
CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) {
|
||||
assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch");
|
||||
return new DynamicCallGenerator(m);
|
||||
}
|
||||
|
||||
CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
|
||||
assert(!m->is_static(), "for_virtual_call mismatch");
|
||||
assert(!m->is_method_handle_invoke(), "should be a direct call");
|
||||
return new VirtualCallGenerator(m, vtable_index);
|
||||
}
|
||||
|
||||
@ -576,6 +647,155 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
|
||||
}
|
||||
|
||||
|
||||
//------------------------PredictedDynamicCallGenerator-----------------------
|
||||
// Internal class which handles all out-of-line calls checking receiver type.
|
||||
class PredictedDynamicCallGenerator : public CallGenerator {
|
||||
ciMethodHandle* _predicted_method_handle;
|
||||
CallGenerator* _if_missed;
|
||||
CallGenerator* _if_hit;
|
||||
float _hit_prob;
|
||||
|
||||
public:
|
||||
PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle,
|
||||
CallGenerator* if_missed,
|
||||
CallGenerator* if_hit,
|
||||
float hit_prob)
|
||||
: CallGenerator(if_missed->method()),
|
||||
_predicted_method_handle(predicted_method_handle),
|
||||
_if_missed(if_missed),
|
||||
_if_hit(if_hit),
|
||||
_hit_prob(hit_prob)
|
||||
{}
|
||||
|
||||
virtual bool is_inline() const { return _if_hit->is_inline(); }
|
||||
virtual bool is_deferred() const { return _if_hit->is_deferred(); }
|
||||
|
||||
virtual JVMState* generate(JVMState* jvms);
|
||||
};
|
||||
|
||||
|
||||
CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
|
||||
CallGenerator* if_missed,
|
||||
CallGenerator* if_hit,
|
||||
float hit_prob) {
|
||||
return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob);
|
||||
}
|
||||
|
||||
|
||||
JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
|
||||
GraphKit kit(jvms);
|
||||
PhaseGVN& gvn = kit.gvn();
|
||||
|
||||
CompileLog* log = kit.C->log();
|
||||
if (log != NULL) {
|
||||
log->elem("predicted_dynamic_call bci='%d'", jvms->bci());
|
||||
}
|
||||
|
||||
// Get the constant pool cache from the caller class.
|
||||
ciMethod* caller_method = jvms->method();
|
||||
ciBytecodeStream str(caller_method);
|
||||
str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
|
||||
ciCPCache* cpcache = str.get_cpcache();
|
||||
|
||||
// Get the offset of the CallSite from the constant pool cache
|
||||
// pointer.
|
||||
int index = str.get_method_index();
|
||||
size_t call_site_offset = cpcache->get_f1_offset(index);
|
||||
|
||||
// Load the CallSite object from the constant pool cache.
|
||||
const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
|
||||
Node* cpcache_adr = kit.makecon(cpcache_ptr);
|
||||
Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
|
||||
Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
|
||||
|
||||
// Load the target MethodHandle from the CallSite object.
|
||||
Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
|
||||
Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT);
|
||||
|
||||
// Check if the MethodHandle is still the same.
|
||||
const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true);
|
||||
Node* predicted_mh = kit.makecon(predicted_mh_ptr);
|
||||
|
||||
Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh));
|
||||
Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
|
||||
IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN);
|
||||
kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff)));
|
||||
Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff));
|
||||
|
||||
SafePointNode* slow_map = NULL;
|
||||
JVMState* slow_jvms;
|
||||
{ PreserveJVMState pjvms(&kit);
|
||||
kit.set_control(slow_ctl);
|
||||
if (!kit.stopped()) {
|
||||
slow_jvms = _if_missed->generate(kit.sync_jvms());
|
||||
assert(slow_jvms != NULL, "miss path must not fail to generate");
|
||||
kit.add_exception_states_from(slow_jvms);
|
||||
kit.set_map(slow_jvms->map());
|
||||
if (!kit.stopped())
|
||||
slow_map = kit.stop();
|
||||
}
|
||||
}
|
||||
|
||||
if (kit.stopped()) {
|
||||
// Instance exactly does not matches the desired type.
|
||||
kit.set_jvms(slow_jvms);
|
||||
return kit.transfer_exceptions_into_jvms();
|
||||
}
|
||||
|
||||
// Make the hot call:
|
||||
JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
|
||||
if (new_jvms == NULL) {
|
||||
// Inline failed, so make a direct call.
|
||||
assert(_if_hit->is_inline(), "must have been a failed inline");
|
||||
CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
|
||||
new_jvms = cg->generate(kit.sync_jvms());
|
||||
}
|
||||
kit.add_exception_states_from(new_jvms);
|
||||
kit.set_jvms(new_jvms);
|
||||
|
||||
// Need to merge slow and fast?
|
||||
if (slow_map == NULL) {
|
||||
// The fast path is the only path remaining.
|
||||
return kit.transfer_exceptions_into_jvms();
|
||||
}
|
||||
|
||||
if (kit.stopped()) {
|
||||
// Inlined method threw an exception, so it's just the slow path after all.
|
||||
kit.set_jvms(slow_jvms);
|
||||
return kit.transfer_exceptions_into_jvms();
|
||||
}
|
||||
|
||||
// Finish the diamond.
|
||||
kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
|
||||
RegionNode* region = new (kit.C, 3) RegionNode(3);
|
||||
region->init_req(1, kit.control());
|
||||
region->init_req(2, slow_map->control());
|
||||
kit.set_control(gvn.transform(region));
|
||||
Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
|
||||
iophi->set_req(2, slow_map->i_o());
|
||||
kit.set_i_o(gvn.transform(iophi));
|
||||
kit.merge_memory(slow_map->merged_memory(), region, 2);
|
||||
uint tos = kit.jvms()->stkoff() + kit.sp();
|
||||
uint limit = slow_map->req();
|
||||
for (uint i = TypeFunc::Parms; i < limit; i++) {
|
||||
// Skip unused stack slots; fast forward to monoff();
|
||||
if (i == tos) {
|
||||
i = kit.jvms()->monoff();
|
||||
if( i >= limit ) break;
|
||||
}
|
||||
Node* m = kit.map()->in(i);
|
||||
Node* n = slow_map->in(i);
|
||||
if (m != n) {
|
||||
const Type* t = gvn.type(m)->meet(gvn.type(n));
|
||||
Node* phi = PhiNode::make(region, m, t);
|
||||
phi->set_req(2, n);
|
||||
kit.map()->set_req(i, gvn.transform(phi));
|
||||
}
|
||||
}
|
||||
return kit.transfer_exceptions_into_jvms();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------UncommonTrapCallGenerator-----------------------------
|
||||
// Internal class which handles all out-of-line calls checking receiver type.
|
||||
class UncommonTrapCallGenerator : public CallGenerator {
|
||||
|
@ -100,6 +100,7 @@ class CallGenerator : public ResourceObj {
|
||||
|
||||
// How to generate vanilla out-of-line call sites:
|
||||
static CallGenerator* for_direct_call(ciMethod* m, bool separate_io_projs = false); // static, special
|
||||
static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic
|
||||
static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface
|
||||
|
||||
// How to generate a replace a direct call with an inline version
|
||||
@ -116,6 +117,12 @@ class CallGenerator : public ResourceObj {
|
||||
CallGenerator* if_hit,
|
||||
float hit_prob);
|
||||
|
||||
// How to make a call that optimistically assumes a MethodHandle target:
|
||||
static CallGenerator* for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
|
||||
CallGenerator* if_missed,
|
||||
CallGenerator* if_hit,
|
||||
float hit_prob);
|
||||
|
||||
// How to make a call that gives up and goes back to the interpreter:
|
||||
static CallGenerator* for_uncommon_trap(ciMethod* m,
|
||||
Deoptimization::DeoptReason reason,
|
||||
|
@ -562,12 +562,15 @@ protected:
|
||||
virtual uint size_of() const; // Size is bigger
|
||||
|
||||
bool _optimized_virtual;
|
||||
bool _method_handle_invoke;
|
||||
ciMethod* _method; // Method being direct called
|
||||
public:
|
||||
const int _bci; // Byte Code Index of call byte code
|
||||
CallJavaNode(const TypeFunc* tf , address addr, ciMethod* method, int bci)
|
||||
: CallNode(tf, addr, TypePtr::BOTTOM),
|
||||
_method(method), _bci(bci), _optimized_virtual(false)
|
||||
_method(method), _bci(bci),
|
||||
_optimized_virtual(false),
|
||||
_method_handle_invoke(false)
|
||||
{
|
||||
init_class_id(Class_CallJava);
|
||||
}
|
||||
@ -577,6 +580,8 @@ public:
|
||||
void set_method(ciMethod *m) { _method = m; }
|
||||
void set_optimized_virtual(bool f) { _optimized_virtual = f; }
|
||||
bool is_optimized_virtual() const { return _optimized_virtual; }
|
||||
void set_method_handle_invoke(bool f) { _method_handle_invoke = f; }
|
||||
bool is_method_handle_invoke() const { return _method_handle_invoke; }
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const;
|
||||
|
@ -224,6 +224,57 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
|
||||
}
|
||||
}
|
||||
|
||||
// Do MethodHandle calls.
|
||||
if (call_method->is_method_handle_invoke()) {
|
||||
if (jvms->method()->java_code_at_bci(jvms->bci()) != Bytecodes::_invokedynamic) {
|
||||
GraphKit kit(jvms);
|
||||
Node* n = kit.argument(0);
|
||||
|
||||
if (n->Opcode() == Op_ConP) {
|
||||
const TypeOopPtr* oop_ptr = n->bottom_type()->is_oopptr();
|
||||
ciObject* const_oop = oop_ptr->const_oop();
|
||||
ciMethodHandle* method_handle = const_oop->as_method_handle();
|
||||
|
||||
// Set the actually called method to have access to the class
|
||||
// and signature in the MethodHandleCompiler.
|
||||
method_handle->set_callee(call_method);
|
||||
|
||||
// Get an adapter for the MethodHandle.
|
||||
ciMethod* target_method = method_handle->get_method_handle_adapter();
|
||||
|
||||
CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
|
||||
if (hit_cg != NULL && hit_cg->is_inline())
|
||||
return hit_cg;
|
||||
}
|
||||
|
||||
return CallGenerator::for_direct_call(call_method);
|
||||
}
|
||||
else {
|
||||
// Get the MethodHandle from the CallSite.
|
||||
ciMethod* caller_method = jvms->method();
|
||||
ciBytecodeStream str(caller_method);
|
||||
str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
|
||||
ciCallSite* call_site = str.get_call_site();
|
||||
ciMethodHandle* method_handle = call_site->get_target();
|
||||
|
||||
// Set the actually called method to have access to the class
|
||||
// and signature in the MethodHandleCompiler.
|
||||
method_handle->set_callee(call_method);
|
||||
|
||||
// Get an adapter for the MethodHandle.
|
||||
ciMethod* target_method = method_handle->get_invokedynamic_adapter();
|
||||
|
||||
CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
|
||||
if (hit_cg != NULL && hit_cg->is_inline()) {
|
||||
CallGenerator* miss_cg = CallGenerator::for_dynamic_call(call_method);
|
||||
return CallGenerator::for_predicted_dynamic_call(method_handle, miss_cg, hit_cg, prof_factor);
|
||||
}
|
||||
|
||||
// If something failed, generate a normal dynamic call.
|
||||
return CallGenerator::for_dynamic_call(call_method);
|
||||
}
|
||||
}
|
||||
|
||||
// There was no special inlining tactic, or it bailed out.
|
||||
// Use a more generic tactic, like a simple call.
|
||||
if (call_is_virtual) {
|
||||
@ -299,7 +350,7 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl
|
||||
// Interface classes can be loaded & linked and never get around to
|
||||
// being initialized. Uncommon-trap for not-initialized static or
|
||||
// v-calls. Let interface calls happen.
|
||||
ciInstanceKlass* holder_klass = dest_method->holder();
|
||||
ciInstanceKlass* holder_klass = dest_method->holder();
|
||||
if (!holder_klass->is_initialized() &&
|
||||
!holder_klass->is_interface()) {
|
||||
uncommon_trap(Deoptimization::Reason_uninitialized,
|
||||
@ -307,14 +358,6 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl
|
||||
holder_klass);
|
||||
return true;
|
||||
}
|
||||
if (dest_method->is_method_handle_invoke()
|
||||
&& holder_klass->name() == ciSymbol::java_dyn_Dynamic()) {
|
||||
// FIXME: NYI
|
||||
uncommon_trap(Deoptimization::Reason_unhandled,
|
||||
Deoptimization::Action_none,
|
||||
holder_klass);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility");
|
||||
return false;
|
||||
@ -333,6 +376,7 @@ void Parse::do_call() {
|
||||
bool is_virtual = bc() == Bytecodes::_invokevirtual;
|
||||
bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface;
|
||||
bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial;
|
||||
bool is_invokedynamic = bc() == Bytecodes::_invokedynamic;
|
||||
|
||||
// Find target being called
|
||||
bool will_link;
|
||||
@ -341,7 +385,8 @@ void Parse::do_call() {
|
||||
ciKlass* holder = iter().get_declared_method_holder();
|
||||
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
|
||||
|
||||
int nargs = dest_method->arg_size();
|
||||
int nargs = dest_method->arg_size();
|
||||
if (is_invokedynamic) nargs -= 1;
|
||||
|
||||
// uncommon-trap when callee is unloaded, uninitialized or will not link
|
||||
// bailout when too many arguments for register representation
|
||||
@ -355,7 +400,7 @@ void Parse::do_call() {
|
||||
return;
|
||||
}
|
||||
assert(holder_klass->is_loaded(), "");
|
||||
assert(dest_method->is_static() == !has_receiver, "must match bc");
|
||||
assert((dest_method->is_static() || is_invokedynamic) == !has_receiver , "must match bc");
|
||||
// Note: this takes into account invokeinterface of methods declared in java/lang/Object,
|
||||
// which should be invokevirtuals but according to the VM spec may be invokeinterfaces
|
||||
assert(holder_klass->is_interface() || holder_klass->super() == NULL || (bc() != Bytecodes::_invokeinterface), "must match bc");
|
||||
|
@ -1916,7 +1916,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
|
||||
Node *arg = call->in(i)->uncast();
|
||||
|
||||
if (at->isa_oopptr() != NULL &&
|
||||
ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) {
|
||||
ptnode_adr(arg->_idx)->escape_state() < PointsToNode::GlobalEscape) {
|
||||
|
||||
bool global_escapes = false;
|
||||
bool fields_escapes = false;
|
||||
|
@ -981,14 +981,19 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth) {
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokeinterface:
|
||||
{
|
||||
bool is_static = (depth == 0);
|
||||
bool ignore;
|
||||
ciBytecodeStream iter(method());
|
||||
iter.reset_to_bci(bci());
|
||||
iter.next();
|
||||
ciMethod* method = iter.get_method(ignore);
|
||||
inputs = method->arg_size_no_receiver();
|
||||
if (!is_static) inputs += 1;
|
||||
// Add a receiver argument, maybe:
|
||||
if (code != Bytecodes::_invokestatic &&
|
||||
code != Bytecodes::_invokedynamic)
|
||||
inputs += 1;
|
||||
// (Do not use ciMethod::arg_size(), because
|
||||
// it might be an unloaded method, which doesn't
|
||||
// know whether it is static or not.)
|
||||
int size = method->return_type()->size();
|
||||
depth = size - inputs;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user