This commit is contained in:
Igor Veresov 2010-01-06 22:21:39 -08:00
commit 5bec0d60ab
144 changed files with 4007 additions and 823 deletions

View File

@ -63,12 +63,12 @@ public class SystemDictionary {
javaSystemLoaderField = type.getOopField("_java_system_loader"); javaSystemLoaderField = type.getOopField("_java_system_loader");
nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue(); nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue();
objectKlassField = type.getOopField(WK_KLASS("object_klass")); objectKlassField = type.getOopField(WK_KLASS("Object_klass"));
classLoaderKlassField = type.getOopField(WK_KLASS("classloader_klass")); classLoaderKlassField = type.getOopField(WK_KLASS("ClassLoader_klass"));
stringKlassField = type.getOopField(WK_KLASS("string_klass")); stringKlassField = type.getOopField(WK_KLASS("String_klass"));
systemKlassField = type.getOopField(WK_KLASS("system_klass")); systemKlassField = type.getOopField(WK_KLASS("System_klass"));
threadKlassField = type.getOopField(WK_KLASS("thread_klass")); threadKlassField = type.getOopField(WK_KLASS("Thread_klass"));
threadGroupKlassField = type.getOopField(WK_KLASS("threadGroup_klass")); threadGroupKlassField = type.getOopField(WK_KLASS("ThreadGroup_klass"));
} }
// This WK functions must follow the definitions in systemDictionary.hpp: // This WK functions must follow the definitions in systemDictionary.hpp:

View File

@ -1885,6 +1885,10 @@ RegMask Matcher::modL_proj_mask() {
return RegMask(); return RegMask();
} }
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return RegMask();
}
%} %}

View File

@ -330,6 +330,14 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
// This is the sp before any possible extension (adapter/locals). // This is the sp before any possible extension (adapter/locals).
intptr_t* unextended_sp = interpreter_frame_sender_sp(); 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 // The interpreter and compiler(s) always save EBP/RBP in a known
// location on entry. We must record where that location is // location on entry. We must record where that location is
// so this if EBP/RBP was live on callout from c2 we can find // 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 // AMD64
} }
#endif /* COMPILER2 */ #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 *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()) { if (map->update_map()) {
// Tell GC to use argument oopmaps for some runtime stubs that need it. // 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 // 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"); 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 { frame frame::sender(RegisterMap* map) const {

View File

@ -225,11 +225,12 @@ inline methodOop* frame::interpreter_frame_method_addr() const {
// top of expression stack // top of expression stack
inline intptr_t* frame::interpreter_frame_tos_address() const { inline intptr_t* frame::interpreter_frame_tos_address() const {
intptr_t* last_sp = interpreter_frame_last_sp(); intptr_t* last_sp = interpreter_frame_last_sp();
if (last_sp == NULL ) { if (last_sp == NULL) {
return sp(); return sp();
} else { } else {
// sp() may have been extended by an adapter // sp() may have been extended or shrunk by an adapter. At least
assert(last_sp < fp() && last_sp >= sp(), "bad tos"); // check that we don't fall behind the legal region.
assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(), "bad tos");
return last_sp; return last_sp;
} }
} }

View File

@ -65,9 +65,9 @@ static void verify_argslot(MacroAssembler* _masm, Register rax_argslot,
// Verify that argslot lies within (rsp, rbp]. // Verify that argslot lies within (rsp, rbp].
Label L_ok, L_bad; Label L_ok, L_bad;
__ cmpptr(rax_argslot, rbp); __ cmpptr(rax_argslot, rbp);
__ jcc(Assembler::above, L_bad); __ jccb(Assembler::above, L_bad);
__ cmpptr(rsp, rax_argslot); __ cmpptr(rsp, rax_argslot);
__ jcc(Assembler::below, L_ok); __ jccb(Assembler::below, L_ok);
__ bind(L_bad); __ bind(L_bad);
__ stop(error_message); __ stop(error_message);
__ bind(L_ok); __ bind(L_ok);
@ -136,9 +136,9 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
if (arg_slots.is_register()) { if (arg_slots.is_register()) {
Label L_ok, L_bad; Label L_ok, L_bad;
__ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); __ 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); __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
__ jcc(Assembler::zero, L_ok); __ jccb(Assembler::zero, L_ok);
__ bind(L_bad); __ bind(L_bad);
__ stop("assert arg_slots <= 0 and clear low bits"); __ stop("assert arg_slots <= 0 and clear low bits");
__ bind(L_ok); __ 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); __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
__ addptr(rdx_temp, wordSize); __ addptr(rdx_temp, wordSize);
__ cmpptr(rdx_temp, rax_argslot); __ 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. // 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; Label L_ok, L_bad;
__ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
__ cmpptr(rbx_temp, rbp); __ cmpptr(rbx_temp, rbp);
__ jcc(Assembler::above, L_bad); __ jccb(Assembler::above, L_bad);
__ cmpptr(rsp, rax_argslot); __ cmpptr(rsp, rax_argslot);
__ jcc(Assembler::below, L_ok); __ jccb(Assembler::below, L_ok);
__ bind(L_bad); __ bind(L_bad);
__ stop("deleted argument(s) must fall within current frame"); __ stop("deleted argument(s) must fall within current frame");
__ bind(L_ok); __ bind(L_ok);
@ -221,9 +221,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
if (arg_slots.is_register()) { if (arg_slots.is_register()) {
Label L_ok, L_bad; Label L_ok, L_bad;
__ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); __ 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); __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
__ jcc(Assembler::zero, L_ok); __ jccb(Assembler::zero, L_ok);
__ bind(L_bad); __ bind(L_bad);
__ stop("assert arg_slots >= 0 and clear low bits"); __ stop("assert arg_slots >= 0 and clear low bits");
__ bind(L_ok); __ 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); __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
__ addptr(rdx_temp, -wordSize); __ addptr(rdx_temp, -wordSize);
__ cmpptr(rdx_temp, rsp); __ cmpptr(rdx_temp, rsp);
__ jcc(Assembler::greaterEqual, loop); __ jccb(Assembler::greaterEqual, loop);
} }
// Now move the argslot up, to point to the just-copied block. // 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 #ifndef PRODUCT
extern "C" void print_method_handle(oop mh);
void trace_method_handle_stub(const char* adaptername, void trace_method_handle_stub(const char* adaptername,
oopDesc* mh, oop mh,
intptr_t* entry_sp, intptr_t* entry_sp,
intptr_t* saved_sp, intptr_t* saved_sp,
intptr_t* saved_bp) { 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); 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) if (last_sp != saved_sp)
printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp); printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
if (Verbose) print_method_handle(mh);
} }
#endif //PRODUCT #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 // FIXME: fill in _raise_exception_method with a suitable sun.dyn method
__ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
__ testptr(rbx_method, rbx_method); __ testptr(rbx_method, rbx_method);
__ jcc(Assembler::zero, no_method); __ jccb(Assembler::zero, no_method);
int jobject_oop_offset = 0; int jobject_oop_offset = 0;
__ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject
__ testptr(rbx_method, rbx_method); __ testptr(rbx_method, rbx_method);
__ jcc(Assembler::zero, no_method); __ jccb(Assembler::zero, no_method);
__ verify_oop(rbx_method); __ verify_oop(rbx_method);
__ push(rdi_pc); // and restore caller PC __ push(rdi_pc); // and restore caller PC
__ jmp(rbx_method_fie); __ jmp(rbx_method_fie);
@ -533,16 +535,15 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
if (arg_type == T_OBJECT) { if (arg_type == T_OBJECT) {
__ movptr(Address(rax_argslot, 0), rbx_temp); __ movptr(Address(rax_argslot, 0), rbx_temp);
} else { } 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)); 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 #ifndef _LP64
if (arg_slots == 2) { if (arg_slots == 2) {
__ movl(rbx_temp, prim_value_addr.plus_disp(wordSize)); __ movl(rdx_temp, prim_value_addr.plus_disp(wordSize));
__ movl(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp); __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rdx_temp);
} }
#endif //_LP64 #endif //_LP64
break;
} }
if (direct_to_method) { if (direct_to_method) {
@ -584,7 +585,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
Label done; Label done;
__ movptr(rdx_temp, vmarg); __ movptr(rdx_temp, vmarg);
__ testl(rdx_temp, rdx_temp); __ 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); __ load_klass(rdx_temp, rdx_temp);
// live at this point: // 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) // (now we are done with the old MH)
// original 32-bit vmdata word must be of this form: // original 32-bit vmdata word must be of this form:
// | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | // | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
__ xchgl(rcx, rbx_vminfo); // free rcx for shifts __ xchgptr(rcx, rbx_vminfo); // free rcx for shifts
__ shll(rdx_temp /*, rcx*/); __ shll(rdx_temp /*, rcx*/);
Label zero_extend, done; Label zero_extend, done;
__ testl(rcx, CONV_VMINFO_SIGN_FLAG); __ 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 // this path is taken for int->byte, int->short
__ sarl(rdx_temp /*, rcx*/); __ sarl(rdx_temp /*, rcx*/);
__ jmp(done); __ jmpb(done);
__ bind(zero_extend); __ bind(zero_extend);
// this is taken for int->char // this is taken for int->char
__ shrl(rdx_temp /*, rcx*/); __ shrl(rdx_temp /*, rcx*/);
__ bind(done); __ bind(done);
__ movptr(vmarg, rdx_temp); __ movl(vmarg, rdx_temp);
__ xchgl(rcx, rbx_vminfo); // restore rcx_recv __ xchgptr(rcx, rbx_vminfo); // restore rcx_recv
__ jump_to_method_handle_entry(rcx_recv, rdx_temp); __ 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. // Verify that argslot > destslot, by at least swap_bytes.
Label L_ok; Label L_ok;
__ cmpptr(rax_argslot, rbx_destslot); __ cmpptr(rax_argslot, rbx_destslot);
__ jcc(Assembler::aboveEqual, L_ok); __ jccb(Assembler::aboveEqual, L_ok);
__ stop("source must be above destination (upward rotation)"); __ stop("source must be above destination (upward rotation)");
__ bind(L_ok); __ bind(L_ok);
} }
@ -877,7 +878,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ movptr(Address(rax_argslot, swap_bytes), rdx_temp); __ movptr(Address(rax_argslot, swap_bytes), rdx_temp);
__ addptr(rax_argslot, -wordSize); __ addptr(rax_argslot, -wordSize);
__ cmpptr(rax_argslot, rbx_destslot); __ cmpptr(rax_argslot, rbx_destslot);
__ jcc(Assembler::aboveEqual, loop); __ jccb(Assembler::aboveEqual, loop);
} else { } else {
__ addptr(rax_argslot, swap_bytes); __ addptr(rax_argslot, swap_bytes);
#ifdef ASSERT #ifdef ASSERT
@ -885,7 +886,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
// Verify that argslot < destslot, by at least swap_bytes. // Verify that argslot < destslot, by at least swap_bytes.
Label L_ok; Label L_ok;
__ cmpptr(rax_argslot, rbx_destslot); __ cmpptr(rax_argslot, rbx_destslot);
__ jcc(Assembler::belowEqual, L_ok); __ jccb(Assembler::belowEqual, L_ok);
__ stop("source must be below destination (downward rotation)"); __ stop("source must be below destination (downward rotation)");
__ bind(L_ok); __ bind(L_ok);
} }
@ -901,7 +902,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ movptr(Address(rax_argslot, -swap_bytes), rdx_temp); __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp);
__ addptr(rax_argslot, wordSize); __ addptr(rax_argslot, wordSize);
__ cmpptr(rax_argslot, rbx_destslot); __ cmpptr(rax_argslot, rbx_destslot);
__ jcc(Assembler::belowEqual, loop); __ jccb(Assembler::belowEqual, loop);
} }
// pop the original first chunk into the destination slot, now free // 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(rax_argslot, wordSize);
__ addptr(rdx_newarg, wordSize); __ addptr(rdx_newarg, wordSize);
__ cmpptr(rdx_newarg, rbx_oldarg); __ cmpptr(rdx_newarg, rbx_oldarg);
__ jcc(Assembler::less, loop); __ jccb(Assembler::less, loop);
__ pop(rdi); // restore temp __ pop(rdi); // restore temp
@ -1119,7 +1120,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
} }
__ addptr(rax_argslot, Interpreter::stackElementSize()); __ addptr(rax_argslot, Interpreter::stackElementSize());
__ cmpptr(rax_argslot, rdx_argslot_limit); __ cmpptr(rax_argslot, rdx_argslot_limit);
__ jcc(Assembler::less, loop); __ jccb(Assembler::less, loop);
} else if (length_constant == 0) { } else if (length_constant == 0) {
__ bind(skip_array_check); __ bind(skip_array_check);
// nothing to copy // nothing to copy

View File

@ -43,11 +43,11 @@ ExceptionBlob* OptoRuntime::_exception_blob;
// This code is entered with a jmp. // This code is entered with a jmp.
// //
// Arguments: // Arguments:
// rax,: exception oop // rax: exception oop
// rdx: exception pc // rdx: exception pc
// //
// Results: // Results:
// rax,: exception oop // rax: exception oop
// rdx: exception pc in caller or ??? // rdx: exception pc in caller or ???
// destination: exception handler of caller // destination: exception handler of caller
// //
@ -113,17 +113,17 @@ void OptoRuntime::generate_exception_blob() {
__ addptr(rsp, return_off * wordSize); // Epilog! __ addptr(rsp, return_off * wordSize); // Epilog!
__ pop(rdx); // Exception pc __ 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) // We have a handler in rax, (could be deopt blob)
// rdx - throwing pc, deopt blob will need it. // rdx - throwing pc, deopt blob will need it.
__ push(rax); __ push(rax);
// rcx contains handler address
__ get_thread(rcx); // TLS
// Get the exception // Get the exception
__ movptr(rax, Address(rcx, JavaThread::exception_oop_offset())); __ movptr(rax, Address(rcx, JavaThread::exception_oop_offset()));
// Get the exception pc in case we are deoptimized // Get the exception pc in case we are deoptimized
@ -137,7 +137,7 @@ void OptoRuntime::generate_exception_blob() {
__ pop(rcx); __ pop(rcx);
// rax,: exception oop // rax: exception oop
// rcx: exception handler // rcx: exception handler
// rdx: exception pc // rdx: exception pc
__ jmp (rcx); __ jmp (rcx);

View File

@ -638,6 +638,10 @@ static void gen_i2c_adapter(MacroAssembler *masm,
__ movptr(rax, Address(rsp, 0)); __ 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 // 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. // in registers, we will occasionally have no stack args.
int comp_words_on_stack = 0; 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 // as far as the placement of the call instruction
__ push(rax); __ 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. // 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. // Pre-load the register-jump target early, to schedule it better.
__ movptr(r11, Address(rbx, in_bytes(methodOopDesc::from_compiled_offset()))); __ 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(), assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(),
"scrambled load targets?"); "scrambled load targets?");
// Load in argument order going down. // Load in argument order going down.
// int ld_off = (total_args_passed + comp_words_on_stack -i)*wordSize; int ld_off = (total_args_passed - i)*Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes();
// 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();
// Point to interpreter value (vs. tag) // Point to interpreter value (vs. tag)
int next_off = ld_off - Interpreter::stackElementSize(); int next_off = ld_off - Interpreter::stackElementSize();
// //
@ -699,10 +703,14 @@ static void gen_i2c_adapter(MacroAssembler *masm,
if (r_1->is_stack()) { if (r_1->is_stack()) {
// Convert stack slot to an SP offset (+ wordSize to account for return address ) // 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; 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()) { if (!r_2->is_valid()) {
// sign extend??? // sign extend???
__ movl(rax, Address(r13, ld_off)); __ movl(r13, Address(saved_sp, ld_off));
__ movptr(Address(rsp, st_off), rax); __ movptr(Address(rsp, st_off), r13);
} else { } else {
// //
// We are using two optoregs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE // 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 // ld_off is MSW so get LSW
const int offset = (sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)? const int offset = (sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)?
next_off : ld_off; next_off : ld_off;
__ movq(rax, Address(r13, offset)); __ movq(r13, Address(saved_sp, offset));
// st_off is LSW (i.e. reg.first()) // 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 } else if (r_1->is_Register()) { // Register argument
Register r = r_1->as_Register(); Register r = r_1->as_Register();
@ -732,16 +740,16 @@ static void gen_i2c_adapter(MacroAssembler *masm,
next_off : ld_off; next_off : ld_off;
// this can be a misaligned move // this can be a misaligned move
__ movq(r, Address(r13, offset)); __ movq(r, Address(saved_sp, offset));
} else { } else {
// sign extend and use a full word? // sign extend and use a full word?
__ movl(r, Address(r13, ld_off)); __ movl(r, Address(saved_sp, ld_off));
} }
} else { } else {
if (!r_2->is_valid()) { 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 { } 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 // 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). // We have a handler in rax (could be deopt blob).
__ mov(r8, rax); __ mov(r8, rax);

View File

@ -1488,7 +1488,10 @@ int AbstractInterpreter::layout_activation(methodOop method,
if (interpreter_frame != NULL) { if (interpreter_frame != NULL) {
#ifdef ASSERT #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)"); assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
#endif #endif

View File

@ -449,8 +449,12 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
__ addptr(rax, stack_base); __ addptr(rax, stack_base);
__ subptr(rax, stack_size); __ 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 // 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 // check against the current stack bottom
__ cmpptr(rsp, rax); __ cmpptr(rsp, rax);
@ -1502,8 +1506,10 @@ int AbstractInterpreter::layout_activation(methodOop method,
tempcount* Interpreter::stackElementWords() + popframe_extra_args; tempcount* Interpreter::stackElementWords() + popframe_extra_args;
if (interpreter_frame != NULL) { if (interpreter_frame != NULL) {
#ifdef ASSERT #ifdef ASSERT
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), if (!EnableMethodHandles)
"Frame not properly walkable"); // @@@ 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)"); assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
#endif #endif

View File

@ -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 *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)); 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 // !!!!! 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 // from the start of the call to the point where the return address
// will point. // will point.
int MachCallStaticJavaNode::ret_addr_offset() { 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() { 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; static int sizeof_FFree_Float_Stack_All = -1;
int MachCallRuntimeNode::ret_addr_offset() { int MachCallRuntimeNode::ret_addr_offset() {
assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already"); 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. // 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 // 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. // ensure that it does not span a cache line so that it can be patched.
int CallStaticJavaDirectNode::compute_padding(int current_offset) const { int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
if (Compile::current()->in_24_bit_fp_mode()) current_offset += pre_call_FPU_size(); // skip fldcw, if any
current_offset += 6; // skip fldcw in pre_call_FPU, 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 current_offset += 1; // skip call opcode byte
return round_to(current_offset, alignment_required()) - current_offset; 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 // 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. // ensure that it does not span a cache line so that it can be patched.
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const { int CallDynamicJavaDirectNode::compute_padding(int current_offset) const {
if (Compile::current()->in_24_bit_fp_mode()) current_offset += pre_call_FPU_size(); // skip fldcw, if any
current_offset += 6; // skip fldcw in pre_call_FPU, if any
current_offset += 5; // skip MOV instruction current_offset += 5; // skip MOV instruction
current_offset += 1; // skip call opcode byte current_offset += 1; // skip call opcode byte
return round_to(current_offset, alignment_required()) - current_offset; return round_to(current_offset, alignment_required()) - current_offset;
@ -1460,6 +1481,10 @@ RegMask Matcher::modL_proj_mask() {
return RegMask(); return RegMask();
} }
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return EBP_REG_mask;
}
%} %}
//----------ENCODING BLOCK----------------------------------------------------- //----------ENCODING BLOCK-----------------------------------------------------
@ -1772,10 +1797,13 @@ encode %{
enc_class pre_call_FPU %{ enc_class pre_call_FPU %{
// If method sets FPU control word restore it here // If method sets FPU control word restore it here
debug_only(int off0 = cbuf.code_size());
if( Compile::current()->in_24_bit_fp_mode() ) { if( Compile::current()->in_24_bit_fp_mode() ) {
MacroAssembler masm(&cbuf); MacroAssembler masm(&cbuf);
masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); 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 %{ 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 enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL
// CALL to fixup routine. Fixup routine uses ScopeDesc info to determine // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
// who we intended to call. // 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. // compute_padding() functions will have to be adjusted.
instruct CallStaticJavaDirect(method meth) %{ instruct CallStaticJavaDirect(method meth) %{
match(CallStaticJava); match(CallStaticJava);
predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
effect(USE meth); effect(USE meth);
ins_cost(300); ins_cost(300);
@ -13420,6 +13464,30 @@ instruct CallStaticJavaDirect(method meth) %{
ins_alignment(4); 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 // Call Java Dynamic Instruction
// Note: If this code changes, the corresponding ret_addr_offset() and // Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted. // compute_padding() functions will have to be adjusted.

View File

@ -551,12 +551,19 @@ source %{
#define __ _masm. #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 // !!!!! 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 // from the start of the call to the point where the return address
// will point. // will point.
int MachCallStaticJavaNode::ret_addr_offset() 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() 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; 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 // 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. // ensure that it does not span a cache line so that it can be patched.
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
@ -2113,6 +2129,10 @@ RegMask Matcher::modL_proj_mask() {
return LONG_RDX_REG_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) { static Address build_address(int b, int i, int s, int d) {
Register index = as_Register(i); Register index = as_Register(i);
Address::ScaleFactor scale = (Address::ScaleFactor)s; Address::ScaleFactor scale = (Address::ScaleFactor)s;
@ -2608,6 +2628,21 @@ encode %{
RELOC_DISP32); 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) enc_class Java_Static_Call(method meth)
%{ %{
// JAVA STATIC CALL // JAVA STATIC CALL
@ -12526,9 +12561,9 @@ instruct safePoint_poll(rFlagsReg cr)
// Call Java Static Instruction // Call Java Static Instruction
// Note: If this code changes, the corresponding ret_addr_offset() and // Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted. // compute_padding() functions will have to be adjusted.
instruct CallStaticJavaDirect(method meth) instruct CallStaticJavaDirect(method meth) %{
%{
match(CallStaticJava); match(CallStaticJava);
predicate(!((CallStaticJavaNode*) n)->is_method_handle_invoke());
effect(USE meth); effect(USE meth);
ins_cost(300); ins_cost(300);
@ -12540,6 +12575,28 @@ instruct CallStaticJavaDirect(method meth)
ins_alignment(4); 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 // Call Java Dynamic Instruction
// Note: If this code changes, the corresponding ret_addr_offset() and // Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted. // compute_padding() functions will have to be adjusted.

View File

@ -245,7 +245,7 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
if (handlerAddr == NULL) { if (handlerAddr == NULL) {
CALL_VM_NOCHECK(InterpreterRuntime::prepare_native_call(thread, method)); CALL_VM_NOCHECK(InterpreterRuntime::prepare_native_call(thread, method));
if (HAS_PENDING_EXCEPTION) if (HAS_PENDING_EXCEPTION)
goto unwind_and_return; goto unlock_unwind_and_return;
handlerAddr = method->signature_handler(); handlerAddr = method->signature_handler();
assert(handlerAddr != NULL, "eh?"); assert(handlerAddr != NULL, "eh?");
@ -254,7 +254,7 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
CALL_VM_NOCHECK(handlerAddr = CALL_VM_NOCHECK(handlerAddr =
InterpreterRuntime::slow_signature_handler(thread, method, NULL,NULL)); InterpreterRuntime::slow_signature_handler(thread, method, NULL,NULL));
if (HAS_PENDING_EXCEPTION) if (HAS_PENDING_EXCEPTION)
goto unwind_and_return; goto unlock_unwind_and_return;
} }
handler = \ handler = \
InterpreterRuntime::SignatureHandler::from_handlerAddr(handlerAddr); InterpreterRuntime::SignatureHandler::from_handlerAddr(handlerAddr);
@ -365,10 +365,10 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
// Reset handle block // Reset handle block
thread->active_handles()->clear(); thread->active_handles()->clear();
// Unlock if necessary. It seems totally wrong that this unlock_unwind_and_return:
// is skipped in the event of an exception but apparently
// the template interpreter does this so we do too. // Unlock if necessary
if (monitor && !HAS_PENDING_EXCEPTION) { if (monitor) {
BasicLock *lock = monitor->lock(); BasicLock *lock = monitor->lock();
markOop header = lock->displaced_header(); markOop header = lock->displaced_header();
oop rcvr = monitor->obj(); oop rcvr = monitor->obj();

View File

@ -251,8 +251,9 @@ class IRScopeDebugInfo: public CompilationResourceObj {
DebugToken* expvals = recorder->create_scope_values(expressions()); DebugToken* expvals = recorder->create_scope_values(expressions());
DebugToken* monvals = recorder->create_monitor_values(monitors()); DebugToken* monvals = recorder->create_monitor_values(monitors());
// reexecute allowed only for the topmost frame // reexecute allowed only for the topmost frame
bool reexecute = topmost ? should_reexecute() : false; bool reexecute = topmost ? should_reexecute() : false;
recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, locvals, expvals, monvals); bool is_method_handle_invoke = false;
recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, locvals, expvals, monvals);
} }
}; };

View File

@ -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.not_null(), "NULL exceptions should be handled by throw_exception");
assert(exception->is_oop(), "just checking"); assert(exception->is_oop(), "just checking");
// Check that exception is a subclass of Throwable, otherwise we have a VerifyError // 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); if (ExitVMOnVerifyError) vm_exit(-1);
ShouldNotReachHere(); ShouldNotReachHere();
} }

View 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();
}

View 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();
};

View 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();
}

View 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();
};

View File

@ -25,6 +25,7 @@
class ciEnv; class ciEnv;
class ciObjectFactory; class ciObjectFactory;
class ciConstantPoolCache; class ciConstantPoolCache;
class ciCPCache;
class ciField; class ciField;
class ciConstant; class ciConstant;
@ -42,6 +43,8 @@ class ciTypeFlow;
class ciObject; class ciObject;
class ciNullObject; class ciNullObject;
class ciInstance; class ciInstance;
class ciCallSite;
class ciMethodHandle;
class ciMethod; class ciMethod;
class ciMethodData; class ciMethodData;
class ciReceiverTypeData; // part of ciMethodData class ciReceiverTypeData; // part of ciMethodData
@ -78,6 +81,7 @@ friend class ciObjectFactory;
// Any more access must be given explicitly. // Any more access must be given explicitly.
#define CI_PACKAGE_ACCESS_TO \ #define CI_PACKAGE_ACCESS_TO \
friend class ciObjectFactory; \ friend class ciObjectFactory; \
friend class ciCallSite; \
friend class ciConstantPoolCache; \ friend class ciConstantPoolCache; \
friend class ciField; \ friend class ciField; \
friend class ciConstant; \ friend class ciConstant; \
@ -93,6 +97,7 @@ friend class ciNullObject; \
friend class ciInstance; \ friend class ciInstance; \
friend class ciMethod; \ friend class ciMethod; \
friend class ciMethodData; \ friend class ciMethodData; \
friend class ciMethodHandle; \
friend class ciReceiverTypeData; \ friend class ciReceiverTypeData; \
friend class ciSymbol; \ friend class ciSymbol; \
friend class ciArray; \ friend class ciArray; \

View File

@ -38,17 +38,9 @@ ciInstanceKlassKlass* ciEnv::_instance_klass_klass_instance;
ciTypeArrayKlassKlass* ciEnv::_type_array_klass_klass_instance; ciTypeArrayKlassKlass* ciEnv::_type_array_klass_klass_instance;
ciObjArrayKlassKlass* ciEnv::_obj_array_klass_klass_instance; ciObjArrayKlassKlass* ciEnv::_obj_array_klass_klass_instance;
ciInstanceKlass* ciEnv::_ArrayStoreException; #define WK_KLASS_DEFN(name, ignore_s, ignore_o) ciInstanceKlass* ciEnv::_##name = NULL;
ciInstanceKlass* ciEnv::_Class; WK_KLASSES_DO(WK_KLASS_DEFN)
ciInstanceKlass* ciEnv::_ClassCastException; #undef WK_KLASS_DEFN
ciInstanceKlass* ciEnv::_Object;
ciInstanceKlass* ciEnv::_Throwable;
ciInstanceKlass* ciEnv::_Thread;
ciInstanceKlass* ciEnv::_OutOfMemoryError;
ciInstanceKlass* ciEnv::_String;
ciInstanceKlass* ciEnv::_StringBuffer;
ciInstanceKlass* ciEnv::_StringBuilder;
ciInstanceKlass* ciEnv::_Integer;
ciSymbol* ciEnv::_unloaded_cisymbol = NULL; ciSymbol* ciEnv::_unloaded_cisymbol = NULL;
ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = 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 // ciEnv::get_klass_by_index_impl
// //
// Implementation of get_klass_by_index. // 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, int index,
bool& is_accessible) { bool& is_accessible,
assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool"); ciInstanceKlass* accessor) {
EXCEPTION_CONTEXT; EXCEPTION_CONTEXT;
constantPoolHandle cpool(THREAD, accessor->get_instanceKlass()->constants());
KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index));
symbolHandle klass_name; symbolHandle klass_name;
if (klass.is_null()) { if (klass.is_null()) {
@ -509,22 +500,21 @@ ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor,
// ciEnv::get_klass_by_index // ciEnv::get_klass_by_index
// //
// Get a klass from the constant pool. // 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, int index,
bool& is_accessible) { bool& is_accessible,
GUARDED_VM_ENTRY(return get_klass_by_index_impl(accessor, index, is_accessible);) ciInstanceKlass* accessor) {
GUARDED_VM_ENTRY(return get_klass_by_index_impl(cpool, index, is_accessible, accessor);)
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciEnv::get_constant_by_index_impl // ciEnv::get_constant_by_index_impl
// //
// Implementation of get_constant_by_index(). // Implementation of get_constant_by_index().
ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor, ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
int index) { int index,
ciInstanceKlass* accessor) {
EXCEPTION_CONTEXT; 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); constantTag tag = cpool->tag_at(index);
if (tag.is_int()) { if (tag.is_int()) {
return ciConstant(T_INT, (jint)cpool->int_at(index)); 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()) { } else if (tag.is_klass() || tag.is_unresolved_klass()) {
// 4881222: allow ldc to take a class type // 4881222: allow ldc to take a class type
bool ignore; 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) { if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION;
record_out_of_memory_failure(); 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(), assert (klass->is_instance_klass() || klass->is_array_klass(),
"must be an instance or array klass "); "must be an instance or array klass ");
return ciConstant(T_OBJECT, 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 { } else {
ShouldNotReachHere(); ShouldNotReachHere();
return ciConstant(); 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. // Pull a constant out of the constant pool. How appropriate.
// //
// Implementation note: this query is currently in no way cached. // Implementation note: this query is currently in no way cached.
ciConstant ciEnv::get_constant_by_index(ciInstanceKlass* accessor, ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
int index) { int index,
GUARDED_VM_ENTRY(return get_constant_by_index_impl(accessor, 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. // Implementation note: this query is currently in no way cached.
bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor, 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); ) 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. // Implementation note: this query is currently in no way cached.
bool ciEnv::is_unresolved_klass(ciInstanceKlass* accessor, 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); ) 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 // ciEnv::get_method_by_index_impl
ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor, ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
int index, Bytecodes::Code bc) { int index, Bytecodes::Code bc,
// Get the method's declared holder. ciInstanceKlass* accessor) {
assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
constantPoolHandle cpool = accessor->get_instanceKlass()->constants();
int holder_index = cpool->klass_ref_index_at(index); int holder_index = cpool->klass_ref_index_at(index);
bool holder_is_accessible; 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); ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
// Get the method's name and signature. // 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 // ciEnv::get_instance_klass_for_declared_method_holder
ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* 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 // ciEnv::get_method_by_index
ciMethod* ciEnv::get_method_by_index(ciInstanceKlass* accessor, ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool,
int index, Bytecodes::Code bc) { int index, Bytecodes::Code bc,
GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, 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 // ciEnv::name_buffer
char *ciEnv::name_buffer(int req_len) { char *ciEnv::name_buffer(int req_len) {

View File

@ -74,17 +74,9 @@ private:
static ciTypeArrayKlassKlass* _type_array_klass_klass_instance; static ciTypeArrayKlassKlass* _type_array_klass_klass_instance;
static ciObjArrayKlassKlass* _obj_array_klass_klass_instance; static ciObjArrayKlassKlass* _obj_array_klass_klass_instance;
static ciInstanceKlass* _ArrayStoreException; #define WK_KLASS_DECL(name, ignore_s, ignore_o) static ciInstanceKlass* _##name;
static ciInstanceKlass* _Class; WK_KLASSES_DO(WK_KLASS_DECL)
static ciInstanceKlass* _ClassCastException; #undef WK_KLASS_DECL
static ciInstanceKlass* _Object;
static ciInstanceKlass* _Throwable;
static ciInstanceKlass* _Thread;
static ciInstanceKlass* _OutOfMemoryError;
static ciInstanceKlass* _String;
static ciInstanceKlass* _StringBuffer;
static ciInstanceKlass* _StringBuilder;
static ciInstanceKlass* _Integer;
static ciSymbol* _unloaded_cisymbol; static ciSymbol* _unloaded_cisymbol;
static ciInstanceKlass* _unloaded_ciinstance_klass; static ciInstanceKlass* _unloaded_ciinstance_klass;
@ -120,37 +112,45 @@ private:
bool require_local); bool require_local);
// Constant pool access. // Constant pool access.
ciKlass* get_klass_by_index(ciInstanceKlass* loading_klass, ciKlass* get_klass_by_index(constantPoolHandle cpool,
int klass_index, int klass_index,
bool& is_accessible); bool& is_accessible,
ciConstant get_constant_by_index(ciInstanceKlass* loading_klass, ciInstanceKlass* loading_klass);
int constant_index); ciConstant get_constant_by_index(constantPoolHandle cpool,
int constant_index,
ciInstanceKlass* accessor);
bool is_unresolved_string(ciInstanceKlass* loading_klass, bool is_unresolved_string(ciInstanceKlass* loading_klass,
int constant_index) const; int constant_index) const;
bool is_unresolved_klass(ciInstanceKlass* loading_klass, bool is_unresolved_klass(ciInstanceKlass* loading_klass,
int constant_index) const; int constant_index) const;
ciField* get_field_by_index(ciInstanceKlass* loading_klass, ciField* get_field_by_index(ciInstanceKlass* loading_klass,
int field_index); int field_index);
ciMethod* get_method_by_index(ciInstanceKlass* loading_klass, ciMethod* get_method_by_index(constantPoolHandle cpool,
int method_index, Bytecodes::Code bc); int method_index, Bytecodes::Code bc,
ciInstanceKlass* loading_klass);
// Implementation methods for loading and constant pool access. // Implementation methods for loading and constant pool access.
ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass, ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass,
ciSymbol* klass_name, ciSymbol* klass_name,
bool require_local); bool require_local);
ciKlass* get_klass_by_index_impl(ciInstanceKlass* loading_klass, ciKlass* get_klass_by_index_impl(constantPoolHandle cpool,
int klass_index, int klass_index,
bool& is_accessible); bool& is_accessible,
ciConstant get_constant_by_index_impl(ciInstanceKlass* loading_klass, ciInstanceKlass* loading_klass);
int constant_index); ciConstant get_constant_by_index_impl(constantPoolHandle cpool,
int constant_index,
ciInstanceKlass* loading_klass);
bool is_unresolved_string_impl (instanceKlass* loading_klass, bool is_unresolved_string_impl (instanceKlass* loading_klass,
int constant_index) const; int constant_index) const;
bool is_unresolved_klass_impl (instanceKlass* loading_klass, bool is_unresolved_klass_impl (instanceKlass* loading_klass,
int constant_index) const; int constant_index) const;
ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass, ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass,
int field_index); int field_index);
ciMethod* get_method_by_index_impl(ciInstanceKlass* loading_klass, ciMethod* get_method_by_index_impl(constantPoolHandle cpool,
int method_index, Bytecodes::Code bc); int method_index, Bytecodes::Code bc,
ciInstanceKlass* loading_klass);
ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
int index, Bytecodes::Code bc);
// Helper methods // Helper methods
bool check_klass_accessibility(ciKlass* accessing_klass, bool check_klass_accessibility(ciKlass* accessing_klass,
@ -292,39 +292,13 @@ public:
// Access to certain well known ciObjects. // Access to certain well known ciObjects.
ciInstanceKlass* ArrayStoreException_klass() { #define WK_KLASS_FUNC(name, ignore_s, ignore_o) \
return _ArrayStoreException; ciInstanceKlass* name() { \
} return _##name;\
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;
} }
WK_KLASSES_DO(WK_KLASS_FUNC)
#undef WK_KLASS_FUNC
ciInstance* NullPointerException_instance() { ciInstance* NullPointerException_instance() {
assert(_NullPointerException_instance != NULL, "initialization problem"); assert(_NullPointerException_instance != NULL, "initialization problem");
return _NullPointerException_instance; return _NullPointerException_instance;

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -34,12 +34,16 @@
// //
// Get the exception klass that this handler catches. // Get the exception klass that this handler catches.
ciInstanceKlass* ciExceptionHandler::catch_klass() { ciInstanceKlass* ciExceptionHandler::catch_klass() {
VM_ENTRY_MARK;
assert(!is_catch_all(), "bad index"); assert(!is_catch_all(), "bad index");
if (_catch_klass == NULL) { if (_catch_klass == NULL) {
bool will_link; 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, _catch_klass_index,
will_link); will_link,
_loading_klass);
if (!will_link && k->is_loaded()) { if (!will_link && k->is_loaded()) {
GUARDED_VM_ENTRY( GUARDED_VM_ENTRY(
k = CURRENT_ENV->get_unloaded_klass(_loading_klass, k->name()); k = CURRENT_ENV->get_unloaded_klass(_loading_klass, k->name());

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -86,7 +86,7 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with(NULL) {
bool ignore; bool ignore;
// This is not really a class reference; the index always refers to the // 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. // 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 { } else {
_type = ciType::make(field_type); _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); int holder_index = cpool->klass_ref_index_at(index);
bool holder_is_accessible; bool holder_is_accessible;
ciInstanceKlass* declared_holder = ciInstanceKlass* declared_holder =
ciEnv::current(thread)->get_klass_by_index(klass, holder_index, ciEnv::current(thread)->get_klass_by_index(cpool, holder_index,
holder_is_accessible) holder_is_accessible,
->as_instance_klass(); klass)->as_instance_klass();
// The declared holder of this field may not have been loaded. // The declared holder of this field may not have been loaded.
// Bail out with partial field information. // 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(); _holder = CURRENT_ENV->get_object(fd->field_holder())->as_instance_klass();
// Check to see if the field is constant. // Check to see if the field is constant.
if (_holder->is_initialized() && if (_holder->is_initialized() && this->is_final()) {
this->is_final() && this->is_static()) { 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 // This field just may be constant. The only cases where it will
// not be constant are: // not be constant are:
// //
@ -182,8 +192,8 @@ void ciField::initialize_from(fieldDescriptor* fd) {
// java.lang.System.out, and java.lang.System.err. // java.lang.System.out, and java.lang.System.err.
klassOop k = _holder->get_klassOop(); klassOop k = _holder->get_klassOop();
assert( SystemDictionary::system_klass() != NULL, "Check once per vm"); assert( SystemDictionary::System_klass() != NULL, "Check once per vm");
if( k == SystemDictionary::system_klass() ) { if( k == SystemDictionary::System_klass() ) {
// Check offsets for case 2: System.in, System.out, or System.err // Check offsets for case 2: System.in, System.out, or System.err
if( _offset == java_lang_System::in_offset_in_bytes() || if( _offset == java_lang_System::in_offset_in_bytes() ||
_offset == java_lang_System::out_offset_in_bytes() || _offset == java_lang_System::out_offset_in_bytes() ||

View File

@ -138,10 +138,18 @@ public:
// Get the constant value of this field. // Get the constant value of this field.
ciConstant constant_value() { ciConstant constant_value() {
assert(is_constant(), "illegal call to constant_value()"); assert(is_static() && is_constant(), "illegal call to constant_value()");
return _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 // Check for link time errors. Accessing a field from a
// certain class via a certain bytecode may or may not be legal. // certain class via a certain bytecode may or may not be legal.
// This call checks to see if an exception may be raised by // This call checks to see if an exception may be raised by

View File

@ -36,7 +36,7 @@ ciType* ciInstance::java_mirror_type() {
VM_ENTRY_MARK; VM_ENTRY_MARK;
oop m = get_oop(); oop m = get_oop();
// Return NULL if it is not java.lang.Class. // 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 NULL;
} }
// Return either a primitive type or a klass. // Return either a primitive type or a klass.

View File

@ -75,7 +75,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
_java_mirror = NULL; _java_mirror = NULL;
if (is_shared()) { if (is_shared()) {
if (h_k() != SystemDictionary::object_klass()) { if (h_k() != SystemDictionary::Object_klass()) {
super(); super();
} }
java_mirror(); java_mirror();
@ -232,8 +232,48 @@ bool ciInstanceKlass::is_java_lang_Object() {
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciInstanceKlass::uses_default_loader // ciInstanceKlass::uses_default_loader
bool ciInstanceKlass::uses_default_loader() { bool ciInstanceKlass::uses_default_loader() {
VM_ENTRY_MARK; // Note: We do not need to resolve the handle or enter the VM
return loader() == NULL; // 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;
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------

View File

@ -29,10 +29,11 @@
// be loaded. // be loaded.
class ciInstanceKlass : public ciKlass { class ciInstanceKlass : public ciKlass {
CI_PACKAGE_ACCESS CI_PACKAGE_ACCESS
friend class ciBytecodeStream;
friend class ciEnv; friend class ciEnv;
friend class ciExceptionHandler;
friend class ciMethod; friend class ciMethod;
friend class ciField; friend class ciField;
friend class ciBytecodeStream;
private: private:
jobject _loader; jobject _loader;
@ -78,6 +79,8 @@ protected:
const char* type_string() { return "ciInstanceKlass"; } const char* type_string() { return "ciInstanceKlass"; }
bool is_in_package_impl(const char* packagename, int len);
void print_impl(outputStream* st); void print_impl(outputStream* st);
ciConstantPoolCache* field_cache(); ciConstantPoolCache* field_cache();
@ -196,6 +199,12 @@ public:
bool is_java_lang_Object(); 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? // What kind of ciObject is this?
bool is_instance_klass() { return true; } bool is_instance_klass() { return true; }
bool is_java_klass() { return true; } bool is_java_klass() { return true; }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -69,7 +69,7 @@ public:
ciKlass(KlassHandle k_h); ciKlass(KlassHandle k_h);
// What is the name of this klass? // What is the name of this klass?
ciSymbol* name() { return _name; } ciSymbol* name() const { return _name; }
// What is its layout helper value? // What is its layout helper value?
jint layout_helper() { return _layout_helper; } jint layout_helper() { return _layout_helper; }

View File

@ -687,7 +687,7 @@ int ciMethod::scale_count(int count, float prof_factor) {
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// invokedynamic support // invokedynamic support
// //
bool ciMethod::is_method_handle_invoke() { bool ciMethod::is_method_handle_invoke() const {
check_is_loaded(); check_is_loaded();
bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS); bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
#ifdef ASSERT #ifdef ASSERT

View File

@ -38,6 +38,8 @@ class ciMethod : public ciObject {
CI_PACKAGE_ACCESS CI_PACKAGE_ACCESS
friend class ciEnv; friend class ciEnv;
friend class ciExceptionHandlerStream; friend class ciExceptionHandlerStream;
friend class ciBytecodeStream;
friend class ciMethodHandle;
private: private:
// General method information. // General method information.
@ -213,7 +215,7 @@ class ciMethod : public ciObject {
bool check_call(int refinfo_index, bool is_static) const; bool check_call(int refinfo_index, bool is_static) const;
void build_method_data(); // make sure it exists in the VM also 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 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(); ciInstance* method_handle_type();
// What kind of ciObject is this? // What kind of ciObject is this?
@ -251,4 +253,10 @@ class ciMethod : public ciObject {
// Print the name of this method in various incarnations. // Print the name of this method in various incarnations.
void print_name(outputStream* st = tty); void print_name(outputStream* st = tty);
void print_short_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);
}
}; };

View 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();
}

View 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);
}
};

View File

@ -131,9 +131,12 @@ public:
// What kind of ciObject is this? // What kind of ciObject is this?
virtual bool is_null_object() const { return false; } 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_instance() { return false; }
virtual bool is_method() { return false; } virtual bool is_method() { return false; }
virtual bool is_method_data() { 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_array() { return false; }
virtual bool is_obj_array() { return false; } virtual bool is_obj_array() { return false; }
virtual bool is_type_array() { return false; } virtual bool is_type_array() { return false; }
@ -185,6 +188,14 @@ public:
assert(is_null_object(), "bad cast"); assert(is_null_object(), "bad cast");
return (ciNullObject*)this; 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() { ciInstance* as_instance() {
assert(is_instance(), "bad cast"); assert(is_instance(), "bad cast");
return (ciInstance*)this; return (ciInstance*)this;
@ -197,6 +208,10 @@ public:
assert(is_method_data(), "bad cast"); assert(is_method_data(), "bad cast");
return (ciMethodData*)this; return (ciMethodData*)this;
} }
ciMethodHandle* as_method_handle() {
assert(is_method_handle(), "bad cast");
return (ciMethodHandle*) this;
}
ciArray* as_array() { ciArray* as_array() {
assert(is_array(), "bad cast"); assert(is_array(), "bad cast");
return (ciArray*)this; return (ciArray*)this;

View File

@ -144,39 +144,13 @@ void ciObjectFactory::init_shared_objects() {
ciEnv::_obj_array_klass_klass_instance = ciEnv::_obj_array_klass_klass_instance =
get(Universe::objArrayKlassKlassObj()) get(Universe::objArrayKlassKlassObj())
->as_obj_array_klass_klass(); ->as_obj_array_klass_klass();
ciEnv::_ArrayStoreException =
get(SystemDictionary::ArrayStoreException_klass()) #define WK_KLASS_DEFN(name, ignore_s, opt) \
->as_instance_klass(); if (SystemDictionary::name() != NULL) \
ciEnv::_Class = ciEnv::_##name = get(SystemDictionary::name())->as_instance_klass();
get(SystemDictionary::class_klass())
->as_instance_klass(); WK_KLASSES_DO(WK_KLASS_DEFN)
ciEnv::_ClassCastException = #undef WK_KLASS_DEFN
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();
for (int len = -1; len != _ci_objects->length(); ) { for (int len = -1; len != _ci_objects->length(); ) {
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); return new (arena()) ciMethodData(h_md);
} else if (o->is_instance()) { } else if (o->is_instance()) {
instanceHandle h_i(THREAD, (instanceOop)o); 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()) { } else if (o->is_objArray()) {
objArrayHandle h_oa(THREAD, (objArrayOop)o); objArrayHandle h_oa(THREAD, (objArrayOop)o);
return new (arena()) ciObjArray(h_oa); return new (arena()) ciObjArray(h_oa);
} else if (o->is_typeArray()) { } else if (o->is_typeArray()) {
typeArrayHandle h_ta(THREAD, (typeArrayOop)o); typeArrayHandle h_ta(THREAD, (typeArrayOop)o);
return new (arena()) ciTypeArray(h_ta); 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. // 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) { if (key->is_perm() && _non_perm_count == 0) {
return emptyBucket; return emptyBucket;
} else if (key->is_instance()) { } else if (key->is_instance()) {
if (key->klass() == SystemDictionary::class_klass()) { if (key->klass() == SystemDictionary::Class_klass()) {
// class mirror instances are always perm // class mirror instances are always perm
return emptyBucket; return emptyBucket;
} }

View File

@ -186,8 +186,9 @@ int ciBytecodeStream::get_klass_index() const {
// If this bytecode is a new, newarray, multianewarray, instanceof, // If this bytecode is a new, newarray, multianewarray, instanceof,
// or checkcast, get the referenced klass. // or checkcast, get the referenced klass.
ciKlass* ciBytecodeStream::get_klass(bool& will_link) { ciKlass* ciBytecodeStream::get_klass(bool& will_link) {
return CURRENT_ENV->get_klass_by_index(_holder, get_klass_index(), VM_ENTRY_MARK;
will_link); 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 // If this bytecode is one of the ldc variants, get the referenced
// constant. // constant.
ciConstant ciBytecodeStream::get_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 // There is no "will_link" result passed back. The user is responsible
// for checking linkability when retrieving the associated field. // for checking linkability when retrieving the associated field.
ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() { ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() {
VM_ENTRY_MARK;
constantPoolHandle cpool(_method->get_methodOop()->constants());
int holder_index = get_field_holder_index(); int holder_index = get_field_holder_index();
bool ignore; 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(); ->as_instance_klass();
} }
@ -277,9 +282,10 @@ ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() {
// referenced by the current bytecode. Used for generating // referenced by the current bytecode. Used for generating
// deoptimization information. // deoptimization information.
int ciBytecodeStream::get_field_holder_index() { int ciBytecodeStream::get_field_holder_index() {
VM_ENTRY_MARK; GUARDED_VM_ENTRY(
constantPoolOop cpool = _holder->get_instanceKlass()->constants(); constantPoolOop cpool = _holder->get_instanceKlass()->constants();
return cpool->klass_ref_index_at(get_field_index()); 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. // If this is a method invocation bytecode, get the invoked method.
ciMethod* ciBytecodeStream::get_method(bool& will_link) { 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(); will_link = m->is_loaded();
return m; 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 // There is no "will_link" result passed back. The user is responsible
// for checking linkability when retrieving the associated method. // for checking linkability when retrieving the associated method.
ciKlass* ciBytecodeStream::get_declared_method_holder() { ciKlass* ciBytecodeStream::get_declared_method_holder() {
VM_ENTRY_MARK;
constantPoolHandle cpool(_method->get_methodOop()->constants());
bool ignore; 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) if (cur_bc() == Bytecodes::_invokedynamic)
return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_Dynamic(), false); return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false);
return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore); 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 // referenced by the current bytecode. Used for generating
// deoptimization information. // deoptimization information.
int ciBytecodeStream::get_method_holder_index() { int ciBytecodeStream::get_method_holder_index() {
VM_ENTRY_MARK; constantPoolOop cpool = _method->get_methodOop()->constants();
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
return cpool->klass_ref_index_at(get_method_index()); 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); int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
return cpool->signature_ref_index_at(name_and_type_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();
}

View File

@ -232,6 +232,9 @@ public:
int get_method_holder_index(); int get_method_holder_index();
int get_method_signature_index(); int get_method_signature_index();
ciCPCache* get_cpcache();
ciCallSite* get_call_site();
private: private:
void assert_index_size(int required_size) const { void assert_index_size(int required_size) const {
#ifdef ASSERT #ifdef ASSERT

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -59,6 +59,22 @@ int ciSymbol::byte_at(int i) {
GUARDED_VM_ENTRY(return get_symbolOop()->byte_at(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 // ciSymbol::utf8_length
int ciSymbol::utf8_length() { int ciSymbol::utf8_length() {

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@
// machine. // machine.
class ciSymbol : public ciObject { class ciSymbol : public ciObject {
CI_PACKAGE_ACCESS CI_PACKAGE_ACCESS
// These friends all make direct use of get_symbolOop:
friend class ciEnv; friend class ciEnv;
friend class ciInstanceKlass; friend class ciInstanceKlass;
friend class ciSignature; friend class ciSignature;
@ -38,13 +39,13 @@ private:
ciSymbol(symbolOop s) : ciObject(s) {} ciSymbol(symbolOop s) : ciObject(s) {}
ciSymbol(symbolHandle s); // for use with vmSymbolHandles 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"; } const char* type_string() { return "ciSymbol"; }
void print_impl(outputStream* st); 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(); jbyte* base();
// Make a ciSymbol from a C string (implementation). // Make a ciSymbol from a C string (implementation).
@ -55,6 +56,15 @@ public:
const char* as_utf8(); const char* as_utf8();
int utf8_length(); 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? // What kind of ciObject is this?
bool is_symbol() { return true; } bool is_symbol() { return true; }

View File

@ -111,7 +111,7 @@ ciType* ciType::make(BasicType t) {
// short, etc. // short, etc.
// Note: Bare T_ADDRESS means a raw pointer type, not a return_address. // Note: Bare T_ADDRESS means a raw pointer type, not a return_address.
assert((uint)t < T_CONFLICT+1, "range check"); 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"); assert(_basic_types[t] != NULL, "domain check");
return _basic_types[t]; return _basic_types[t];
} }

View File

@ -635,8 +635,15 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str,
ciMethod* method = str->get_method(will_link); ciMethod* method = str->get_method(will_link);
if (!will_link) { if (!will_link) {
// We weren't able to find the method. // We weren't able to find the method.
ciKlass* unloaded_holder = method->holder(); if (str->cur_bc() == Bytecodes::_invokedynamic) {
trap(str, unloaded_holder, str->get_method_holder_index()); 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 { } else {
ciSignature* signature = method->signature(); ciSignature* signature = method->signature();
ciSignatureStream sigstr(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::_invokeinterface: do_invoke(str, true); break;
case Bytecodes::_invokespecial: do_invoke(str, true); break; case Bytecodes::_invokespecial: do_invoke(str, true); break;
case Bytecodes::_invokestatic: do_invoke(str, false); break; case Bytecodes::_invokestatic: do_invoke(str, false); break;
case Bytecodes::_invokevirtual: do_invoke(str, true); 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: store_local_int(str->get_index()); break;
case Bytecodes::_istore_0: store_local_int(0); break; case Bytecodes::_istore_0: store_local_int(0); break;

View File

@ -79,7 +79,7 @@
THREAD); \ THREAD); \
if (HAS_PENDING_EXCEPTION) { \ if (HAS_PENDING_EXCEPTION) { \
if (PENDING_EXCEPTION->klass() == \ if (PENDING_EXCEPTION->klass() == \
SystemDictionary::threaddeath_klass()) { \ SystemDictionary::ThreadDeath_klass()) { \
/* Kill the compilation. */ \ /* Kill the compilation. */ \
fatal("unhandled ci exception"); \ fatal("unhandled ci exception"); \
return (result); \ return (result); \

View File

@ -430,7 +430,7 @@ void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Hand
case JVM_CONSTANT_UnresolvedClass : case JVM_CONSTANT_UnresolvedClass :
// Patching a class means pre-resolving it. // Patching a class means pre-resolving it.
// The name in the constant pool is ignored. // 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()), guarantee_property(!java_lang_Class::is_primitive(patch()),
"Illegal class patch at %d in class file %s", "Illegal class patch at %d in class file %s",
index, CHECK); 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); guarantee_property(value_type.is_int(), "Inconsistent constant value type in class file %s", CHECK);
break; break;
case T_OBJECT: 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())), && (value_type.is_string() || value_type.is_unresolved_string())),
"Bad string initial value in class file %s", CHECK); "Bad string initial value in class file %s", CHECK);
break; break;
@ -1718,9 +1718,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
m->set_exception_table(exception_handlers()); m->set_exception_table(exception_handlers());
// Copy byte codes // Copy byte codes
if (code_length > 0) { m->set_code(code_start);
memcpy(m->code_base(), code_start, code_length);
}
// Copy line number table // Copy line number table
if (linenumber_table != NULL) { if (linenumber_table != NULL) {
@ -3471,8 +3469,8 @@ void ClassFileParser::set_precomputed_flags(instanceKlassHandle k) {
#endif #endif
// Check if this klass supports the java.lang.Cloneable interface // Check if this klass supports the java.lang.Cloneable interface
if (SystemDictionary::cloneable_klass_loaded()) { if (SystemDictionary::Cloneable_klass_loaded()) {
if (k->is_subtype_of(SystemDictionary::cloneable_klass())) { if (k->is_subtype_of(SystemDictionary::Cloneable_klass())) {
k->set_is_cloneable(); 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 // Check if ch is Java identifier start or is Java identifier part
// 4672820: call java.lang.Character methods directly without generating separate tables. // 4672820: call java.lang.Character methods directly without generating separate tables.
EXCEPTION_MARK; EXCEPTION_MARK;
instanceKlassHandle klass (THREAD, SystemDictionary::char_klass()); instanceKlassHandle klass (THREAD, SystemDictionary::Character_klass());
// return value // return value
JavaValue result(T_BOOLEAN); JavaValue result(T_BOOLEAN);

View File

@ -819,7 +819,7 @@ objArrayOop ClassLoader::get_system_packages(TRAPS) {
_package_hash_table->copy_pkgnames(packages); _package_hash_table->copy_pkgnames(packages);
} }
// Allocate objArray and fill with java.lang.String // 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); nof_entries, CHECK_0);
objArrayHandle result(THREAD, r); objArrayHandle result(THREAD, r);
for (int i = 0; i < nof_entries; i++) { for (int i = 0; i < nof_entries; i++) {

View File

@ -95,14 +95,14 @@ oop JavaAssertions::createAssertionStatusDirectives(TRAPS) {
int len; int len;
typeArrayOop t; typeArrayOop t;
len = OptionList::count(_packages); 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); objArrayHandle pkgNames (THREAD, pn);
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL); t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
typeArrayHandle pkgEnabled(THREAD, t); typeArrayHandle pkgEnabled(THREAD, t);
fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL); fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL);
len = OptionList::count(_classes); 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); objArrayHandle classNames (THREAD, cn);
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL); t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
typeArrayHandle classEnabled(THREAD, t); typeArrayHandle classEnabled(THREAD, t);

View File

@ -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. // and the char array it points to end up in the same cache line.
oop obj; oop obj;
if (tenured) { 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 { } 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 // 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) { bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
assert(SharedSkipVerify || assert(SharedSkipVerify ||
java_string->klass() == SystemDictionary::string_klass(), java_string->klass() == SystemDictionary::String_klass(),
"must be java_string"); "must be java_string");
typeArrayOop value = java_lang_String::value(java_string); typeArrayOop value = java_lang_String::value(java_string);
int offset = java_lang_String::offset(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) { void java_lang_String::print(Handle java_string, outputStream* st) {
oop obj = java_string(); 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); typeArrayOop value = java_lang_String::value(obj);
int offset = java_lang_String::offset(obj); int offset = java_lang_String::offset(obj);
int length = java_lang_String::length(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. // class is put into the system dictionary.
int computed_modifiers = k->compute_modifier_flags(CHECK_0); int computed_modifiers = k->compute_modifier_flags(CHECK_0);
k->set_modifier_flags(computed_modifiers); k->set_modifier_flags(computed_modifiers);
if (SystemDictionary::class_klass_loaded()) { if (SystemDictionary::Class_klass_loaded()) {
// Allocate mirror (java.lang.Class instance) // 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 // Setup indirections
mirror->obj_field_put(klass_offset, k()); mirror->obj_field_put(klass_offset, k());
k->set_java_mirror(mirror()); 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) { 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 // This should be improved by adding a field at the Java level or by
// introducing a new VM klass (see comment in ClassFileParser) // 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) { if (type != T_VOID) {
klassOop aklass = Universe::typeArrayKlassObj(type); klassOop aklass = Universe::typeArrayKlassObj(type);
assert(aklass != NULL, "correct bootstrap"); 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 java_lang_Class::primitive_mirror(BasicType t) {
oop mirror = Universe::java_mirror(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"); assert(java_lang_Class::is_primitive(mirror), "must be primitive");
return mirror; return mirror;
} }
@ -515,14 +515,14 @@ void java_lang_Class::compute_offsets() {
assert(!offsets_computed, "offsets should be initialized only once"); assert(!offsets_computed, "offsets should be initialized only once");
offsets_computed = true; offsets_computed = true;
klassOop k = SystemDictionary::class_klass(); klassOop k = SystemDictionary::Class_klass();
// The classRedefinedCount field is only present starting in 1.5, // The classRedefinedCount field is only present starting in 1.5,
// so don't go fatal. // so don't go fatal.
compute_optional_offset(classRedefinedCount_offset, compute_optional_offset(classRedefinedCount_offset,
k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
// The field indicating parallelCapable (parallelLockMap) is only present starting in 7, // 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, compute_optional_offset(parallelCapable_offset,
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); 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() { void java_lang_Thread::compute_offsets() {
assert(_group_offset == 0, "offsets should be initialized only once"); 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(_name_offset, k, vmSymbols::name_name(), vmSymbols::char_array_signature());
compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature()); compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature());
compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_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() { void java_lang_ThreadGroup::compute_offsets() {
assert(_parent_offset == 0, "offsets should be initialized only once"); 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(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature());
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_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 // No-op if stack trace is disabled
if (!StackTraceInThrowable) return; 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()); oop backtrace = java_lang_Throwable::backtrace(throwable());
assert(backtrace != NULL, "backtrace not preallocated"); 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"); assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4");
// Allocate java.lang.StackTraceElement instance // Allocate java.lang.StackTraceElement instance
klassOop k = SystemDictionary::stackTraceElement_klass(); klassOop k = SystemDictionary::StackTraceElement_klass();
assert(k != NULL, "must be loaded in 1.4+"); assert(k != NULL, "must be loaded in 1.4+");
instanceKlassHandle ik (THREAD, k); instanceKlassHandle ik (THREAD, k);
if (ik->should_be_initialized()) { 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() { 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()); 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() { 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(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_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) { Handle java_lang_reflect_Method::create(TRAPS) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); 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 // This class is eagerly initialized during VM initialization, since we keep a refence
// to one of the methods // to one of the methods
assert(instanceKlass::cast(klass)->is_initialized(), "must be initialized"); 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() { 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(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_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()); 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() { 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(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_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() { 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 // This null test can be removed post beta
if (k != NULL) { if (k != NULL) {
compute_offset(_cp_oop_offset, k, vmSymbols::constantPoolOop_name(), vmSymbols::object_signature()); 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) { Handle sun_reflect_ConstantPool::create(TRAPS) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); 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); instanceKlassHandle klass (THREAD, k);
// Ensure it is initialized // Ensure it is initialized
klass->initialize(CHECK_NH); 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() { 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 // This null test can be removed post beta
if (k != NULL) { if (k != NULL) {
compute_offset(_base_offset, k, 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 // Support for java_lang_ref_Reference
oop java_lang_ref_Reference::pending_list_lock() { 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); char *addr = (((char *)ik->start_of_static_fields()) + static_lock_offset);
if (UseCompressedOops) { if (UseCompressedOops) {
return oopDesc::load_decode_heap_oop((narrowOop *)addr); 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() { 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); char *addr = (((char *)ik->start_of_static_fields()) + static_pending_offset);
// XXX This might not be HeapWord aligned, almost rather be char *. // XXX This might not be HeapWord aligned, almost rather be char *.
return (HeapWord*)addr; return (HeapWord*)addr;
@ -2105,17 +2105,17 @@ jlong java_lang_ref_SoftReference::timestamp(oop ref) {
} }
jlong java_lang_ref_SoftReference::clock() { 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; 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) { 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; 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); return ptypes(mt)->obj_at(idx);
} }
int java_dyn_MethodType::ptype_count(oop mt) {
return ptypes(mt)->length();
}
// Support for java_dyn_MethodTypeForm // 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" // the generated bytecodes for reflection, and if so, "magically"
// delegate to its parent to prevent class loading from occurring // delegate to its parent to prevent class loading from occurring
// in places where applications using reflection didn't expect it. // 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 // This might be null in non-1.4 JDKs
if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) { if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) {
return parent(loader); return parent(loader);
@ -2549,7 +2553,7 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
void java_lang_System::compute_offsets() { void java_lang_System::compute_offsets() {
assert(offset_of_static_fields == 0, "offsets should be initialized only once"); 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(); offset_of_static_fields = ik->offset_of_static_fields();
} }

View File

@ -111,7 +111,7 @@ class java_lang_String : AllStatic {
// Testers // Testers
static bool is_instance(oop obj) { static bool is_instance(oop obj) {
return obj != NULL && obj->klass() == SystemDictionary::string_klass(); return obj != NULL && obj->klass() == SystemDictionary::String_klass();
} }
// Debugging // Debugging
@ -161,7 +161,7 @@ class java_lang_Class : AllStatic {
static void print_signature(oop java_class, outputStream *st); static void print_signature(oop java_class, outputStream *st);
// Testing // Testing
static bool is_instance(oop obj) { 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 bool is_primitive(oop java_class);
static BasicType primitive_type(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 form(oop mt);
static oop ptype(oop mt, int index); 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 symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS);
static void print_signature(oop mt, outputStream* st); static void print_signature(oop mt, outputStream* st);
@ -1083,6 +1084,14 @@ public:
static oop vmmethod(oop site); static oop vmmethod(oop site);
static void set_vmmethod(oop site, oop ref); 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: // Accessors for code generation:
static int target_offset_in_bytes() { return _target_offset; } static int target_offset_in_bytes() { return _target_offset; }
static int type_offset_in_bytes() { return _type_offset; } static int type_offset_in_bytes() { return _type_offset; }

View File

@ -60,10 +60,10 @@ oop SystemDictionary::java_system_loader() {
} }
void SystemDictionary::compute_java_system_loader(TRAPS) { 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); JavaValue result(T_OBJECT);
JavaCalls::call_static(&result, JavaCalls::call_static(&result,
KlassHandle(THREAD, WK_KLASS(classloader_klass)), KlassHandle(THREAD, WK_KLASS(ClassLoader_klass)),
vmSymbolHandles::getSystemClassLoader_name(), vmSymbolHandles::getSystemClassLoader_name(),
vmSymbolHandles::void_classloader_signature(), vmSymbolHandles::void_classloader_signature(),
CHECK); 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, // in which case we have to check whether the pending exception is a ClassNotFoundException,
// and if so convert it to a NoClassDefFoundError // and if so convert it to a NoClassDefFoundError
// And chain the original ClassNotFoundException // 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); ResourceMark rm(THREAD);
assert(klass_h() == NULL, "Should not have result with exception pending"); assert(klass_h() == NULL, "Should not have result with exception pending");
Handle e(THREAD, PENDING_EXCEPTION); 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"); 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, JavaCalls::call_special(&result,
class_loader, class_loader,
system_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 // Bootstrap goes through here to allow for an extra guarantee check
if (UnsyncloadClass || (class_loader.is_null())) { if (UnsyncloadClass || (class_loader.is_null())) {
if (k.is_null() && HAS_PENDING_EXCEPTION 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); MutexLocker mu(SystemDictionary_lock, THREAD);
klassOop check = find_class(d_index, d_hash, name, class_loader); klassOop check = find_class(d_index, d_hash, name, class_loader);
if (check != NULL) { if (check != NULL) {
@ -1367,7 +1367,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_nam
JavaValue result(T_OBJECT); 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 // Call public unsynchronized loadClass(String) directly for all class loaders
// for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will // 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) { 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 // Preload commonly used klasses
WKID scan = FIRST_WKID; WKID scan = FIRST_WKID;
// first do Object, String, Class // 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. // Fixup mirrors for classes loaded before java.lang.Class.
// These calls iterate over the objects currently in the perm gen // 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); Universe::fixup_mirrors(CHECK);
// do a bunch more: // 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 // Preload ref klasses and set reference types
instanceKlass::cast(WK_KLASS(reference_klass))->set_reference_type(REF_OTHER); instanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(reference_klass)); instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass));
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(phantom_reference_klass), scan, CHECK); initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK);
instanceKlass::cast(WK_KLASS(soft_reference_klass))->set_reference_type(REF_SOFT); instanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
instanceKlass::cast(WK_KLASS(weak_reference_klass))->set_reference_type(REF_WEAK); instanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK);
instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL); instanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM); instanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass); WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_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); scan = WKID(meth_group_end+1);
} }
WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass); 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); initialize_wk_klasses_until(indy_group_start, scan, CHECK);
if (EnableInvokeDynamic) { if (EnableInvokeDynamic) {
initialize_wk_klasses_through(indy_group_end, scan, CHECK); 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); initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
_box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass); _box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
_box_klasses[T_CHAR] = WK_KLASS(char_klass); _box_klasses[T_CHAR] = WK_KLASS(Character_klass);
_box_klasses[T_FLOAT] = WK_KLASS(float_klass); _box_klasses[T_FLOAT] = WK_KLASS(Float_klass);
_box_klasses[T_DOUBLE] = WK_KLASS(double_klass); _box_klasses[T_DOUBLE] = WK_KLASS(Double_klass);
_box_klasses[T_BYTE] = WK_KLASS(byte_klass); _box_klasses[T_BYTE] = WK_KLASS(Byte_klass);
_box_klasses[T_SHORT] = WK_KLASS(short_klass); _box_klasses[T_SHORT] = WK_KLASS(Short_klass);
_box_klasses[T_INT] = WK_KLASS(int_klass); _box_klasses[T_INT] = WK_KLASS(Integer_klass);
_box_klasses[T_LONG] = WK_KLASS(long_klass); _box_klasses[T_LONG] = WK_KLASS(Long_klass);
//_box_klasses[T_OBJECT] = WK_KLASS(object_klass); //_box_klasses[T_OBJECT] = WK_KLASS(object_klass);
//_box_klasses[T_ARRAY] = WK_KLASS(object_klass); //_box_klasses[T_ARRAY] = WK_KLASS(object_klass);
@ -2014,11 +2014,11 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
#endif // KERNEL #endif // KERNEL
{ // Compute whether we should use loadClass or loadClassInternal when loading classes. { // 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); _has_loadClassInternal = (method != NULL);
} }
{ // Compute whether we should use checkPackageAccess or NOT { // 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); _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); SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
if (spe == NULL || spe->property_oop() == NULL) { if (spe == NULL || spe->property_oop() == NULL) {
// Must create lots of stuff here, but outside of the SystemDictionary lock. // 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(), Handle mt = compute_method_handle_type(signature(),
class_loader, protection_domain, class_loader, protection_domain,
CHECK_NULL); CHECK_NULL);
@ -2372,7 +2374,7 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
TRAPS) { TRAPS) {
Handle empty; Handle empty;
int npts = ArgumentCount(signature()).size(); 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; int arg = 0;
Handle rt; // the return type from the signature Handle rt; // the return type from the signature
for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) { for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {

View File

@ -82,55 +82,55 @@ class SymbolPropertyTable;
#define WK_KLASSES_DO(template) \ #define WK_KLASSES_DO(template) \
/* well-known classes */ \ /* well-known classes */ \
template(object_klass, java_lang_Object, Pre) \ template(Object_klass, java_lang_Object, Pre) \
template(string_klass, java_lang_String, Pre) \ template(String_klass, java_lang_String, Pre) \
template(class_klass, java_lang_Class, Pre) \ template(Class_klass, java_lang_Class, Pre) \
template(cloneable_klass, java_lang_Cloneable, Pre) \ template(Cloneable_klass, java_lang_Cloneable, Pre) \
template(classloader_klass, java_lang_ClassLoader, Pre) \ template(ClassLoader_klass, java_lang_ClassLoader, Pre) \
template(serializable_klass, java_io_Serializable, Pre) \ template(Serializable_klass, java_io_Serializable, Pre) \
template(system_klass, java_lang_System, Pre) \ template(System_klass, java_lang_System, Pre) \
template(throwable_klass, java_lang_Throwable, Pre) \ template(Throwable_klass, java_lang_Throwable, Pre) \
template(error_klass, java_lang_Error, Pre) \ template(Error_klass, java_lang_Error, Pre) \
template(threaddeath_klass, java_lang_ThreadDeath, Pre) \ template(ThreadDeath_klass, java_lang_ThreadDeath, Pre) \
template(exception_klass, java_lang_Exception, Pre) \ template(Exception_klass, java_lang_Exception, Pre) \
template(runtime_exception_klass, java_lang_RuntimeException, Pre) \ template(RuntimeException_klass, java_lang_RuntimeException, Pre) \
template(protectionDomain_klass, java_security_ProtectionDomain, Pre) \ template(ProtectionDomain_klass, java_security_ProtectionDomain, Pre) \
template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \ template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \
template(classNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \ template(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \
template(noClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \ template(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \
template(linkageError_klass, java_lang_LinkageError, Pre) \ template(LinkageError_klass, java_lang_LinkageError, Pre) \
template(ClassCastException_klass, java_lang_ClassCastException, Pre) \ template(ClassCastException_klass, java_lang_ClassCastException, Pre) \
template(ArrayStoreException_klass, java_lang_ArrayStoreException, 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(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre) \
template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \ template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \
template(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, 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 */ \ /* Preload ref klasses and set reference types */ \
template(soft_reference_klass, java_lang_ref_SoftReference, Pre) \ template(SoftReference_klass, java_lang_ref_SoftReference, Pre) \
template(weak_reference_klass, java_lang_ref_WeakReference, Pre) \ template(WeakReference_klass, java_lang_ref_WeakReference, Pre) \
template(final_reference_klass, java_lang_ref_FinalReference, Pre) \ template(FinalReference_klass, java_lang_ref_FinalReference, Pre) \
template(phantom_reference_klass, java_lang_ref_PhantomReference, Pre) \ template(PhantomReference_klass, java_lang_ref_PhantomReference, Pre) \
template(finalizer_klass, java_lang_ref_Finalizer, Pre) \ template(Finalizer_klass, java_lang_ref_Finalizer, Pre) \
\ \
template(thread_klass, java_lang_Thread, Pre) \ template(Thread_klass, java_lang_Thread, Pre) \
template(threadGroup_klass, java_lang_ThreadGroup, Pre) \ template(ThreadGroup_klass, java_lang_ThreadGroup, Pre) \
template(properties_klass, java_util_Properties, Pre) \ template(Properties_klass, java_util_Properties, Pre) \
template(reflect_accessible_object_klass, java_lang_reflect_AccessibleObject, Pre) \ template(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre) \
template(reflect_field_klass, java_lang_reflect_Field, Pre) \ template(reflect_Field_klass, java_lang_reflect_Field, Pre) \
template(reflect_method_klass, java_lang_reflect_Method, Pre) \ template(reflect_Method_klass, java_lang_reflect_Method, Pre) \
template(reflect_constructor_klass, java_lang_reflect_Constructor, Pre) \ template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \
\ \
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ /* 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. */ \ /* 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. */ \ /* 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_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \
template(reflect_method_accessor_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
template(reflect_constructor_accessor_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
template(reflect_delegating_classloader_klass, sun_reflect_DelegatingClassLoader, Opt) \ template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \
template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, 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 */ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \ template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \
@ -144,16 +144,14 @@ class SymbolPropertyTable;
template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \ template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
template(Linkage_klass, java_dyn_Linkage, Opt) \ template(Linkage_klass, java_dyn_Linkage, Opt) \
template(CallSite_klass, java_dyn_CallSite, 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 */ \ /* Note: MethodHandle must be first, and Dynamic last in group */ \
\ \
template(vector_klass, java_util_Vector, Pre) \ template(StringBuffer_klass, java_lang_StringBuffer, Pre) \
template(hashtable_klass, java_util_Hashtable, Pre) \
template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
template(StringBuilder_klass, java_lang_StringBuilder, Pre) \ template(StringBuilder_klass, java_lang_StringBuilder, Pre) \
\ \
/* It's NULL in non-1.4 JDKs. */ \ /* 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. */ \ /* 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. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \ 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) \ template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
\ \
/* Preload boxing klasses */ \ /* Preload boxing klasses */ \
template(boolean_klass, java_lang_Boolean, Pre) \ template(Boolean_klass, java_lang_Boolean, Pre) \
template(char_klass, java_lang_Character, Pre) \ template(Character_klass, java_lang_Character, Pre) \
template(float_klass, java_lang_Float, Pre) \ template(Float_klass, java_lang_Float, Pre) \
template(double_klass, java_lang_Double, Pre) \ template(Double_klass, java_lang_Double, Pre) \
template(byte_klass, java_lang_Byte, Pre) \ template(Byte_klass, java_lang_Byte, Pre) \
template(short_klass, java_lang_Short, Pre) \ template(Short_klass, java_lang_Short, Pre) \
template(int_klass, java_lang_Integer, Pre) \ template(Integer_klass, java_lang_Integer, Pre) \
template(long_klass, java_lang_Long, Pre) \ template(Long_klass, java_lang_Long, Pre) \
/*end*/ /*end*/
@ -438,8 +436,8 @@ public:
// Tells whether ClassLoader.checkPackageAccess is present // Tells whether ClassLoader.checkPackageAccess is present
static bool has_checkPackageAccess() { return _has_checkPackageAccess; } static bool has_checkPackageAccess() { return _has_checkPackageAccess; }
static bool class_klass_loaded() { return WK_KLASS(class_klass) != NULL; } static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; }
static bool cloneable_klass_loaded() { return WK_KLASS(cloneable_klass) != NULL; } static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; }
// Returns default system loader // Returns default system loader
static oop java_system_loader(); static oop java_system_loader();

View File

@ -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) { bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) {
symbolOop name = klass->name(); 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 (should_verify_for(klass->class_loader(), should_verify_class) &&
// return if the class is a bootstrapping class // return if the class is a bootstrapping class

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -70,6 +70,7 @@ static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGN
void vmSymbols::initialize(TRAPS) { void vmSymbols::initialize(TRAPS) {
assert((int)SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield"); 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((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) { if (!UseSharedSpaces) {
const char* string = &vm_symbol_bodies[0]; const char* string = &vm_symbol_bodies[0];
@ -271,6 +272,58 @@ vmSymbols::SID vmSymbols::find_sid(symbolOop symbol) {
return sid; 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" #define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0"
static const char* vm_intrinsic_name_bodies = static const char* vm_intrinsic_name_bodies =
@ -330,15 +383,15 @@ inline bool match_F_RNY(jshort flags) {
} }
// These are for forming case labels: // These are for forming case labels:
#define ID3(x, y, z) (( jint)(z) + \ #define ID3(x, y, z) (( jlong)(z) + \
((jint)(y) << vmSymbols::log2_SID_LIMIT) + \ ((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \
((jint)(x) << (2*vmSymbols::log2_SID_LIMIT)) ) ((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) )
#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n) #define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n)
vmIntrinsics::ID vmIntrinsics::find_id(vmSymbols::SID holder, vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder,
vmSymbols::SID name, vmSymbols::SID name,
vmSymbols::SID sig, vmSymbols::SID sig,
jshort flags) { jshort flags) {
assert((int)vmSymbols::SID_LIMIT <= (1<<vmSymbols::log2_SID_LIMIT), "must fit"); assert((int)vmSymbols::SID_LIMIT <= (1<<vmSymbols::log2_SID_LIMIT), "must fit");
// Let the C compiler build the decision tree. // 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) { vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) {
#ifndef PRODUCT jlong info = intrinsic_info(id);
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ int shift = 2*vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
case id: return SID_ENUM(klass); assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1021, "");
return vmSymbols::SID( (info >> shift) & mask );
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;
} }
vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) { vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) {
#ifndef PRODUCT jlong info = intrinsic_info(id);
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
case id: return SID_ENUM(name); assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, "");
return vmSymbols::SID( (info >> shift) & mask );
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;
} }
vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) { vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) {
#ifndef PRODUCT jlong info = intrinsic_info(id);
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
case id: return SID_ENUM(sig); assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, "");
return vmSymbols::SID( (info >> shift) & mask );
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;
} }
vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) { vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) {
#ifndef PRODUCT jlong info = intrinsic_info(id);
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT);
case id: return fcode; assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, "");
return Flags( (info >> shift) & mask );
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;
} }

View File

@ -219,7 +219,7 @@
template(base_name, "base") \ template(base_name, "base") \
\ \
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ /* 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_Linkage, "java/dyn/Linkage") \
template(java_dyn_CallSite, "java/dyn/CallSite") \ template(java_dyn_CallSite, "java/dyn/CallSite") \
template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \ template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
@ -347,9 +347,14 @@
\ \
/* common signatures names */ \ /* common signatures names */ \
template(void_method_signature, "()V") \ 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_int_signature, "()I") \
template(void_long_signature, "()J") \ 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_void_signature, "(I)V") \
template(int_int_signature, "(I)I") \ template(int_int_signature, "(I)I") \
template(int_bool_signature, "(I)Z") \ 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) \ do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
/* (symbols invoke_name and invoke_signature defined above) */ \ /* (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*/ /*end*/
@ -984,7 +1029,12 @@ class vmIntrinsics: AllStatic {
F_Y, // !static ?native synchronized F_Y, // !static ?native synchronized
F_RN, // !static native !synchronized F_RN, // !static native !synchronized
F_SN, // 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: public:
@ -996,15 +1046,32 @@ public:
static const char* name_at(ID id); 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. // Given a method's class, name, signature, and access flags, report its ID.
static ID find_id(vmSymbols::SID holder, static ID find_id(vmSymbols::SID holder,
vmSymbols::SID name, vmSymbols::SID name,
vmSymbols::SID sig, 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; 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 class_for(ID id);
static vmSymbols::SID name_for(ID id); static vmSymbols::SID name_for(ID id);
static vmSymbols::SID signature_for(ID id); static vmSymbols::SID signature_for(ID id);
@ -1014,4 +1081,11 @@ public:
// Access to intrinsic methods: // Access to intrinsic methods:
static methodOop method_for(ID id); 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);
}; };

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -102,6 +102,9 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
virtual bool is_compiled_by_c2() const { return false; } virtual bool is_compiled_by_c2() const { return false; }
virtual bool is_compiled_by_c1() 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 // Boundaries
address header_begin() const { return (address) this; } address header_begin() const { return (address) this; }
address header_end() const { return ((address) this) + _header_size; }; address header_end() const { return ((address) this) + _header_size; };

View File

@ -281,6 +281,7 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
ciMethod* method, ciMethod* method,
int bci, int bci,
bool reexecute, bool reexecute,
bool is_method_handle_invoke,
DebugToken* locals, DebugToken* locals,
DebugToken* expressions, DebugToken* expressions,
DebugToken* monitors) { DebugToken* monitors) {
@ -292,8 +293,9 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
int stream_offset = stream()->position(); int stream_offset = stream()->position();
last_pd->set_scope_decode_offset(stream_offset); 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_should_reexecute(reexecute);
last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
// serialize sender stream offest // serialize sender stream offest
stream()->write_int(sender_stream_offset); stream()->write_int(sender_stream_offset);

View File

@ -88,6 +88,7 @@ class DebugInformationRecorder: public ResourceObj {
ciMethod* method, ciMethod* method,
int bci, int bci,
bool reexecute, bool reexecute,
bool is_method_handle_invoke = false,
DebugToken* locals = NULL, DebugToken* locals = NULL,
DebugToken* expressions = NULL, DebugToken* expressions = NULL,
DebugToken* monitors = NULL); DebugToken* monitors = NULL);

View File

@ -1170,7 +1170,7 @@ void nmethod::log_state_change() const {
} }
// Common functionality for both make_not_entrant and make_zombie // 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"); assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
// If the method is already zombie there is nothing to do // 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()) { if (!method()->is_native()) {
SimpleScopeDesc ssd(this, fr.pc()); SimpleScopeDesc ssd(this, fr.pc());
Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci()); 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(); 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"); "must end with a sentinel");
#endif //ASSERT #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); int size = count * sizeof(PcDesc);
assert(scopes_pcs_size() >= size, "oob"); assert(scopes_pcs_size() >= size, "oob");
memcpy(scopes_pcs_begin(), pcs, size); 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 // Verification

View File

@ -81,18 +81,19 @@ class PcDescCache VALUE_OBJ_CLASS_SPEC {
struct nmFlags { struct nmFlags {
friend class VMStructs; friend class VMStructs;
unsigned int version:8; // version number (0 = first version) unsigned int version:8; // version number (0 = first version)
unsigned int level:4; // optimization level unsigned int level:4; // optimization level
unsigned int age:4; // age (in # of sweep steps) 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 isUncommonRecompiled:1; // recompiled because of uncommon trap?
unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures
unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies
unsigned int markedForReclamation:1; // Used by NMethodSweeper 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(); void clear();
}; };
@ -254,7 +255,7 @@ class nmethod : public CodeBlob {
const char* reloc_string_for(u_char* begin, u_char* end); const char* reloc_string_for(u_char* begin, u_char* end);
// Returns true if this thread changed the state of the nmethod or // Returns true if this thread changed the state of the nmethod or
// false if another thread performed the transition. // 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(); void inc_decompile_count();
// used to check that writes to nmFlags are done consistently. // 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; } bool has_unsafe_access() const { return flags.has_unsafe_access; }
void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; } 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; } int level() const { return flags.level; }
void set_level(int newLevel) { check_safepoint(); flags.level = newLevel; } 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); } 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; } 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: // jvmti support:
void post_compiled_method_load_event(); void post_compiled_method_load_event();

View File

@ -38,6 +38,7 @@ class PcDesc VALUE_OBJ_CLASS_SPEC {
int word; int word;
struct { struct {
unsigned int reexecute: 1; unsigned int reexecute: 1;
unsigned int is_method_handle_invoke: 1;
} bits; } bits;
bool operator ==(const PcDescFlags& other) { return word == other.word; } bool operator ==(const PcDescFlags& other) { return word == other.word; }
} _flags; } _flags;
@ -72,6 +73,9 @@ class PcDesc VALUE_OBJ_CLASS_SPEC {
_flags == pd->_flags; _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 // Returns the real pc
address real_pc(const nmethod* code) const; address real_pc(const nmethod* code) const;

View File

@ -1820,9 +1820,11 @@ void CompileBroker::print_times() {
CompileBroker::_t_standard_compilation.seconds(), CompileBroker::_t_standard_compilation.seconds(),
CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count); 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); 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)) { if (compiler(CompLevel_fast_compile)) {
compiler(CompLevel_highest_tier)->print_timers(); compiler(CompLevel_fast_compile)->print_timers();
if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier))
compiler(CompLevel_highest_tier)->print_timers();
} }
tty->cr(); tty->cr();

View File

@ -782,6 +782,7 @@ void MethodLiveness::BasicBlock::compute_gen_kill_single(ciBytecodeStream *instr
case Bytecodes::_invokespecial: case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic: case Bytecodes::_invokestatic:
case Bytecodes::_invokeinterface: case Bytecodes::_invokeinterface:
case Bytecodes::_invokedynamic:
case Bytecodes::_newarray: case Bytecodes::_newarray:
case Bytecodes::_anewarray: case Bytecodes::_anewarray:
case Bytecodes::_checkcast: case Bytecodes::_checkcast:

View File

@ -274,7 +274,7 @@ CollectedHeap::fill_with_object_impl(HeapWord* start, size_t words)
fill_with_array(start, words); fill_with_array(start, words);
} else if (words > 0) { } else if (words > 0) {
assert(words == min_fill_size(), "unaligned size"); assert(words == min_fill_size(), "unaligned size");
post_allocation_setup_common(SystemDictionary::object_klass(), start, post_allocation_setup_common(SystemDictionary::Object_klass(), start,
words); words);
} }
} }

View File

@ -155,6 +155,9 @@ callGenerator.cpp callnode.hpp
callGenerator.cpp cfgnode.hpp callGenerator.cpp cfgnode.hpp
callGenerator.cpp compileLog.hpp callGenerator.cpp compileLog.hpp
callGenerator.cpp connode.hpp callGenerator.cpp connode.hpp
callGenerator.cpp ciCPCache.hpp
callGenerator.cpp ciMethodHandle.hpp
callGenerator.cpp javaClasses.hpp
callGenerator.cpp parse.hpp callGenerator.cpp parse.hpp
callGenerator.cpp rootnode.hpp callGenerator.cpp rootnode.hpp
callGenerator.cpp runtime.hpp callGenerator.cpp runtime.hpp
@ -391,6 +394,9 @@ divnode.hpp type.hpp
doCall.cpp addnode.hpp doCall.cpp addnode.hpp
doCall.cpp callGenerator.hpp doCall.cpp callGenerator.hpp
doCall.cpp ciCallSite.hpp
doCall.cpp ciCPCache.hpp
doCall.cpp ciMethodHandle.hpp
doCall.cpp cfgnode.hpp doCall.cpp cfgnode.hpp
doCall.cpp compileLog.hpp doCall.cpp compileLog.hpp
doCall.cpp linkResolver.hpp doCall.cpp linkResolver.hpp

View File

@ -516,6 +516,11 @@ ciArrayKlassKlass.hpp ciKlassKlass.hpp
ciCallProfile.hpp ciClassList.hpp ciCallProfile.hpp ciClassList.hpp
ciCallSite.cpp ciCallSite.hpp
ciCallSite.cpp ciUtilities.hpp
ciCallSite.hpp ciInstance.hpp
ciConstant.cpp allocation.hpp ciConstant.cpp allocation.hpp
ciConstant.cpp allocation.inline.hpp ciConstant.cpp allocation.inline.hpp
ciConstant.cpp ciConstant.hpp ciConstant.cpp ciConstant.hpp
@ -532,6 +537,12 @@ ciConstantPoolCache.cpp ciUtilities.hpp
ciConstantPoolCache.hpp growableArray.hpp ciConstantPoolCache.hpp growableArray.hpp
ciConstantPoolCache.hpp resourceArea.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 allocation.inline.hpp
ciEnv.cpp ciConstant.hpp ciEnv.cpp ciConstant.hpp
ciEnv.cpp ciEnv.hpp ciEnv.cpp ciEnv.hpp
@ -593,6 +604,7 @@ ciField.cpp universe.inline.hpp
ciField.hpp ciClassList.hpp ciField.hpp ciClassList.hpp
ciField.hpp ciConstant.hpp ciField.hpp ciConstant.hpp
ciField.hpp ciFlags.hpp ciField.hpp ciFlags.hpp
ciField.hpp ciInstance.hpp
ciFlags.cpp ciFlags.hpp ciFlags.cpp ciFlags.hpp
@ -679,6 +691,7 @@ ciMethod.hpp ciFlags.hpp
ciMethod.hpp ciInstanceKlass.hpp ciMethod.hpp ciInstanceKlass.hpp
ciMethod.hpp ciObject.hpp ciMethod.hpp ciObject.hpp
ciMethod.hpp ciSignature.hpp ciMethod.hpp ciSignature.hpp
ciMethod.hpp methodHandles.hpp
ciMethod.hpp methodLiveness.hpp ciMethod.hpp methodLiveness.hpp
ciMethodBlocks.cpp bytecode.hpp ciMethodBlocks.cpp bytecode.hpp
@ -710,6 +723,15 @@ ciMethodKlass.cpp ciUtilities.hpp
ciMethodKlass.hpp ciKlass.hpp ciMethodKlass.hpp ciKlass.hpp
ciMethodKlass.hpp ciSymbol.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.cpp ciNullObject.hpp
ciNullObject.hpp ciClassList.hpp ciNullObject.hpp ciClassList.hpp
@ -755,11 +777,14 @@ ciObject.hpp handles.hpp
ciObject.hpp jniHandles.hpp ciObject.hpp jniHandles.hpp
ciObjectFactory.cpp allocation.inline.hpp ciObjectFactory.cpp allocation.inline.hpp
ciObjectFactory.cpp ciCallSite.hpp
ciObjectFactory.cpp ciCPCache.hpp
ciObjectFactory.cpp ciInstance.hpp ciObjectFactory.cpp ciInstance.hpp
ciObjectFactory.cpp ciInstanceKlass.hpp ciObjectFactory.cpp ciInstanceKlass.hpp
ciObjectFactory.cpp ciInstanceKlassKlass.hpp ciObjectFactory.cpp ciInstanceKlassKlass.hpp
ciObjectFactory.cpp ciMethod.hpp ciObjectFactory.cpp ciMethod.hpp
ciObjectFactory.cpp ciMethodData.hpp ciObjectFactory.cpp ciMethodData.hpp
ciObjectFactory.cpp ciMethodHandle.hpp
ciObjectFactory.cpp ciMethodKlass.hpp ciObjectFactory.cpp ciMethodKlass.hpp
ciObjectFactory.cpp ciNullObject.hpp ciObjectFactory.cpp ciNullObject.hpp
ciObjectFactory.cpp ciObjArray.hpp ciObjectFactory.cpp ciObjArray.hpp
@ -793,6 +818,7 @@ ciSignature.hpp ciSymbol.hpp
ciSignature.hpp globalDefinitions.hpp ciSignature.hpp globalDefinitions.hpp
ciSignature.hpp growableArray.hpp ciSignature.hpp growableArray.hpp
ciStreams.cpp ciCallSite.hpp
ciStreams.cpp ciConstant.hpp ciStreams.cpp ciConstant.hpp
ciStreams.cpp ciField.hpp ciStreams.cpp ciField.hpp
ciStreams.cpp ciStreams.hpp ciStreams.cpp ciStreams.hpp
@ -2814,6 +2840,12 @@ methodDataOop.hpp oop.hpp
methodDataOop.hpp orderAccess.hpp methodDataOop.hpp orderAccess.hpp
methodDataOop.hpp universe.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 frame.inline.hpp
methodHandles.hpp globals.hpp methodHandles.hpp globals.hpp
methodHandles.hpp interfaceSupport.hpp methodHandles.hpp interfaceSupport.hpp

View File

@ -102,7 +102,9 @@ methodHandle Bytecode_invoke::static_target(TRAPS) {
KlassHandle resolved_klass; KlassHandle resolved_klass;
constantPoolHandle constants(THREAD, _method->constants()); 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())); LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
} else { } else {
LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle())); LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));

View File

@ -205,12 +205,14 @@ class Bytecode_invoke: public ResourceObj {
bool is_invokespecial() const { return adjusted_invoke_code() == Bytecodes::_invokespecial; } bool is_invokespecial() const { return adjusted_invoke_code() == Bytecodes::_invokespecial; }
bool is_invokedynamic() const { return adjusted_invoke_code() == Bytecodes::_invokedynamic; } 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 has_giant_index() const { return is_invokedynamic(); }
bool is_valid() const { return is_invokeinterface() || bool is_valid() const { return is_invokeinterface() ||
is_invokevirtual() || is_invokevirtual() ||
is_invokestatic() || is_invokestatic() ||
is_invokespecial(); } is_invokespecial() ||
is_invokedynamic(); }
// Creation // Creation
inline friend Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci); inline friend Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci);

View File

@ -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()); st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name());
} else if (tag.is_unresolved_klass()) { } else if (tag.is_unresolved_klass()) {
st->print_cr(" <unresolved klass at %d>", i); st->print_cr(" <unresolved klass at %d>", i);
} else if (tag.is_object()) {
st->print_cr(" " PTR_FORMAT, constants->object_at(i));
} else { } else {
st->print_cr(" bad tag=%d at %d", tag.value(), i); st->print_cr(" bad tag=%d at %d", tag.value(), i);
} }

View File

@ -357,7 +357,7 @@ void Bytecodes::initialize() {
def(_invokespecial , "invokespecial" , "bjj" , NULL , T_ILLEGAL, -1, true); def(_invokespecial , "invokespecial" , "bjj" , NULL , T_ILLEGAL, -1, true);
def(_invokestatic , "invokestatic" , "bjj" , NULL , T_ILLEGAL, 0, true); def(_invokestatic , "invokestatic" , "bjj" , NULL , T_ILLEGAL, 0, true);
def(_invokeinterface , "invokeinterface" , "bjj__", NULL , T_ILLEGAL, -1, 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(_new , "new" , "bii" , NULL , T_OBJECT , 1, true );
def(_newarray , "newarray" , "bc" , NULL , T_OBJECT , 0, true ); def(_newarray , "newarray" , "bc" , NULL , T_OBJECT , 0, true );
def(_anewarray , "anewarray" , "bii" , NULL , T_OBJECT , 0, true ); def(_anewarray , "anewarray" , "bii" , NULL , T_OBJECT , 0, true );

View File

@ -323,7 +323,7 @@ address AbstractInterpreter::deopt_continue_after_entry(methodOop method, addres
// (NOT needed for the old calling convension) // (NOT needed for the old calling convension)
if (!is_top_frame) { if (!is_top_frame) {
int index = Bytes::get_native_u4(bcp+1); 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; break;
} }

View File

@ -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.not_null(), "NULL exceptions should be handled by athrow");
assert(h_exception->is_oop(), "just checking"); assert(h_exception->is_oop(), "just checking");
// Check that exception is a subclass of Throwable, otherwise we have a VerifyError // 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); if (ExitVMOnVerifyError) vm_exit(-1);
ShouldNotReachHere(); ShouldNotReachHere();
} }
@ -585,7 +585,7 @@ IRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThre
Handle exception(thread, thread->vm_result()); Handle exception(thread, thread->vm_result());
assert(exception() != NULL, "vm result should be set"); 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) 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( exception = get_preinitialized_exception(
SystemDictionary::IllegalMonitorStateException_klass(), SystemDictionary::IllegalMonitorStateException_klass(),
CATCH); 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()); 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() == 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 // NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec
// (see also cpCacheOop.cpp for details) // (see also cpCacheOop.cpp for details)
methodHandle rm = info.resolved_method(); 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()); methodHandle mh(thread, fr.interpreter_frame_method());
Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci); Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci);
ArgumentSizeComputer asc(invoke->signature()); 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, Copy::conjoint_bytes(src_address, dest_address,
size_of_arguments * Interpreter::stackElementSize()); size_of_arguments * Interpreter::stackElementSize());
IRT_END IRT_END

View File

@ -55,7 +55,7 @@ void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_kl
// we should pick the vtable index from the resolved method. // we should pick the vtable index from the resolved method.
// Other than that case, there is no valid vtable index to specify. // Other than that case, there is no valid vtable index to specify.
int vtable_index = methodOopDesc::invalid_vtable_index; 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"); assert(resolved_method->vtable_index() == selected_method->vtable_index(), "sanity check");
vtable_index = resolved_method->vtable_index(); vtable_index = resolved_method->vtable_index();
} }
@ -75,6 +75,8 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass
_selected_method = selected_method; _selected_method = selected_method;
_vtable_index = vtable_index; _vtable_index = vtable_index;
if (CompilationPolicy::mustBeCompiled(selected_method)) { 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 // Note: with several active threads, the mustBeCompiled may be true
// while canBeCompiled is false; remove assert // while canBeCompiled is false; remove assert
// assert(CompilationPolicy::canBeCompiled(selected_method), "cannot compile"); // 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 // don't force compilation, resolve was on behalf of compiler
return; 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, CompileBroker::compile_method(selected_method, InvocationEntryBci,
methodHandle(), 0, "mustBeCompiled", CHECK); 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 // 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). // to be false (so we'll short-circuit out of these tests).
if (sel_method->name() == vmSymbols::clone_name() && if (sel_method->name() == vmSymbols::clone_name() &&
sel_klass() == SystemDictionary::object_klass() && sel_klass() == SystemDictionary::Object_klass() &&
resolved_klass->oop_is_array()) { resolved_klass->oop_is_array()) {
// We need to change "protected" to "public". // We need to change "protected" to "public".
assert(flags.is_protected(), "clone not protected?"); 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); 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) { void LinkResolver::resolve_interface_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) {
// resolve klass // resolve klass

View File

@ -133,6 +133,7 @@ class LinkResolver: AllStatic {
// static resolving for all calls except interface calls // 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_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); static void resolve_interface_method(methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS);
// runtime/static resolving for fields // runtime/static resolving for fields

View File

@ -247,15 +247,22 @@ methodHandle Rewriter::rewrite_jsrs(methodHandle method, TRAPS) {
void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) { void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
Rewriter rw(klass, CHECK); Rewriter rw(klass, klass->constants(), klass->methods(), CHECK);
// (That's all, folks.) // (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), : _klass(klass),
// gather starting points _pool(cpool),
_pool( THREAD, klass->constants()), _methods(methods)
_methods(THREAD, klass->methods())
{ {
assert(_pool->cache() == NULL, "constant pool cache must not be set yet"); assert(_pool->cache() == NULL, "constant pool cache must not be set yet");

View File

@ -57,7 +57,7 @@ class Rewriter: public StackObj {
} }
// All the work goes in here: // All the work goes in here:
Rewriter(instanceKlassHandle klass, TRAPS); Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS);
void compute_index_maps(); void compute_index_maps();
void make_constant_pool_cache(TRAPS); void make_constant_pool_cache(TRAPS);
@ -70,6 +70,7 @@ class Rewriter: public StackObj {
public: public:
// Driver routine: // Driver routine:
static void rewrite(instanceKlassHandle klass, TRAPS); static void rewrite(instanceKlassHandle klass, TRAPS);
static void rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS);
enum { enum {
_secondary_entry_tag = nth_bit(30) _secondary_entry_tag = nth_bit(30)

View File

@ -49,7 +49,7 @@ object_type ClassifyObjectClosure::classify_object(oop obj, bool count) {
Klass* k = obj->blueprint(); Klass* k = obj->blueprint();
if (k->as_klassOop() == SystemDictionary::object_klass()) { if (k->as_klassOop() == SystemDictionary::Object_klass()) {
tty->print_cr("Found the class!"); tty->print_cr("Found the class!");
} }

View File

@ -63,7 +63,7 @@ public:
void do_oop(oop* p) { void do_oop(oop* p) {
if (p != NULL) { if (p != NULL) {
oop obj = *p; oop obj = *p;
if (obj->klass() == SystemDictionary::string_klass()) { if (obj->klass() == SystemDictionary::String_klass()) {
int hash; int hash;
typeArrayOop value = java_lang_String::value(obj); 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_instance()) {
if (obj->is_klass() || if (obj->is_klass() ||
obj->is_a(SystemDictionary::class_klass()) || obj->is_a(SystemDictionary::Class_klass()) ||
obj->is_a(SystemDictionary::throwable_klass())) { obj->is_a(SystemDictionary::Throwable_klass())) {
// Do nothing // Do nothing
} }
else if (obj->is_a(SystemDictionary::string_klass())) { else if (obj->is_a(SystemDictionary::String_klass())) {
// immutable objects. // immutable objects.
} else { } else {
// someone added an object we hadn't accounted for. // someone added an object we hadn't accounted for.

View File

@ -71,7 +71,7 @@ void ReferenceProcessor::init_statics() {
assert(_sentinelRef == NULL, "should be initialized precisely once"); assert(_sentinelRef == NULL, "should be initialized precisely once");
EXCEPTION_MARK; EXCEPTION_MARK;
_sentinelRef = instanceKlass::cast( _sentinelRef = instanceKlass::cast(
SystemDictionary::reference_klass())-> SystemDictionary::Reference_klass())->
allocate_permanent_instance(THREAD); allocate_permanent_instance(THREAD);
// Initialize the master soft ref clock. // Initialize the master soft ref clock.

View File

@ -876,7 +876,7 @@ void ContiguousSpace::allocate_temporary_filler(int factor) {
instanceOop obj = (instanceOop) allocate(size); instanceOop obj = (instanceOop) allocate(size);
obj->set_mark(markOopDesc::prototype()); obj->set_mark(markOopDesc::prototype());
obj->set_klass_gap(0); obj->set_klass_gap(0);
obj->set_klass(SystemDictionary::object_klass()); obj->set_klass(SystemDictionary::Object_klass());
} }
} }

View File

@ -291,7 +291,7 @@ void Universe::genesis(TRAPS) {
SystemDictionary::initialize(CHECK); SystemDictionary::initialize(CHECK);
klassOop ok = SystemDictionary::object_klass(); klassOop ok = SystemDictionary::Object_klass();
_the_null_string = StringTable::intern("null", CHECK); _the_null_string = StringTable::intern("null", CHECK);
_the_min_jint_string = StringTable::intern("-2147483648", CHECK); _the_min_jint_string = StringTable::intern("-2147483648", CHECK);
@ -299,9 +299,9 @@ void Universe::genesis(TRAPS) {
if (UseSharedSpaces) { if (UseSharedSpaces) {
// Verify shared interfaces array. // Verify shared interfaces array.
assert(_the_array_interfaces_array->obj_at(0) == assert(_the_array_interfaces_array->obj_at(0) ==
SystemDictionary::cloneable_klass(), "u3"); SystemDictionary::Cloneable_klass(), "u3");
assert(_the_array_interfaces_array->obj_at(1) == assert(_the_array_interfaces_array->obj_at(1) ==
SystemDictionary::serializable_klass(), "u3"); SystemDictionary::Serializable_klass(), "u3");
// Verify element klass for system obj array klass // Verify element klass for system obj array klass
assert(objArrayKlass::cast(_systemObjArrayKlassObj)->element_klass() == ok, "u1"); assert(objArrayKlass::cast(_systemObjArrayKlassObj)->element_klass() == ok, "u1");
@ -320,8 +320,8 @@ void Universe::genesis(TRAPS) {
assert(Klass::cast(systemObjArrayKlassObj())->super() == ok, "u3"); assert(Klass::cast(systemObjArrayKlassObj())->super() == ok, "u3");
} else { } else {
// Set up shared interfaces array. (Do this before supers are set up.) // 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(0, SystemDictionary::Cloneable_klass());
_the_array_interfaces_array->obj_at_put(1, SystemDictionary::serializable_klass()); _the_array_interfaces_array->obj_at_put(1, SystemDictionary::Serializable_klass());
// Set element klass for system obj array klass // Set element klass for system obj array klass
objArrayKlass::cast(_systemObjArrayKlassObj)->set_element_klass(ok); objArrayKlass::cast(_systemObjArrayKlassObj)->set_element_klass(ok);
@ -365,7 +365,7 @@ void Universe::genesis(TRAPS) {
// Initialize _objectArrayKlass after core bootstraping to make // Initialize _objectArrayKlass after core bootstraping to make
// sure the super class is set up properly for _objectArrayKlass. // sure the super class is set up properly for _objectArrayKlass.
_objectArrayKlassObj = instanceKlass:: _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 // Add the class to the class hierarchy manually to make sure that
// its vtable is initialized after core bootstrapping is completed. // its vtable is initialized after core bootstrapping is completed.
Klass::cast(_objectArrayKlassObj)->append_to_sibling_list(); Klass::cast(_objectArrayKlassObj)->append_to_sibling_list();
@ -426,11 +426,11 @@ void Universe::genesis(TRAPS) {
while (i < size) { while (i < size) {
if (!UseConcMarkSweepGC) { if (!UseConcMarkSweepGC) {
// Allocate dummy in old generation // 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); dummy_array->obj_at_put(i++, dummy);
} }
// Allocate dummy in permanent generation // 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); 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 // 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 // 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. // 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; FixupMirrorClosure blk;
Universe::heap()->permanent_object_iterate(&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"); if (TraceReferenceGC) tty->print_cr("Callback to run finalizers on exit");
{ {
PRESERVE_EXCEPTION_MARK; PRESERVE_EXCEPTION_MARK;
KlassHandle finalizer_klass(THREAD, SystemDictionary::finalizer_klass()); KlassHandle finalizer_klass(THREAD, SystemDictionary::Finalizer_klass());
JavaValue result(T_VOID); JavaValue result(T_VOID);
JavaCalls::call_static( JavaCalls::call_static(
&result, &result,
@ -950,7 +950,7 @@ bool universe_post_init() {
{ ResourceMark rm; { ResourceMark rm;
Interpreter::initialize(); // needed for interpreter entry points Interpreter::initialize(); // needed for interpreter entry points
if (!UseSharedSpaces) { 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_vtable_of(ok_h, CHECK_false);
Universe::reinitialize_itables(CHECK_false); Universe::reinitialize_itables(CHECK_false);
} }
@ -960,7 +960,7 @@ bool universe_post_init() {
instanceKlassHandle k_h; instanceKlassHandle k_h;
if (!UseSharedSpaces) { if (!UseSharedSpaces) {
// Setup preallocated empty java.lang.Class array // 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 // Setup preallocated OutOfMemoryError errors
k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_OutOfMemoryError(), true, CHECK_false); k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_OutOfMemoryError(), true, CHECK_false);
k_h = instanceKlassHandle(THREAD, k); k_h = instanceKlassHandle(THREAD, k);
@ -1027,8 +1027,8 @@ bool universe_post_init() {
// Setup static method for registering finalizers // Setup static method for registering finalizers
// The finalizer klass must be linked before looking up the method, in // The finalizer klass must be linked before looking up the method, in
// case it needs to get rewritten. // case it needs to get rewritten.
instanceKlass::cast(SystemDictionary::finalizer_klass())->link_class(CHECK_false); instanceKlass::cast(SystemDictionary::Finalizer_klass())->link_class(CHECK_false);
methodOop m = instanceKlass::cast(SystemDictionary::finalizer_klass())->find_method( methodOop m = instanceKlass::cast(SystemDictionary::Finalizer_klass())->find_method(
vmSymbols::register_method_name(), vmSymbols::register_method_name(),
vmSymbols::register_method_signature()); vmSymbols::register_method_signature());
if (m == NULL || !m->is_static()) { if (m == NULL || !m->is_static()) {
@ -1036,7 +1036,7 @@ bool universe_post_init() {
"java.lang.ref.Finalizer.register", false); "java.lang.ref.Finalizer.register", false);
} }
Universe::_finalizer_register_cache->init( Universe::_finalizer_register_cache->init(
SystemDictionary::finalizer_klass(), m, CHECK_false); SystemDictionary::Finalizer_klass(), m, CHECK_false);
// Resolve on first use and initialize class. // Resolve on first use and initialize class.
// Note: No race-condition here, since a resolve will always return the same result // 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); Universe::_reflect_invoke_cache->init(k_h(), m, CHECK_false);
// Setup method for registering loaded classes in class loader vector // Setup method for registering loaded classes in class loader vector
instanceKlass::cast(SystemDictionary::classloader_klass())->link_class(CHECK_false); instanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false);
m = instanceKlass::cast(SystemDictionary::classloader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature()); m = instanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature());
if (m == NULL || m->is_static()) { if (m == NULL || m->is_static()) {
THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(), THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(),
"java.lang.ClassLoader.addClass", false); "java.lang.ClassLoader.addClass", false);
} }
Universe::_loader_addClass_cache->init( 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 // The folowing is initializing converter functions for serialization in
// JVM.cpp. If we clean up the StrictMath code above we may want to find // JVM.cpp. If we clean up the StrictMath code above we may want to find

View File

@ -43,7 +43,7 @@ klassOop arrayKlass::java_super() const {
if (super() == NULL) return NULL; // bootstrap case if (super() == NULL) return NULL; // bootstrap case
// Array klasses have primary supertypes which are not reported to Java. // Array klasses have primary supertypes which are not reported to Java.
// Example super chain: String[][] -> Object[][] -> Object[] -> Object // 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()); k = arrayKlassHandle(THREAD, base_klass());
assert(!k()->is_parsable(), "not expecting parsability yet."); 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_layout_helper(Klass::_lh_neutral_value);
k->set_dimension(1); k->set_dimension(1);
k->set_higher_dimension(NULL); 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) { bool arrayKlass::compute_is_subtype_of(klassOop k) {
// An array is a subtype of Serializable, Clonable, and Object // An array is a subtype of Serializable, Clonable, and Object
return k == SystemDictionary::object_klass() return k == SystemDictionary::Object_klass()
|| k == SystemDictionary::cloneable_klass() || k == SystemDictionary::Cloneable_klass()
|| k == SystemDictionary::serializable_klass(); || k == SystemDictionary::Serializable_klass();
} }

View File

@ -67,7 +67,7 @@ class arrayKlass: public Klass {
// Compiler/Interpreter offset // Compiler/Interpreter offset
static ByteSize component_mirror_offset() { return byte_offset_of(arrayKlass, _component_mirror); } 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 // Allocation
// Sizes points to the first dimension of the array, subsequent dimensions // Sizes points to the first dimension of the array, subsequent dimensions

View File

@ -258,6 +258,11 @@ public:
LocalVariableTableElement* localvariable_table_start() const; LocalVariableTableElement* localvariable_table_start() const;
// byte codes // 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_base() const { return (address) (this+1); }
address code_end() const { return code_base() + code_size(); } address code_end() const { return code_base() + code_size(); }
bool contains(address bcp) const { return code_base() <= bcp bool contains(address bcp) const { return code_base() <= bcp

View File

@ -110,7 +110,7 @@ klassOop constantPoolOopDesc::klass_at_impl(constantPoolHandle this_oop, int whi
} }
if (!PENDING_EXCEPTION-> if (!PENDING_EXCEPTION->
is_a(SystemDictionary::linkageError_klass())) { is_a(SystemDictionary::LinkageError_klass())) {
// Just throw the exception and don't prevent these classes from // Just throw the exception and don't prevent these classes from
// being loaded due to virtual machine errors like StackOverflow // being loaded due to virtual machine errors like StackOverflow
// and OutOfMemoryError, etc, or if the thread was hit by stop() // and OutOfMemoryError, etc, or if the thread was hit by stop()

View File

@ -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 // For temporary use while constructing constant pool
void string_index_at_put(int which, int string_index) { void string_index_at_put(int which, int string_index) {
tag_at_put(which, JVM_CONSTANT_StringIndex); tag_at_put(which, JVM_CONSTANT_StringIndex);
@ -228,7 +238,8 @@ class constantPoolOopDesc : public oopDesc {
tag.is_unresolved_klass() || tag.is_unresolved_klass() ||
tag.is_symbol() || tag.is_symbol() ||
tag.is_unresolved_string() || tag.is_unresolved_string() ||
tag.is_string(); tag.is_string() ||
tag.is_object();
} }
// Fetching constants // Fetching constants
@ -291,6 +302,11 @@ class constantPoolOopDesc : public oopDesc {
return string_at_impl(h_this, which, CHECK_NULL); 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 "pseudo-string" is an non-string oop that has found is way into
// a String entry. // a String entry.
// Under AnonymousClasses this can happen if the user patches a live // Under AnonymousClasses this can happen if the user patches a live

View File

@ -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::_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::_putfield: do_field(false, false, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_invokevirtual: case Bytecodes::_invokevirtual:
case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break; 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::_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::_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::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_newarray: case Bytecodes::_newarray:
case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break;
case Bytecodes::_checkcast: do_checkcast(); break; case Bytecodes::_checkcast: do_checkcast(); break;
case Bytecodes::_arraylength: case Bytecodes::_arraylength:
case Bytecodes::_instanceof: pp(rCTS, vCTS); break; 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) { void GenerateOopMap::do_ldc(int idx, int bci) {
constantPoolOop cp = method()->constants(); constantPoolOop cp = method()->constants();
constantTag tag = cp->tag_at(idx); CellTypeState cts = cp->is_pointer_entry(idx) ? CellTypeState::make_line_ref(bci) : valCTS;
CellTypeState cts = (tag.is_string() || tag.is_unresolved_string() ||
tag.is_klass() || tag.is_unresolved_klass())
? CellTypeState::make_line_ref(bci) : valCTS;
ppush1(cts); ppush1(cts);
} }

View File

@ -383,7 +383,7 @@ void instanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
this_oop->set_initialization_state_and_notify(initialization_error, THREAD); this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below 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()); THROW_OOP(e());
} else { } else {
JavaCallArguments args(e); JavaCallArguments args(e);
@ -568,7 +568,7 @@ void instanceKlass::check_valid_for_instantiation(bool throwError, TRAPS) {
THROW_MSG(throwError ? vmSymbols::java_lang_InstantiationError() THROW_MSG(throwError ? vmSymbols::java_lang_InstantiationError()
: vmSymbols::java_lang_InstantiationException(), external_name()); : vmSymbols::java_lang_InstantiationException(), external_name());
} }
if (as_klassOop() == SystemDictionary::class_klass()) { if (as_klassOop() == SystemDictionary::Class_klass()) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
THROW_MSG(throwError ? vmSymbols::java_lang_IllegalAccessError() THROW_MSG(throwError ? vmSymbols::java_lang_IllegalAccessError()
: vmSymbols::java_lang_IllegalAccessException(), external_name()); : 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) { void instanceKlass::oop_print_on(oop obj, outputStream* st) {
Klass::oop_print_on(obj, 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); typeArrayOop value = java_lang_String::value(obj);
juint offset = java_lang_String::offset(obj); juint offset = java_lang_String::offset(obj);
juint length = java_lang_String::length(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); FieldPrinter print_nonstatic_field(st, obj);
do_nonstatic_fields(&print_nonstatic_field); do_nonstatic_fields(&print_nonstatic_field);
if (as_klassOop() == SystemDictionary::class_klass()) { if (as_klassOop() == SystemDictionary::Class_klass()) {
st->print(BULLET"signature: "); st->print(BULLET"signature: ");
java_lang_Class::print_signature(obj, st); java_lang_Class::print_signature(obj, st);
st->cr(); st->cr();
@ -2272,7 +2272,7 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) {
st->print("a "); st->print("a ");
name()->print_value_on(st); name()->print_value_on(st);
obj->print_address_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) { && java_lang_String::value(obj) != NULL) {
ResourceMark rm; ResourceMark rm;
int len = java_lang_String::length(obj); 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); st->print(" = \"%s\"", str);
if (len > plen) if (len > plen)
st->print("...[%d]", len); 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); klassOop k = java_lang_Class::as_klassOop(obj);
st->print(" = "); st->print(" = ");
if (k != NULL) { if (k != NULL) {
@ -2348,7 +2348,7 @@ void instanceKlass::verify_class_klass_nonstatic_oop_maps(klassOop k) {
// Check that we have the right class // Check that we have the right class
static bool first_time = true; 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; first_time = false;
const int extra = java_lang_Class::number_of_fake_oop_fields; const int extra = java_lang_Class::number_of_fake_oop_fields;
guarantee(ik->nonstatic_field_size() == extra, "just checking"); guarantee(ik->nonstatic_field_size() == extra, "just checking");

View File

@ -397,7 +397,7 @@ void instanceRefKlass::update_nonstatic_oop_maps(klassOop k) {
// Check that we have the right class // Check that we have the right class
debug_only(static bool first_time = true); 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"); "Invalid update of maps");
debug_only(first_time = false); debug_only(first_time = false);
assert(ik->nonstatic_oop_map_count() == 1, "just checking"); assert(ik->nonstatic_oop_map_count() == 1, "just checking");

View File

@ -217,8 +217,8 @@ void Klass::initialize_supers(klassOop k, TRAPS) {
set_super(NULL); set_super(NULL);
oop_store_without_check((oop*) &_primary_supers[0], (oop) this->as_klassOop()); oop_store_without_check((oop*) &_primary_supers[0], (oop) this->as_klassOop());
assert(super_depth() == 0, "Object must already be initialized properly"); assert(super_depth() == 0, "Object must already be initialized properly");
} else if (k != super() || k == SystemDictionary::object_klass()) { } else if (k != super() || k == SystemDictionary::Object_klass()) {
assert(super() == NULL || super() == SystemDictionary::object_klass(), assert(super() == NULL || super() == SystemDictionary::Object_klass(),
"initialize this only once to a non-trivial value"); "initialize this only once to a non-trivial value");
set_super(k); set_super(k);
Klass* sup = k->klass_part(); Klass* sup = k->klass_part();
@ -370,7 +370,7 @@ void Klass::append_to_sibling_list() {
void Klass::remove_from_sibling_list() { void Klass::remove_from_sibling_list() {
// remove receiver from sibling list // remove receiver from sibling list
instanceKlass* super = superklass(); 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 == NULL) return; // special case: class Object
if (super->subklass() == this) { if (super->subklass() == this) {
// first subklass // first subklass

View File

@ -456,12 +456,12 @@ objArrayHandle methodOopDesc::resolved_checked_exceptions_impl(methodOop this_oo
return objArrayHandle(THREAD, Universe::the_empty_class_klass_array()); return objArrayHandle(THREAD, Universe::the_empty_class_klass_array());
} else { } else {
methodHandle h_this(THREAD, this_oop); 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); objArrayHandle mirrors (THREAD, m_oop);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
CheckedExceptionElement* table = h_this->checked_exceptions_start(); // recompute on each iteration, not gc safe 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())); 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()); mirrors->obj_at_put(i, Klass::cast(k)->java_mirror());
} }
return mirrors; return mirrors;
@ -1032,8 +1032,8 @@ bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) {
// We are loading classes eagerly. If a ClassNotFoundException or // We are loading classes eagerly. If a ClassNotFoundException or
// a LinkageError was generated, be sure to ignore it. // a LinkageError was generated, be sure to ignore it.
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
if (PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass()) || if (PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass()) ||
PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) { PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
CLEAR_PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION;
} else { } else {
return false; return false;

View File

@ -365,6 +365,7 @@ class methodOopDesc : public oopDesc {
#endif #endif
// byte codes // byte codes
void set_code(address code) { return constMethod()->set_code(code); }
address code_base() const { return constMethod()->code_base(); } address code_base() const { return constMethod()->code_base(); }
bool contains(address bcp) const { return constMethod()->contains(bcp); } bool contains(address bcp) const { return constMethod()->contains(bcp); }

View File

@ -246,8 +246,8 @@ objArrayOop objArrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS)
} else { } else {
objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL); objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL);
objArrayHandle secondaries(THREAD, sec_oop); objArrayHandle secondaries(THREAD, sec_oop);
secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::cloneable_klass()); 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+1, SystemDictionary::Serializable_klass());
for (int i = 0; i < num_elem_supers; i++) { for (int i = 0; i < num_elem_supers; i++) {
klassOop elem_super = (klassOop) elem_supers->obj_at(i); klassOop elem_super = (klassOop) elem_supers->obj_at(i);
klassOop array_super = elem_super->klass_part()->array_klass_or_null(); klassOop array_super = elem_super->klass_part()->array_klass_or_null();

View File

@ -99,7 +99,7 @@ klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHand
} }
} else { } else {
// The element type is already Object. Object[] has direct super of Object. // 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());
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,11 @@
# include "incls/_precompiled.incl" # include "incls/_precompiled.incl"
# include "incls/_symbolOop.cpp.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 { bool symbolOopDesc::equals(const char* str, int len) const {
int l = utf8_length(); int l = utf8_length();
if (l != len) return false; if (l != len) return false;
@ -36,6 +41,48 @@ bool symbolOopDesc::equals(const char* str, int len) const {
return true; 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 { char* symbolOopDesc::as_C_string(char* buf, int size) const {
if (size > 0) { if (size > 0) {
int len = MIN2(size - 1, utf8_length()); int len = MIN2(size - 1, utf8_length());

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -70,8 +70,21 @@ class symbolOopDesc : public oopDesc {
void set_utf8_length(int len) { _length = len; } 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, 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 // Three-way compare for sorting; returns -1/0/1 if receiver is </==/> than arg
// note that the ordering is not alfabetical // note that the ordering is not alfabetical

View File

@ -180,6 +180,10 @@ const char* InlineTree::shouldNotInline(ciMethod *callee_method, ciMethod* calle
return NULL; 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 // First check all inlining restrictions which are required for correctness
if (callee_method->is_abstract()) return "abstract method"; if (callee_method->is_abstract()) return "abstract method";
// note: we allow ik->is_abstract() // 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() // stricter than callee_holder->is_initialized()
ciBytecodeStream iter(caller_method); ciBytecodeStream iter(caller_method);
iter.force_bci(caller_bci); 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(); Bytecodes::Code call_bc = iter.cur_bc();
if( !caller_method->check_call(index, call_bc == Bytecodes::_invokestatic) ) { // An invokedynamic instruction does not have a klass.
return false; 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 // We will attempt to see if a class/field/etc got properly loaded. If it

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -136,6 +136,8 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) {
} }
// Mark the call node as virtual, sort of: // Mark the call node as virtual, sort of:
call->set_optimized_virtual(true); 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_arguments_for_java_call(call);
kit.set_edges_for_java_call(call, false, _separate_io_proj); 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(); 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 { class VirtualCallGenerator : public CallGenerator {
private: private:
int _vtable_index; int _vtable_index;
@ -159,8 +226,6 @@ public:
virtual JVMState* generate(JVMState* jvms); virtual JVMState* generate(JVMState* jvms);
}; };
//--------------------------VirtualCallGenerator------------------------------
// Internal class which handles all out-of-line calls checking receiver type.
JVMState* VirtualCallGenerator::generate(JVMState* jvms) { JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms); GraphKit kit(jvms);
Node* receiver = kit.argument(0); 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); 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) { CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
assert(!m->is_static(), "for_virtual_call mismatch"); 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); 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----------------------------- //-------------------------UncommonTrapCallGenerator-----------------------------
// Internal class which handles all out-of-line calls checking receiver type. // Internal class which handles all out-of-line calls checking receiver type.
class UncommonTrapCallGenerator : public CallGenerator { class UncommonTrapCallGenerator : public CallGenerator {

View File

@ -100,6 +100,7 @@ class CallGenerator : public ResourceObj {
// How to generate vanilla out-of-line call sites: // 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_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 static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface
// How to generate a replace a direct call with an inline version // How to generate a replace a direct call with an inline version
@ -116,6 +117,12 @@ class CallGenerator : public ResourceObj {
CallGenerator* if_hit, CallGenerator* if_hit,
float hit_prob); 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: // How to make a call that gives up and goes back to the interpreter:
static CallGenerator* for_uncommon_trap(ciMethod* m, static CallGenerator* for_uncommon_trap(ciMethod* m,
Deoptimization::DeoptReason reason, Deoptimization::DeoptReason reason,

View File

@ -562,12 +562,15 @@ protected:
virtual uint size_of() const; // Size is bigger virtual uint size_of() const; // Size is bigger
bool _optimized_virtual; bool _optimized_virtual;
bool _method_handle_invoke;
ciMethod* _method; // Method being direct called ciMethod* _method; // Method being direct called
public: public:
const int _bci; // Byte Code Index of call byte code const int _bci; // Byte Code Index of call byte code
CallJavaNode(const TypeFunc* tf , address addr, ciMethod* method, int bci) CallJavaNode(const TypeFunc* tf , address addr, ciMethod* method, int bci)
: CallNode(tf, addr, TypePtr::BOTTOM), : 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); init_class_id(Class_CallJava);
} }
@ -577,6 +580,8 @@ public:
void set_method(ciMethod *m) { _method = m; } void set_method(ciMethod *m) { _method = m; }
void set_optimized_virtual(bool f) { _optimized_virtual = f; } void set_optimized_virtual(bool f) { _optimized_virtual = f; }
bool is_optimized_virtual() const { return _optimized_virtual; } 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 #ifndef PRODUCT
virtual void dump_spec(outputStream *st) const; virtual void dump_spec(outputStream *st) const;

View File

@ -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. // There was no special inlining tactic, or it bailed out.
// Use a more generic tactic, like a simple call. // Use a more generic tactic, like a simple call.
if (call_is_virtual) { 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 // Interface classes can be loaded & linked and never get around to
// being initialized. Uncommon-trap for not-initialized static or // being initialized. Uncommon-trap for not-initialized static or
// v-calls. Let interface calls happen. // v-calls. Let interface calls happen.
ciInstanceKlass* holder_klass = dest_method->holder(); ciInstanceKlass* holder_klass = dest_method->holder();
if (!holder_klass->is_initialized() && if (!holder_klass->is_initialized() &&
!holder_klass->is_interface()) { !holder_klass->is_interface()) {
uncommon_trap(Deoptimization::Reason_uninitialized, uncommon_trap(Deoptimization::Reason_uninitialized,
@ -307,14 +358,6 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl
holder_klass); holder_klass);
return true; 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"); assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility");
return false; return false;
@ -333,6 +376,7 @@ void Parse::do_call() {
bool is_virtual = bc() == Bytecodes::_invokevirtual; bool is_virtual = bc() == Bytecodes::_invokevirtual;
bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface;
bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial; bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial;
bool is_invokedynamic = bc() == Bytecodes::_invokedynamic;
// Find target being called // Find target being called
bool will_link; bool will_link;
@ -341,7 +385,8 @@ void Parse::do_call() {
ciKlass* holder = iter().get_declared_method_holder(); ciKlass* holder = iter().get_declared_method_holder();
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(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 // uncommon-trap when callee is unloaded, uninitialized or will not link
// bailout when too many arguments for register representation // bailout when too many arguments for register representation
@ -355,7 +400,7 @@ void Parse::do_call() {
return; return;
} }
assert(holder_klass->is_loaded(), ""); 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, // 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 // 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"); assert(holder_klass->is_interface() || holder_klass->super() == NULL || (bc() != Bytecodes::_invokeinterface), "must match bc");

View File

@ -1916,7 +1916,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
Node *arg = call->in(i)->uncast(); Node *arg = call->in(i)->uncast();
if (at->isa_oopptr() != NULL && 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 global_escapes = false;
bool fields_escapes = false; bool fields_escapes = false;

View File

@ -981,14 +981,19 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth) {
case Bytecodes::_invokedynamic: case Bytecodes::_invokedynamic:
case Bytecodes::_invokeinterface: case Bytecodes::_invokeinterface:
{ {
bool is_static = (depth == 0);
bool ignore; bool ignore;
ciBytecodeStream iter(method()); ciBytecodeStream iter(method());
iter.reset_to_bci(bci()); iter.reset_to_bci(bci());
iter.next(); iter.next();
ciMethod* method = iter.get_method(ignore); ciMethod* method = iter.get_method(ignore);
inputs = method->arg_size_no_receiver(); 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(); int size = method->return_type()->size();
depth = size - inputs; depth = size - inputs;
} }

Some files were not shown because too many files have changed in this diff Show More