# HG changeset patch # User iveresov # Date 1262845299 28800 # Node ID 9b9c1ee9b3f6e835a4ce9fb7063a8a3cbb9acae2 # Parent a5a6adfca6ecefb5894a848debabfe442ff50e25# Parent aad340e07bc41c7b02440b8451c96cf726ca3864 Merge diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java --- a/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Wed Dec 23 03:12:16 2009 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Wed Jan 06 22:21:39 2010 -0800 @@ -63,12 +63,12 @@ javaSystemLoaderField = type.getOopField("_java_system_loader"); nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue(); - objectKlassField = type.getOopField(WK_KLASS("object_klass")); - classLoaderKlassField = type.getOopField(WK_KLASS("classloader_klass")); - stringKlassField = type.getOopField(WK_KLASS("string_klass")); - systemKlassField = type.getOopField(WK_KLASS("system_klass")); - threadKlassField = type.getOopField(WK_KLASS("thread_klass")); - threadGroupKlassField = type.getOopField(WK_KLASS("threadGroup_klass")); + objectKlassField = type.getOopField(WK_KLASS("Object_klass")); + classLoaderKlassField = type.getOopField(WK_KLASS("ClassLoader_klass")); + stringKlassField = type.getOopField(WK_KLASS("String_klass")); + systemKlassField = type.getOopField(WK_KLASS("System_klass")); + threadKlassField = type.getOopField(WK_KLASS("Thread_klass")); + threadGroupKlassField = type.getOopField(WK_KLASS("ThreadGroup_klass")); } // This WK functions must follow the definitions in systemDictionary.hpp: diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/sparc/vm/sparc.ad Wed Jan 06 22:21:39 2010 -0800 @@ -1885,6 +1885,10 @@ return RegMask(); } +const RegMask Matcher::method_handle_invoke_SP_save_mask() { + return RegMask(); +} + %} diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/x86/vm/frame_x86.cpp --- a/src/cpu/x86/vm/frame_x86.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/x86/vm/frame_x86.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -330,6 +330,14 @@ // This is the sp before any possible extension (adapter/locals). intptr_t* unextended_sp = interpreter_frame_sender_sp(); + address sender_pc = this->sender_pc(); + CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc); + assert(sender_cb, "sanity"); + nmethod* sender_nm = sender_cb->as_nmethod_or_null(); + if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) { + unextended_sp = (intptr_t*) at(link_offset); + } + // The interpreter and compiler(s) always save EBP/RBP in a known // location on entry. We must record where that location is // so this if EBP/RBP was live on callout from c2 we can find @@ -352,7 +360,7 @@ #endif // AMD64 } #endif /* COMPILER2 */ - return frame(sp, unextended_sp, link(), sender_pc()); + return frame(sp, unextended_sp, link(), sender_pc); } @@ -375,6 +383,18 @@ intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); + intptr_t* unextended_sp = sender_sp; + // If we are returning to a compiled method handle call site, + // the saved_fp will in fact be a saved value of the unextended SP. + // The simplest way to tell whether we are returning to such a call + // site is as follows: + CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc); + assert(sender_cb, "sanity"); + nmethod* sender_nm = sender_cb->as_nmethod_or_null(); + if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) { + unextended_sp = saved_fp; + } + if (map->update_map()) { // Tell GC to use argument oopmaps for some runtime stubs that need it. // For C1, the runtime stub might not have oop maps, so set this flag @@ -399,7 +419,7 @@ } 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 { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/x86/vm/frame_x86.inline.hpp --- a/src/cpu/x86/vm/frame_x86.inline.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/x86/vm/frame_x86.inline.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -225,11 +225,12 @@ // top of expression stack inline intptr_t* frame::interpreter_frame_tos_address() const { intptr_t* last_sp = interpreter_frame_last_sp(); - if (last_sp == NULL ) { + if (last_sp == NULL) { return sp(); } else { - // sp() may have been extended by an adapter - assert(last_sp < fp() && last_sp >= sp(), "bad tos"); + // sp() may have been extended or shrunk by an adapter. At least + // check that we don't fall behind the legal region. + assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(), "bad tos"); return last_sp; } } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/x86/vm/methodHandles_x86.cpp --- a/src/cpu/x86/vm/methodHandles_x86.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -65,9 +65,9 @@ // Verify that argslot lies within (rsp, rbp]. Label L_ok, L_bad; __ cmpptr(rax_argslot, rbp); - __ jcc(Assembler::above, L_bad); + __ jccb(Assembler::above, L_bad); __ cmpptr(rsp, rax_argslot); - __ jcc(Assembler::below, L_ok); + __ jccb(Assembler::below, L_ok); __ bind(L_bad); __ stop(error_message); __ bind(L_ok); @@ -136,9 +136,9 @@ if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); - __ jcc(Assembler::greater, L_bad); + __ jccb(Assembler::greater, L_bad); __ testl(arg_slots.as_register(), -stack_move_unit() - 1); - __ jcc(Assembler::zero, L_ok); + __ jccb(Assembler::zero, L_ok); __ bind(L_bad); __ stop("assert arg_slots <= 0 and clear low bits"); __ bind(L_ok); @@ -173,7 +173,7 @@ __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); __ addptr(rdx_temp, wordSize); __ cmpptr(rdx_temp, rax_argslot); - __ jcc(Assembler::less, loop); + __ jccb(Assembler::less, loop); } // Now move the argslot down, to point to the opened-up space. @@ -211,9 +211,9 @@ Label L_ok, L_bad; __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); __ cmpptr(rbx_temp, rbp); - __ jcc(Assembler::above, L_bad); + __ jccb(Assembler::above, L_bad); __ cmpptr(rsp, rax_argslot); - __ jcc(Assembler::below, L_ok); + __ jccb(Assembler::below, L_ok); __ bind(L_bad); __ stop("deleted argument(s) must fall within current frame"); __ bind(L_ok); @@ -221,9 +221,9 @@ if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); - __ jcc(Assembler::less, L_bad); + __ jccb(Assembler::less, L_bad); __ testl(arg_slots.as_register(), -stack_move_unit() - 1); - __ jcc(Assembler::zero, L_ok); + __ jccb(Assembler::zero, L_ok); __ bind(L_bad); __ stop("assert arg_slots >= 0 and clear low bits"); __ bind(L_ok); @@ -258,7 +258,7 @@ __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); __ addptr(rdx_temp, -wordSize); __ cmpptr(rdx_temp, rsp); - __ jcc(Assembler::greaterEqual, loop); + __ jccb(Assembler::greaterEqual, loop); } // Now move the argslot up, to point to the just-copied block. @@ -268,8 +268,9 @@ } #ifndef PRODUCT +extern "C" void print_method_handle(oop mh); void trace_method_handle_stub(const char* adaptername, - oopDesc* mh, + oop mh, intptr_t* entry_sp, intptr_t* saved_sp, intptr_t* saved_bp) { @@ -280,6 +281,7 @@ adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp); if (last_sp != saved_sp) printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp); + if (Verbose) print_method_handle(mh); } #endif //PRODUCT @@ -382,11 +384,11 @@ // FIXME: fill in _raise_exception_method with a suitable sun.dyn method __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); __ testptr(rbx_method, rbx_method); - __ jcc(Assembler::zero, no_method); + __ jccb(Assembler::zero, no_method); int jobject_oop_offset = 0; __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject __ testptr(rbx_method, rbx_method); - __ jcc(Assembler::zero, no_method); + __ jccb(Assembler::zero, no_method); __ verify_oop(rbx_method); __ push(rdi_pc); // and restore caller PC __ jmp(rbx_method_fie); @@ -533,16 +535,15 @@ if (arg_type == T_OBJECT) { __ movptr(Address(rax_argslot, 0), rbx_temp); } else { - __ load_sized_value(rbx_temp, prim_value_addr, + __ load_sized_value(rdx_temp, prim_value_addr, type2aelembytes(arg_type), is_signed_subword_type(arg_type)); - __ movptr(Address(rax_argslot, 0), rbx_temp); + __ movptr(Address(rax_argslot, 0), rdx_temp); #ifndef _LP64 if (arg_slots == 2) { - __ movl(rbx_temp, prim_value_addr.plus_disp(wordSize)); - __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp); + __ movl(rdx_temp, prim_value_addr.plus_disp(wordSize)); + __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rdx_temp); } #endif //_LP64 - break; } if (direct_to_method) { @@ -584,7 +585,7 @@ Label done; __ movptr(rdx_temp, vmarg); __ testl(rdx_temp, rdx_temp); - __ jcc(Assembler::zero, done); // no cast if null + __ jccb(Assembler::zero, done); // no cast if null __ load_klass(rdx_temp, rdx_temp); // live at this point: @@ -675,24 +676,24 @@ // (now we are done with the old MH) // original 32-bit vmdata word must be of this form: - // | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | - __ xchgl(rcx, rbx_vminfo); // free rcx for shifts + // | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | + __ xchgptr(rcx, rbx_vminfo); // free rcx for shifts __ shll(rdx_temp /*, rcx*/); Label zero_extend, done; __ testl(rcx, CONV_VMINFO_SIGN_FLAG); - __ jcc(Assembler::zero, zero_extend); + __ jccb(Assembler::zero, zero_extend); // this path is taken for int->byte, int->short __ sarl(rdx_temp /*, rcx*/); - __ jmp(done); + __ jmpb(done); __ bind(zero_extend); // this is taken for int->char __ shrl(rdx_temp /*, rcx*/); __ bind(done); - __ movptr(vmarg, rdx_temp); - __ xchgl(rcx, rbx_vminfo); // restore rcx_recv + __ movl(vmarg, rdx_temp); + __ xchgptr(rcx, rbx_vminfo); // restore rcx_recv __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } @@ -861,7 +862,7 @@ // Verify that argslot > destslot, by at least swap_bytes. Label L_ok; __ cmpptr(rax_argslot, rbx_destslot); - __ jcc(Assembler::aboveEqual, L_ok); + __ jccb(Assembler::aboveEqual, L_ok); __ stop("source must be above destination (upward rotation)"); __ bind(L_ok); } @@ -877,7 +878,7 @@ __ movptr(Address(rax_argslot, swap_bytes), rdx_temp); __ addptr(rax_argslot, -wordSize); __ cmpptr(rax_argslot, rbx_destslot); - __ jcc(Assembler::aboveEqual, loop); + __ jccb(Assembler::aboveEqual, loop); } else { __ addptr(rax_argslot, swap_bytes); #ifdef ASSERT @@ -885,7 +886,7 @@ // Verify that argslot < destslot, by at least swap_bytes. Label L_ok; __ cmpptr(rax_argslot, rbx_destslot); - __ jcc(Assembler::belowEqual, L_ok); + __ jccb(Assembler::belowEqual, L_ok); __ stop("source must be below destination (downward rotation)"); __ bind(L_ok); } @@ -901,7 +902,7 @@ __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp); __ addptr(rax_argslot, wordSize); __ cmpptr(rax_argslot, rbx_destslot); - __ jcc(Assembler::belowEqual, loop); + __ jccb(Assembler::belowEqual, loop); } // pop the original first chunk into the destination slot, now free @@ -967,7 +968,7 @@ __ addptr(rax_argslot, wordSize); __ addptr(rdx_newarg, wordSize); __ cmpptr(rdx_newarg, rbx_oldarg); - __ jcc(Assembler::less, loop); + __ jccb(Assembler::less, loop); __ pop(rdi); // restore temp @@ -1119,7 +1120,7 @@ } __ addptr(rax_argslot, Interpreter::stackElementSize()); __ cmpptr(rax_argslot, rdx_argslot_limit); - __ jcc(Assembler::less, loop); + __ jccb(Assembler::less, loop); } else if (length_constant == 0) { __ bind(skip_array_check); // nothing to copy diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/x86/vm/runtime_x86_32.cpp --- a/src/cpu/x86/vm/runtime_x86_32.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/x86/vm/runtime_x86_32.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -43,11 +43,11 @@ // This code is entered with a jmp. // // Arguments: -// rax,: exception oop +// rax: exception oop // rdx: exception pc // // Results: -// rax,: exception oop +// rax: exception oop // rdx: exception pc in caller or ??? // destination: exception handler of caller // @@ -113,17 +113,17 @@ __ addptr(rsp, return_off * wordSize); // Epilog! __ pop(rdx); // Exception pc + // rax: exception handler for given - // rax,: exception handler for given + // Restore SP from BP if the exception PC is a MethodHandle call. + __ cmpl(Address(rcx, JavaThread::is_method_handle_exception_offset()), 0); + __ cmovptr(Assembler::notEqual, rsp, rbp); // We have a handler in rax, (could be deopt blob) // rdx - throwing pc, deopt blob will need it. __ push(rax); - // rcx contains handler address - - __ get_thread(rcx); // TLS // Get the exception __ movptr(rax, Address(rcx, JavaThread::exception_oop_offset())); // Get the exception pc in case we are deoptimized @@ -137,7 +137,7 @@ __ pop(rcx); - // rax,: exception oop + // rax: exception oop // rcx: exception handler // rdx: exception pc __ jmp (rcx); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -638,6 +638,10 @@ __ movptr(rax, Address(rsp, 0)); + // Must preserve original SP for loading incoming arguments because + // we need to align the outgoing SP for compiled code. + __ movptr(r11, rsp); + // Cut-out for having no stack args. Since up to 2 int/oop args are passed // in registers, we will occasionally have no stack args. int comp_words_on_stack = 0; @@ -661,6 +665,10 @@ // as far as the placement of the call instruction __ push(rax); + // Put saved SP in another register + const Register saved_sp = rax; + __ movptr(saved_sp, r11); + // Will jump to the compiled code just as if compiled code was doing it. // Pre-load the register-jump target early, to schedule it better. __ movptr(r11, Address(rbx, in_bytes(methodOopDesc::from_compiled_offset()))); @@ -680,11 +688,7 @@ assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(), "scrambled load targets?"); // Load in argument order going down. - // int ld_off = (total_args_passed + comp_words_on_stack -i)*wordSize; - // base ld_off on r13 (sender_sp) as the stack alignment makes offsets from rsp - // unpredictable - int ld_off = ((total_args_passed - 1) - i)*Interpreter::stackElementSize(); - + int ld_off = (total_args_passed - i)*Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); // Point to interpreter value (vs. tag) int next_off = ld_off - Interpreter::stackElementSize(); // @@ -699,10 +703,14 @@ if (r_1->is_stack()) { // Convert stack slot to an SP offset (+ wordSize to account for return address ) int st_off = regs[i].first()->reg2stack()*VMRegImpl::stack_slot_size + wordSize; + + // We can use r13 as a temp here because compiled code doesn't need r13 as an input + // and if we end up going thru a c2i because of a miss a reasonable value of r13 + // will be generated. if (!r_2->is_valid()) { // sign extend??? - __ movl(rax, Address(r13, ld_off)); - __ movptr(Address(rsp, st_off), rax); + __ movl(r13, Address(saved_sp, ld_off)); + __ movptr(Address(rsp, st_off), r13); } else { // // We are using two optoregs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE @@ -715,9 +723,9 @@ // ld_off is MSW so get LSW const int offset = (sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)? next_off : ld_off; - __ movq(rax, Address(r13, offset)); + __ movq(r13, Address(saved_sp, offset)); // st_off is LSW (i.e. reg.first()) - __ movq(Address(rsp, st_off), rax); + __ movq(Address(rsp, st_off), r13); } } else if (r_1->is_Register()) { // Register argument Register r = r_1->as_Register(); @@ -732,16 +740,16 @@ next_off : ld_off; // this can be a misaligned move - __ movq(r, Address(r13, offset)); + __ movq(r, Address(saved_sp, offset)); } else { // sign extend and use a full word? - __ movl(r, Address(r13, ld_off)); + __ movl(r, Address(saved_sp, ld_off)); } } else { if (!r_2->is_valid()) { - __ movflt(r_1->as_XMMRegister(), Address(r13, ld_off)); + __ movflt(r_1->as_XMMRegister(), Address(saved_sp, ld_off)); } else { - __ movdbl(r_1->as_XMMRegister(), Address(r13, next_off)); + __ movdbl(r_1->as_XMMRegister(), Address(saved_sp, next_off)); } } } @@ -3319,6 +3327,10 @@ // rax: exception handler + // Restore SP from BP if the exception PC is a MethodHandle call. + __ cmpl(Address(r15_thread, JavaThread::is_method_handle_exception_offset()), 0); + __ cmovptr(Assembler::notEqual, rsp, rbp); + // We have a handler in rax (could be deopt blob). __ mov(r8, rax); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1488,7 +1488,10 @@ if (interpreter_frame != NULL) { #ifdef ASSERT - assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); + if (!EnableMethodHandles) + // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? + // Probably, since deoptimization doesn't work yet. + assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)"); #endif diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -449,8 +449,12 @@ __ addptr(rax, stack_base); __ subptr(rax, stack_size); + // Use the maximum number of pages we might bang. + const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages) ? StackShadowPages : + (StackRedPages+StackYellowPages); + // add in the red and yellow zone sizes - __ addptr(rax, (StackRedPages + StackYellowPages) * page_size); + __ addptr(rax, max_pages * page_size); // check against the current stack bottom __ cmpptr(rsp, rax); @@ -1502,8 +1506,10 @@ tempcount* Interpreter::stackElementWords() + popframe_extra_args; if (interpreter_frame != NULL) { #ifdef ASSERT - assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), - "Frame not properly walkable"); + if (!EnableMethodHandles) + // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? + // Probably, since deoptimization doesn't work yet. + assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)"); #endif diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/x86/vm/x86_32.ad --- a/src/cpu/x86/vm/x86_32.ad Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/x86/vm/x86_32.ad Wed Jan 06 22:21:39 2010 -0800 @@ -268,22 +268,36 @@ static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000)); static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000)); +// Offset hacking within calls. +static int pre_call_FPU_size() { + if (Compile::current()->in_24_bit_fp_mode()) + return 6; // fldcw + return 0; +} + +static int preserve_SP_size() { + return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg) +} + // !!!!! Special hack to get all type of calls to specify the byte offset // from the start of the call to the point where the return address // will point. int MachCallStaticJavaNode::ret_addr_offset() { - return 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 5 bytes from start of call to where return address points + int offset = 5 + pre_call_FPU_size(); // 5 bytes from start of call to where return address points + if (_method_handle_invoke) + offset += preserve_SP_size(); + return offset; } int MachCallDynamicJavaNode::ret_addr_offset() { - return 10 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 10 bytes from start of call to where return address points + return 10 + pre_call_FPU_size(); // 10 bytes from start of call to where return address points } static int sizeof_FFree_Float_Stack_All = -1; int MachCallRuntimeNode::ret_addr_offset() { assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already"); - return sizeof_FFree_Float_Stack_All + 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); + return sizeof_FFree_Float_Stack_All + 5 + pre_call_FPU_size(); } // Indicate if the safepoint node needs the polling page as an input. @@ -299,8 +313,16 @@ // The address of the call instruction needs to be 4-byte aligned to // ensure that it does not span a cache line so that it can be patched. int CallStaticJavaDirectNode::compute_padding(int current_offset) const { - if (Compile::current()->in_24_bit_fp_mode()) - current_offset += 6; // skip fldcw in pre_call_FPU, if any + current_offset += pre_call_FPU_size(); // skip fldcw, if any + current_offset += 1; // skip call opcode byte + return round_to(current_offset, alignment_required()) - current_offset; +} + +// The address of the call instruction needs to be 4-byte aligned to +// ensure that it does not span a cache line so that it can be patched. +int CallStaticJavaHandleNode::compute_padding(int current_offset) const { + current_offset += pre_call_FPU_size(); // skip fldcw, if any + current_offset += preserve_SP_size(); // skip mov rbp, rsp current_offset += 1; // skip call opcode byte return round_to(current_offset, alignment_required()) - current_offset; } @@ -308,8 +330,7 @@ // The address of the call instruction needs to be 4-byte aligned to // ensure that it does not span a cache line so that it can be patched. int CallDynamicJavaDirectNode::compute_padding(int current_offset) const { - if (Compile::current()->in_24_bit_fp_mode()) - current_offset += 6; // skip fldcw in pre_call_FPU, if any + current_offset += pre_call_FPU_size(); // skip fldcw, if any current_offset += 5; // skip MOV instruction current_offset += 1; // skip call opcode byte return round_to(current_offset, alignment_required()) - current_offset; @@ -1460,6 +1481,10 @@ return RegMask(); } +const RegMask Matcher::method_handle_invoke_SP_save_mask() { + return EBP_REG_mask; +} + %} //----------ENCODING BLOCK----------------------------------------------------- @@ -1772,10 +1797,13 @@ enc_class pre_call_FPU %{ // If method sets FPU control word restore it here + debug_only(int off0 = cbuf.code_size()); if( Compile::current()->in_24_bit_fp_mode() ) { MacroAssembler masm(&cbuf); masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } + debug_only(int off1 = cbuf.code_size()); + assert(off1 - off0 == pre_call_FPU_size(), "correct size prediction"); %} enc_class post_call_FPU %{ @@ -1786,6 +1814,21 @@ } %} + enc_class preserve_SP %{ + debug_only(int off0 = cbuf.code_size()); + MacroAssembler _masm(&cbuf); + // RBP is preserved across all calls, even compiled calls. + // Use it to preserve RSP in places where the callee might change the SP. + __ movptr(rbp, rsp); + debug_only(int off1 = cbuf.code_size()); + assert(off1 - off0 == preserve_SP_size(), "correct size prediction"); + %} + + enc_class restore_SP %{ + MacroAssembler _masm(&cbuf); + __ movptr(rsp, rbp); + %} + enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine // who we intended to call. @@ -13406,6 +13449,7 @@ // compute_padding() functions will have to be adjusted. instruct CallStaticJavaDirect(method meth) %{ match(CallStaticJava); + predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke()); effect(USE meth); ins_cost(300); @@ -13420,6 +13464,30 @@ ins_alignment(4); %} +// Call Java Static Instruction (method handle version) +// Note: If this code changes, the corresponding ret_addr_offset() and +// compute_padding() functions will have to be adjusted. +instruct CallStaticJavaHandle(method meth, eBPRegP ebp) %{ + match(CallStaticJava); + predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); + effect(USE meth); + // EBP is saved by all callees (for interpreter stack correction). + // We use it here for a similar purpose, in {preserve,restore}_SP. + + ins_cost(300); + format %{ "CALL,static/MethodHandle " %} + opcode(0xE8); /* E8 cd */ + ins_encode( pre_call_FPU, + preserve_SP, + Java_Static_Call( meth ), + restore_SP, + call_epilog, + post_call_FPU ); + ins_pipe( pipe_slow ); + ins_pc_relative(1); + ins_alignment(4); +%} + // Call Java Dynamic Instruction // Note: If this code changes, the corresponding ret_addr_offset() and // compute_padding() functions will have to be adjusted. diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/x86/vm/x86_64.ad --- a/src/cpu/x86/vm/x86_64.ad Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/x86/vm/x86_64.ad Wed Jan 06 22:21:39 2010 -0800 @@ -551,12 +551,19 @@ #define __ _masm. +static int preserve_SP_size() { + return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg) +} + // !!!!! Special hack to get all types of calls to specify the byte offset // from the start of the call to the point where the return address // will point. int MachCallStaticJavaNode::ret_addr_offset() { - return 5; // 5 bytes from start of call to where return address points + int offset = 5; // 5 bytes from start of call to where return address points + if (_method_handle_invoke) + offset += preserve_SP_size(); + return offset; } int MachCallDynamicJavaNode::ret_addr_offset() @@ -589,6 +596,15 @@ // The address of the call instruction needs to be 4-byte aligned to // ensure that it does not span a cache line so that it can be patched. +int CallStaticJavaHandleNode::compute_padding(int current_offset) const +{ + current_offset += preserve_SP_size(); // skip mov rbp, rsp + current_offset += 1; // skip call opcode byte + return round_to(current_offset, alignment_required()) - current_offset; +} + +// The address of the call instruction needs to be 4-byte aligned to +// ensure that it does not span a cache line so that it can be patched. int CallDynamicJavaDirectNode::compute_padding(int current_offset) const { current_offset += 11; // skip movq instruction + call opcode byte @@ -2113,6 +2129,10 @@ return LONG_RDX_REG_mask; } +const RegMask Matcher::method_handle_invoke_SP_save_mask() { + return PTR_RBP_REG_mask; +} + static Address build_address(int b, int i, int s, int d) { Register index = as_Register(i); Address::ScaleFactor scale = (Address::ScaleFactor)s; @@ -2608,6 +2628,21 @@ RELOC_DISP32); %} + enc_class preserve_SP %{ + debug_only(int off0 = cbuf.code_size()); + MacroAssembler _masm(&cbuf); + // RBP is preserved across all calls, even compiled calls. + // Use it to preserve RSP in places where the callee might change the SP. + __ movptr(rbp, rsp); + debug_only(int off1 = cbuf.code_size()); + assert(off1 - off0 == preserve_SP_size(), "correct size prediction"); + %} + + enc_class restore_SP %{ + MacroAssembler _masm(&cbuf); + __ movptr(rsp, rbp); + %} + enc_class Java_Static_Call(method meth) %{ // JAVA STATIC CALL @@ -12526,9 +12561,9 @@ // Call Java Static Instruction // Note: If this code changes, the corresponding ret_addr_offset() and // compute_padding() functions will have to be adjusted. -instruct CallStaticJavaDirect(method meth) -%{ +instruct CallStaticJavaDirect(method meth) %{ match(CallStaticJava); + predicate(!((CallStaticJavaNode*) n)->is_method_handle_invoke()); effect(USE meth); ins_cost(300); @@ -12540,6 +12575,28 @@ ins_alignment(4); %} +// Call Java Static Instruction (method handle version) +// Note: If this code changes, the corresponding ret_addr_offset() and +// compute_padding() functions will have to be adjusted. +instruct CallStaticJavaHandle(method meth, rbp_RegP rbp) %{ + match(CallStaticJava); + predicate(((CallStaticJavaNode*) n)->is_method_handle_invoke()); + effect(USE meth); + // RBP is saved by all callees (for interpreter stack correction). + // We use it here for a similar purpose, in {preserve,restore}_SP. + + ins_cost(300); + format %{ "call,static/MethodHandle " %} + opcode(0xE8); /* E8 cd */ + ins_encode(preserve_SP, + Java_Static_Call(meth), + restore_SP, + call_epilog); + ins_pipe(pipe_slow); + ins_pc_relative(1); + ins_alignment(4); +%} + // Call Java Dynamic Instruction // Note: If this code changes, the corresponding ret_addr_offset() and // compute_padding() functions will have to be adjusted. diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -245,7 +245,7 @@ if (handlerAddr == NULL) { CALL_VM_NOCHECK(InterpreterRuntime::prepare_native_call(thread, method)); if (HAS_PENDING_EXCEPTION) - goto unwind_and_return; + goto unlock_unwind_and_return; handlerAddr = method->signature_handler(); assert(handlerAddr != NULL, "eh?"); @@ -254,7 +254,7 @@ CALL_VM_NOCHECK(handlerAddr = InterpreterRuntime::slow_signature_handler(thread, method, NULL,NULL)); if (HAS_PENDING_EXCEPTION) - goto unwind_and_return; + goto unlock_unwind_and_return; } handler = \ InterpreterRuntime::SignatureHandler::from_handlerAddr(handlerAddr); @@ -365,10 +365,10 @@ // Reset handle block thread->active_handles()->clear(); - // Unlock if necessary. It seems totally wrong that this - // is skipped in the event of an exception but apparently - // the template interpreter does this so we do too. - if (monitor && !HAS_PENDING_EXCEPTION) { + unlock_unwind_and_return: + + // Unlock if necessary + if (monitor) { BasicLock *lock = monitor->lock(); markOop header = lock->displaced_header(); oop rcvr = monitor->obj(); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/c1/c1_IR.hpp --- a/src/share/vm/c1/c1_IR.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/c1/c1_IR.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -251,8 +251,9 @@ DebugToken* expvals = recorder->create_scope_values(expressions()); DebugToken* monvals = recorder->create_monitor_values(monitors()); // reexecute allowed only for the topmost frame - bool reexecute = topmost ? should_reexecute() : false; - recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, locvals, expvals, monvals); + bool reexecute = topmost ? should_reexecute() : false; + bool is_method_handle_invoke = false; + recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, locvals, expvals, monvals); } }; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/c1/c1_Runtime1.cpp --- a/src/share/vm/c1/c1_Runtime1.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/c1/c1_Runtime1.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -425,7 +425,7 @@ assert(exception.not_null(), "NULL exceptions should be handled by throw_exception"); assert(exception->is_oop(), "just checking"); // Check that exception is a subclass of Throwable, otherwise we have a VerifyError - if (!(exception->is_a(SystemDictionary::throwable_klass()))) { + if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { if (ExitVMOnVerifyError) vm_exit(-1); ShouldNotReachHere(); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciCPCache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/ci/ciCPCache.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -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(); +} diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciCPCache.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/ci/ciCPCache.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -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(); +}; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciCallSite.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/ci/ciCallSite.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -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(); +} diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciCallSite.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/ci/ciCallSite.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -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(); +}; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciClassList.hpp --- a/src/share/vm/ci/ciClassList.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciClassList.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -25,6 +25,7 @@ class ciEnv; class ciObjectFactory; class ciConstantPoolCache; +class ciCPCache; class ciField; class ciConstant; @@ -42,6 +43,8 @@ class ciObject; class ciNullObject; class ciInstance; +class ciCallSite; +class ciMethodHandle; class ciMethod; class ciMethodData; class ciReceiverTypeData; // part of ciMethodData @@ -78,6 +81,7 @@ // Any more access must be given explicitly. #define CI_PACKAGE_ACCESS_TO \ friend class ciObjectFactory; \ +friend class ciCallSite; \ friend class ciConstantPoolCache; \ friend class ciField; \ friend class ciConstant; \ @@ -93,6 +97,7 @@ friend class ciInstance; \ friend class ciMethod; \ friend class ciMethodData; \ +friend class ciMethodHandle; \ friend class ciReceiverTypeData; \ friend class ciSymbol; \ friend class ciArray; \ diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciEnv.cpp --- a/src/share/vm/ci/ciEnv.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciEnv.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -38,17 +38,9 @@ ciTypeArrayKlassKlass* ciEnv::_type_array_klass_klass_instance; ciObjArrayKlassKlass* ciEnv::_obj_array_klass_klass_instance; -ciInstanceKlass* ciEnv::_ArrayStoreException; -ciInstanceKlass* ciEnv::_Class; -ciInstanceKlass* ciEnv::_ClassCastException; -ciInstanceKlass* ciEnv::_Object; -ciInstanceKlass* ciEnv::_Throwable; -ciInstanceKlass* ciEnv::_Thread; -ciInstanceKlass* ciEnv::_OutOfMemoryError; -ciInstanceKlass* ciEnv::_String; -ciInstanceKlass* ciEnv::_StringBuffer; -ciInstanceKlass* ciEnv::_StringBuilder; -ciInstanceKlass* ciEnv::_Integer; +#define WK_KLASS_DEFN(name, ignore_s, ignore_o) ciInstanceKlass* ciEnv::_##name = NULL; +WK_KLASSES_DO(WK_KLASS_DEFN) +#undef WK_KLASS_DEFN ciSymbol* ciEnv::_unloaded_cisymbol = NULL; ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = NULL; @@ -442,12 +434,11 @@ // ciEnv::get_klass_by_index_impl // // Implementation of get_klass_by_index. -ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor, +ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool, int index, - bool& is_accessible) { - assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool"); + bool& is_accessible, + ciInstanceKlass* accessor) { EXCEPTION_CONTEXT; - constantPoolHandle cpool(THREAD, accessor->get_instanceKlass()->constants()); KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); symbolHandle klass_name; if (klass.is_null()) { @@ -509,22 +500,21 @@ // ciEnv::get_klass_by_index // // Get a klass from the constant pool. -ciKlass* ciEnv::get_klass_by_index(ciInstanceKlass* accessor, +ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool, int index, - bool& is_accessible) { - GUARDED_VM_ENTRY(return get_klass_by_index_impl(accessor, index, is_accessible);) + bool& is_accessible, + ciInstanceKlass* accessor) { + GUARDED_VM_ENTRY(return get_klass_by_index_impl(cpool, index, is_accessible, accessor);) } // ------------------------------------------------------------------ // ciEnv::get_constant_by_index_impl // // Implementation of get_constant_by_index(). -ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor, - int index) { +ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool, + int index, + ciInstanceKlass* accessor) { EXCEPTION_CONTEXT; - instanceKlass* ik_accessor = accessor->get_instanceKlass(); - assert(ik_accessor->is_linked(), "must be linked before accessing constant pool"); - constantPoolOop cpool = ik_accessor->constants(); constantTag tag = cpool->tag_at(index); if (tag.is_int()) { return ciConstant(T_INT, (jint)cpool->int_at(index)); @@ -552,7 +542,7 @@ } else if (tag.is_klass() || tag.is_unresolved_klass()) { // 4881222: allow ldc to take a class type bool ignore; - ciKlass* klass = get_klass_by_index_impl(accessor, index, ignore); + ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; record_out_of_memory_failure(); @@ -561,6 +551,11 @@ assert (klass->is_instance_klass() || klass->is_array_klass(), "must be an instance or array klass "); return ciConstant(T_OBJECT, klass); + } else if (tag.is_object()) { + oop obj = cpool->object_at(index); + assert(obj->is_instance(), "must be an instance"); + ciObject* ciobj = get_object(obj); + return ciConstant(T_OBJECT, ciobj); } else { ShouldNotReachHere(); return ciConstant(); @@ -597,9 +592,10 @@ // Pull a constant out of the constant pool. How appropriate. // // Implementation note: this query is currently in no way cached. -ciConstant ciEnv::get_constant_by_index(ciInstanceKlass* accessor, - int index) { - GUARDED_VM_ENTRY(return get_constant_by_index_impl(accessor, index); ) +ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool, + int index, + ciInstanceKlass* accessor) { + GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, index, accessor);) } // ------------------------------------------------------------------ @@ -609,7 +605,7 @@ // // Implementation note: this query is currently in no way cached. bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor, - int index) const { + int index) const { GUARDED_VM_ENTRY(return is_unresolved_string_impl(accessor->get_instanceKlass(), index); ) } @@ -620,7 +616,7 @@ // // Implementation note: this query is currently in no way cached. bool ciEnv::is_unresolved_klass(ciInstanceKlass* accessor, - int index) const { + int index) const { GUARDED_VM_ENTRY(return is_unresolved_klass_impl(accessor->get_instanceKlass(), index); ) } @@ -701,15 +697,12 @@ // ------------------------------------------------------------------ // ciEnv::get_method_by_index_impl -ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor, - int index, Bytecodes::Code bc) { - // Get the method's declared holder. - - assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool"); - constantPoolHandle cpool = accessor->get_instanceKlass()->constants(); +ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool, + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor) { int holder_index = cpool->klass_ref_index_at(index); bool holder_is_accessible; - ciKlass* holder = get_klass_by_index_impl(accessor, holder_index, holder_is_accessible); + ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor); ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder); // Get the method's name and signature. @@ -736,6 +729,33 @@ // ------------------------------------------------------------------ +// ciEnv::get_fake_invokedynamic_method_impl +ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, + int index, Bytecodes::Code bc) { + assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic"); + + // Get the CallSite from the constant pool cache. + ConstantPoolCacheEntry* cpc_entry = cpool->cache()->secondary_entry_at(index); + assert(cpc_entry != NULL && cpc_entry->is_secondary_entry(), "sanity"); + Handle call_site = cpc_entry->f1(); + + // Call site might not be linked yet. + if (call_site.is_null()) { + ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); + ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol(); + return get_unloaded_method(mh_klass, ciSymbol::invoke_name(), sig_sym); + } + + // Get the methodOop from the CallSite. + methodOop method_oop = (methodOop) java_dyn_CallSite::vmmethod(call_site()); + assert(method_oop != NULL, "sanity"); + assert(method_oop->is_method_handle_invoke(), "consistent"); + + return get_object(method_oop)->as_method(); +} + + +// ------------------------------------------------------------------ // ciEnv::get_instance_klass_for_declared_method_holder ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* method_holder) { // For the case of .clone(), the method holder can be a ciArrayKlass @@ -757,15 +777,19 @@ } - - // ------------------------------------------------------------------ // ciEnv::get_method_by_index -ciMethod* ciEnv::get_method_by_index(ciInstanceKlass* accessor, - int index, Bytecodes::Code bc) { - GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, bc);) +ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool, + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor) { + if (bc == Bytecodes::_invokedynamic) { + GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc);) + } else { + GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);) + } } + // ------------------------------------------------------------------ // ciEnv::name_buffer char *ciEnv::name_buffer(int req_len) { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciEnv.hpp --- a/src/share/vm/ci/ciEnv.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciEnv.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -74,17 +74,9 @@ static ciTypeArrayKlassKlass* _type_array_klass_klass_instance; static ciObjArrayKlassKlass* _obj_array_klass_klass_instance; - static ciInstanceKlass* _ArrayStoreException; - static ciInstanceKlass* _Class; - static ciInstanceKlass* _ClassCastException; - static ciInstanceKlass* _Object; - static ciInstanceKlass* _Throwable; - static ciInstanceKlass* _Thread; - static ciInstanceKlass* _OutOfMemoryError; - static ciInstanceKlass* _String; - static ciInstanceKlass* _StringBuffer; - static ciInstanceKlass* _StringBuilder; - static ciInstanceKlass* _Integer; +#define WK_KLASS_DECL(name, ignore_s, ignore_o) static ciInstanceKlass* _##name; + WK_KLASSES_DO(WK_KLASS_DECL) +#undef WK_KLASS_DECL static ciSymbol* _unloaded_cisymbol; static ciInstanceKlass* _unloaded_ciinstance_klass; @@ -120,37 +112,45 @@ bool require_local); // Constant pool access. - ciKlass* get_klass_by_index(ciInstanceKlass* loading_klass, + ciKlass* get_klass_by_index(constantPoolHandle cpool, int klass_index, - bool& is_accessible); - ciConstant get_constant_by_index(ciInstanceKlass* loading_klass, - int constant_index); + bool& is_accessible, + ciInstanceKlass* loading_klass); + ciConstant get_constant_by_index(constantPoolHandle cpool, + int constant_index, + ciInstanceKlass* accessor); bool is_unresolved_string(ciInstanceKlass* loading_klass, int constant_index) const; bool is_unresolved_klass(ciInstanceKlass* loading_klass, int constant_index) const; ciField* get_field_by_index(ciInstanceKlass* loading_klass, int field_index); - ciMethod* get_method_by_index(ciInstanceKlass* loading_klass, - int method_index, Bytecodes::Code bc); + ciMethod* get_method_by_index(constantPoolHandle cpool, + int method_index, Bytecodes::Code bc, + ciInstanceKlass* loading_klass); // Implementation methods for loading and constant pool access. ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass, ciSymbol* klass_name, bool require_local); - ciKlass* get_klass_by_index_impl(ciInstanceKlass* loading_klass, + ciKlass* get_klass_by_index_impl(constantPoolHandle cpool, int klass_index, - bool& is_accessible); - ciConstant get_constant_by_index_impl(ciInstanceKlass* loading_klass, - int constant_index); + bool& is_accessible, + ciInstanceKlass* loading_klass); + ciConstant get_constant_by_index_impl(constantPoolHandle cpool, + int constant_index, + ciInstanceKlass* loading_klass); bool is_unresolved_string_impl (instanceKlass* loading_klass, int constant_index) const; bool is_unresolved_klass_impl (instanceKlass* loading_klass, int constant_index) const; ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass, int field_index); - ciMethod* get_method_by_index_impl(ciInstanceKlass* loading_klass, - int method_index, Bytecodes::Code bc); + ciMethod* get_method_by_index_impl(constantPoolHandle cpool, + int method_index, Bytecodes::Code bc, + ciInstanceKlass* loading_klass); + ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool, + int index, Bytecodes::Code bc); // Helper methods bool check_klass_accessibility(ciKlass* accessing_klass, @@ -292,39 +292,13 @@ // Access to certain well known ciObjects. - ciInstanceKlass* ArrayStoreException_klass() { - return _ArrayStoreException; - } - ciInstanceKlass* Class_klass() { - return _Class; - } - ciInstanceKlass* ClassCastException_klass() { - return _ClassCastException; - } - ciInstanceKlass* Object_klass() { - return _Object; - } - ciInstanceKlass* Throwable_klass() { - return _Throwable; +#define WK_KLASS_FUNC(name, ignore_s, ignore_o) \ + ciInstanceKlass* name() { \ + return _##name;\ } - 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() { assert(_NullPointerException_instance != NULL, "initialization problem"); return _NullPointerException_instance; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciExceptionHandler.cpp --- a/src/share/vm/ci/ciExceptionHandler.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciExceptionHandler.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,12 +34,16 @@ // // Get the exception klass that this handler catches. ciInstanceKlass* ciExceptionHandler::catch_klass() { + VM_ENTRY_MARK; assert(!is_catch_all(), "bad index"); if (_catch_klass == NULL) { bool will_link; - ciKlass* k = CURRENT_ENV->get_klass_by_index(_loading_klass, + assert(_loading_klass->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool"); + constantPoolHandle cpool(_loading_klass->get_instanceKlass()->constants()); + ciKlass* k = CURRENT_ENV->get_klass_by_index(cpool, _catch_klass_index, - will_link); + will_link, + _loading_klass); if (!will_link && k->is_loaded()) { GUARDED_VM_ENTRY( k = CURRENT_ENV->get_unloaded_klass(_loading_klass, k->name()); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciField.cpp --- a/src/share/vm/ci/ciField.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciField.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,7 @@ bool ignore; // This is not really a class reference; the index always refers to the // field's type signature, as a symbol. Linkage checks do not apply. - _type = ciEnv::current(thread)->get_klass_by_index(klass, sig_index, ignore); + _type = ciEnv::current(thread)->get_klass_by_index(cpool, sig_index, ignore, klass); } else { _type = ciType::make(field_type); } @@ -100,9 +100,9 @@ int holder_index = cpool->klass_ref_index_at(index); bool holder_is_accessible; ciInstanceKlass* declared_holder = - ciEnv::current(thread)->get_klass_by_index(klass, holder_index, - holder_is_accessible) - ->as_instance_klass(); + ciEnv::current(thread)->get_klass_by_index(cpool, holder_index, + holder_is_accessible, + klass)->as_instance_klass(); // The declared holder of this field may not have been loaded. // Bail out with partial field information. @@ -168,8 +168,18 @@ _holder = CURRENT_ENV->get_object(fd->field_holder())->as_instance_klass(); // Check to see if the field is constant. - if (_holder->is_initialized() && - this->is_final() && this->is_static()) { + if (_holder->is_initialized() && this->is_final()) { + if (!this->is_static()) { + // A field can be constant if it's a final static field or if it's + // a final non-static field of a trusted class ({java,sun}.dyn). + if (_holder->is_in_package("java/dyn") || _holder->is_in_package("sun/dyn")) { + _is_constant = true; + return; + } + _is_constant = false; + return; + } + // This field just may be constant. The only cases where it will // not be constant are: // @@ -182,8 +192,8 @@ // java.lang.System.out, and java.lang.System.err. klassOop k = _holder->get_klassOop(); - assert( SystemDictionary::system_klass() != NULL, "Check once per vm"); - if( k == SystemDictionary::system_klass() ) { + assert( SystemDictionary::System_klass() != NULL, "Check once per vm"); + if( k == SystemDictionary::System_klass() ) { // Check offsets for case 2: System.in, System.out, or System.err if( _offset == java_lang_System::in_offset_in_bytes() || _offset == java_lang_System::out_offset_in_bytes() || diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciField.hpp --- a/src/share/vm/ci/ciField.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciField.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -138,10 +138,18 @@ // Get the constant value of this field. ciConstant constant_value() { - assert(is_constant(), "illegal call to constant_value()"); + assert(is_static() && is_constant(), "illegal call to constant_value()"); return _constant_value; } + // Get the constant value of non-static final field in the given + // object. + ciConstant constant_value_of(ciObject* object) { + assert(!is_static() && is_constant(), "only if field is non-static constant"); + assert(object->is_instance(), "must be instance"); + return object->as_instance()->field_value(this); + } + // Check for link time errors. Accessing a field from a // certain class via a certain bytecode may or may not be legal. // This call checks to see if an exception may be raised by diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciInstance.cpp --- a/src/share/vm/ci/ciInstance.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciInstance.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -36,7 +36,7 @@ VM_ENTRY_MARK; oop m = get_oop(); // Return NULL if it is not java.lang.Class. - if (m == NULL || m->klass() != SystemDictionary::class_klass()) { + if (m == NULL || m->klass() != SystemDictionary::Class_klass()) { return NULL; } // Return either a primitive type or a klass. diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciInstanceKlass.cpp --- a/src/share/vm/ci/ciInstanceKlass.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciInstanceKlass.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -75,7 +75,7 @@ _java_mirror = NULL; if (is_shared()) { - if (h_k() != SystemDictionary::object_klass()) { + if (h_k() != SystemDictionary::Object_klass()) { super(); } java_mirror(); @@ -232,8 +232,48 @@ // ------------------------------------------------------------------ // ciInstanceKlass::uses_default_loader bool ciInstanceKlass::uses_default_loader() { - VM_ENTRY_MARK; - return loader() == NULL; + // Note: We do not need to resolve the handle or enter the VM + // in order to test null-ness. + return _loader == NULL; +} + +// ------------------------------------------------------------------ +// ciInstanceKlass::is_in_package +// +// Is this klass in the given package? +bool ciInstanceKlass::is_in_package(const char* packagename, int len) { + // To avoid class loader mischief, this test always rejects application classes. + if (!uses_default_loader()) + return false; + GUARDED_VM_ENTRY( + return is_in_package_impl(packagename, len); + ) +} + +bool ciInstanceKlass::is_in_package_impl(const char* packagename, int len) { + ASSERT_IN_VM; + + // If packagename contains trailing '/' exclude it from the + // prefix-test since we test for it explicitly. + if (packagename[len - 1] == '/') + len--; + + if (!name()->starts_with(packagename, len)) + return false; + + // Test if the class name is something like "java/lang". + if ((len + 1) > name()->utf8_length()) + return false; + + // Test for trailing '/' + if ((char) name()->byte_at(len) != '/') + return false; + + // Make sure it's not actually in a subpackage: + if (name()->index_of_at(len+1, "/", 1) >= 0) + return false; + + return true; } // ------------------------------------------------------------------ diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciInstanceKlass.hpp --- a/src/share/vm/ci/ciInstanceKlass.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciInstanceKlass.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -29,10 +29,11 @@ // be loaded. class ciInstanceKlass : public ciKlass { CI_PACKAGE_ACCESS + friend class ciBytecodeStream; friend class ciEnv; + friend class ciExceptionHandler; friend class ciMethod; friend class ciField; - friend class ciBytecodeStream; private: jobject _loader; @@ -78,6 +79,8 @@ const char* type_string() { return "ciInstanceKlass"; } + bool is_in_package_impl(const char* packagename, int len); + void print_impl(outputStream* st); ciConstantPoolCache* field_cache(); @@ -196,6 +199,12 @@ bool is_java_lang_Object(); + // Is this klass in the given package? + bool is_in_package(const char* packagename) { + return is_in_package(packagename, (int) strlen(packagename)); + } + bool is_in_package(const char* packagename, int len); + // What kind of ciObject is this? bool is_instance_klass() { return true; } bool is_java_klass() { return true; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciKlass.cpp --- a/src/share/vm/ci/ciKlass.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciKlass.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciKlass.hpp --- a/src/share/vm/ci/ciKlass.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciKlass.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,7 +69,7 @@ ciKlass(KlassHandle k_h); // What is the name of this klass? - ciSymbol* name() { return _name; } + ciSymbol* name() const { return _name; } // What is its layout helper value? jint layout_helper() { return _layout_helper; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciMethod.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -687,7 +687,7 @@ // ------------------------------------------------------------------ // invokedynamic support // -bool ciMethod::is_method_handle_invoke() { +bool ciMethod::is_method_handle_invoke() const { check_is_loaded(); bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS); #ifdef ASSERT diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciMethod.hpp --- a/src/share/vm/ci/ciMethod.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciMethod.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -38,6 +38,8 @@ CI_PACKAGE_ACCESS friend class ciEnv; friend class ciExceptionHandlerStream; + friend class ciBytecodeStream; + friend class ciMethodHandle; private: // General method information. @@ -213,7 +215,7 @@ bool check_call(int refinfo_index, bool is_static) const; void build_method_data(); // make sure it exists in the VM also int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC - bool is_method_handle_invoke(); + bool is_method_handle_invoke() const; ciInstance* method_handle_type(); // What kind of ciObject is this? @@ -251,4 +253,10 @@ // Print the name of this method in various incarnations. void print_name(outputStream* st = tty); void print_short_name(outputStream* st = tty); + + methodOop get_method_handle_target() { + klassOop receiver_limit_oop = NULL; + int flags = 0; + return MethodHandles::decode_method(get_oop(), receiver_limit_oop, flags); + } }; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciMethodHandle.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/ci/ciMethodHandle.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -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(); +} diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciMethodHandle.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/ci/ciMethodHandle.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -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); + } +}; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciObject.hpp --- a/src/share/vm/ci/ciObject.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciObject.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -131,9 +131,12 @@ // What kind of ciObject is this? virtual bool is_null_object() const { return false; } + virtual bool is_call_site() const { return false; } + virtual bool is_cpcache() const { return false; } virtual bool is_instance() { return false; } virtual bool is_method() { return false; } virtual bool is_method_data() { return false; } + virtual bool is_method_handle() const { return false; } virtual bool is_array() { return false; } virtual bool is_obj_array() { return false; } virtual bool is_type_array() { return false; } @@ -185,6 +188,14 @@ assert(is_null_object(), "bad cast"); return (ciNullObject*)this; } + ciCallSite* as_call_site() { + assert(is_call_site(), "bad cast"); + return (ciCallSite*) this; + } + ciCPCache* as_cpcache() { + assert(is_cpcache(), "bad cast"); + return (ciCPCache*) this; + } ciInstance* as_instance() { assert(is_instance(), "bad cast"); return (ciInstance*)this; @@ -197,6 +208,10 @@ assert(is_method_data(), "bad cast"); return (ciMethodData*)this; } + ciMethodHandle* as_method_handle() { + assert(is_method_handle(), "bad cast"); + return (ciMethodHandle*) this; + } ciArray* as_array() { assert(is_array(), "bad cast"); return (ciArray*)this; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciObjectFactory.cpp --- a/src/share/vm/ci/ciObjectFactory.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciObjectFactory.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -144,39 +144,13 @@ ciEnv::_obj_array_klass_klass_instance = get(Universe::objArrayKlassKlassObj()) ->as_obj_array_klass_klass(); - ciEnv::_ArrayStoreException = - get(SystemDictionary::ArrayStoreException_klass()) - ->as_instance_klass(); - ciEnv::_Class = - get(SystemDictionary::class_klass()) - ->as_instance_klass(); - ciEnv::_ClassCastException = - get(SystemDictionary::ClassCastException_klass()) - ->as_instance_klass(); - ciEnv::_Object = - get(SystemDictionary::object_klass()) - ->as_instance_klass(); - ciEnv::_Throwable = - get(SystemDictionary::throwable_klass()) - ->as_instance_klass(); - ciEnv::_Thread = - get(SystemDictionary::thread_klass()) - ->as_instance_klass(); - ciEnv::_OutOfMemoryError = - get(SystemDictionary::OutOfMemoryError_klass()) - ->as_instance_klass(); - ciEnv::_String = - get(SystemDictionary::string_klass()) - ->as_instance_klass(); - ciEnv::_StringBuffer = - get(SystemDictionary::stringBuffer_klass()) - ->as_instance_klass(); - ciEnv::_StringBuilder = - get(SystemDictionary::StringBuilder_klass()) - ->as_instance_klass(); - ciEnv::_Integer = - get(SystemDictionary::int_klass()) - ->as_instance_klass(); + +#define WK_KLASS_DEFN(name, ignore_s, opt) \ + if (SystemDictionary::name() != NULL) \ + ciEnv::_##name = get(SystemDictionary::name())->as_instance_klass(); + + WK_KLASSES_DO(WK_KLASS_DEFN) +#undef WK_KLASS_DEFN for (int len = -1; len != _ci_objects->length(); ) { len = _ci_objects->length(); @@ -333,13 +307,21 @@ return new (arena()) ciMethodData(h_md); } else if (o->is_instance()) { instanceHandle h_i(THREAD, (instanceOop)o); - return new (arena()) ciInstance(h_i); + if (java_dyn_CallSite::is_instance(o)) + return new (arena()) ciCallSite(h_i); + else if (java_dyn_MethodHandle::is_instance(o)) + return new (arena()) ciMethodHandle(h_i); + else + return new (arena()) ciInstance(h_i); } else if (o->is_objArray()) { objArrayHandle h_oa(THREAD, (objArrayOop)o); return new (arena()) ciObjArray(h_oa); } else if (o->is_typeArray()) { typeArrayHandle h_ta(THREAD, (typeArrayOop)o); return new (arena()) ciTypeArray(h_ta); + } else if (o->is_constantPoolCache()) { + constantPoolCacheHandle h_cpc(THREAD, (constantPoolCacheOop) o); + return new (arena()) ciCPCache(h_cpc); } // The oop is of some type not supported by the compiler interface. @@ -576,7 +558,7 @@ if (key->is_perm() && _non_perm_count == 0) { return emptyBucket; } else if (key->is_instance()) { - if (key->klass() == SystemDictionary::class_klass()) { + if (key->klass() == SystemDictionary::Class_klass()) { // class mirror instances are always perm return emptyBucket; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciStreams.cpp --- a/src/share/vm/ci/ciStreams.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciStreams.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -186,8 +186,9 @@ // If this bytecode is a new, newarray, multianewarray, instanceof, // or checkcast, get the referenced klass. ciKlass* ciBytecodeStream::get_klass(bool& will_link) { - return CURRENT_ENV->get_klass_by_index(_holder, get_klass_index(), - will_link); + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); + return CURRENT_ENV->get_klass_by_index(cpool, get_klass_index(), will_link, _holder); } // ------------------------------------------------------------------ @@ -213,7 +214,9 @@ // If this bytecode is one of the ldc variants, get the referenced // constant. ciConstant ciBytecodeStream::get_constant() { - return CURRENT_ENV->get_constant_by_index(_holder, get_constant_index()); + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); + return CURRENT_ENV->get_constant_by_index(cpool, get_constant_index(), _holder); } // ------------------------------------------------------------------ @@ -264,9 +267,11 @@ // There is no "will_link" result passed back. The user is responsible // for checking linkability when retrieving the associated field. ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() { + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); int holder_index = get_field_holder_index(); bool ignore; - return CURRENT_ENV->get_klass_by_index(_holder, holder_index, ignore) + return CURRENT_ENV->get_klass_by_index(cpool, holder_index, ignore, _holder) ->as_instance_klass(); } @@ -277,9 +282,10 @@ // referenced by the current bytecode. Used for generating // deoptimization information. int ciBytecodeStream::get_field_holder_index() { - VM_ENTRY_MARK; - constantPoolOop cpool = _holder->get_instanceKlass()->constants(); - return cpool->klass_ref_index_at(get_field_index()); + GUARDED_VM_ENTRY( + constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + return cpool->klass_ref_index_at(get_field_index()); + ) } // ------------------------------------------------------------------ @@ -321,7 +327,9 @@ // // If this is a method invocation bytecode, get the invoked method. ciMethod* ciBytecodeStream::get_method(bool& will_link) { - ciMethod* m = CURRENT_ENV->get_method_by_index(_holder, get_method_index(),cur_bc()); + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); + ciMethod* m = CURRENT_ENV->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder); will_link = m->is_loaded(); return m; } @@ -338,11 +346,13 @@ // There is no "will_link" result passed back. The user is responsible // for checking linkability when retrieving the associated method. ciKlass* ciBytecodeStream::get_declared_method_holder() { + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); bool ignore; - // report as Dynamic for invokedynamic, which is syntactically classless + // report as InvokeDynamic for invokedynamic, which is syntactically classless if (cur_bc() == Bytecodes::_invokedynamic) - return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_Dynamic(), false); - return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore); + return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false); + return CURRENT_ENV->get_klass_by_index(cpool, get_method_holder_index(), ignore, _holder); } // ------------------------------------------------------------------ @@ -352,8 +362,7 @@ // referenced by the current bytecode. Used for generating // deoptimization information. int ciBytecodeStream::get_method_holder_index() { - VM_ENTRY_MARK; - constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + constantPoolOop cpool = _method->get_methodOop()->constants(); return cpool->klass_ref_index_at(get_method_index()); } @@ -370,3 +379,31 @@ int name_and_type_index = cpool->name_and_type_ref_index_at(method_index); return cpool->signature_ref_index_at(name_and_type_index); } + +// ------------------------------------------------------------------ +// ciBytecodeStream::get_cpcache +ciCPCache* ciBytecodeStream::get_cpcache() { + VM_ENTRY_MARK; + // Get the constant pool. + constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + constantPoolCacheOop cpcache = cpool->cache(); + + return CURRENT_ENV->get_object(cpcache)->as_cpcache(); +} + +// ------------------------------------------------------------------ +// ciBytecodeStream::get_call_site +ciCallSite* ciBytecodeStream::get_call_site() { + VM_ENTRY_MARK; + // Get the constant pool. + constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + constantPoolCacheOop cpcache = cpool->cache(); + + // Get the CallSite from the constant pool cache. + int method_index = get_method_index(); + ConstantPoolCacheEntry* cpcache_entry = cpcache->secondary_entry_at(method_index); + oop call_site_oop = cpcache_entry->f1(); + + // Create a CallSite object and return it. + return CURRENT_ENV->get_object(call_site_oop)->as_call_site(); +} diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciStreams.hpp --- a/src/share/vm/ci/ciStreams.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciStreams.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -232,6 +232,9 @@ int get_method_holder_index(); int get_method_signature_index(); + ciCPCache* get_cpcache(); + ciCallSite* get_call_site(); + private: void assert_index_size(int required_size) const { #ifdef ASSERT diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciSymbol.cpp --- a/src/share/vm/ci/ciSymbol.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciSymbol.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,6 +60,22 @@ } // ------------------------------------------------------------------ +// ciSymbol::starts_with +// +// Tests if the symbol starts with the given prefix. +bool ciSymbol::starts_with(const char* prefix, int len) const { + GUARDED_VM_ENTRY(return get_symbolOop()->starts_with(prefix, len);) +} + +// ------------------------------------------------------------------ +// ciSymbol::index_of +// +// Determines where the symbol contains the given substring. +int ciSymbol::index_of_at(int i, const char* str, int len) const { + GUARDED_VM_ENTRY(return get_symbolOop()->index_of_at(i, str, len);) +} + +// ------------------------------------------------------------------ // ciSymbol::utf8_length int ciSymbol::utf8_length() { GUARDED_VM_ENTRY(return get_symbolOop()->utf8_length();) diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciSymbol.hpp --- a/src/share/vm/ci/ciSymbol.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciSymbol.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ // machine. class ciSymbol : public ciObject { CI_PACKAGE_ACCESS + // These friends all make direct use of get_symbolOop: friend class ciEnv; friend class ciInstanceKlass; friend class ciSignature; @@ -38,13 +39,13 @@ ciSymbol(symbolOop s) : ciObject(s) {} ciSymbol(symbolHandle s); // for use with vmSymbolHandles - symbolOop get_symbolOop() { return (symbolOop)get_oop(); } + symbolOop get_symbolOop() const { return (symbolOop)get_oop(); } const char* type_string() { return "ciSymbol"; } void print_impl(outputStream* st); - int byte_at(int i); + // This is public in symbolOop but private here, because the base can move: jbyte* base(); // Make a ciSymbol from a C string (implementation). @@ -55,6 +56,15 @@ const char* as_utf8(); int utf8_length(); + // Return the i-th utf8 byte, where i < utf8_length + int byte_at(int i); + + // Tests if the symbol starts with the given prefix. + bool starts_with(const char* prefix, int len) const; + + // Determines where the symbol contains the given substring. + int index_of_at(int i, const char* str, int len) const; + // What kind of ciObject is this? bool is_symbol() { return true; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciType.cpp --- a/src/share/vm/ci/ciType.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciType.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -111,7 +111,7 @@ // short, etc. // Note: Bare T_ADDRESS means a raw pointer type, not a return_address. assert((uint)t < T_CONFLICT+1, "range check"); - if (t == T_OBJECT) return ciEnv::_Object; // java/lang/Object + if (t == T_OBJECT) return ciEnv::_Object_klass; // java/lang/Object assert(_basic_types[t] != NULL, "domain check"); return _basic_types[t]; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciTypeFlow.cpp --- a/src/share/vm/ci/ciTypeFlow.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciTypeFlow.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -635,8 +635,15 @@ ciMethod* method = str->get_method(will_link); if (!will_link) { // We weren't able to find the method. - ciKlass* unloaded_holder = method->holder(); - trap(str, unloaded_holder, str->get_method_holder_index()); + if (str->cur_bc() == Bytecodes::_invokedynamic) { + trap(str, NULL, + Deoptimization::make_trap_request + (Deoptimization::Reason_uninitialized, + Deoptimization::Action_reinterpret)); + } else { + ciKlass* unloaded_holder = method->holder(); + trap(str, unloaded_holder, str->get_method_holder_index()); + } } else { ciSignature* signature = method->signature(); ciSignatureStream sigstr(signature); @@ -1292,8 +1299,8 @@ case Bytecodes::_invokeinterface: do_invoke(str, true); break; case Bytecodes::_invokespecial: do_invoke(str, true); break; case Bytecodes::_invokestatic: do_invoke(str, false); break; - case Bytecodes::_invokevirtual: do_invoke(str, true); break; + case Bytecodes::_invokedynamic: do_invoke(str, false); break; case Bytecodes::_istore: store_local_int(str->get_index()); break; case Bytecodes::_istore_0: store_local_int(0); break; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/ci/ciUtilities.hpp --- a/src/share/vm/ci/ciUtilities.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/ci/ciUtilities.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -79,7 +79,7 @@ THREAD); \ if (HAS_PENDING_EXCEPTION) { \ if (PENDING_EXCEPTION->klass() == \ - SystemDictionary::threaddeath_klass()) { \ + SystemDictionary::ThreadDeath_klass()) { \ /* Kill the compilation. */ \ fatal("unhandled ci exception"); \ return (result); \ diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/classFileParser.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -430,7 +430,7 @@ case JVM_CONSTANT_UnresolvedClass : // Patching a class means pre-resolving it. // The name in the constant pool is ignored. - if (patch->klass() == SystemDictionary::class_klass()) { // %%% java_lang_Class::is_instance + if (patch->klass() == SystemDictionary::Class_klass()) { // %%% java_lang_Class::is_instance guarantee_property(!java_lang_Class::is_primitive(patch()), "Illegal class patch at %d in class file %s", index, CHECK); @@ -643,7 +643,7 @@ guarantee_property(value_type.is_int(), "Inconsistent constant value type in class file %s", CHECK); break; case T_OBJECT: - guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;", 18) + guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;") && (value_type.is_string() || value_type.is_unresolved_string())), "Bad string initial value in class file %s", CHECK); break; @@ -1718,9 +1718,7 @@ m->set_exception_table(exception_handlers()); // Copy byte codes - if (code_length > 0) { - memcpy(m->code_base(), code_start, code_length); - } + m->set_code(code_start); // Copy line number table if (linenumber_table != NULL) { @@ -3471,8 +3469,8 @@ #endif // Check if this klass supports the java.lang.Cloneable interface - if (SystemDictionary::cloneable_klass_loaded()) { - if (k->is_subtype_of(SystemDictionary::cloneable_klass())) { + if (SystemDictionary::Cloneable_klass_loaded()) { + if (k->is_subtype_of(SystemDictionary::Cloneable_klass())) { k->set_is_cloneable(); } } @@ -4178,7 +4176,7 @@ // Check if ch is Java identifier start or is Java identifier part // 4672820: call java.lang.Character methods directly without generating separate tables. EXCEPTION_MARK; - instanceKlassHandle klass (THREAD, SystemDictionary::char_klass()); + instanceKlassHandle klass (THREAD, SystemDictionary::Character_klass()); // return value JavaValue result(T_BOOLEAN); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/classLoader.cpp --- a/src/share/vm/classfile/classLoader.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/classLoader.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -819,7 +819,7 @@ _package_hash_table->copy_pkgnames(packages); } // Allocate objArray and fill with java.lang.String - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), nof_entries, CHECK_0); objArrayHandle result(THREAD, r); for (int i = 0; i < nof_entries; i++) { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/javaAssertions.cpp --- a/src/share/vm/classfile/javaAssertions.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/javaAssertions.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -95,14 +95,14 @@ int len; typeArrayOop t; len = OptionList::count(_packages); - objArrayOop pn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL); + objArrayOop pn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL); objArrayHandle pkgNames (THREAD, pn); t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL); typeArrayHandle pkgEnabled(THREAD, t); fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL); len = OptionList::count(_classes); - objArrayOop cn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL); + objArrayOop cn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL); objArrayHandle classNames (THREAD, cn); t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL); typeArrayHandle classEnabled(THREAD, t); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/javaClasses.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -68,9 +68,9 @@ // and the char array it points to end up in the same cache line. oop obj; if (tenured) { - obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_permanent_instance(CHECK_NH); + obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_permanent_instance(CHECK_NH); } else { - obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_instance(CHECK_NH); + obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_instance(CHECK_NH); } // Create the char array. The String object must be handlized here @@ -293,7 +293,7 @@ bool java_lang_String::equals(oop java_string, jchar* chars, int len) { assert(SharedSkipVerify || - java_string->klass() == SystemDictionary::string_klass(), + java_string->klass() == SystemDictionary::String_klass(), "must be java_string"); typeArrayOop value = java_lang_String::value(java_string); int offset = java_lang_String::offset(java_string); @@ -311,7 +311,7 @@ void java_lang_String::print(Handle java_string, outputStream* st) { oop obj = java_string(); - assert(obj->klass() == SystemDictionary::string_klass(), "must be java_string"); + assert(obj->klass() == SystemDictionary::String_klass(), "must be java_string"); typeArrayOop value = java_lang_String::value(obj); int offset = java_lang_String::offset(obj); int length = java_lang_String::length(obj); @@ -339,9 +339,9 @@ // class is put into the system dictionary. int computed_modifiers = k->compute_modifier_flags(CHECK_0); k->set_modifier_flags(computed_modifiers); - if (SystemDictionary::class_klass_loaded()) { + if (SystemDictionary::Class_klass_loaded()) { // Allocate mirror (java.lang.Class instance) - Handle mirror = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0); + Handle mirror = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0); // Setup indirections mirror->obj_field_put(klass_offset, k()); k->set_java_mirror(mirror()); @@ -378,7 +378,7 @@ oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) { // This should be improved by adding a field at the Java level or by // introducing a new VM klass (see comment in ClassFileParser) - oop java_class = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0); + oop java_class = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0); if (type != T_VOID) { klassOop aklass = Universe::typeArrayKlassObj(type); assert(aklass != NULL, "correct bootstrap"); @@ -502,7 +502,7 @@ oop java_lang_Class::primitive_mirror(BasicType t) { oop mirror = Universe::java_mirror(t); - assert(mirror != NULL && mirror->is_a(SystemDictionary::class_klass()), "must be a Class"); + assert(mirror != NULL && mirror->is_a(SystemDictionary::Class_klass()), "must be a Class"); assert(java_lang_Class::is_primitive(mirror), "must be primitive"); return mirror; } @@ -515,14 +515,14 @@ assert(!offsets_computed, "offsets should be initialized only once"); offsets_computed = true; - klassOop k = SystemDictionary::class_klass(); + klassOop k = SystemDictionary::Class_klass(); // The classRedefinedCount field is only present starting in 1.5, // so don't go fatal. compute_optional_offset(classRedefinedCount_offset, k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); // The field indicating parallelCapable (parallelLockMap) is only present starting in 7, - klassOop k1 = SystemDictionary::classloader_klass(); + klassOop k1 = SystemDictionary::ClassLoader_klass(); compute_optional_offset(parallelCapable_offset, k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); } @@ -588,7 +588,7 @@ void java_lang_Thread::compute_offsets() { assert(_group_offset == 0, "offsets should be initialized only once"); - klassOop k = SystemDictionary::thread_klass(); + klassOop k = SystemDictionary::Thread_klass(); compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::char_array_signature()); compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature()); compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature()); @@ -847,7 +847,7 @@ void java_lang_ThreadGroup::compute_offsets() { assert(_parent_offset == 0, "offsets should be initialized only once"); - klassOop k = SystemDictionary::threadGroup_klass(); + klassOop k = SystemDictionary::ThreadGroup_klass(); compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature()); compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); @@ -1344,7 +1344,7 @@ // No-op if stack trace is disabled if (!StackTraceInThrowable) return; - assert(throwable->is_a(SystemDictionary::throwable_klass()), "sanity check"); + assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check"); oop backtrace = java_lang_Throwable::backtrace(throwable()); assert(backtrace != NULL, "backtrace not preallocated"); @@ -1449,7 +1449,7 @@ assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4"); // Allocate java.lang.StackTraceElement instance - klassOop k = SystemDictionary::stackTraceElement_klass(); + klassOop k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); instanceKlassHandle ik (THREAD, k); if (ik->should_be_initialized()) { @@ -1487,7 +1487,7 @@ void java_lang_reflect_AccessibleObject::compute_offsets() { - klassOop k = SystemDictionary::reflect_accessible_object_klass(); + klassOop k = SystemDictionary::reflect_AccessibleObject_klass(); compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); } @@ -1502,7 +1502,7 @@ } void java_lang_reflect_Method::compute_offsets() { - klassOop k = SystemDictionary::reflect_method_klass(); + klassOop k = SystemDictionary::reflect_Method_klass(); compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature()); @@ -1523,7 +1523,7 @@ Handle java_lang_reflect_Method::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); - klassOop klass = SystemDictionary::reflect_method_klass(); + klassOop klass = SystemDictionary::reflect_Method_klass(); // This class is eagerly initialized during VM initialization, since we keep a refence // to one of the methods assert(instanceKlass::cast(klass)->is_initialized(), "must be initialized"); @@ -1665,7 +1665,7 @@ } void java_lang_reflect_Constructor::compute_offsets() { - klassOop k = SystemDictionary::reflect_constructor_klass(); + klassOop k = SystemDictionary::reflect_Constructor_klass(); compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature()); compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature()); @@ -1789,7 +1789,7 @@ } void java_lang_reflect_Field::compute_offsets() { - klassOop k = SystemDictionary::reflect_field_klass(); + klassOop k = SystemDictionary::reflect_Field_klass(); compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature()); @@ -1896,7 +1896,7 @@ void sun_reflect_ConstantPool::compute_offsets() { - klassOop k = SystemDictionary::reflect_constant_pool_klass(); + klassOop k = SystemDictionary::reflect_ConstantPool_klass(); // This null test can be removed post beta if (k != NULL) { compute_offset(_cp_oop_offset, k, vmSymbols::constantPoolOop_name(), vmSymbols::object_signature()); @@ -1906,7 +1906,7 @@ Handle sun_reflect_ConstantPool::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); - klassOop k = SystemDictionary::reflect_constant_pool_klass(); + klassOop k = SystemDictionary::reflect_ConstantPool_klass(); instanceKlassHandle klass (THREAD, k); // Ensure it is initialized klass->initialize(CHECK_NH); @@ -1926,7 +1926,7 @@ } void sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() { - klassOop k = SystemDictionary::reflect_unsafe_static_field_accessor_impl_klass(); + klassOop k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass(); // This null test can be removed post beta if (k != NULL) { compute_offset(_base_offset, k, @@ -2072,7 +2072,7 @@ // Support for java_lang_ref_Reference oop java_lang_ref_Reference::pending_list_lock() { - instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass()); char *addr = (((char *)ik->start_of_static_fields()) + static_lock_offset); if (UseCompressedOops) { return oopDesc::load_decode_heap_oop((narrowOop *)addr); @@ -2082,7 +2082,7 @@ } HeapWord *java_lang_ref_Reference::pending_list_addr() { - instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass()); char *addr = (((char *)ik->start_of_static_fields()) + static_pending_offset); // XXX This might not be HeapWord aligned, almost rather be char *. return (HeapWord*)addr; @@ -2105,17 +2105,17 @@ } jlong java_lang_ref_SoftReference::clock() { - instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass()); int offset = ik->offset_of_static_fields() + static_clock_offset; - return SystemDictionary::soft_reference_klass()->long_field(offset); + return SystemDictionary::SoftReference_klass()->long_field(offset); } void java_lang_ref_SoftReference::set_clock(jlong value) { - instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass()); int offset = ik->offset_of_static_fields() + static_clock_offset; - SystemDictionary::soft_reference_klass()->long_field_put(offset, value); + SystemDictionary::SoftReference_klass()->long_field_put(offset, value); } @@ -2403,6 +2403,10 @@ return ptypes(mt)->obj_at(idx); } +int java_dyn_MethodType::ptype_count(oop mt) { + return ptypes(mt)->length(); +} + // Support for java_dyn_MethodTypeForm @@ -2534,7 +2538,7 @@ // the generated bytecodes for reflection, and if so, "magically" // delegate to its parent to prevent class loading from occurring // in places where applications using reflection didn't expect it. - klassOop delegating_cl_class = SystemDictionary::reflect_delegating_classloader_klass(); + klassOop delegating_cl_class = SystemDictionary::reflect_DelegatingClassLoader_klass(); // This might be null in non-1.4 JDKs if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) { return parent(loader); @@ -2549,7 +2553,7 @@ void java_lang_System::compute_offsets() { assert(offset_of_static_fields == 0, "offsets should be initialized only once"); - instanceKlass* ik = instanceKlass::cast(SystemDictionary::system_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::System_klass()); offset_of_static_fields = ik->offset_of_static_fields(); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/javaClasses.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -111,7 +111,7 @@ // Testers static bool is_instance(oop obj) { - return obj != NULL && obj->klass() == SystemDictionary::string_klass(); + return obj != NULL && obj->klass() == SystemDictionary::String_klass(); } // Debugging @@ -161,7 +161,7 @@ static void print_signature(oop java_class, outputStream *st); // Testing static bool is_instance(oop obj) { - return obj != NULL && obj->klass() == SystemDictionary::class_klass(); + return obj != NULL && obj->klass() == SystemDictionary::Class_klass(); } static bool is_primitive(oop java_class); static BasicType primitive_type(oop java_class); @@ -1027,6 +1027,7 @@ static oop form(oop mt); static oop ptype(oop mt, int index); + static int ptype_count(oop mt); static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS); static void print_signature(oop mt, outputStream* st); @@ -1083,6 +1084,14 @@ static oop vmmethod(oop site); static void set_vmmethod(oop site, oop ref); + // Testers + static bool is_subclass(klassOop klass) { + return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass()); + } + static bool is_instance(oop obj) { + return obj != NULL && is_subclass(obj->klass()); + } + // Accessors for code generation: static int target_offset_in_bytes() { return _target_offset; } static int type_offset_in_bytes() { return _type_offset; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/systemDictionary.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -60,10 +60,10 @@ } void SystemDictionary::compute_java_system_loader(TRAPS) { - KlassHandle system_klass(THREAD, WK_KLASS(classloader_klass)); + KlassHandle system_klass(THREAD, WK_KLASS(ClassLoader_klass)); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, - KlassHandle(THREAD, WK_KLASS(classloader_klass)), + KlassHandle(THREAD, WK_KLASS(ClassLoader_klass)), vmSymbolHandles::getSystemClassLoader_name(), vmSymbolHandles::void_classloader_signature(), CHECK); @@ -128,7 +128,7 @@ // in which case we have to check whether the pending exception is a ClassNotFoundException, // and if so convert it to a NoClassDefFoundError // And chain the original ClassNotFoundException - if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass())) { + if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass())) { ResourceMark rm(THREAD); assert(klass_h() == NULL, "Should not have result with exception pending"); Handle e(THREAD, PENDING_EXCEPTION); @@ -359,7 +359,7 @@ assert(class_loader() != NULL, "should not have non-null protection domain for null classloader"); - KlassHandle system_loader(THREAD, SystemDictionary::classloader_klass()); + KlassHandle system_loader(THREAD, SystemDictionary::ClassLoader_klass()); JavaCalls::call_special(&result, class_loader, system_loader, @@ -743,7 +743,7 @@ // Bootstrap goes through here to allow for an extra guarantee check if (UnsyncloadClass || (class_loader.is_null())) { if (k.is_null() && HAS_PENDING_EXCEPTION - && PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) { + && PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { MutexLocker mu(SystemDictionary_lock, THREAD); klassOop check = find_class(d_index, d_hash, name, class_loader); if (check != NULL) { @@ -1367,7 +1367,7 @@ JavaValue result(T_OBJECT); - KlassHandle spec_klass (THREAD, SystemDictionary::classloader_klass()); + KlassHandle spec_klass (THREAD, SystemDictionary::ClassLoader_klass()); // Call public unsynchronized loadClass(String) directly for all class loaders // for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will @@ -1944,13 +1944,13 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { - assert(WK_KLASS(object_klass) == NULL, "preloaded classes should only be initialized once"); + assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once"); // Preload commonly used klasses WKID scan = FIRST_WKID; // first do Object, String, Class - initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(class_klass), scan, CHECK); + initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK); - debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(class_klass))); + debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(Class_klass))); // Fixup mirrors for classes loaded before java.lang.Class. // These calls iterate over the objects currently in the perm gen @@ -1961,17 +1961,17 @@ Universe::fixup_mirrors(CHECK); // do a bunch more: - initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(reference_klass), scan, CHECK); + initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Reference_klass), scan, CHECK); // Preload ref klasses and set reference types - instanceKlass::cast(WK_KLASS(reference_klass))->set_reference_type(REF_OTHER); - instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(reference_klass)); + instanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER); + instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass)); - initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(phantom_reference_klass), scan, CHECK); - instanceKlass::cast(WK_KLASS(soft_reference_klass))->set_reference_type(REF_SOFT); - instanceKlass::cast(WK_KLASS(weak_reference_klass))->set_reference_type(REF_WEAK); - instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL); - instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM); + initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK); + instanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT); + instanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK); + instanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL); + instanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM); WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass); WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass); @@ -1984,7 +1984,7 @@ scan = WKID(meth_group_end+1); } WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass); - WKID indy_group_end = WK_KLASS_ENUM_NAME(Dynamic_klass); + WKID indy_group_end = WK_KLASS_ENUM_NAME(InvokeDynamic_klass); initialize_wk_klasses_until(indy_group_start, scan, CHECK); if (EnableInvokeDynamic) { initialize_wk_klasses_through(indy_group_end, scan, CHECK); @@ -1996,14 +1996,14 @@ initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK); - _box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass); - _box_klasses[T_CHAR] = WK_KLASS(char_klass); - _box_klasses[T_FLOAT] = WK_KLASS(float_klass); - _box_klasses[T_DOUBLE] = WK_KLASS(double_klass); - _box_klasses[T_BYTE] = WK_KLASS(byte_klass); - _box_klasses[T_SHORT] = WK_KLASS(short_klass); - _box_klasses[T_INT] = WK_KLASS(int_klass); - _box_klasses[T_LONG] = WK_KLASS(long_klass); + _box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass); + _box_klasses[T_CHAR] = WK_KLASS(Character_klass); + _box_klasses[T_FLOAT] = WK_KLASS(Float_klass); + _box_klasses[T_DOUBLE] = WK_KLASS(Double_klass); + _box_klasses[T_BYTE] = WK_KLASS(Byte_klass); + _box_klasses[T_SHORT] = WK_KLASS(Short_klass); + _box_klasses[T_INT] = WK_KLASS(Integer_klass); + _box_klasses[T_LONG] = WK_KLASS(Long_klass); //_box_klasses[T_OBJECT] = WK_KLASS(object_klass); //_box_klasses[T_ARRAY] = WK_KLASS(object_klass); @@ -2014,11 +2014,11 @@ #endif // KERNEL { // Compute whether we should use loadClass or loadClassInternal when loading classes. - methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); + methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); _has_loadClassInternal = (method != NULL); } { // Compute whether we should use checkPackageAccess or NOT - methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature()); + methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature()); _has_checkPackageAccess = (method != NULL); } } @@ -2340,6 +2340,8 @@ SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature); if (spe == NULL || spe->property_oop() == NULL) { // Must create lots of stuff here, but outside of the SystemDictionary lock. + if (THREAD->is_Compiler_thread()) + return NULL; // do not attempt from within compiler Handle mt = compute_method_handle_type(signature(), class_loader, protection_domain, CHECK_NULL); @@ -2372,7 +2374,7 @@ TRAPS) { Handle empty; int npts = ArgumentCount(signature()).size(); - objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty)); + objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); int arg = 0; Handle rt; // the return type from the signature for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/systemDictionary.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -82,55 +82,55 @@ #define WK_KLASSES_DO(template) \ /* well-known classes */ \ - template(object_klass, java_lang_Object, Pre) \ - template(string_klass, java_lang_String, Pre) \ - template(class_klass, java_lang_Class, Pre) \ - template(cloneable_klass, java_lang_Cloneable, Pre) \ - template(classloader_klass, java_lang_ClassLoader, Pre) \ - template(serializable_klass, java_io_Serializable, Pre) \ - template(system_klass, java_lang_System, Pre) \ - template(throwable_klass, java_lang_Throwable, Pre) \ - template(error_klass, java_lang_Error, Pre) \ - template(threaddeath_klass, java_lang_ThreadDeath, Pre) \ - template(exception_klass, java_lang_Exception, Pre) \ - template(runtime_exception_klass, java_lang_RuntimeException, Pre) \ - template(protectionDomain_klass, java_security_ProtectionDomain, Pre) \ + template(Object_klass, java_lang_Object, Pre) \ + template(String_klass, java_lang_String, Pre) \ + template(Class_klass, java_lang_Class, Pre) \ + template(Cloneable_klass, java_lang_Cloneable, Pre) \ + template(ClassLoader_klass, java_lang_ClassLoader, Pre) \ + template(Serializable_klass, java_io_Serializable, Pre) \ + template(System_klass, java_lang_System, Pre) \ + template(Throwable_klass, java_lang_Throwable, Pre) \ + template(Error_klass, java_lang_Error, Pre) \ + template(ThreadDeath_klass, java_lang_ThreadDeath, Pre) \ + template(Exception_klass, java_lang_Exception, Pre) \ + template(RuntimeException_klass, java_lang_RuntimeException, Pre) \ + template(ProtectionDomain_klass, java_security_ProtectionDomain, Pre) \ template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \ - template(classNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \ - template(noClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \ - template(linkageError_klass, java_lang_LinkageError, Pre) \ + template(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \ + template(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \ + template(LinkageError_klass, java_lang_LinkageError, Pre) \ template(ClassCastException_klass, java_lang_ClassCastException, Pre) \ template(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre) \ - template(virtualMachineError_klass, java_lang_VirtualMachineError, Pre) \ + template(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre) \ template(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre) \ template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \ template(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre) \ - template(reference_klass, java_lang_ref_Reference, Pre) \ + template(Reference_klass, java_lang_ref_Reference, Pre) \ \ /* Preload ref klasses and set reference types */ \ - template(soft_reference_klass, java_lang_ref_SoftReference, Pre) \ - template(weak_reference_klass, java_lang_ref_WeakReference, Pre) \ - template(final_reference_klass, java_lang_ref_FinalReference, Pre) \ - template(phantom_reference_klass, java_lang_ref_PhantomReference, Pre) \ - template(finalizer_klass, java_lang_ref_Finalizer, Pre) \ + template(SoftReference_klass, java_lang_ref_SoftReference, Pre) \ + template(WeakReference_klass, java_lang_ref_WeakReference, Pre) \ + template(FinalReference_klass, java_lang_ref_FinalReference, Pre) \ + template(PhantomReference_klass, java_lang_ref_PhantomReference, Pre) \ + template(Finalizer_klass, java_lang_ref_Finalizer, Pre) \ \ - template(thread_klass, java_lang_Thread, Pre) \ - template(threadGroup_klass, java_lang_ThreadGroup, Pre) \ - template(properties_klass, java_util_Properties, Pre) \ - template(reflect_accessible_object_klass, java_lang_reflect_AccessibleObject, Pre) \ - template(reflect_field_klass, java_lang_reflect_Field, Pre) \ - template(reflect_method_klass, java_lang_reflect_Method, Pre) \ - template(reflect_constructor_klass, java_lang_reflect_Constructor, Pre) \ + template(Thread_klass, java_lang_Thread, Pre) \ + template(ThreadGroup_klass, java_lang_ThreadGroup, Pre) \ + template(Properties_klass, java_util_Properties, Pre) \ + template(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre) \ + template(reflect_Field_klass, java_lang_reflect_Field, Pre) \ + template(reflect_Method_klass, java_lang_reflect_Method, Pre) \ + template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \ \ /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ - template(reflect_magic_klass, sun_reflect_MagicAccessorImpl, Opt) \ - template(reflect_method_accessor_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_constructor_accessor_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_delegating_classloader_klass, sun_reflect_DelegatingClassLoader, Opt) \ - template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ - template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ + template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ + template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ + template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ + template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \ @@ -144,16 +144,14 @@ template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \ template(Linkage_klass, java_dyn_Linkage, Opt) \ template(CallSite_klass, java_dyn_CallSite, Opt) \ - template(Dynamic_klass, java_dyn_Dynamic, Opt) \ + template(InvokeDynamic_klass, java_dyn_InvokeDynamic, Opt) \ /* Note: MethodHandle must be first, and Dynamic last in group */ \ \ - template(vector_klass, java_util_Vector, Pre) \ - template(hashtable_klass, java_util_Hashtable, Pre) \ - template(stringBuffer_klass, java_lang_StringBuffer, Pre) \ + template(StringBuffer_klass, java_lang_StringBuffer, Pre) \ template(StringBuilder_klass, java_lang_StringBuilder, Pre) \ \ /* It's NULL in non-1.4 JDKs. */ \ - template(stackTraceElement_klass, java_lang_StackTraceElement, Opt) \ + template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \ /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \ @@ -164,14 +162,14 @@ template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \ \ /* Preload boxing klasses */ \ - template(boolean_klass, java_lang_Boolean, Pre) \ - template(char_klass, java_lang_Character, Pre) \ - template(float_klass, java_lang_Float, Pre) \ - template(double_klass, java_lang_Double, Pre) \ - template(byte_klass, java_lang_Byte, Pre) \ - template(short_klass, java_lang_Short, Pre) \ - template(int_klass, java_lang_Integer, Pre) \ - template(long_klass, java_lang_Long, Pre) \ + template(Boolean_klass, java_lang_Boolean, Pre) \ + template(Character_klass, java_lang_Character, Pre) \ + template(Float_klass, java_lang_Float, Pre) \ + template(Double_klass, java_lang_Double, Pre) \ + template(Byte_klass, java_lang_Byte, Pre) \ + template(Short_klass, java_lang_Short, Pre) \ + template(Integer_klass, java_lang_Integer, Pre) \ + template(Long_klass, java_lang_Long, Pre) \ /*end*/ @@ -438,8 +436,8 @@ // Tells whether ClassLoader.checkPackageAccess is present static bool has_checkPackageAccess() { return _has_checkPackageAccess; } - static bool class_klass_loaded() { return WK_KLASS(class_klass) != NULL; } - static bool cloneable_klass_loaded() { return WK_KLASS(cloneable_klass) != NULL; } + static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; } + static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; } // Returns default system loader static oop java_system_loader(); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/verifier.cpp --- a/src/share/vm/classfile/verifier.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/verifier.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -143,7 +143,7 @@ bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) { symbolOop name = klass->name(); - klassOop refl_magic_klass = SystemDictionary::reflect_magic_klass(); + klassOop refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass(); return (should_verify_for(klass->class_loader(), should_verify_class) && // return if the class is a bootstrapping class diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/vmSymbols.cpp --- a/src/share/vm/classfile/vmSymbols.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/vmSymbols.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,6 +70,7 @@ void vmSymbols::initialize(TRAPS) { assert((int)SID_LIMIT <= (1< (1<find_method(mname, msig); +} + #define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0" static const char* vm_intrinsic_name_bodies = @@ -330,15 +383,15 @@ } // These are for forming case labels: -#define ID3(x, y, z) (( jint)(z) + \ - ((jint)(y) << vmSymbols::log2_SID_LIMIT) + \ - ((jint)(x) << (2*vmSymbols::log2_SID_LIMIT)) ) +#define ID3(x, y, z) (( jlong)(z) + \ + ((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \ + ((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) ) #define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n) -vmIntrinsics::ID vmIntrinsics::find_id(vmSymbols::SID holder, - vmSymbols::SID name, - vmSymbols::SID sig, - jshort flags) { +vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder, + vmSymbols::SID name, + vmSymbols::SID sig, + jshort flags) { assert((int)vmSymbols::SID_LIMIT <= (1<> shift) & mask) == 1021, ""); + return vmSymbols::SID( (info >> shift) & mask ); } vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) { -#ifndef PRODUCT -#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ - case id: return SID_ENUM(name); - - switch (id) { - VM_INTRINSICS_DO(VM_INTRINSIC_CASE, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); - } -#undef VM_INTRINSIC_CASE -#endif //PRODUCT - return vmSymbols::NO_SID; + jlong info = intrinsic_info(id); + int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, ""); + return vmSymbols::SID( (info >> shift) & mask ); } vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) { -#ifndef PRODUCT -#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ - case id: return SID_ENUM(sig); - - switch (id) { - VM_INTRINSICS_DO(VM_INTRINSIC_CASE, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); - } -#undef VM_INTRINSIC_CASE -#endif //PRODUCT - return vmSymbols::NO_SID; + jlong info = intrinsic_info(id); + int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, ""); + return vmSymbols::SID( (info >> shift) & mask ); } vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) { -#ifndef PRODUCT -#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ - case id: return fcode; - - switch (id) { - VM_INTRINSICS_DO(VM_INTRINSIC_CASE, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); - } -#undef VM_INTRINSIC_CASE -#endif //PRODUCT - return F_none; + jlong info = intrinsic_info(id); + int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, ""); + return Flags( (info >> shift) & mask ); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/classfile/vmSymbols.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -219,7 +219,7 @@ template(base_name, "base") \ \ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ - template(java_dyn_Dynamic, "java/dyn/Dynamic") \ + template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") \ template(java_dyn_Linkage, "java/dyn/Linkage") \ template(java_dyn_CallSite, "java/dyn/CallSite") \ template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \ @@ -347,9 +347,14 @@ \ /* common signatures names */ \ template(void_method_signature, "()V") \ + template(void_boolean_signature, "()Z") \ + template(void_byte_signature, "()B") \ + template(void_char_signature, "()C") \ + template(void_short_signature, "()S") \ template(void_int_signature, "()I") \ template(void_long_signature, "()J") \ - template(void_boolean_signature, "()Z") \ + template(void_float_signature, "()F") \ + template(void_double_signature, "()D") \ template(int_void_signature, "(I)V") \ template(int_int_signature, "(I)I") \ template(int_bool_signature, "(I)Z") \ @@ -854,6 +859,46 @@ \ do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ /* (symbols invoke_name and invoke_signature defined above) */ \ + do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \ + do_name( checkSpreadArgument_name, "checkSpreadArgument") \ + do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \ + \ + /* unboxing methods: */ \ + do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ + do_name( booleanValue_name, "booleanValue") \ + do_intrinsic(_byteValue, java_lang_Byte, byteValue_name, void_byte_signature, F_R) \ + do_name( byteValue_name, "byteValue") \ + do_intrinsic(_charValue, java_lang_Character, charValue_name, void_char_signature, F_R) \ + do_name( charValue_name, "charValue") \ + do_intrinsic(_shortValue, java_lang_Short, shortValue_name, void_short_signature, F_R) \ + do_name( shortValue_name, "shortValue") \ + do_intrinsic(_intValue, java_lang_Integer, intValue_name, void_int_signature, F_R) \ + do_name( intValue_name, "intValue") \ + do_intrinsic(_longValue, java_lang_Long, longValue_name, void_long_signature, F_R) \ + do_name( longValue_name, "longValue") \ + do_intrinsic(_floatValue, java_lang_Float, floatValue_name, void_float_signature, F_R) \ + do_name( floatValue_name, "floatValue") \ + do_intrinsic(_doubleValue, java_lang_Double, doubleValue_name, void_double_signature, F_R) \ + do_name( doubleValue_name, "doubleValue") \ + \ + /* boxing methods: */ \ + do_name( valueOf_name, "valueOf") \ + do_intrinsic(_Boolean_valueOf, java_lang_Boolean, valueOf_name, Boolean_valueOf_signature, F_S) \ + do_name( Boolean_valueOf_signature, "(Z)Ljava/lang/Boolean;") \ + do_intrinsic(_Byte_valueOf, java_lang_Byte, valueOf_name, Byte_valueOf_signature, F_S) \ + do_name( Byte_valueOf_signature, "(B)Ljava/lang/Byte;") \ + do_intrinsic(_Character_valueOf, java_lang_Character, valueOf_name, Character_valueOf_signature, F_S) \ + do_name( Character_valueOf_signature, "(C)Ljava/lang/Character;") \ + do_intrinsic(_Short_valueOf, java_lang_Short, valueOf_name, Short_valueOf_signature, F_S) \ + do_name( Short_valueOf_signature, "(S)Ljava/lang/Short;") \ + do_intrinsic(_Integer_valueOf, java_lang_Integer, valueOf_name, Integer_valueOf_signature, F_S) \ + do_name( Integer_valueOf_signature, "(I)Ljava/lang/Integer;") \ + do_intrinsic(_Long_valueOf, java_lang_Long, valueOf_name, Long_valueOf_signature, F_S) \ + do_name( Long_valueOf_signature, "(J)Ljava/lang/Long;") \ + do_intrinsic(_Float_valueOf, java_lang_Float, valueOf_name, Float_valueOf_signature, F_S) \ + do_name( Float_valueOf_signature, "(F)Ljava/lang/Float;") \ + do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \ + do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \ \ /*end*/ @@ -984,7 +1029,12 @@ F_Y, // !static ?native synchronized F_RN, // !static native !synchronized F_SN, // static native !synchronized - F_RNY // !static native synchronized + F_RNY, // !static native synchronized + + FLAG_LIMIT + }; + enum { + log2_FLAG_LIMIT = 4 // checked by an assert at start-up }; public: @@ -996,15 +1046,32 @@ static const char* name_at(ID id); +private: + static ID find_id_impl(vmSymbols::SID holder, + vmSymbols::SID name, + vmSymbols::SID sig, + jshort flags); + +public: // Given a method's class, name, signature, and access flags, report its ID. static ID find_id(vmSymbols::SID holder, vmSymbols::SID name, vmSymbols::SID sig, - jshort flags); + jshort flags) { + ID id = find_id_impl(holder, name, sig, flags); +#ifdef ASSERT + // ID _none does not hold the following asserts. + if (id == _none) return id; +#endif + assert( class_for(id) == holder, "correct id"); + assert( name_for(id) == name, "correct id"); + assert(signature_for(id) == sig, "correct id"); + return id; + } static void verify_method(ID actual_id, methodOop m) PRODUCT_RETURN; - // No need for these in the product: + // Find out the symbols behind an intrinsic: static vmSymbols::SID class_for(ID id); static vmSymbols::SID name_for(ID id); static vmSymbols::SID signature_for(ID id); @@ -1014,4 +1081,11 @@ // Access to intrinsic methods: static methodOop method_for(ID id); + + // Wrapper object methods: + static ID for_boxing(BasicType type); + static ID for_unboxing(BasicType type); + + // Raw conversion: + static ID for_raw_conversion(BasicType src, BasicType dest); }; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/code/codeBlob.hpp --- a/src/share/vm/code/codeBlob.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/code/codeBlob.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,6 +102,9 @@ virtual bool is_compiled_by_c2() const { return false; } virtual bool is_compiled_by_c1() const { return false; } + // Casting + nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; } + // Boundaries address header_begin() const { return (address) this; } address header_end() const { return ((address) this) + _header_size; }; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/code/debugInfoRec.cpp --- a/src/share/vm/code/debugInfoRec.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/code/debugInfoRec.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -281,6 +281,7 @@ ciMethod* method, int bci, bool reexecute, + bool is_method_handle_invoke, DebugToken* locals, DebugToken* expressions, DebugToken* monitors) { @@ -292,8 +293,9 @@ int stream_offset = stream()->position(); last_pd->set_scope_decode_offset(stream_offset); - // Record reexecute bit into pcDesc + // Record flags into pcDesc. last_pd->set_should_reexecute(reexecute); + last_pd->set_is_method_handle_invoke(is_method_handle_invoke); // serialize sender stream offest stream()->write_int(sender_stream_offset); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/code/debugInfoRec.hpp --- a/src/share/vm/code/debugInfoRec.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/code/debugInfoRec.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -88,6 +88,7 @@ ciMethod* method, int bci, bool reexecute, + bool is_method_handle_invoke = false, DebugToken* locals = NULL, DebugToken* expressions = NULL, DebugToken* monitors = NULL); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/code/nmethod.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1170,7 +1170,7 @@ } // Common functionality for both make_not_entrant and make_zombie -bool nmethod::make_not_entrant_or_zombie(int state) { +bool nmethod::make_not_entrant_or_zombie(unsigned int state) { assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); // If the method is already zombie there is nothing to do @@ -1724,9 +1724,9 @@ if (!method()->is_native()) { SimpleScopeDesc ssd(this, fr.pc()); Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci()); - bool is_static = call->is_invokestatic(); + bool has_receiver = call->has_receiver(); symbolOop signature = call->signature(); - fr.oops_compiled_arguments_do(signature, is_static, reg_map, f); + fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f); } } @@ -1763,6 +1763,14 @@ "must end with a sentinel"); #endif //ASSERT + // Search for MethodHandle invokes and tag the nmethod. + for (int i = 0; i < count; i++) { + if (pcs[i].is_method_handle_invoke()) { + set_has_method_handle_invokes(true); + break; + } + } + int size = count * sizeof(PcDesc); assert(scopes_pcs_size() >= size, "oob"); memcpy(scopes_pcs_begin(), pcs, size); @@ -2030,6 +2038,18 @@ // ----------------------------------------------------------------------------- +// 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 class VerifyOopsClosure: public OopClosure { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/code/nmethod.hpp --- a/src/share/vm/code/nmethod.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/code/nmethod.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -81,18 +81,19 @@ struct nmFlags { friend class VMStructs; - unsigned int version:8; // version number (0 = first version) - unsigned int level:4; // optimization level - unsigned int age:4; // age (in # of sweep steps) + unsigned int version:8; // version number (0 = first version) + unsigned int level:4; // optimization level + unsigned int age:4; // age (in # of sweep steps) - unsigned int state:2; // {alive, zombie, unloaded) + unsigned int state:2; // {alive, zombie, unloaded) - unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap? - unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures - unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies - unsigned int markedForReclamation:1; // Used by NMethodSweeper + unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap? + unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures + unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies + unsigned int markedForReclamation:1; // Used by NMethodSweeper - unsigned int has_unsafe_access:1; // May fault due to unsafe access. + unsigned int has_unsafe_access:1; // May fault due to unsafe access. + unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes? void clear(); }; @@ -254,7 +255,7 @@ const char* reloc_string_for(u_char* begin, u_char* end); // Returns true if this thread changed the state of the nmethod or // false if another thread performed the transition. - bool make_not_entrant_or_zombie(int state); + bool make_not_entrant_or_zombie(unsigned int state); void inc_decompile_count(); // used to check that writes to nmFlags are done consistently. @@ -409,6 +410,9 @@ bool has_unsafe_access() const { return flags.has_unsafe_access; } void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; } + bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; } + void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; } + int level() const { return flags.level; } void set_level(int newLevel) { check_safepoint(); flags.level = newLevel; } @@ -541,6 +545,9 @@ address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); } void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; } + // MethodHandle + bool is_method_handle_return(address return_pc); + // jvmti support: void post_compiled_method_load_event(); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/code/pcDesc.hpp --- a/src/share/vm/code/pcDesc.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/code/pcDesc.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -38,6 +38,7 @@ int word; struct { unsigned int reexecute: 1; + unsigned int is_method_handle_invoke: 1; } bits; bool operator ==(const PcDescFlags& other) { return word == other.word; } } _flags; @@ -72,6 +73,9 @@ _flags == pd->_flags; } + bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; } + void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; } + // Returns the real pc address real_pc(const nmethod* code) const; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/compiler/compileBroker.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1820,9 +1820,11 @@ CompileBroker::_t_standard_compilation.seconds(), CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count); tty->print_cr(" On stack replacement : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count); - compiler(CompLevel_fast_compile)->print_timers(); - if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier)) { - compiler(CompLevel_highest_tier)->print_timers(); + + if (compiler(CompLevel_fast_compile)) { + compiler(CompLevel_fast_compile)->print_timers(); + if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier)) + compiler(CompLevel_highest_tier)->print_timers(); } tty->cr(); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/compiler/methodLiveness.cpp --- a/src/share/vm/compiler/methodLiveness.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/compiler/methodLiveness.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -782,6 +782,7 @@ case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: case Bytecodes::_invokeinterface: + case Bytecodes::_invokedynamic: case Bytecodes::_newarray: case Bytecodes::_anewarray: case Bytecodes::_checkcast: diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/gc_interface/collectedHeap.cpp --- a/src/share/vm/gc_interface/collectedHeap.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -274,7 +274,7 @@ fill_with_array(start, words); } else if (words > 0) { assert(words == min_fill_size(), "unaligned size"); - post_allocation_setup_common(SystemDictionary::object_klass(), start, + post_allocation_setup_common(SystemDictionary::Object_klass(), start, words); } } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/includeDB_compiler2 --- a/src/share/vm/includeDB_compiler2 Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/includeDB_compiler2 Wed Jan 06 22:21:39 2010 -0800 @@ -155,6 +155,9 @@ callGenerator.cpp cfgnode.hpp callGenerator.cpp compileLog.hpp callGenerator.cpp connode.hpp +callGenerator.cpp ciCPCache.hpp +callGenerator.cpp ciMethodHandle.hpp +callGenerator.cpp javaClasses.hpp callGenerator.cpp parse.hpp callGenerator.cpp rootnode.hpp callGenerator.cpp runtime.hpp @@ -391,6 +394,9 @@ doCall.cpp addnode.hpp doCall.cpp callGenerator.hpp +doCall.cpp ciCallSite.hpp +doCall.cpp ciCPCache.hpp +doCall.cpp ciMethodHandle.hpp doCall.cpp cfgnode.hpp doCall.cpp compileLog.hpp doCall.cpp linkResolver.hpp diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/includeDB_core --- a/src/share/vm/includeDB_core Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/includeDB_core Wed Jan 06 22:21:39 2010 -0800 @@ -516,6 +516,11 @@ ciCallProfile.hpp ciClassList.hpp +ciCallSite.cpp ciCallSite.hpp +ciCallSite.cpp ciUtilities.hpp + +ciCallSite.hpp ciInstance.hpp + ciConstant.cpp allocation.hpp ciConstant.cpp allocation.inline.hpp ciConstant.cpp ciConstant.hpp @@ -532,6 +537,12 @@ ciConstantPoolCache.hpp growableArray.hpp ciConstantPoolCache.hpp resourceArea.hpp +ciCPCache.cpp cpCacheOop.hpp +ciCPCache.cpp ciCPCache.hpp + +ciCPCache.hpp ciClassList.hpp +ciCPCache.hpp ciObject.hpp + ciEnv.cpp allocation.inline.hpp ciEnv.cpp ciConstant.hpp ciEnv.cpp ciEnv.hpp @@ -593,6 +604,7 @@ ciField.hpp ciClassList.hpp ciField.hpp ciConstant.hpp ciField.hpp ciFlags.hpp +ciField.hpp ciInstance.hpp ciFlags.cpp ciFlags.hpp @@ -679,6 +691,7 @@ ciMethod.hpp ciInstanceKlass.hpp ciMethod.hpp ciObject.hpp ciMethod.hpp ciSignature.hpp +ciMethod.hpp methodHandles.hpp ciMethod.hpp methodLiveness.hpp ciMethodBlocks.cpp bytecode.hpp @@ -710,6 +723,15 @@ ciMethodKlass.hpp ciKlass.hpp ciMethodKlass.hpp ciSymbol.hpp +ciMethodHandle.cpp ciClassList.hpp +ciMethodHandle.cpp ciInstance.hpp +ciMethodHandle.cpp ciMethodHandle.hpp +ciMethodHandle.cpp ciUtilities.hpp +ciMethodHandle.cpp methodHandles.hpp +ciMethodHandle.cpp methodHandleWalk.hpp + +ciMethodHandle.hpp methodHandles.hpp + ciNullObject.cpp ciNullObject.hpp ciNullObject.hpp ciClassList.hpp @@ -755,11 +777,14 @@ ciObject.hpp jniHandles.hpp ciObjectFactory.cpp allocation.inline.hpp +ciObjectFactory.cpp ciCallSite.hpp +ciObjectFactory.cpp ciCPCache.hpp ciObjectFactory.cpp ciInstance.hpp ciObjectFactory.cpp ciInstanceKlass.hpp ciObjectFactory.cpp ciInstanceKlassKlass.hpp ciObjectFactory.cpp ciMethod.hpp ciObjectFactory.cpp ciMethodData.hpp +ciObjectFactory.cpp ciMethodHandle.hpp ciObjectFactory.cpp ciMethodKlass.hpp ciObjectFactory.cpp ciNullObject.hpp ciObjectFactory.cpp ciObjArray.hpp @@ -793,6 +818,7 @@ ciSignature.hpp globalDefinitions.hpp ciSignature.hpp growableArray.hpp +ciStreams.cpp ciCallSite.hpp ciStreams.cpp ciConstant.hpp ciStreams.cpp ciField.hpp ciStreams.cpp ciStreams.hpp @@ -2814,6 +2840,12 @@ methodDataOop.hpp orderAccess.hpp methodDataOop.hpp universe.hpp +methodHandleWalk.hpp methodHandles.hpp + +methodHandleWalk.cpp methodHandleWalk.hpp +methodHandleWalk.cpp oopFactory.hpp +methodHandleWalk.cpp rewriter.hpp + methodHandles.hpp frame.inline.hpp methodHandles.hpp globals.hpp methodHandles.hpp interfaceSupport.hpp diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/bytecode.cpp --- a/src/share/vm/interpreter/bytecode.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/bytecode.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -102,7 +102,9 @@ KlassHandle resolved_klass; constantPoolHandle constants(THREAD, _method->constants()); - if (adjusted_invoke_code() != Bytecodes::_invokeinterface) { + if (adjusted_invoke_code() == Bytecodes::_invokedynamic) { + LinkResolver::resolve_dynamic_method(m, resolved_klass, constants, index(), CHECK_(methodHandle())); + } else if (adjusted_invoke_code() != Bytecodes::_invokeinterface) { LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle())); } else { LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle())); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/bytecode.hpp --- a/src/share/vm/interpreter/bytecode.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/bytecode.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -205,12 +205,14 @@ bool is_invokespecial() const { return adjusted_invoke_code() == Bytecodes::_invokespecial; } bool is_invokedynamic() const { return adjusted_invoke_code() == Bytecodes::_invokedynamic; } + bool has_receiver() const { return !is_invokestatic() && !is_invokedynamic(); } bool has_giant_index() const { return is_invokedynamic(); } bool is_valid() const { return is_invokeinterface() || is_invokevirtual() || is_invokestatic() || - is_invokespecial(); } + is_invokespecial() || + is_invokedynamic(); } // Creation inline friend Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/bytecodeTracer.cpp --- a/src/share/vm/interpreter/bytecodeTracer.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/bytecodeTracer.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -270,6 +270,8 @@ st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name()); } else if (tag.is_unresolved_klass()) { st->print_cr(" ", i); + } else if (tag.is_object()) { + st->print_cr(" " PTR_FORMAT, constants->object_at(i)); } else { st->print_cr(" bad tag=%d at %d", tag.value(), i); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/bytecodes.cpp --- a/src/share/vm/interpreter/bytecodes.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/bytecodes.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -357,7 +357,7 @@ def(_invokespecial , "invokespecial" , "bjj" , NULL , T_ILLEGAL, -1, true); def(_invokestatic , "invokestatic" , "bjj" , NULL , T_ILLEGAL, 0, true); def(_invokeinterface , "invokeinterface" , "bjj__", NULL , T_ILLEGAL, -1, true); - def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, -1, true ); + def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, 0, true ); def(_new , "new" , "bii" , NULL , T_OBJECT , 1, true ); def(_newarray , "newarray" , "bc" , NULL , T_OBJECT , 0, true ); def(_anewarray , "anewarray" , "bii" , NULL , T_OBJECT , 0, true ); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/interpreter.cpp --- a/src/share/vm/interpreter/interpreter.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/interpreter.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -323,7 +323,7 @@ // (NOT needed for the old calling convension) if (!is_top_frame) { int index = Bytes::get_native_u4(bcp+1); - method->constants()->cache()->entry_at(index)->set_parameter_size(callee_parameters); + method->constants()->cache()->secondary_entry_at(index)->set_parameter_size(callee_parameters); } break; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -353,7 +353,7 @@ assert(h_exception.not_null(), "NULL exceptions should be handled by athrow"); assert(h_exception->is_oop(), "just checking"); // Check that exception is a subclass of Throwable, otherwise we have a VerifyError - if (!(h_exception->is_a(SystemDictionary::throwable_klass()))) { + if (!(h_exception->is_a(SystemDictionary::Throwable_klass()))) { if (ExitVMOnVerifyError) vm_exit(-1); ShouldNotReachHere(); } @@ -585,7 +585,7 @@ Handle exception(thread, thread->vm_result()); assert(exception() != NULL, "vm result should be set"); thread->set_vm_result(NULL); // clear vm result before continuing (may cause memory leaks and assert failures) - if (!exception->is_a(SystemDictionary::threaddeath_klass())) { + if (!exception->is_a(SystemDictionary::ThreadDeath_klass())) { exception = get_preinitialized_exception( SystemDictionary::IllegalMonitorStateException_klass(), CATCH); @@ -660,7 +660,7 @@ tty->print_cr("Resolving: klass: %s to method: %s", info.resolved_klass()->name()->as_C_string(), info.resolved_method()->name()->as_C_string()); } if (info.resolved_method()->method_holder() == - SystemDictionary::object_klass()) { + SystemDictionary::Object_klass()) { // NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec // (see also cpCacheOop.cpp for details) methodHandle rm = info.resolved_method(); @@ -1250,7 +1250,7 @@ methodHandle mh(thread, fr.interpreter_frame_method()); Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci); ArgumentSizeComputer asc(invoke->signature()); - int size_of_arguments = (asc.size() + (invoke->is_invokestatic() ? 0 : 1)); // receiver + int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver Copy::conjoint_bytes(src_address, dest_address, size_of_arguments * Interpreter::stackElementSize()); IRT_END diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/linkResolver.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -55,7 +55,7 @@ // we should pick the vtable index from the resolved method. // Other than that case, there is no valid vtable index to specify. int vtable_index = methodOopDesc::invalid_vtable_index; - if (resolved_method->method_holder() == SystemDictionary::object_klass()) { + if (resolved_method->method_holder() == SystemDictionary::Object_klass()) { assert(resolved_method->vtable_index() == selected_method->vtable_index(), "sanity check"); vtable_index = resolved_method->vtable_index(); } @@ -75,6 +75,8 @@ _selected_method = selected_method; _vtable_index = vtable_index; if (CompilationPolicy::mustBeCompiled(selected_method)) { + // This path is unusual, mostly used by the '-Xcomp' stress test mode. + // Note: with several active threads, the mustBeCompiled may be true // while canBeCompiled is false; remove assert // assert(CompilationPolicy::canBeCompiled(selected_method), "cannot compile"); @@ -82,6 +84,16 @@ // don't force compilation, resolve was on behalf of compiler return; } + if (instanceKlass::cast(selected_method->method_holder())->is_not_initialized()) { + // 'is_not_initialized' means not only '!is_initialized', but also that + // initialization has not been started yet ('!being_initialized') + // Do not force compilation of methods in uninitialized classes. + // Note that doing this would throw an assert later, + // in CompileBroker::compile_method. + // We sometimes use the link resolver to do reflective lookups + // even before classes are initialized. + return; + } CompileBroker::compile_method(selected_method, InvocationEntryBci, methodHandle(), 0, "mustBeCompiled", CHECK); } @@ -181,7 +193,7 @@ // We'll check for the method name first, as that's most likely // to be false (so we'll short-circuit out of these tests). if (sel_method->name() == vmSymbols::clone_name() && - sel_klass() == SystemDictionary::object_klass() && + sel_klass() == SystemDictionary::Object_klass() && resolved_klass->oop_is_array()) { // We need to change "protected" to "public". assert(flags.is_protected(), "clone not protected?"); @@ -223,6 +235,18 @@ resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); } +void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) { + // The class is java.dyn.MethodHandle + resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); + + symbolHandle method_name = vmSymbolHandles::invoke_name(); + + symbolHandle method_signature(THREAD, pool->signature_ref_at(index)); + KlassHandle current_klass (THREAD, pool->pool_holder()); + + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); +} + void LinkResolver::resolve_interface_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) { // resolve klass diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/linkResolver.hpp --- a/src/share/vm/interpreter/linkResolver.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/linkResolver.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -133,6 +133,7 @@ // static resolving for all calls except interface calls static void resolve_method (methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS); + static void resolve_dynamic_method (methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS); static void resolve_interface_method(methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS); // runtime/static resolving for fields diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/rewriter.cpp --- a/src/share/vm/interpreter/rewriter.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/rewriter.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -247,15 +247,22 @@ void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) { ResourceMark rm(THREAD); - Rewriter rw(klass, CHECK); + Rewriter rw(klass, klass->constants(), klass->methods(), CHECK); // (That's all, folks.) } -Rewriter::Rewriter(instanceKlassHandle klass, TRAPS) + +void Rewriter::rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS) { + ResourceMark rm(THREAD); + Rewriter rw(klass, cpool, methods, CHECK); + // (That's all, folks.) +} + + +Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS) : _klass(klass), - // gather starting points - _pool( THREAD, klass->constants()), - _methods(THREAD, klass->methods()) + _pool(cpool), + _methods(methods) { assert(_pool->cache() == NULL, "constant pool cache must not be set yet"); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/interpreter/rewriter.hpp --- a/src/share/vm/interpreter/rewriter.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/interpreter/rewriter.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -57,7 +57,7 @@ } // All the work goes in here: - Rewriter(instanceKlassHandle klass, TRAPS); + Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS); void compute_index_maps(); void make_constant_pool_cache(TRAPS); @@ -70,6 +70,7 @@ public: // Driver routine: static void rewrite(instanceKlassHandle klass, TRAPS); + static void rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS); enum { _secondary_entry_tag = nth_bit(30) diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/memory/classify.cpp --- a/src/share/vm/memory/classify.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/memory/classify.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -49,7 +49,7 @@ Klass* k = obj->blueprint(); - if (k->as_klassOop() == SystemDictionary::object_klass()) { + if (k->as_klassOop() == SystemDictionary::Object_klass()) { tty->print_cr("Found the class!"); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/memory/dump.cpp --- a/src/share/vm/memory/dump.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/memory/dump.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -63,7 +63,7 @@ void do_oop(oop* p) { if (p != NULL) { oop obj = *p; - if (obj->klass() == SystemDictionary::string_klass()) { + if (obj->klass() == SystemDictionary::String_klass()) { int hash; typeArrayOop value = java_lang_String::value(obj); @@ -625,11 +625,11 @@ if (obj->is_klass() || obj->is_instance()) { if (obj->is_klass() || - obj->is_a(SystemDictionary::class_klass()) || - obj->is_a(SystemDictionary::throwable_klass())) { + obj->is_a(SystemDictionary::Class_klass()) || + obj->is_a(SystemDictionary::Throwable_klass())) { // Do nothing } - else if (obj->is_a(SystemDictionary::string_klass())) { + else if (obj->is_a(SystemDictionary::String_klass())) { // immutable objects. } else { // someone added an object we hadn't accounted for. diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/memory/referenceProcessor.cpp --- a/src/share/vm/memory/referenceProcessor.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/memory/referenceProcessor.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -71,7 +71,7 @@ assert(_sentinelRef == NULL, "should be initialized precisely once"); EXCEPTION_MARK; _sentinelRef = instanceKlass::cast( - SystemDictionary::reference_klass())-> + SystemDictionary::Reference_klass())-> allocate_permanent_instance(THREAD); // Initialize the master soft ref clock. diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/memory/space.cpp --- a/src/share/vm/memory/space.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/memory/space.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -876,7 +876,7 @@ instanceOop obj = (instanceOop) allocate(size); obj->set_mark(markOopDesc::prototype()); obj->set_klass_gap(0); - obj->set_klass(SystemDictionary::object_klass()); + obj->set_klass(SystemDictionary::Object_klass()); } } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/memory/universe.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -291,7 +291,7 @@ SystemDictionary::initialize(CHECK); - klassOop ok = SystemDictionary::object_klass(); + klassOop ok = SystemDictionary::Object_klass(); _the_null_string = StringTable::intern("null", CHECK); _the_min_jint_string = StringTable::intern("-2147483648", CHECK); @@ -299,9 +299,9 @@ if (UseSharedSpaces) { // Verify shared interfaces array. assert(_the_array_interfaces_array->obj_at(0) == - SystemDictionary::cloneable_klass(), "u3"); + SystemDictionary::Cloneable_klass(), "u3"); assert(_the_array_interfaces_array->obj_at(1) == - SystemDictionary::serializable_klass(), "u3"); + SystemDictionary::Serializable_klass(), "u3"); // Verify element klass for system obj array klass assert(objArrayKlass::cast(_systemObjArrayKlassObj)->element_klass() == ok, "u1"); @@ -320,8 +320,8 @@ assert(Klass::cast(systemObjArrayKlassObj())->super() == ok, "u3"); } else { // Set up shared interfaces array. (Do this before supers are set up.) - _the_array_interfaces_array->obj_at_put(0, SystemDictionary::cloneable_klass()); - _the_array_interfaces_array->obj_at_put(1, SystemDictionary::serializable_klass()); + _the_array_interfaces_array->obj_at_put(0, SystemDictionary::Cloneable_klass()); + _the_array_interfaces_array->obj_at_put(1, SystemDictionary::Serializable_klass()); // Set element klass for system obj array klass objArrayKlass::cast(_systemObjArrayKlassObj)->set_element_klass(ok); @@ -365,7 +365,7 @@ // Initialize _objectArrayKlass after core bootstraping to make // sure the super class is set up properly for _objectArrayKlass. _objectArrayKlassObj = instanceKlass:: - cast(SystemDictionary::object_klass())->array_klass(1, CHECK); + cast(SystemDictionary::Object_klass())->array_klass(1, CHECK); // Add the class to the class hierarchy manually to make sure that // its vtable is initialized after core bootstrapping is completed. Klass::cast(_objectArrayKlassObj)->append_to_sibling_list(); @@ -426,11 +426,11 @@ while (i < size) { if (!UseConcMarkSweepGC) { // Allocate dummy in old generation - oop dummy = instanceKlass::cast(SystemDictionary::object_klass())->allocate_instance(CHECK); + oop dummy = instanceKlass::cast(SystemDictionary::Object_klass())->allocate_instance(CHECK); dummy_array->obj_at_put(i++, dummy); } // Allocate dummy in permanent generation - oop dummy = instanceKlass::cast(SystemDictionary::object_klass())->allocate_permanent_instance(CHECK); + oop dummy = instanceKlass::cast(SystemDictionary::Object_klass())->allocate_permanent_instance(CHECK); dummy_array->obj_at_put(i++, dummy); } { @@ -540,7 +540,7 @@ // but we cannot do that for classes created before java.lang.Class is loaded. Here we simply // walk over permanent objects created so far (mostly classes) and fixup their mirrors. Note // that the number of objects allocated at this point is very small. - assert(SystemDictionary::class_klass_loaded(), "java.lang.Class should be loaded"); + assert(SystemDictionary::Class_klass_loaded(), "java.lang.Class should be loaded"); FixupMirrorClosure blk; Universe::heap()->permanent_object_iterate(&blk); } @@ -556,7 +556,7 @@ if (TraceReferenceGC) tty->print_cr("Callback to run finalizers on exit"); { PRESERVE_EXCEPTION_MARK; - KlassHandle finalizer_klass(THREAD, SystemDictionary::finalizer_klass()); + KlassHandle finalizer_klass(THREAD, SystemDictionary::Finalizer_klass()); JavaValue result(T_VOID); JavaCalls::call_static( &result, @@ -950,7 +950,7 @@ { ResourceMark rm; Interpreter::initialize(); // needed for interpreter entry points if (!UseSharedSpaces) { - KlassHandle ok_h(THREAD, SystemDictionary::object_klass()); + KlassHandle ok_h(THREAD, SystemDictionary::Object_klass()); Universe::reinitialize_vtable_of(ok_h, CHECK_false); Universe::reinitialize_itables(CHECK_false); } @@ -960,7 +960,7 @@ instanceKlassHandle k_h; if (!UseSharedSpaces) { // Setup preallocated empty java.lang.Class array - Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_false); + Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false); // Setup preallocated OutOfMemoryError errors k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_OutOfMemoryError(), true, CHECK_false); k_h = instanceKlassHandle(THREAD, k); @@ -1027,8 +1027,8 @@ // Setup static method for registering finalizers // The finalizer klass must be linked before looking up the method, in // case it needs to get rewritten. - instanceKlass::cast(SystemDictionary::finalizer_klass())->link_class(CHECK_false); - methodOop m = instanceKlass::cast(SystemDictionary::finalizer_klass())->find_method( + instanceKlass::cast(SystemDictionary::Finalizer_klass())->link_class(CHECK_false); + methodOop m = instanceKlass::cast(SystemDictionary::Finalizer_klass())->find_method( vmSymbols::register_method_name(), vmSymbols::register_method_signature()); if (m == NULL || !m->is_static()) { @@ -1036,7 +1036,7 @@ "java.lang.ref.Finalizer.register", false); } Universe::_finalizer_register_cache->init( - SystemDictionary::finalizer_klass(), m, CHECK_false); + SystemDictionary::Finalizer_klass(), m, CHECK_false); // Resolve on first use and initialize class. // Note: No race-condition here, since a resolve will always return the same result @@ -1053,14 +1053,14 @@ Universe::_reflect_invoke_cache->init(k_h(), m, CHECK_false); // Setup method for registering loaded classes in class loader vector - instanceKlass::cast(SystemDictionary::classloader_klass())->link_class(CHECK_false); - m = instanceKlass::cast(SystemDictionary::classloader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature()); + instanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false); + m = instanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature()); if (m == NULL || m->is_static()) { THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(), "java.lang.ClassLoader.addClass", false); } Universe::_loader_addClass_cache->init( - SystemDictionary::classloader_klass(), m, CHECK_false); + SystemDictionary::ClassLoader_klass(), m, CHECK_false); // The folowing is initializing converter functions for serialization in // JVM.cpp. If we clean up the StrictMath code above we may want to find diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/arrayKlass.cpp --- a/src/share/vm/oops/arrayKlass.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/arrayKlass.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -43,7 +43,7 @@ if (super() == NULL) return NULL; // bootstrap case // Array klasses have primary supertypes which are not reported to Java. // Example super chain: String[][] -> Object[][] -> Object[] -> Object - return SystemDictionary::object_klass(); + return SystemDictionary::Object_klass(); } @@ -82,7 +82,7 @@ k = arrayKlassHandle(THREAD, base_klass()); assert(!k()->is_parsable(), "not expecting parsability yet."); - k->set_super(Universe::is_bootstrapping() ? (klassOop)NULL : SystemDictionary::object_klass()); + k->set_super(Universe::is_bootstrapping() ? (klassOop)NULL : SystemDictionary::Object_klass()); k->set_layout_helper(Klass::_lh_neutral_value); k->set_dimension(1); k->set_higher_dimension(NULL); @@ -117,9 +117,9 @@ bool arrayKlass::compute_is_subtype_of(klassOop k) { // An array is a subtype of Serializable, Clonable, and Object - return k == SystemDictionary::object_klass() - || k == SystemDictionary::cloneable_klass() - || k == SystemDictionary::serializable_klass(); + return k == SystemDictionary::Object_klass() + || k == SystemDictionary::Cloneable_klass() + || k == SystemDictionary::Serializable_klass(); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/arrayKlass.hpp --- a/src/share/vm/oops/arrayKlass.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/arrayKlass.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -67,7 +67,7 @@ // Compiler/Interpreter offset static ByteSize component_mirror_offset() { return byte_offset_of(arrayKlass, _component_mirror); } - virtual klassOop java_super() const;//{ return SystemDictionary::object_klass(); } + virtual klassOop java_super() const;//{ return SystemDictionary::Object_klass(); } // Allocation // Sizes points to the first dimension of the array, subsequent dimensions diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/constMethodOop.hpp --- a/src/share/vm/oops/constMethodOop.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/constMethodOop.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -258,6 +258,11 @@ LocalVariableTableElement* localvariable_table_start() const; // byte codes + void set_code(address code) { + if (code_size() > 0) { + memcpy(code_base(), code, code_size()); + } + } address code_base() const { return (address) (this+1); } address code_end() const { return code_base() + code_size(); } bool contains(address bcp) const { return code_base() <= bcp diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/constantPoolOop.cpp --- a/src/share/vm/oops/constantPoolOop.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/constantPoolOop.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -110,7 +110,7 @@ } if (!PENDING_EXCEPTION-> - is_a(SystemDictionary::linkageError_klass())) { + is_a(SystemDictionary::LinkageError_klass())) { // Just throw the exception and don't prevent these classes from // being loaded due to virtual machine errors like StackOverflow // and OutOfMemoryError, etc, or if the thread was hit by stop() diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/constantPoolOop.hpp --- a/src/share/vm/oops/constantPoolOop.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/constantPoolOop.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -191,6 +191,16 @@ } } + void object_at_put(int which, oop str) { + oop_store((volatile oop*) obj_at_addr(which), str); + release_tag_at_put(which, JVM_CONSTANT_Object); + if (UseConcMarkSweepGC) { + // In case the earlier card-mark was consumed by a concurrent + // marking thread before the tag was updated, redirty the card. + oop_store_without_check((volatile oop*) obj_at_addr(which), str); + } + } + // For temporary use while constructing constant pool void string_index_at_put(int which, int string_index) { tag_at_put(which, JVM_CONSTANT_StringIndex); @@ -228,7 +238,8 @@ tag.is_unresolved_klass() || tag.is_symbol() || tag.is_unresolved_string() || - tag.is_string(); + tag.is_string() || + tag.is_object(); } // Fetching constants @@ -291,6 +302,11 @@ return string_at_impl(h_this, which, CHECK_NULL); } + oop object_at(int which) { + assert(tag_at(which).is_object(), "Corrupted constant pool"); + return *obj_at_addr(which); + } + // A "pseudo-string" is an non-string oop that has found is way into // a String entry. // Under AnonymousClasses this can happen if the user patches a live diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/generateOopMap.cpp --- a/src/share/vm/oops/generateOopMap.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/generateOopMap.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1556,13 +1556,13 @@ case Bytecodes::_getfield: do_field(true, false, itr->get_index_big(), itr->bci()); break; case Bytecodes::_putfield: do_field(false, false, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_invokevirtual: - case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break; + case Bytecodes::_invokevirtual: + case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break; + case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break; case Bytecodes::_invokedynamic: do_method(true, false, itr->get_index_int(), itr->bci()); break; - case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_newarray: - case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; + case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break; + case Bytecodes::_newarray: + case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; case Bytecodes::_checkcast: do_checkcast(); break; case Bytecodes::_arraylength: case Bytecodes::_instanceof: pp(rCTS, vCTS); break; @@ -1830,12 +1830,8 @@ void GenerateOopMap::do_ldc(int idx, int bci) { - constantPoolOop cp = method()->constants(); - constantTag tag = cp->tag_at(idx); - - CellTypeState cts = (tag.is_string() || tag.is_unresolved_string() || - tag.is_klass() || tag.is_unresolved_klass()) - ? CellTypeState::make_line_ref(bci) : valCTS; + constantPoolOop cp = method()->constants(); + CellTypeState cts = cp->is_pointer_entry(idx) ? CellTypeState::make_line_ref(bci) : valCTS; ppush1(cts); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/instanceKlass.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -383,7 +383,7 @@ this_oop->set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below } - if (e->is_a(SystemDictionary::error_klass())) { + if (e->is_a(SystemDictionary::Error_klass())) { THROW_OOP(e()); } else { JavaCallArguments args(e); @@ -568,7 +568,7 @@ THROW_MSG(throwError ? vmSymbols::java_lang_InstantiationError() : vmSymbols::java_lang_InstantiationException(), external_name()); } - if (as_klassOop() == SystemDictionary::class_klass()) { + if (as_klassOop() == SystemDictionary::Class_klass()) { ResourceMark rm(THREAD); THROW_MSG(throwError ? vmSymbols::java_lang_IllegalAccessError() : vmSymbols::java_lang_IllegalAccessException(), external_name()); @@ -2225,7 +2225,7 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) { Klass::oop_print_on(obj, st); - if (as_klassOop() == SystemDictionary::string_klass()) { + if (as_klassOop() == SystemDictionary::String_klass()) { typeArrayOop value = java_lang_String::value(obj); juint offset = java_lang_String::offset(obj); juint length = java_lang_String::length(obj); @@ -2245,7 +2245,7 @@ FieldPrinter print_nonstatic_field(st, obj); do_nonstatic_fields(&print_nonstatic_field); - if (as_klassOop() == SystemDictionary::class_klass()) { + if (as_klassOop() == SystemDictionary::Class_klass()) { st->print(BULLET"signature: "); java_lang_Class::print_signature(obj, st); st->cr(); @@ -2272,7 +2272,7 @@ st->print("a "); name()->print_value_on(st); obj->print_address_on(st); - if (as_klassOop() == SystemDictionary::string_klass() + if (as_klassOop() == SystemDictionary::String_klass() && java_lang_String::value(obj) != NULL) { ResourceMark rm; int len = java_lang_String::length(obj); @@ -2281,7 +2281,7 @@ st->print(" = \"%s\"", str); if (len > plen) st->print("...[%d]", len); - } else if (as_klassOop() == SystemDictionary::class_klass()) { + } else if (as_klassOop() == SystemDictionary::Class_klass()) { klassOop k = java_lang_Class::as_klassOop(obj); st->print(" = "); if (k != NULL) { @@ -2348,7 +2348,7 @@ // Check that we have the right class static bool first_time = true; - guarantee(k == SystemDictionary::class_klass() && first_time, "Invalid verify of maps"); + guarantee(k == SystemDictionary::Class_klass() && first_time, "Invalid verify of maps"); first_time = false; const int extra = java_lang_Class::number_of_fake_oop_fields; guarantee(ik->nonstatic_field_size() == extra, "just checking"); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/instanceRefKlass.cpp --- a/src/share/vm/oops/instanceRefKlass.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/instanceRefKlass.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -397,7 +397,7 @@ // Check that we have the right class debug_only(static bool first_time = true); - assert(k == SystemDictionary::reference_klass() && first_time, + assert(k == SystemDictionary::Reference_klass() && first_time, "Invalid update of maps"); debug_only(first_time = false); assert(ik->nonstatic_oop_map_count() == 1, "just checking"); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/klass.cpp --- a/src/share/vm/oops/klass.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/klass.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -217,8 +217,8 @@ set_super(NULL); oop_store_without_check((oop*) &_primary_supers[0], (oop) this->as_klassOop()); assert(super_depth() == 0, "Object must already be initialized properly"); - } else if (k != super() || k == SystemDictionary::object_klass()) { - assert(super() == NULL || super() == SystemDictionary::object_klass(), + } else if (k != super() || k == SystemDictionary::Object_klass()) { + assert(super() == NULL || super() == SystemDictionary::Object_klass(), "initialize this only once to a non-trivial value"); set_super(k); Klass* sup = k->klass_part(); @@ -370,7 +370,7 @@ void Klass::remove_from_sibling_list() { // remove receiver from sibling list instanceKlass* super = superklass(); - assert(super != NULL || as_klassOop() == SystemDictionary::object_klass(), "should have super"); + assert(super != NULL || as_klassOop() == SystemDictionary::Object_klass(), "should have super"); if (super == NULL) return; // special case: class Object if (super->subklass() == this) { // first subklass diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/methodOop.cpp --- a/src/share/vm/oops/methodOop.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/methodOop.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -456,12 +456,12 @@ return objArrayHandle(THREAD, Universe::the_empty_class_klass_array()); } else { methodHandle h_this(THREAD, this_oop); - objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::class_klass(), length, CHECK_(objArrayHandle())); + objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::Class_klass(), length, CHECK_(objArrayHandle())); objArrayHandle mirrors (THREAD, m_oop); for (int i = 0; i < length; i++) { CheckedExceptionElement* table = h_this->checked_exceptions_start(); // recompute on each iteration, not gc safe klassOop k = h_this->constants()->klass_at(table[i].class_cp_index, CHECK_(objArrayHandle())); - assert(Klass::cast(k)->is_subclass_of(SystemDictionary::throwable_klass()), "invalid exception class"); + assert(Klass::cast(k)->is_subclass_of(SystemDictionary::Throwable_klass()), "invalid exception class"); mirrors->obj_at_put(i, Klass::cast(k)->java_mirror()); } return mirrors; @@ -1032,8 +1032,8 @@ // We are loading classes eagerly. If a ClassNotFoundException or // a LinkageError was generated, be sure to ignore it. if (HAS_PENDING_EXCEPTION) { - if (PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass()) || - PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) { + if (PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass()) || + PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { CLEAR_PENDING_EXCEPTION; } else { return false; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/methodOop.hpp --- a/src/share/vm/oops/methodOop.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/methodOop.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -365,6 +365,7 @@ #endif // byte codes + void set_code(address code) { return constMethod()->set_code(code); } address code_base() const { return constMethod()->code_base(); } bool contains(address bcp) const { return constMethod()->contains(bcp); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/objArrayKlass.cpp --- a/src/share/vm/oops/objArrayKlass.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/objArrayKlass.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -246,8 +246,8 @@ } else { objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL); objArrayHandle secondaries(THREAD, sec_oop); - secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::cloneable_klass()); - secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::serializable_klass()); + secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::Cloneable_klass()); + secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::Serializable_klass()); for (int i = 0; i < num_elem_supers; i++) { klassOop elem_super = (klassOop) elem_supers->obj_at(i); klassOop array_super = elem_super->klass_part()->array_klass_or_null(); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/objArrayKlassKlass.cpp --- a/src/share/vm/oops/objArrayKlassKlass.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/objArrayKlassKlass.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -99,7 +99,7 @@ } } else { // The element type is already Object. Object[] has direct super of Object. - super_klass = KlassHandle(THREAD, SystemDictionary::object_klass()); + super_klass = KlassHandle(THREAD, SystemDictionary::Object_klass()); } } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/symbolOop.cpp --- a/src/share/vm/oops/symbolOop.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/symbolOop.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,11 @@ # include "incls/_precompiled.incl" # include "incls/_symbolOop.cpp.incl" + +// ------------------------------------------------------------------ +// symbolOopDesc::equals +// +// Compares the symbol with a string of the given length. bool symbolOopDesc::equals(const char* str, int len) const { int l = utf8_length(); if (l != len) return false; @@ -36,6 +41,48 @@ return true; } + +// ------------------------------------------------------------------ +// symbolOopDesc::starts_with +// +// Tests if the symbol starts with the specified prefix of the given +// length. +bool symbolOopDesc::starts_with(const char* prefix, int len) const { + if (len > utf8_length()) return false; + while (len-- > 0) { + if (prefix[len] != (char) byte_at(len)) + return false; + } + assert(len == -1, "we should be at the beginning"); + return true; +} + + +// ------------------------------------------------------------------ +// symbolOopDesc::index_of +// +// Finds if the given string is a substring of this symbol's utf8 bytes. +// Return -1 on failure. Otherwise return the first index where str occurs. +int symbolOopDesc::index_of_at(int i, const char* str, int len) const { + assert(i >= 0 && i <= utf8_length(), "oob"); + if (len <= 0) return 0; + char first_char = str[0]; + address bytes = (address) ((symbolOopDesc*)this)->base(); + address limit = bytes + utf8_length() - len; // inclusive limit + address scan = bytes + i; + if (scan > limit) + return -1; + for (;;) { + scan = (address) memchr(scan, first_char, (limit + 1 - scan)); + if (scan == NULL) + return -1; // not found + assert(scan >= bytes+i && scan <= limit, "scan oob"); + if (memcmp(scan, str, len) == 0) + return (int)(scan - bytes); + } +} + + char* symbolOopDesc::as_C_string(char* buf, int size) const { if (size > 0) { int len = MIN2(size - 1, utf8_length()); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/oops/symbolOop.hpp --- a/src/share/vm/oops/symbolOop.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/oops/symbolOop.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,8 +70,21 @@ void set_utf8_length(int len) { _length = len; } - // Compares the symbol with a string + // Compares the symbol with a string. bool equals(const char* str, int len) const; + bool equals(const char* str) const { return equals(str, (int) strlen(str)); } + + // Tests if the symbol starts with the given prefix. + bool starts_with(const char* prefix, int len) const; + bool starts_with(const char* prefix) const { + return starts_with(prefix, (int) strlen(prefix)); + } + + // Tests if the symbol starts with the given prefix. + int index_of_at(int i, const char* str, int len) const; + int index_of_at(int i, const char* str) const { + return index_of_at(i, str, (int) strlen(str)); + } // Three-way compare for sorting; returns -1/0/1 if receiver is than arg // note that the ordering is not alfabetical diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/bytecodeInfo.cpp --- a/src/share/vm/opto/bytecodeInfo.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/bytecodeInfo.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -180,6 +180,10 @@ return NULL; } + // Always inline MethodHandle methods. + if (callee_method->is_method_handle_invoke()) + return NULL; + // First check all inlining restrictions which are required for correctness if (callee_method->is_abstract()) return "abstract method"; // note: we allow ik->is_abstract() @@ -322,14 +326,17 @@ // stricter than callee_holder->is_initialized() ciBytecodeStream iter(caller_method); iter.force_bci(caller_bci); - int index = iter.get_index_int(); - if( !caller_method->is_klass_loaded(index, true) ) { - return false; - } - // Try to do constant pool resolution if running Xcomp Bytecodes::Code call_bc = iter.cur_bc(); - if( !caller_method->check_call(index, call_bc == Bytecodes::_invokestatic) ) { - return false; + // An invokedynamic instruction does not have a klass. + if (call_bc != Bytecodes::_invokedynamic) { + int index = iter.get_index_int(); + if (!caller_method->is_klass_loaded(index, true)) { + return false; + } + // Try to do constant pool resolution if running Xcomp + if( !caller_method->check_call(index, call_bc == Bytecodes::_invokestatic) ) { + return false; + } } } // We will attempt to see if a class/field/etc got properly loaded. If it diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/callGenerator.cpp --- a/src/share/vm/opto/callGenerator.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/callGenerator.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -136,6 +136,8 @@ } // Mark the call node as virtual, sort of: call->set_optimized_virtual(true); + if (method()->is_method_handle_invoke()) + call->set_method_handle_invoke(true); } kit.set_arguments_for_java_call(call); kit.set_edges_for_java_call(call, false, _separate_io_proj); @@ -145,6 +147,71 @@ return kit.transfer_exceptions_into_jvms(); } +//---------------------------DynamicCallGenerator----------------------------- +// Internal class which handles all out-of-line invokedynamic calls. +class DynamicCallGenerator : public CallGenerator { +public: + DynamicCallGenerator(ciMethod* method) + : CallGenerator(method) + { + } + virtual JVMState* generate(JVMState* jvms); +}; + +JVMState* DynamicCallGenerator::generate(JVMState* jvms) { + GraphKit kit(jvms); + + if (kit.C->log() != NULL) { + kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci()); + } + + // Get the constant pool cache from the caller class. + ciMethod* caller_method = jvms->method(); + ciBytecodeStream str(caller_method); + str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. + assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!"); + ciCPCache* cpcache = str.get_cpcache(); + + // Get the offset of the CallSite from the constant pool cache + // pointer. + int index = str.get_method_index(); + size_t call_site_offset = cpcache->get_f1_offset(index); + + // Load the CallSite object from the constant pool cache. + const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); + Node* cpcache_adr = kit.makecon(cpcache_ptr); + Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); + Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); + + // Load the target MethodHandle from the CallSite object. + Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); + Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); + + address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); + + CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci()); + // invokedynamic is treated as an optimized invokevirtual. + call->set_optimized_virtual(true); + // Take extra care (in the presence of argument motion) not to trash the SP: + call->set_method_handle_invoke(true); + + // Pass the target MethodHandle as first argument and shift the + // other arguments. + call->init_req(0 + TypeFunc::Parms, target_mh); + uint nargs = call->method()->arg_size(); + for (uint i = 1; i < nargs; i++) { + Node* arg = kit.argument(i - 1); + call->init_req(i + TypeFunc::Parms, arg); + } + + kit.set_edges_for_java_call(call); + Node* ret = kit.set_results_for_java_call(call); + kit.push_node(method()->return_type()->basic_type(), ret); + return kit.transfer_exceptions_into_jvms(); +} + +//--------------------------VirtualCallGenerator------------------------------ +// Internal class which handles all out-of-line calls checking receiver type. class VirtualCallGenerator : public CallGenerator { private: int _vtable_index; @@ -159,8 +226,6 @@ virtual JVMState* generate(JVMState* jvms); }; -//--------------------------VirtualCallGenerator------------------------------ -// Internal class which handles all out-of-line calls checking receiver type. JVMState* VirtualCallGenerator::generate(JVMState* jvms) { GraphKit kit(jvms); Node* receiver = kit.argument(0); @@ -253,8 +318,14 @@ return new DirectCallGenerator(m, separate_io_proj); } +CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { + assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch"); + return new DynamicCallGenerator(m); +} + CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { assert(!m->is_static(), "for_virtual_call mismatch"); + assert(!m->is_method_handle_invoke(), "should be a direct call"); return new VirtualCallGenerator(m, vtable_index); } @@ -576,6 +647,155 @@ } +//------------------------PredictedDynamicCallGenerator----------------------- +// Internal class which handles all out-of-line calls checking receiver type. +class PredictedDynamicCallGenerator : public CallGenerator { + ciMethodHandle* _predicted_method_handle; + CallGenerator* _if_missed; + CallGenerator* _if_hit; + float _hit_prob; + +public: + PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle, + CallGenerator* if_missed, + CallGenerator* if_hit, + float hit_prob) + : CallGenerator(if_missed->method()), + _predicted_method_handle(predicted_method_handle), + _if_missed(if_missed), + _if_hit(if_hit), + _hit_prob(hit_prob) + {} + + virtual bool is_inline() const { return _if_hit->is_inline(); } + virtual bool is_deferred() const { return _if_hit->is_deferred(); } + + virtual JVMState* generate(JVMState* jvms); +}; + + +CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, + CallGenerator* if_missed, + CallGenerator* if_hit, + float hit_prob) { + return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob); +} + + +JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) { + GraphKit kit(jvms); + PhaseGVN& gvn = kit.gvn(); + + CompileLog* log = kit.C->log(); + if (log != NULL) { + log->elem("predicted_dynamic_call bci='%d'", jvms->bci()); + } + + // Get the constant pool cache from the caller class. + ciMethod* caller_method = jvms->method(); + ciBytecodeStream str(caller_method); + str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. + ciCPCache* cpcache = str.get_cpcache(); + + // Get the offset of the CallSite from the constant pool cache + // pointer. + int index = str.get_method_index(); + size_t call_site_offset = cpcache->get_f1_offset(index); + + // Load the CallSite object from the constant pool cache. + const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); + Node* cpcache_adr = kit.makecon(cpcache_ptr); + Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); + Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); + + // Load the target MethodHandle from the CallSite object. + Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); + Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT); + + // Check if the MethodHandle is still the same. + const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true); + Node* predicted_mh = kit.makecon(predicted_mh_ptr); + + Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh)); + Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); + IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN); + kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff))); + Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff)); + + SafePointNode* slow_map = NULL; + JVMState* slow_jvms; + { PreserveJVMState pjvms(&kit); + kit.set_control(slow_ctl); + if (!kit.stopped()) { + slow_jvms = _if_missed->generate(kit.sync_jvms()); + assert(slow_jvms != NULL, "miss path must not fail to generate"); + kit.add_exception_states_from(slow_jvms); + kit.set_map(slow_jvms->map()); + if (!kit.stopped()) + slow_map = kit.stop(); + } + } + + if (kit.stopped()) { + // Instance exactly does not matches the desired type. + kit.set_jvms(slow_jvms); + return kit.transfer_exceptions_into_jvms(); + } + + // Make the hot call: + JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); + if (new_jvms == NULL) { + // Inline failed, so make a direct call. + assert(_if_hit->is_inline(), "must have been a failed inline"); + CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); + new_jvms = cg->generate(kit.sync_jvms()); + } + kit.add_exception_states_from(new_jvms); + kit.set_jvms(new_jvms); + + // Need to merge slow and fast? + if (slow_map == NULL) { + // The fast path is the only path remaining. + return kit.transfer_exceptions_into_jvms(); + } + + if (kit.stopped()) { + // Inlined method threw an exception, so it's just the slow path after all. + kit.set_jvms(slow_jvms); + return kit.transfer_exceptions_into_jvms(); + } + + // Finish the diamond. + kit.C->set_has_split_ifs(true); // Has chance for split-if optimization + RegionNode* region = new (kit.C, 3) RegionNode(3); + region->init_req(1, kit.control()); + region->init_req(2, slow_map->control()); + kit.set_control(gvn.transform(region)); + Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); + iophi->set_req(2, slow_map->i_o()); + kit.set_i_o(gvn.transform(iophi)); + kit.merge_memory(slow_map->merged_memory(), region, 2); + uint tos = kit.jvms()->stkoff() + kit.sp(); + uint limit = slow_map->req(); + for (uint i = TypeFunc::Parms; i < limit; i++) { + // Skip unused stack slots; fast forward to monoff(); + if (i == tos) { + i = kit.jvms()->monoff(); + if( i >= limit ) break; + } + Node* m = kit.map()->in(i); + Node* n = slow_map->in(i); + if (m != n) { + const Type* t = gvn.type(m)->meet(gvn.type(n)); + Node* phi = PhiNode::make(region, m, t); + phi->set_req(2, n); + kit.map()->set_req(i, gvn.transform(phi)); + } + } + return kit.transfer_exceptions_into_jvms(); +} + + //-------------------------UncommonTrapCallGenerator----------------------------- // Internal class which handles all out-of-line calls checking receiver type. class UncommonTrapCallGenerator : public CallGenerator { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/callGenerator.hpp --- a/src/share/vm/opto/callGenerator.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/callGenerator.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -100,6 +100,7 @@ // How to generate vanilla out-of-line call sites: static CallGenerator* for_direct_call(ciMethod* m, bool separate_io_projs = false); // static, special + static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface // How to generate a replace a direct call with an inline version @@ -116,6 +117,12 @@ CallGenerator* if_hit, float hit_prob); + // How to make a call that optimistically assumes a MethodHandle target: + static CallGenerator* for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, + CallGenerator* if_missed, + CallGenerator* if_hit, + float hit_prob); + // How to make a call that gives up and goes back to the interpreter: static CallGenerator* for_uncommon_trap(ciMethod* m, Deoptimization::DeoptReason reason, diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/callnode.hpp --- a/src/share/vm/opto/callnode.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/callnode.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -562,12 +562,15 @@ virtual uint size_of() const; // Size is bigger bool _optimized_virtual; + bool _method_handle_invoke; ciMethod* _method; // Method being direct called public: const int _bci; // Byte Code Index of call byte code CallJavaNode(const TypeFunc* tf , address addr, ciMethod* method, int bci) : CallNode(tf, addr, TypePtr::BOTTOM), - _method(method), _bci(bci), _optimized_virtual(false) + _method(method), _bci(bci), + _optimized_virtual(false), + _method_handle_invoke(false) { init_class_id(Class_CallJava); } @@ -577,6 +580,8 @@ void set_method(ciMethod *m) { _method = m; } void set_optimized_virtual(bool f) { _optimized_virtual = f; } bool is_optimized_virtual() const { return _optimized_virtual; } + void set_method_handle_invoke(bool f) { _method_handle_invoke = f; } + bool is_method_handle_invoke() const { return _method_handle_invoke; } #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/doCall.cpp --- a/src/share/vm/opto/doCall.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/doCall.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -224,6 +224,57 @@ } } + // Do MethodHandle calls. + if (call_method->is_method_handle_invoke()) { + if (jvms->method()->java_code_at_bci(jvms->bci()) != Bytecodes::_invokedynamic) { + GraphKit kit(jvms); + Node* n = kit.argument(0); + + if (n->Opcode() == Op_ConP) { + const TypeOopPtr* oop_ptr = n->bottom_type()->is_oopptr(); + ciObject* const_oop = oop_ptr->const_oop(); + ciMethodHandle* method_handle = const_oop->as_method_handle(); + + // Set the actually called method to have access to the class + // and signature in the MethodHandleCompiler. + method_handle->set_callee(call_method); + + // Get an adapter for the MethodHandle. + ciMethod* target_method = method_handle->get_method_handle_adapter(); + + CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor); + if (hit_cg != NULL && hit_cg->is_inline()) + return hit_cg; + } + + return CallGenerator::for_direct_call(call_method); + } + else { + // Get the MethodHandle from the CallSite. + ciMethod* caller_method = jvms->method(); + ciBytecodeStream str(caller_method); + str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. + ciCallSite* call_site = str.get_call_site(); + ciMethodHandle* method_handle = call_site->get_target(); + + // Set the actually called method to have access to the class + // and signature in the MethodHandleCompiler. + method_handle->set_callee(call_method); + + // Get an adapter for the MethodHandle. + ciMethod* target_method = method_handle->get_invokedynamic_adapter(); + + CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor); + if (hit_cg != NULL && hit_cg->is_inline()) { + CallGenerator* miss_cg = CallGenerator::for_dynamic_call(call_method); + return CallGenerator::for_predicted_dynamic_call(method_handle, miss_cg, hit_cg, prof_factor); + } + + // If something failed, generate a normal dynamic call. + return CallGenerator::for_dynamic_call(call_method); + } + } + // There was no special inlining tactic, or it bailed out. // Use a more generic tactic, like a simple call. if (call_is_virtual) { @@ -299,7 +350,7 @@ // Interface classes can be loaded & linked and never get around to // being initialized. Uncommon-trap for not-initialized static or // v-calls. Let interface calls happen. - ciInstanceKlass* holder_klass = dest_method->holder(); + ciInstanceKlass* holder_klass = dest_method->holder(); if (!holder_klass->is_initialized() && !holder_klass->is_interface()) { uncommon_trap(Deoptimization::Reason_uninitialized, @@ -307,14 +358,6 @@ holder_klass); return true; } - if (dest_method->is_method_handle_invoke() - && holder_klass->name() == ciSymbol::java_dyn_Dynamic()) { - // FIXME: NYI - uncommon_trap(Deoptimization::Reason_unhandled, - Deoptimization::Action_none, - holder_klass); - return true; - } assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility"); return false; @@ -333,6 +376,7 @@ bool is_virtual = bc() == Bytecodes::_invokevirtual; bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial; + bool is_invokedynamic = bc() == Bytecodes::_invokedynamic; // Find target being called bool will_link; @@ -341,7 +385,8 @@ ciKlass* holder = iter().get_declared_method_holder(); ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); - int nargs = dest_method->arg_size(); + int nargs = dest_method->arg_size(); + if (is_invokedynamic) nargs -= 1; // uncommon-trap when callee is unloaded, uninitialized or will not link // bailout when too many arguments for register representation @@ -355,7 +400,7 @@ return; } assert(holder_klass->is_loaded(), ""); - assert(dest_method->is_static() == !has_receiver, "must match bc"); + assert((dest_method->is_static() || is_invokedynamic) == !has_receiver , "must match bc"); // Note: this takes into account invokeinterface of methods declared in java/lang/Object, // which should be invokevirtuals but according to the VM spec may be invokeinterfaces assert(holder_klass->is_interface() || holder_klass->super() == NULL || (bc() != Bytecodes::_invokeinterface), "must match bc"); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/escape.cpp --- a/src/share/vm/opto/escape.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/escape.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1916,7 +1916,7 @@ Node *arg = call->in(i)->uncast(); if (at->isa_oopptr() != NULL && - ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) { + ptnode_adr(arg->_idx)->escape_state() < PointsToNode::GlobalEscape) { bool global_escapes = false; bool fields_escapes = false; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/graphKit.cpp --- a/src/share/vm/opto/graphKit.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/graphKit.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -981,14 +981,19 @@ case Bytecodes::_invokedynamic: case Bytecodes::_invokeinterface: { - bool is_static = (depth == 0); bool ignore; ciBytecodeStream iter(method()); iter.reset_to_bci(bci()); iter.next(); ciMethod* method = iter.get_method(ignore); inputs = method->arg_size_no_receiver(); - if (!is_static) inputs += 1; + // Add a receiver argument, maybe: + if (code != Bytecodes::_invokestatic && + code != Bytecodes::_invokedynamic) + inputs += 1; + // (Do not use ciMethod::arg_size(), because + // it might be an unloaded method, which doesn't + // know whether it is static or not.) int size = method->return_type()->size(); depth = size - inputs; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/lcm.cpp --- a/src/share/vm/opto/lcm.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/lcm.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -542,6 +542,16 @@ // pointers as far as the kill mask goes. bool exclude_soe = op == Op_CallRuntime; + // If the call is a MethodHandle invoke, we need to exclude the + // register which is used to save the SP value over MH invokes from + // the mask. Otherwise this register could be used for + // deoptimization information. + if (op == Op_CallStaticJava) { + MachCallStaticJavaNode* mcallstaticjava = (MachCallStaticJavaNode*) mcall; + if (mcallstaticjava->_method_handle_invoke) + proj->_rout.OR(Matcher::method_handle_invoke_SP_save_mask()); + } + // Fill in the kill mask for the call for( OptoReg::Name r = OptoReg::Name(0); r < _last_Mach_Reg; r=OptoReg::add(r,1) ) { if( !regs.Member(r) ) { // Not already defined by the call diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/machnode.cpp --- a/src/share/vm/opto/machnode.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/machnode.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -636,7 +636,9 @@ } #ifndef PRODUCT void MachCallJavaNode::dump_spec(outputStream *st) const { - if( _method ) { + if (_method_handle_invoke) + st->print("MethodHandle "); + if (_method) { _method->print_short_name(st); st->print(" "); } @@ -644,6 +646,20 @@ } #endif +//------------------------------Registers-------------------------------------- +const RegMask &MachCallJavaNode::in_RegMask(uint idx) const { + // Values in the domain use the users calling convention, embodied in the + // _in_rms array of RegMasks. + if (idx < tf()->domain()->cnt()) return _in_rms[idx]; + // Values outside the domain represent debug info + Matcher* m = Compile::current()->matcher(); + // If this call is a MethodHandle invoke we have to use a different + // debugmask which does not include the register we use to save the + // SP over MH invokes. + RegMask** debugmask = _method_handle_invoke ? m->idealreg2mhdebugmask : m->idealreg2debugmask; + return *debugmask[in(idx)->ideal_reg()]; +} + //============================================================================= uint MachCallStaticJavaNode::size_of() const { return sizeof(*this); } uint MachCallStaticJavaNode::cmp( const Node &n ) const { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/machnode.hpp --- a/src/share/vm/opto/machnode.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/machnode.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -662,9 +662,13 @@ ciMethod* _method; // Method being direct called int _bci; // Byte Code index of call byte code bool _optimized_virtual; // Tells if node is a static call or an optimized virtual + bool _method_handle_invoke; // Tells if the call has to preserve SP MachCallJavaNode() : MachCallNode() { init_class_id(Class_MachCallJava); } + + virtual const RegMask &in_RegMask(uint) const; + #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; #endif diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/matcher.cpp --- a/src/share/vm/opto/matcher.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/matcher.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -70,19 +70,27 @@ _dontcare(&_states_arena) { C->set_matcher(this); - idealreg2spillmask[Op_RegI] = NULL; - idealreg2spillmask[Op_RegN] = NULL; - idealreg2spillmask[Op_RegL] = NULL; - idealreg2spillmask[Op_RegF] = NULL; - idealreg2spillmask[Op_RegD] = NULL; - idealreg2spillmask[Op_RegP] = NULL; + idealreg2spillmask [Op_RegI] = NULL; + idealreg2spillmask [Op_RegN] = NULL; + idealreg2spillmask [Op_RegL] = NULL; + idealreg2spillmask [Op_RegF] = NULL; + idealreg2spillmask [Op_RegD] = NULL; + idealreg2spillmask [Op_RegP] = NULL; - idealreg2debugmask[Op_RegI] = NULL; - idealreg2debugmask[Op_RegN] = NULL; - idealreg2debugmask[Op_RegL] = NULL; - idealreg2debugmask[Op_RegF] = NULL; - idealreg2debugmask[Op_RegD] = NULL; - idealreg2debugmask[Op_RegP] = NULL; + idealreg2debugmask [Op_RegI] = NULL; + idealreg2debugmask [Op_RegN] = NULL; + idealreg2debugmask [Op_RegL] = NULL; + idealreg2debugmask [Op_RegF] = NULL; + idealreg2debugmask [Op_RegD] = NULL; + idealreg2debugmask [Op_RegP] = NULL; + + idealreg2mhdebugmask[Op_RegI] = NULL; + idealreg2mhdebugmask[Op_RegN] = NULL; + idealreg2mhdebugmask[Op_RegL] = NULL; + idealreg2mhdebugmask[Op_RegF] = NULL; + idealreg2mhdebugmask[Op_RegD] = NULL; + idealreg2mhdebugmask[Op_RegP] = NULL; + debug_only(_mem_node = NULL;) // Ideal memory node consumed by mach node } @@ -389,19 +397,28 @@ void Matcher::init_first_stack_mask() { // Allocate storage for spill masks as masks for the appropriate load type. - RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask)*12); - idealreg2spillmask[Op_RegN] = &rms[0]; - idealreg2spillmask[Op_RegI] = &rms[1]; - idealreg2spillmask[Op_RegL] = &rms[2]; - idealreg2spillmask[Op_RegF] = &rms[3]; - idealreg2spillmask[Op_RegD] = &rms[4]; - idealreg2spillmask[Op_RegP] = &rms[5]; - idealreg2debugmask[Op_RegN] = &rms[6]; - idealreg2debugmask[Op_RegI] = &rms[7]; - idealreg2debugmask[Op_RegL] = &rms[8]; - idealreg2debugmask[Op_RegF] = &rms[9]; - idealreg2debugmask[Op_RegD] = &rms[10]; - idealreg2debugmask[Op_RegP] = &rms[11]; + RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask) * 3*6); + + idealreg2spillmask [Op_RegN] = &rms[0]; + idealreg2spillmask [Op_RegI] = &rms[1]; + idealreg2spillmask [Op_RegL] = &rms[2]; + idealreg2spillmask [Op_RegF] = &rms[3]; + idealreg2spillmask [Op_RegD] = &rms[4]; + idealreg2spillmask [Op_RegP] = &rms[5]; + + idealreg2debugmask [Op_RegN] = &rms[6]; + idealreg2debugmask [Op_RegI] = &rms[7]; + idealreg2debugmask [Op_RegL] = &rms[8]; + idealreg2debugmask [Op_RegF] = &rms[9]; + idealreg2debugmask [Op_RegD] = &rms[10]; + idealreg2debugmask [Op_RegP] = &rms[11]; + + idealreg2mhdebugmask[Op_RegN] = &rms[12]; + idealreg2mhdebugmask[Op_RegI] = &rms[13]; + idealreg2mhdebugmask[Op_RegL] = &rms[14]; + idealreg2mhdebugmask[Op_RegF] = &rms[15]; + idealreg2mhdebugmask[Op_RegD] = &rms[16]; + idealreg2mhdebugmask[Op_RegP] = &rms[17]; OptoReg::Name i; @@ -442,12 +459,19 @@ // Make up debug masks. Any spill slot plus callee-save registers. // Caller-save registers are assumed to be trashable by the various // inline-cache fixup routines. - *idealreg2debugmask[Op_RegN]= *idealreg2spillmask[Op_RegN]; - *idealreg2debugmask[Op_RegI]= *idealreg2spillmask[Op_RegI]; - *idealreg2debugmask[Op_RegL]= *idealreg2spillmask[Op_RegL]; - *idealreg2debugmask[Op_RegF]= *idealreg2spillmask[Op_RegF]; - *idealreg2debugmask[Op_RegD]= *idealreg2spillmask[Op_RegD]; - *idealreg2debugmask[Op_RegP]= *idealreg2spillmask[Op_RegP]; + *idealreg2debugmask [Op_RegN]= *idealreg2spillmask[Op_RegN]; + *idealreg2debugmask [Op_RegI]= *idealreg2spillmask[Op_RegI]; + *idealreg2debugmask [Op_RegL]= *idealreg2spillmask[Op_RegL]; + *idealreg2debugmask [Op_RegF]= *idealreg2spillmask[Op_RegF]; + *idealreg2debugmask [Op_RegD]= *idealreg2spillmask[Op_RegD]; + *idealreg2debugmask [Op_RegP]= *idealreg2spillmask[Op_RegP]; + + *idealreg2mhdebugmask[Op_RegN]= *idealreg2spillmask[Op_RegN]; + *idealreg2mhdebugmask[Op_RegI]= *idealreg2spillmask[Op_RegI]; + *idealreg2mhdebugmask[Op_RegL]= *idealreg2spillmask[Op_RegL]; + *idealreg2mhdebugmask[Op_RegF]= *idealreg2spillmask[Op_RegF]; + *idealreg2mhdebugmask[Op_RegD]= *idealreg2spillmask[Op_RegD]; + *idealreg2mhdebugmask[Op_RegP]= *idealreg2spillmask[Op_RegP]; // Prevent stub compilations from attempting to reference // callee-saved registers from debug info @@ -458,14 +482,31 @@ if( _register_save_policy[i] == 'C' || _register_save_policy[i] == 'A' || (_register_save_policy[i] == 'E' && exclude_soe) ) { - idealreg2debugmask[Op_RegN]->Remove(i); - idealreg2debugmask[Op_RegI]->Remove(i); // Exclude save-on-call - idealreg2debugmask[Op_RegL]->Remove(i); // registers from debug - idealreg2debugmask[Op_RegF]->Remove(i); // masks - idealreg2debugmask[Op_RegD]->Remove(i); - idealreg2debugmask[Op_RegP]->Remove(i); + idealreg2debugmask [Op_RegN]->Remove(i); + idealreg2debugmask [Op_RegI]->Remove(i); // Exclude save-on-call + idealreg2debugmask [Op_RegL]->Remove(i); // registers from debug + idealreg2debugmask [Op_RegF]->Remove(i); // masks + idealreg2debugmask [Op_RegD]->Remove(i); + idealreg2debugmask [Op_RegP]->Remove(i); + + idealreg2mhdebugmask[Op_RegN]->Remove(i); + idealreg2mhdebugmask[Op_RegI]->Remove(i); + idealreg2mhdebugmask[Op_RegL]->Remove(i); + idealreg2mhdebugmask[Op_RegF]->Remove(i); + idealreg2mhdebugmask[Op_RegD]->Remove(i); + idealreg2mhdebugmask[Op_RegP]->Remove(i); } } + + // Subtract the register we use to save the SP for MethodHandle + // invokes to from the debug mask. + const RegMask save_mask = method_handle_invoke_SP_save_mask(); + idealreg2mhdebugmask[Op_RegN]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegI]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegL]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegF]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegD]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegP]->SUBTRACT(save_mask); } //---------------------------is_save_on_entry---------------------------------- @@ -989,6 +1030,7 @@ CallNode *call; const TypeTuple *domain; ciMethod* method = NULL; + bool is_method_handle_invoke = false; // for special kill effects if( sfpt->is_Call() ) { call = sfpt->as_Call(); domain = call->tf()->domain(); @@ -1013,6 +1055,8 @@ mcall_java->_method = method; mcall_java->_bci = call_java->_bci; mcall_java->_optimized_virtual = call_java->is_optimized_virtual(); + is_method_handle_invoke = call_java->is_method_handle_invoke(); + mcall_java->_method_handle_invoke = is_method_handle_invoke; if( mcall_java->is_MachCallStaticJava() ) mcall_java->as_MachCallStaticJava()->_name = call_java->as_CallStaticJava()->_name; @@ -1126,6 +1170,15 @@ mcall->_argsize = out_arg_limit_per_call - begin_out_arg_area; } + if (is_method_handle_invoke) { + // Kill some extra stack space in case method handles want to do + // a little in-place argument insertion. + int regs_per_word = NOT_LP64(1) LP64_ONLY(2); // %%% make a global const! + out_arg_limit_per_call += MethodHandlePushLimit * regs_per_word; + // Do not update mcall->_argsize because (a) the extra space is not + // pushed as arguments and (b) _argsize is dead (not used anywhere). + } + // Compute the max stack slot killed by any call. These will not be // available for debug info, and will be used to adjust FIRST_STACK_mask // after all call sites have been visited. diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/matcher.hpp --- a/src/share/vm/opto/matcher.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/matcher.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -117,8 +117,9 @@ static const int base2reg[]; // Map Types to machine register types // Convert ideal machine register to a register mask for spill-loads static const RegMask *idealreg2regmask[]; - RegMask *idealreg2spillmask[_last_machine_leaf]; - RegMask *idealreg2debugmask[_last_machine_leaf]; + RegMask *idealreg2spillmask [_last_machine_leaf]; + RegMask *idealreg2debugmask [_last_machine_leaf]; + RegMask *idealreg2mhdebugmask[_last_machine_leaf]; void init_spill_mask( Node *ret ); // Convert machine register number to register mask static uint mreg2regmask_max; @@ -297,6 +298,8 @@ // Register for MODL projection of divmodL static RegMask modL_proj_mask(); + static const RegMask method_handle_invoke_SP_save_mask(); + // Java-Interpreter calling convention // (what you use when calling between compiled-Java and Interpreted-Java diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/output.cpp --- a/src/share/vm/opto/output.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/output.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -794,6 +794,7 @@ #endif int safepoint_pc_offset = current_offset; + bool is_method_handle_invoke = false; // Add the safepoint in the DebugInfoRecorder if( !mach->is_MachCall() ) { @@ -801,6 +802,11 @@ debug_info()->add_safepoint(safepoint_pc_offset, sfn->_oop_map); } else { mcall = mach->as_MachCall(); + + // Is the call a MethodHandle call? + if (mcall->is_MachCallJava()) + is_method_handle_invoke = mcall->as_MachCallJava()->_method_handle_invoke; + safepoint_pc_offset += mcall->ret_addr_offset(); debug_info()->add_safepoint(safepoint_pc_offset, mcall->_oop_map); } @@ -911,9 +917,9 @@ ciMethod* scope_method = method ? method : _method; // Describe the scope here assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI"); - assert(!jvms->should_reexecute() || depth==max_depth, "reexecute allowed only for the youngest"); + assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest"); // Now we can describe the scope. - debug_info()->describe_scope(safepoint_pc_offset,scope_method,jvms->bci(),jvms->should_reexecute(),locvals,expvals,monvals); + debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, locvals, expvals, monvals); } // End jvms loop // Mark the end of the scope set. diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/parse3.cpp --- a/src/share/vm/opto/parse3.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/parse3.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -125,7 +125,25 @@ void Parse::do_get_xxx(const TypePtr* obj_type, Node* obj, ciField* field, bool is_field) { // Does this field have a constant value? If so, just push the value. - if (field->is_constant() && push_constant(field->constant_value())) return; + if (field->is_constant()) { + if (field->is_static()) { + // final static field + if (push_constant(field->constant_value())) + return; + } + else { + // final non-static field of a trusted class ({java,sun}.dyn + // classes). + if (obj->is_Con()) { + const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr(); + ciObject* constant_oop = oop_ptr->const_oop(); + ciConstant constant = field->constant_value_of(constant_oop); + + if (push_constant(constant, true)) + return; + } + } + } ciType* field_klass = field->type(); bool is_vol = field->is_volatile(); @@ -145,7 +163,7 @@ if (!field->type()->is_loaded()) { type = TypeInstPtr::BOTTOM; must_assert_null = true; - } else if (field->is_constant()) { + } else if (field->is_constant() && field->is_static()) { // This can happen if the constant oop is non-perm. ciObject* con = field->constant_value().as_object(); // Do not "join" in the previous type; it doesn't add value, diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/runtime.cpp --- a/src/share/vm/opto/runtime.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/runtime.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -790,7 +790,7 @@ NOT_PRODUCT(Exceptions::debug_check_abort(exception)); #ifdef ASSERT - if (!(exception->is_a(SystemDictionary::throwable_klass()))) { + if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { // should throw an exception here ShouldNotReachHere(); } @@ -858,6 +858,9 @@ thread->set_exception_pc(pc); thread->set_exception_handler_pc(handler_address); thread->set_exception_stack_size(0); + + // Check if the exception PC is a MethodHandle call. + thread->set_is_method_handle_exception(nm->is_method_handle_return(pc)); } // Restore correct return pc. Was saved above. @@ -936,7 +939,7 @@ #endif assert (exception != NULL, "should have thrown a NULLPointerException"); #ifdef ASSERT - if (!(exception->is_a(SystemDictionary::throwable_klass()))) { + if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { // should throw an exception here ShouldNotReachHere(); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/opto/type.cpp --- a/src/share/vm/opto/type.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/opto/type.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -2431,7 +2431,7 @@ //------------------------------make_from_constant----------------------------- // Make a java pointer from an oop constant const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_constant) { - if (o->is_method_data() || o->is_method()) { + if (o->is_method_data() || o->is_method() || o->is_cpcache()) { // Treat much like a typeArray of bytes, like below, but fake the type... const Type* etype = (Type*)get_const_basic_type(T_BYTE); const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS); @@ -3966,7 +3966,7 @@ const TypeFunc* tf = C->last_tf(method); // check cache if (tf != NULL) return tf; // The hit rate here is almost 50%. const TypeTuple *domain; - if (method->flags().is_static()) { + if (method->is_static()) { domain = TypeTuple::make_domain(NULL, method->signature()); } else { domain = TypeTuple::make_domain(method->holder(), method->signature()); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/jni.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -396,11 +396,11 @@ oop mirror = NULL; int slot = 0; - if (reflected->klass() == SystemDictionary::reflect_constructor_klass()) { + if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) { mirror = java_lang_reflect_Constructor::clazz(reflected); slot = java_lang_reflect_Constructor::slot(reflected); } else { - assert(reflected->klass() == SystemDictionary::reflect_method_klass(), "wrong type"); + assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type"); mirror = java_lang_reflect_Method::clazz(reflected); slot = java_lang_reflect_Method::slot(reflected); } @@ -496,7 +496,7 @@ klassOop super = Klass::cast(k)->java_super(); // super2 is the value computed by the compiler's getSuperClass intrinsic: debug_only(klassOop super2 = ( Klass::cast(k)->oop_is_javaArray() - ? SystemDictionary::object_klass() + ? SystemDictionary::Object_klass() : Klass::cast(k)->super() ) ); assert(super == super2, "java_super computation depends on interface, array, other super"); @@ -584,7 +584,7 @@ if (thread->has_pending_exception()) { Handle ex(thread, thread->pending_exception()); thread->clear_pending_exception(); - if (ex->is_a(SystemDictionary::threaddeath_klass())) { + if (ex->is_a(SystemDictionary::ThreadDeath_klass())) { // Don't print anything if we are being killed. } else { jio_fprintf(defaultStream::error_stream(), "Exception "); @@ -593,12 +593,12 @@ jio_fprintf(defaultStream::error_stream(), "in thread \"%s\" ", thread->get_thread_name()); } - if (ex->is_a(SystemDictionary::throwable_klass())) { + if (ex->is_a(SystemDictionary::Throwable_klass())) { JavaValue result(T_VOID); JavaCalls::call_virtual(&result, ex, KlassHandle(THREAD, - SystemDictionary::throwable_klass()), + SystemDictionary::Throwable_klass()), vmSymbolHandles::printStackTrace_name(), vmSymbolHandles::void_method_signature(), THREAD); @@ -3241,7 +3241,7 @@ jint b = Atomic::xchg(0xdeadbeef, &a); void *c = &a; void *d = Atomic::xchg_ptr(&b, &c); - assert(a == 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works"); + assert(a == (jint) 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works"); assert(c == &b && d == &a, "Atomic::xchg_ptr() works"); } #endif // ZERO && ASSERT diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/jniCheck.cpp --- a/src/share/vm/prims/jniCheck.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/jniCheck.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -341,7 +341,7 @@ ReportJNIFatalError(thr, fatal_received_null_class); } - if (mirror->klass() != SystemDictionary::class_klass()) { + if (mirror->klass() != SystemDictionary::Class_klass()) { ReportJNIFatalError(thr, fatal_class_not_a_class); } @@ -358,7 +358,7 @@ assert(klass != NULL, "klass argument must have a value"); if (!Klass::cast(klass)->oop_is_instance() || - !instanceKlass::cast(klass)->is_subclass_of(SystemDictionary::throwable_klass())) { + !instanceKlass::cast(klass)->is_subclass_of(SystemDictionary::Throwable_klass())) { ReportJNIFatalError(thr, fatal_class_not_a_throwable_class); } } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/jvm.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -80,7 +80,7 @@ while (!vfst.at_end()) { methodOop m = vfst.method(); - if (!vfst.method()->method_holder()->klass_part()->is_subclass_of(SystemDictionary::classloader_klass())&& + if (!vfst.method()->method_holder()->klass_part()->is_subclass_of(SystemDictionary::ClassLoader_klass())&& !vfst.method()->method_holder()->klass_part()->is_subclass_of(access_controller_klass) && !vfst.method()->method_holder()->klass_part()->is_subclass_of(privileged_action_klass)) { break; @@ -257,7 +257,7 @@ Handle value_str = java_lang_String::create_from_platform_dependent_str((value != NULL ? value : ""), CHECK); JavaCalls::call_virtual(&r, props, - KlassHandle(THREAD, SystemDictionary::properties_klass()), + KlassHandle(THREAD, SystemDictionary::Properties_klass()), vmSymbolHandles::put_name(), vmSymbolHandles::object_object_object_signature(), key_str, @@ -495,7 +495,7 @@ guarantee(klass->is_cloneable(), "all arrays are cloneable"); } else { guarantee(obj->is_instance(), "should be instanceOop"); - bool cloneable = klass->is_subtype_of(SystemDictionary::cloneable_klass()); + bool cloneable = klass->is_subtype_of(SystemDictionary::Cloneable_klass()); guarantee(cloneable == klass->is_cloneable(), "incorrect cloneable flag"); } #endif @@ -908,7 +908,7 @@ // Special handling for primitive objects if (java_lang_Class::is_primitive(mirror)) { // Primitive objects does not have any interfaces - objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, r); } @@ -923,7 +923,7 @@ } // Allocate result array - objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), size, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), size, CHECK_NULL); objArrayHandle result (THREAD, r); // Fill in result if (klass->oop_is_instance()) { @@ -934,8 +934,8 @@ } } else { // All arrays implement java.lang.Cloneable and java.io.Serializable - result->obj_at_put(0, Klass::cast(SystemDictionary::cloneable_klass())->java_mirror()); - result->obj_at_put(1, Klass::cast(SystemDictionary::serializable_klass())->java_mirror()); + result->obj_at_put(0, Klass::cast(SystemDictionary::Cloneable_klass())->java_mirror()); + result->obj_at_put(1, Klass::cast(SystemDictionary::Serializable_klass())->java_mirror()); } return (jobjectArray) JNIHandles::make_local(env, result()); JVM_END @@ -1098,8 +1098,8 @@ pending_exception = Handle(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; - if ( pending_exception->is_a(SystemDictionary::exception_klass()) && - !pending_exception->is_a(SystemDictionary::runtime_exception_klass())) { + if ( pending_exception->is_a(SystemDictionary::Exception_klass()) && + !pending_exception->is_a(SystemDictionary::RuntimeException_klass())) { // Throw a java.security.PrivilegedActionException(Exception e) exception JavaCallArguments args(pending_exception); THROW_ARG_0(vmSymbolHandles::java_security_PrivilegedActionException(), @@ -1190,7 +1190,7 @@ // the resource area must be registered in case of a gc RegisterArrayForGC ragc(thread, local_array); - objArrayOop context = oopFactory::new_objArray(SystemDictionary::protectionDomain_klass(), + objArrayOop context = oopFactory::new_objArray(SystemDictionary::ProtectionDomain_klass(), local_array->length(), CHECK_NULL); objArrayHandle h_context(thread, context); for (int index = 0; index < local_array->length(); index++) { @@ -1251,7 +1251,7 @@ if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) { - oop result = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL); + oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); return (jobjectArray)JNIHandles::make_local(env, result); } @@ -1259,7 +1259,7 @@ if (k->inner_classes()->length() == 0) { // Neither an inner nor outer class - oop result = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL); + oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); return (jobjectArray)JNIHandles::make_local(env, result); } @@ -1269,7 +1269,7 @@ int length = icls->length(); // Allocate temp. result array - objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), length/4, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), length/4, CHECK_NULL); objArrayHandle result (THREAD, r); int members = 0; @@ -1299,7 +1299,7 @@ if (members != length) { // Return array of right length - objArrayOop res = oopFactory::new_objArray(SystemDictionary::class_klass(), members, CHECK_NULL); + objArrayOop res = oopFactory::new_objArray(SystemDictionary::Class_klass(), members, CHECK_NULL); for(int i = 0; i < members; i++) { res->obj_at_put(i, result->obj_at(i)); } @@ -1470,11 +1470,11 @@ oop mirror = NULL; int slot = 0; - if (reflected->klass() == SystemDictionary::reflect_constructor_klass()) { + if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) { mirror = java_lang_reflect_Constructor::clazz(reflected); slot = java_lang_reflect_Constructor::slot(reflected); } else { - assert(reflected->klass() == SystemDictionary::reflect_method_klass(), + assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type"); mirror = java_lang_reflect_Method::clazz(reflected); slot = java_lang_reflect_Method::slot(reflected); @@ -1530,7 +1530,7 @@ if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) { // Return empty array - oop res = oopFactory::new_objArray(SystemDictionary::reflect_field_klass(), 0, CHECK_NULL); + oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); } @@ -1558,13 +1558,13 @@ } else { num_fields = fields_len / instanceKlass::next_offset; - if (k() == SystemDictionary::throwable_klass()) { + if (k() == SystemDictionary::Throwable_klass()) { num_fields--; skip_backtrace = true; } } - objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_field_klass(), num_fields, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), num_fields, CHECK_NULL); objArrayHandle result (THREAD, r); int out_idx = 0; @@ -1598,7 +1598,7 @@ if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) { // Return empty array - oop res = oopFactory::new_objArray(SystemDictionary::reflect_method_klass(), 0, CHECK_NULL); + oop res = oopFactory::new_objArray(SystemDictionary::reflect_Method_klass(), 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); } @@ -1622,7 +1622,7 @@ } // Allocate result - objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_method_klass(), num_methods, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Method_klass(), num_methods, CHECK_NULL); objArrayHandle result (THREAD, r); int out_idx = 0; @@ -1650,7 +1650,7 @@ if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) { // Return empty array - oop res = oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), 0 , CHECK_NULL); + oop res = oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0 , CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); } @@ -1674,7 +1674,7 @@ } // Allocate result - objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), num_constructors, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), num_constructors, CHECK_NULL); objArrayHandle result(THREAD, r); int out_idx = 0; @@ -1887,7 +1887,7 @@ symbolHandle klass_name (THREAD, cp->klass_name_at(klass_ref)); symbolHandle member_name(THREAD, cp->uncached_name_ref_at(index)); symbolHandle member_sig (THREAD, cp->uncached_signature_ref_at(index)); - objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::string_klass(), 3, CHECK_NULL); + objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::String_klass(), 3, CHECK_NULL); objArrayHandle dest(THREAD, dest_o); Handle str = java_lang_String::create_from_symbol(klass_name, CHECK_NULL); dest->obj_at_put(0, str()); @@ -2575,7 +2575,7 @@ JavaValue result(T_VOID); JavaCalls::call_virtual(&result, obj, - KlassHandle(THREAD, SystemDictionary::thread_klass()), + KlassHandle(THREAD, SystemDictionary::Thread_klass()), vmSymbolHandles::run_method_name(), vmSymbolHandles::void_method_signature(), THREAD); @@ -2673,7 +2673,7 @@ // Fix for 4314342, 4145910, perhaps others: it now doesn't have // any effect on the "liveness" of a thread; see // JVM_IsThreadAlive, below. - if (java_throwable->is_a(SystemDictionary::threaddeath_klass())) { + if (java_throwable->is_a(SystemDictionary::ThreadDeath_klass())) { java_lang_Thread::set_stillborn(java_thread); } THROW_OOP(java_throwable); @@ -3028,7 +3028,7 @@ } // Create result array of type [Ljava/lang/Class; - objArrayOop result = oopFactory::new_objArray(SystemDictionary::class_klass(), depth, CHECK_NULL); + objArrayOop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), depth, CHECK_NULL); // Fill in mirrors corresponding to method holders int index = 0; while (first != NULL) { @@ -4324,7 +4324,7 @@ JvmtiVMObjectAllocEventCollector oam; int num_threads = tle.num_threads(); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::thread_klass(), num_threads, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NULL); objArrayHandle threads_ah(THREAD, r); for (int i = 0; i < num_threads; i++) { @@ -4358,7 +4358,7 @@ // check if threads is not an array of objects of Thread class klassOop k = objArrayKlass::cast(ah->klass())->element_klass(); - if (k != SystemDictionary::thread_klass()) { + if (k != SystemDictionary::Thread_klass()) { THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0); } @@ -4418,7 +4418,7 @@ if (encl_method_class_idx == 0) { return NULL; } - objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::object_klass(), 3, CHECK_NULL); + objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::Object_klass(), 3, CHECK_NULL); objArrayHandle dest(THREAD, dest_o); klassOop enc_k = ik_h->constants()->klass_at(encl_method_class_idx, CHECK_NULL); dest->obj_at_put(0, Klass::cast(enc_k)->java_mirror()); @@ -4532,7 +4532,7 @@ values_h->int_at(0) == java_lang_Thread::NEW, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 1, /* only 1 substate */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4545,7 +4545,7 @@ values_h->int_at(0) == java_lang_Thread::RUNNABLE, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 1, /* only 1 substate */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4558,7 +4558,7 @@ values_h->int_at(0) == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 1, /* only 1 substate */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4571,7 +4571,7 @@ values_h->int_at(0) == java_lang_Thread::IN_OBJECT_WAIT && values_h->int_at(1) == java_lang_Thread::PARKED, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 2, /* number of substates */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4589,7 +4589,7 @@ values_h->int_at(1) == java_lang_Thread::IN_OBJECT_WAIT_TIMED && values_h->int_at(2) == java_lang_Thread::PARKED_TIMED, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 3, /* number of substates */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4608,7 +4608,7 @@ assert(values_h->length() == 1 && values_h->int_at(0) == java_lang_Thread::TERMINATED, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 1, /* only 1 substate */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4643,4 +4643,3 @@ #endif // KERNEL } JVM_END - diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/jvmtiEnter.xsl --- a/src/share/vm/prims/jvmtiEnter.xsl Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/jvmtiEnter.xsl Wed Jan 06 22:21:39 2010 -0800 @@ -773,7 +773,7 @@ } - if (!thread_oop->is_a(SystemDictionary::thread_klass())) { + if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { JVMTI_ERROR_INVALID_THREAD @@ -857,7 +857,7 @@ } - if (!k_mirror->is_a(SystemDictionary::class_klass())) { + if (!k_mirror->is_a(SystemDictionary::Class_klass())) { JVMTI_ERROR_INVALID_CLASS diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/jvmtiEnv.cpp --- a/src/share/vm/prims/jvmtiEnv.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/jvmtiEnv.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -133,7 +133,7 @@ if (thread_oop == NULL) { return JVMTI_ERROR_INVALID_THREAD; } - if (!thread_oop->is_a(SystemDictionary::thread_klass())) { + if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { return JVMTI_ERROR_INVALID_THREAD; } JavaThread* java_thread = java_lang_Thread::thread(thread_oop); @@ -199,7 +199,7 @@ if (k_mirror == NULL) { return JVMTI_ERROR_INVALID_CLASS; } - if (!k_mirror->is_a(SystemDictionary::class_klass())) { + if (!k_mirror->is_a(SystemDictionary::Class_klass())) { return JVMTI_ERROR_INVALID_CLASS; } @@ -266,7 +266,7 @@ oop mirror = JNIHandles::resolve_external_guard(object); NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); - if (mirror->klass() == SystemDictionary::class_klass()) { + if (mirror->klass() == SystemDictionary::Class_klass()) { if (!java_lang_Class::is_primitive(mirror)) { mirror = java_lang_Class::as_klassOop(mirror); assert(mirror != NULL, "class for non-primitive mirror must exist"); @@ -327,7 +327,7 @@ if (thread_oop == NULL) { return JVMTI_ERROR_INVALID_THREAD; } - if (!thread_oop->is_a(SystemDictionary::thread_klass())) { + if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { return JVMTI_ERROR_INVALID_THREAD; } java_thread = java_lang_Thread::thread(thread_oop); @@ -632,7 +632,7 @@ thread_oop = JNIHandles::resolve_external_guard(thread); } - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) { + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { return JVMTI_ERROR_INVALID_THREAD; } @@ -870,7 +870,7 @@ jvmtiError JvmtiEnv::InterruptThread(jthread thread) { oop thread_oop = JNIHandles::resolve_external_guard(thread); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) return JVMTI_ERROR_INVALID_THREAD; JavaThread* current_thread = JavaThread::current(); @@ -907,7 +907,7 @@ } else { thread_oop = JNIHandles::resolve_external_guard(thread); } - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) return JVMTI_ERROR_INVALID_THREAD; Handle thread_obj(current_thread, thread_oop); @@ -1073,7 +1073,7 @@ jvmtiError JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* arg, jint priority) { oop thread_oop = JNIHandles::resolve_external_guard(thread); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) { + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { return JVMTI_ERROR_INVALID_THREAD; } if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/jvmtiEnvBase.cpp --- a/src/share/vm/prims/jvmtiEnvBase.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/jvmtiEnvBase.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -527,7 +527,7 @@ JavaThread * JvmtiEnvBase::get_JavaThread(jthread jni_thread) { oop t = JNIHandles::resolve_external_guard(jni_thread); - if (t == NULL || !t->is_a(SystemDictionary::thread_klass())) { + if (t == NULL || !t->is_a(SystemDictionary::Thread_klass())) { return NULL; } // The following returns NULL if the thread has not yet run or is in @@ -1269,7 +1269,7 @@ for (int i = 0; i < _thread_count; ++i) { jthread jt = _thread_list[i]; oop thread_oop = JNIHandles::resolve_external_guard(jt); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) { + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { set_result(JVMTI_ERROR_INVALID_THREAD); return; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/jvmtiExport.cpp --- a/src/share/vm/prims/jvmtiExport.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/jvmtiExport.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -656,7 +656,7 @@ klassOop k = obj->klass(); // if the object is a java.lang.Class then return the java mirror - if (k == SystemDictionary::class_klass()) { + if (k == SystemDictionary::Class_klass()) { if (!java_lang_Class::is_primitive(obj)) { k = java_lang_Class::as_klassOop(obj); assert(k != NULL, "class for non-primitive mirror must exist"); @@ -1925,7 +1925,7 @@ if (collector != NULL && collector->is_enabled()) { // Don't record classes as these will be notified via the ClassLoad // event. - if (obj->klass() != SystemDictionary::class_klass()) { + if (obj->klass() != SystemDictionary::Class_klass()) { collector->record_allocation(obj); } } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -3214,7 +3214,7 @@ // - all instanceKlasses for redefined classes reused & contents updated the_class->vtable()->initialize_vtable(false, THREAD); the_class->itable()->initialize_itable(false, THREAD); - assert(!HAS_PENDING_EXCEPTION || (THREAD->pending_exception()->is_a(SystemDictionary::threaddeath_klass())), "redefine exception"); + assert(!HAS_PENDING_EXCEPTION || (THREAD->pending_exception()->is_a(SystemDictionary::ThreadDeath_klass())), "redefine exception"); } // Leave arrays of jmethodIDs and itable index cache unchanged diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/jvmtiTagMap.cpp --- a/src/share/vm/prims/jvmtiTagMap.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/jvmtiTagMap.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -579,7 +579,7 @@ // If the object is a java.lang.Class then return the klassOop, // otherwise return the original object static inline oop klassOop_if_java_lang_Class(oop o) { - if (o->klass() == SystemDictionary::class_klass()) { + if (o->klass() == SystemDictionary::Class_klass()) { if (!java_lang_Class::is_primitive(o)) { o = (oop)java_lang_Class::as_klassOop(o); assert(o != NULL, "class for non-primitive mirror must exist"); @@ -644,7 +644,7 @@ } else { // if the object represents a runtime class then use the // tag for java.lang.Class - _klass = SystemDictionary::class_klass(); + _klass = SystemDictionary::Class_klass(); } _klass_tag = tag_for(tag_map, _klass); } @@ -747,7 +747,7 @@ // get referrer class tag. klassOop k = (_referrer == referrer) ? // Check if referrer is a class... _referrer->klass() // No, just get its class - : SystemDictionary::class_klass(); // Yes, its class is Class + : SystemDictionary::Class_klass(); // Yes, its class is Class _referrer_klass_tag = tag_for(tag_map, k); } } @@ -1126,7 +1126,7 @@ oop str, void* user_data) { - assert(str->klass() == SystemDictionary::string_klass(), "not a string"); + assert(str->klass() == SystemDictionary::String_klass(), "not a string"); // get the string value and length // (string value may be offset from the base) @@ -1186,7 +1186,7 @@ // for static fields only the index will be set static jvmtiHeapReferenceInfo reference_info = { 0 }; - assert(obj->klass() == SystemDictionary::class_klass(), "not a class"); + assert(obj->klass() == SystemDictionary::Class_klass(), "not a class"); if (java_lang_Class::is_primitive(obj)) { return 0; } @@ -1498,7 +1498,7 @@ if (callbacks()->primitive_field_callback != NULL && obj->is_instance()) { jint res; jvmtiPrimitiveFieldCallback cb = callbacks()->primitive_field_callback; - if (obj->klass() == SystemDictionary::class_klass()) { + if (obj->klass() == SystemDictionary::Class_klass()) { res = invoke_primitive_field_callback_for_static_fields(&wrapper, obj, cb, @@ -1515,7 +1515,7 @@ // string callback if (!is_array && callbacks()->string_primitive_value_callback != NULL && - obj->klass() == SystemDictionary::string_klass()) { + obj->klass() == SystemDictionary::String_klass()) { jint res = invoke_string_value_callback( callbacks()->string_primitive_value_callback, &wrapper, @@ -2381,7 +2381,7 @@ // invoke the string value callback inline bool CallbackInvoker::report_string_value(oop str) { - assert(str->klass() == SystemDictionary::string_klass(), "not a string"); + assert(str->klass() == SystemDictionary::String_klass(), "not a string"); AdvancedHeapWalkContext* context = advanced_context(); assert(context->string_primitive_value_callback() != NULL, "no callback"); @@ -2928,7 +2928,7 @@ // super (only if something more interesting than java.lang.Object) klassOop java_super = ik->java_super(); - if (java_super != NULL && java_super != SystemDictionary::object_klass()) { + if (java_super != NULL && java_super != SystemDictionary::Object_klass()) { oop super = Klass::cast(java_super)->java_mirror(); if (!CallbackInvoker::report_superclass_reference(mirror, super)) { return false; @@ -3070,7 +3070,7 @@ // if the object is a java.lang.String if (is_reporting_string_values() && - o->klass() == SystemDictionary::string_klass()) { + o->klass() == SystemDictionary::String_klass()) { if (!CallbackInvoker::report_string_value(o)) { return false; } @@ -3255,7 +3255,7 @@ // instance if (o->is_instance()) { - if (o->klass() == SystemDictionary::class_klass()) { + if (o->klass() == SystemDictionary::Class_klass()) { o = klassOop_if_java_lang_Class(o); if (o->is_klass()) { // a java.lang.Class diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/methodHandleWalk.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/prims/methodHandleWalk.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -0,0 +1,1396 @@ +/* + * Copyright 2008-2010 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. + * + */ + +/* + * JSR 292 reference implementation: method handle structure analysis + */ + +#include "incls/_precompiled.incl" +#include "incls/_methodHandleWalk.cpp.incl" + + +// ----------------------------------------------------------------------------- +// MethodHandleChain + +void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { + if (!java_dyn_MethodHandle::is_instance(mh())) lose("bad method handle", CHECK); + + // set current method handle and unpack partially + _method_handle = mh; + _is_last = false; + _is_bound = false; + _arg_slot = -1; + _arg_type = T_VOID; + _conversion = -1; + _last_invoke = Bytecodes::_nop; //arbitrary non-garbage + + if (sun_dyn_DirectMethodHandle::is_instance(mh())) { + set_last_method(mh(), THREAD); + return; + } + if (sun_dyn_AdapterMethodHandle::is_instance(mh())) { + _conversion = AdapterMethodHandle_conversion(); + assert(_conversion != -1, "bad conv value"); + assert(sun_dyn_BoundMethodHandle::is_instance(mh()), "also BMH"); + } + if (sun_dyn_BoundMethodHandle::is_instance(mh())) { + if (!is_adapter()) // keep AMH and BMH separate in this model + _is_bound = true; + _arg_slot = BoundMethodHandle_vmargslot(); + oop target = MethodHandle_vmtarget_oop(); + if (!is_bound() || java_dyn_MethodHandle::is_instance(target)) { + _arg_type = compute_bound_arg_type(target, NULL, _arg_slot, CHECK); + } else if (target != NULL && target->is_method()) { + methodOop m = (methodOop) target; + _arg_type = compute_bound_arg_type(NULL, m, _arg_slot, CHECK); + set_last_method(mh(), CHECK); + } else { + _is_bound = false; // lose! + } + } + if (is_bound() && _arg_type == T_VOID) { + lose("bad vmargslot", CHECK); + } + if (!is_bound() && !is_adapter()) { + lose("unrecognized MH type", CHECK); + } +} + + +void MethodHandleChain::set_last_method(oop target, TRAPS) { + _is_last = true; + klassOop receiver_limit_oop = NULL; + int flags = 0; + methodOop m = MethodHandles::decode_method(target, receiver_limit_oop, flags); + _last_method = methodHandle(THREAD, m); + if ((flags & MethodHandles::_dmf_has_receiver) == 0) + _last_invoke = Bytecodes::_invokestatic; + else if ((flags & MethodHandles::_dmf_does_dispatch) == 0) + _last_invoke = Bytecodes::_invokespecial; + else if ((flags & MethodHandles::_dmf_from_interface) != 0) + _last_invoke = Bytecodes::_invokeinterface; + else + _last_invoke = Bytecodes::_invokevirtual; +} + + +BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS) { + // There is no direct indication of whether the argument is primitive or not. + // It is implied by the _vmentry code, and by the MethodType of the target. + // FIXME: Make it explicit MethodHandleImpl refactors out from MethodHandle + BasicType arg_type = T_VOID; + if (target != NULL) { + oop mtype = java_dyn_MethodHandle::type(target); + int arg_num = MethodHandles::argument_slot_to_argnum(mtype, arg_slot); + if (arg_num >= 0) { + oop ptype = java_dyn_MethodType::ptype(mtype, arg_num); + arg_type = java_lang_Class::as_BasicType(ptype); + } + } else if (m != NULL) { + // figure out the argument type from the slot + // FIXME: make this explicit in the MH + int cur_slot = m->size_of_parameters(); + if (arg_slot >= cur_slot) + return T_VOID; + if (!m->is_static()) { + cur_slot -= type2size[T_OBJECT]; + if (cur_slot == arg_slot) + return T_OBJECT; + } + for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) { + BasicType bt = ss.type(); + cur_slot -= type2size[bt]; + if (cur_slot <= arg_slot) { + if (cur_slot == arg_slot) + arg_type = bt; + break; + } + } + } + if (arg_type == T_ARRAY) + arg_type = T_OBJECT; + return arg_type; +} + + +void MethodHandleChain::lose(const char* msg, TRAPS) { + assert(false, "lose"); + _lose_message = msg; + if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) { + // throw a preallocated exception + THROW_OOP(Universe::virtual_machine_error_instance()); + } + THROW_MSG(vmSymbols::java_lang_InternalError(), msg); +} + + +// ----------------------------------------------------------------------------- +// MethodHandleWalker + +Bytecodes::Code MethodHandleWalker::conversion_code(BasicType src, BasicType dest) { + if (is_subword_type(src)) { + src = T_INT; // all subword src types act like int + } + if (src == dest) { + return Bytecodes::_nop; + } + +#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d)) + switch (SRC_DEST(src, dest)) { + case SRC_DEST(T_INT, T_LONG): return Bytecodes::_i2l; + case SRC_DEST(T_INT, T_FLOAT): return Bytecodes::_i2f; + case SRC_DEST(T_INT, T_DOUBLE): return Bytecodes::_i2d; + case SRC_DEST(T_INT, T_BYTE): return Bytecodes::_i2b; + case SRC_DEST(T_INT, T_CHAR): return Bytecodes::_i2c; + case SRC_DEST(T_INT, T_SHORT): return Bytecodes::_i2s; + + case SRC_DEST(T_LONG, T_INT): return Bytecodes::_l2i; + case SRC_DEST(T_LONG, T_FLOAT): return Bytecodes::_l2f; + case SRC_DEST(T_LONG, T_DOUBLE): return Bytecodes::_l2d; + + case SRC_DEST(T_FLOAT, T_INT): return Bytecodes::_f2i; + case SRC_DEST(T_FLOAT, T_LONG): return Bytecodes::_f2l; + case SRC_DEST(T_FLOAT, T_DOUBLE): return Bytecodes::_f2d; + + case SRC_DEST(T_DOUBLE, T_INT): return Bytecodes::_d2i; + case SRC_DEST(T_DOUBLE, T_LONG): return Bytecodes::_d2l; + case SRC_DEST(T_DOUBLE, T_FLOAT): return Bytecodes::_d2f; + } +#undef SRC_DEST + + // cannot do it in one step, or at all + return Bytecodes::_illegal; +} + + +// ----------------------------------------------------------------------------- +// MethodHandleWalker::walk +// +MethodHandleWalker::ArgToken +MethodHandleWalker::walk(TRAPS) { + ArgToken empty = ArgToken(); // Empty return value. + + walk_incoming_state(CHECK_(empty)); + + for (;;) { + set_method_handle(chain().method_handle_oop()); + + assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); + + if (chain().is_adapter()) { + int conv_op = chain().adapter_conversion_op(); + int arg_slot = chain().adapter_arg_slot(); + SlotState* arg_state = slot_state(arg_slot); + if (arg_state == NULL + && conv_op > sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) { + lose("bad argument index", CHECK_(empty)); + } + + // perform the adapter action + switch (chain().adapter_conversion_op()) { + case sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY: + // No changes to arguments; pass the bits through. + break; + + case sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW: { + // To keep the verifier happy, emit bitwise ("raw") conversions as needed. + // See MethodHandles::same_basic_type_for_arguments for allowed conversions. + Handle incoming_mtype(THREAD, chain().method_type_oop()); + oop outgoing_mh_oop = chain().vmtarget_oop(); + if (!java_dyn_MethodHandle::is_instance(outgoing_mh_oop)) + lose("outgoing target not a MethodHandle", CHECK_(empty)); + Handle outgoing_mtype(THREAD, java_dyn_MethodHandle::type(outgoing_mh_oop)); + outgoing_mh_oop = NULL; // GC safety + + int nptypes = java_dyn_MethodType::ptype_count(outgoing_mtype()); + if (nptypes != java_dyn_MethodType::ptype_count(incoming_mtype())) + lose("incoming and outgoing parameter count do not agree", CHECK_(empty)); + + for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { + SlotState* arg_state = slot_state(slot); + if (arg_state->_type == T_VOID) continue; + ArgToken arg = _outgoing.at(slot)._arg; + + klassOop in_klass = NULL; + klassOop out_klass = NULL; + BasicType inpbt = java_lang_Class::as_BasicType(java_dyn_MethodType::ptype(incoming_mtype(), i), &in_klass); + BasicType outpbt = java_lang_Class::as_BasicType(java_dyn_MethodType::ptype(outgoing_mtype(), i), &out_klass); + assert(inpbt == arg.basic_type(), "sanity"); + + if (inpbt != outpbt) { + vmIntrinsics::ID iid = vmIntrinsics::for_raw_conversion(inpbt, outpbt); + if (iid == vmIntrinsics::_none) { + lose("no raw conversion method", CHECK_(empty)); + } + ArgToken arglist[2]; + arglist[0] = arg; // outgoing 'this' + arglist[1] = ArgToken(); // sentinel + arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty)); + change_argument(inpbt, slot, outpbt, arg); + } + + i++; // We need to skip void slots at the top of the loop. + } + + BasicType inrbt = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(incoming_mtype())); + BasicType outrbt = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(outgoing_mtype())); + if (inrbt != outrbt) { + if (inrbt == T_INT && outrbt == T_VOID) { + // See comments in MethodHandles::same_basic_type_for_arguments. + } else { + assert(false, "IMPLEMENT ME"); + lose("no raw conversion method", CHECK_(empty)); + } + } + break; + } + + case sun_dyn_AdapterMethodHandle::OP_CHECK_CAST: { + // checkcast the Nth outgoing argument in place + klassOop dest_klass = NULL; + BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); + assert(dest == T_OBJECT, ""); + assert(dest == arg_state->_type, ""); + ArgToken arg = arg_state->_arg; + ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); + assert(arg.index() == new_arg.index(), "should be the same index"); + debug_only(dest_klass = (klassOop)badOop); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM: { + // i2l, etc., on the Nth outgoing argument in place + BasicType src = chain().adapter_conversion_src_type(), + dest = chain().adapter_conversion_dest_type(); + Bytecodes::Code bc = conversion_code(src, dest); + ArgToken arg = arg_state->_arg; + if (bc == Bytecodes::_nop) { + break; + } else if (bc != Bytecodes::_illegal) { + arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); + } else if (is_subword_type(dest)) { + bc = conversion_code(src, T_INT); + if (bc != Bytecodes::_illegal) { + arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); + bc = conversion_code(T_INT, dest); + arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); + } + } + if (bc == Bytecodes::_illegal) { + lose("bad primitive conversion", CHECK_(empty)); + } + change_argument(src, arg_slot, dest, arg); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM: { + // checkcast to wrapper type & call intValue, etc. + BasicType dest = chain().adapter_conversion_dest_type(); + ArgToken arg = arg_state->_arg; + arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest), + Bytecodes::_checkcast, arg, CHECK_(empty)); + vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest); + if (unboxer == vmIntrinsics::_none) { + lose("no unboxing method", CHECK_(empty)); + } + ArgToken arglist[2]; + arglist[0] = arg; // outgoing 'this' + arglist[1] = ArgToken(); // sentinel + arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty)); + change_argument(T_OBJECT, arg_slot, dest, arg); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF: { + // call wrapper type.valueOf + BasicType src = chain().adapter_conversion_src_type(); + ArgToken arg = arg_state->_arg; + vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src); + if (boxer == vmIntrinsics::_none) { + lose("no boxing method", CHECK_(empty)); + } + ArgToken arglist[2]; + arglist[0] = arg; // outgoing value + arglist[1] = ArgToken(); // sentinel + assert(false, "I think the argument count must be 1 instead of 0"); + arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 0, &arglist[0], CHECK_(empty)); + change_argument(src, arg_slot, T_OBJECT, arg); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS: { + int dest_arg_slot = chain().adapter_conversion_vminfo(); + if (!slot_has_argument(dest_arg_slot)) { + lose("bad swap index", CHECK_(empty)); + } + // a simple swap between two arguments + SlotState* dest_arg_state = slot_state(dest_arg_slot); + SlotState temp = (*dest_arg_state); + (*dest_arg_state) = (*arg_state); + (*arg_state) = temp; + break; + } + + case sun_dyn_AdapterMethodHandle::OP_ROT_ARGS: { + int dest_arg_slot = chain().adapter_conversion_vminfo(); + if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) { + lose("bad rotate index", CHECK_(empty)); + } + SlotState* dest_arg_state = slot_state(dest_arg_slot); + // Rotate the source argument (plus following N slots) into the + // position occupied by the dest argument (plus following N slots). + int rotate_count = type2size[dest_arg_state->_type]; + // (no other rotate counts are currently supported) + if (arg_slot < dest_arg_slot) { + for (int i = 0; i < rotate_count; i++) { + SlotState temp = _outgoing.at(arg_slot); + _outgoing.remove_at(arg_slot); + _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp); + } + } else { // arg_slot > dest_arg_slot + for (int i = 0; i < rotate_count; i++) { + SlotState temp = _outgoing.at(arg_slot + rotate_count - 1); + _outgoing.remove_at(arg_slot + rotate_count - 1); + _outgoing.insert_before(dest_arg_slot, temp); + } + } + break; + } + + case sun_dyn_AdapterMethodHandle::OP_DUP_ARGS: { + int dup_slots = chain().adapter_conversion_stack_pushes(); + if (dup_slots <= 0) { + lose("bad dup count", CHECK_(empty)); + } + for (int i = 0; i < dup_slots; i++) { + SlotState* dup = slot_state(arg_slot + 2*i); + if (dup == NULL) break; // safety net + if (dup->_type != T_VOID) _outgoing_argc += 1; + _outgoing.insert_before(i, (*dup)); + } + break; + } + + case sun_dyn_AdapterMethodHandle::OP_DROP_ARGS: { + int drop_slots = -chain().adapter_conversion_stack_pushes(); + if (drop_slots <= 0) { + lose("bad drop count", CHECK_(empty)); + } + for (int i = 0; i < drop_slots; i++) { + SlotState* drop = slot_state(arg_slot); + if (drop == NULL) break; // safety net + if (drop->_type != T_VOID) _outgoing_argc -= 1; + _outgoing.remove_at(arg_slot); + } + break; + } + + case sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC + lose("unimplemented", CHECK_(empty)); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS: { + klassOop array_klass_oop = NULL; + BasicType array_type = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), + &array_klass_oop); + assert(array_type == T_OBJECT, ""); + assert(Klass::cast(array_klass_oop)->oop_is_array(), ""); + arrayKlassHandle array_klass(THREAD, array_klass_oop); + debug_only(array_klass_oop = (klassOop)badOop); + + klassOop element_klass_oop = NULL; + BasicType element_type = java_lang_Class::as_BasicType(array_klass->component_mirror(), + &element_klass_oop); + KlassHandle element_klass(THREAD, element_klass_oop); + debug_only(element_klass_oop = (klassOop)badOop); + + // Fetch the argument, which we will cast to the required array type. + assert(arg_state->_type == T_OBJECT, ""); + ArgToken array_arg = arg_state->_arg; + array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_(empty)); + change_argument(T_OBJECT, arg_slot, T_VOID, ArgToken(tt_void)); + + // Check the required length. + int spread_slots = 1 + chain().adapter_conversion_stack_pushes(); + int spread_length = spread_slots; + if (type2size[element_type] == 2) { + if (spread_slots % 2 != 0) spread_slots = -1; // force error + spread_length = spread_slots / 2; + } + if (spread_slots < 0) { + lose("bad spread length", CHECK_(empty)); + } + + jvalue length_jvalue; length_jvalue.i = spread_length; + ArgToken length_arg = make_prim_constant(T_INT, &length_jvalue, CHECK_(empty)); + // Call a built-in method known to the JVM to validate the length. + ArgToken arglist[3]; + arglist[0] = array_arg; // value to check + arglist[1] = length_arg; // length to check + arglist[2] = ArgToken(); // sentinel + make_invoke(NULL, vmIntrinsics::_checkSpreadArgument, + Bytecodes::_invokestatic, false, 3, &arglist[0], CHECK_(empty)); + + // Spread out the array elements. + Bytecodes::Code aload_op = Bytecodes::_aaload; + if (element_type != T_OBJECT) { + lose("primitive array NYI", CHECK_(empty)); + } + int ap = arg_slot; + for (int i = 0; i < spread_length; i++) { + jvalue offset_jvalue; offset_jvalue.i = i; + ArgToken offset_arg = make_prim_constant(T_INT, &offset_jvalue, CHECK_(empty)); + ArgToken element_arg = make_fetch(element_type, element_klass(), aload_op, array_arg, offset_arg, CHECK_(empty)); + change_argument(T_VOID, ap, element_type, element_arg); + ap += type2size[element_type]; + } + break; + } + + case sun_dyn_AdapterMethodHandle::OP_FLYBY: //NYI, runs Java code + case sun_dyn_AdapterMethodHandle::OP_RICOCHET: //NYI, runs Java code + lose("unimplemented", CHECK_(empty)); + break; + + default: + lose("bad adapter conversion", CHECK_(empty)); + break; + } + } + + if (chain().is_bound()) { + // push a new argument + BasicType arg_type = chain().bound_arg_type(); + jint arg_slot = chain().bound_arg_slot(); + oop arg_oop = chain().bound_arg_oop(); + ArgToken arg; + if (arg_type == T_OBJECT) { + arg = make_oop_constant(arg_oop, CHECK_(empty)); + } else { + jvalue arg_value; + BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value); + if (bt == arg_type) { + arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty)); + } else { + lose("bad bound value", CHECK_(empty)); + } + } + debug_only(arg_oop = badOop); + change_argument(T_VOID, arg_slot, arg_type, arg); + } + + // this test must come after the body of the loop + if (!chain().is_last()) { + chain().next(CHECK_(empty)); + } else { + break; + } + } + + // finish the sequence with a tail-call to the ultimate target + // parameters are passed in logical order (recv 1st), not slot order + ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1); + int ap = 0; + for (int i = _outgoing.length() - 1; i >= 0; i--) { + SlotState* arg_state = slot_state(i); + if (arg_state->_type == T_VOID) continue; + arglist[ap++] = _outgoing.at(i)._arg; + } + assert(ap == _outgoing_argc, ""); + arglist[ap] = ArgToken(); // add a sentinel, for the sake of asserts + return make_invoke(chain().last_method_oop(), + vmIntrinsics::_none, + chain().last_invoke_code(), true, + ap, arglist, THREAD); +} + + +// ----------------------------------------------------------------------------- +// MethodHandleWalker::walk_incoming_state +// +void MethodHandleWalker::walk_incoming_state(TRAPS) { + Handle mtype(THREAD, chain().method_type_oop()); + int nptypes = java_dyn_MethodType::ptype_count(mtype()); + _outgoing_argc = nptypes; + int argp = nptypes - 1; + if (argp >= 0) { + _outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize + } + for (int i = 0; i < nptypes; i++) { + klassOop arg_type_klass = NULL; + BasicType arg_type = java_lang_Class::as_BasicType( + java_dyn_MethodType::ptype(mtype(), i), &arg_type_klass); + int index = new_local_index(arg_type); + ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); + debug_only(arg_type_klass = (klassOop) NULL); + _outgoing.at_put(argp, make_state(arg_type, arg)); + if (type2size[arg_type] == 2) { + // add the extra slot, so we can model the JVM stack + _outgoing.insert_before(argp+1, make_state(T_VOID, ArgToken(tt_void))); + } + --argp; + } + // call make_parameter at the end of the list for the return type + klassOop ret_type_klass = NULL; + BasicType ret_type = java_lang_Class::as_BasicType( + java_dyn_MethodType::rtype(mtype()), &ret_type_klass); + ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK); + // ignore ret; client can catch it if needed +} + + +// ----------------------------------------------------------------------------- +// MethodHandleWalker::change_argument +// +// This is messy because some kinds of arguments are paired with +// companion slots containing an empty value. +void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type, + const ArgToken& new_arg) { + int old_size = type2size[old_type]; + int new_size = type2size[new_type]; + if (old_size == new_size) { + // simple case first + _outgoing.at_put(slot, make_state(new_type, new_arg)); + } else if (old_size > new_size) { + for (int i = old_size - 1; i >= new_size; i--) { + assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), ""); + _outgoing.remove_at(slot + i); + } + if (new_size > 0) + _outgoing.at_put(slot, make_state(new_type, new_arg)); + else + _outgoing_argc -= 1; // deleted a real argument + } else { + for (int i = old_size; i < new_size; i++) { + _outgoing.insert_before(slot + i, make_state(T_VOID, ArgToken(tt_void))); + } + _outgoing.at_put(slot, make_state(new_type, new_arg)); + if (old_size == 0) + _outgoing_argc += 1; // inserted a real argument + } +} + + +#ifdef ASSERT +int MethodHandleWalker::argument_count_slow() { + int args_seen = 0; + for (int i = _outgoing.length() - 1; i >= 0; i--) { + if (_outgoing.at(i)._type != T_VOID) { + ++args_seen; + } + } + return args_seen; +} +#endif + + +// ----------------------------------------------------------------------------- +// MethodHandleCompiler + +MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, bool is_invokedynamic, TRAPS) + : MethodHandleWalker(root, is_invokedynamic, THREAD), + _callee(callee), + _thread(THREAD), + _bytecode(THREAD, 50), + _constants(THREAD, 10), + _cur_stack(0), + _max_stack(0), + _rtype(T_ILLEGAL) +{ + + // Element zero is always the null constant. + (void) _constants.append(NULL); + + // Set name and signature index. + _name_index = cpool_symbol_put(_callee->name()); + _signature_index = cpool_symbol_put(_callee->signature()); + + // Get return type klass. + Handle first_mtype(THREAD, chain().method_type_oop()); + // _rklass is NULL for primitives. + _rtype = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(first_mtype()), &_rklass); + + int params = _callee->size_of_parameters(); // Incoming arguments plus receiver. + _num_params = for_invokedynamic() ? params - 1 : params; // XXX Check if callee is static? +} + + +// ----------------------------------------------------------------------------- +// MethodHandleCompiler::compile +// +// Compile this MethodHandle into a bytecode adapter and return a +// methodOop. +methodHandle MethodHandleCompiler::compile(TRAPS) { + assert(_thread == THREAD, "must be same thread"); + methodHandle nullHandle; + (void) walk(CHECK_(nullHandle)); + return get_method_oop(CHECK_(nullHandle)); +} + + +void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { + Bytecodes::check(op); // Are we legal? + + switch (op) { + // b + case Bytecodes::_aconst_null: + case Bytecodes::_iconst_m1: + case Bytecodes::_iconst_0: + case Bytecodes::_iconst_1: + case Bytecodes::_iconst_2: + case Bytecodes::_iconst_3: + case Bytecodes::_iconst_4: + case Bytecodes::_iconst_5: + case Bytecodes::_lconst_0: + case Bytecodes::_lconst_1: + case Bytecodes::_fconst_0: + case Bytecodes::_fconst_1: + case Bytecodes::_fconst_2: + case Bytecodes::_dconst_0: + case Bytecodes::_dconst_1: + case Bytecodes::_iload_0: + case Bytecodes::_iload_1: + case Bytecodes::_iload_2: + case Bytecodes::_iload_3: + case Bytecodes::_lload_0: + case Bytecodes::_lload_1: + case Bytecodes::_lload_2: + case Bytecodes::_lload_3: + case Bytecodes::_fload_0: + case Bytecodes::_fload_1: + case Bytecodes::_fload_2: + case Bytecodes::_fload_3: + case Bytecodes::_dload_0: + case Bytecodes::_dload_1: + case Bytecodes::_dload_2: + case Bytecodes::_dload_3: + case Bytecodes::_aload_0: + case Bytecodes::_aload_1: + case Bytecodes::_aload_2: + case Bytecodes::_aload_3: + case Bytecodes::_istore_0: + case Bytecodes::_istore_1: + case Bytecodes::_istore_2: + case Bytecodes::_istore_3: + case Bytecodes::_lstore_0: + case Bytecodes::_lstore_1: + case Bytecodes::_lstore_2: + case Bytecodes::_lstore_3: + case Bytecodes::_fstore_0: + case Bytecodes::_fstore_1: + case Bytecodes::_fstore_2: + case Bytecodes::_fstore_3: + case Bytecodes::_dstore_0: + case Bytecodes::_dstore_1: + case Bytecodes::_dstore_2: + case Bytecodes::_dstore_3: + case Bytecodes::_astore_0: + case Bytecodes::_astore_1: + case Bytecodes::_astore_2: + case Bytecodes::_astore_3: + case Bytecodes::_i2l: + case Bytecodes::_i2f: + case Bytecodes::_i2d: + case Bytecodes::_i2b: + case Bytecodes::_i2c: + case Bytecodes::_i2s: + case Bytecodes::_l2i: + case Bytecodes::_l2f: + case Bytecodes::_l2d: + case Bytecodes::_f2i: + case Bytecodes::_f2l: + case Bytecodes::_f2d: + case Bytecodes::_d2i: + case Bytecodes::_d2l: + case Bytecodes::_d2f: + case Bytecodes::_ireturn: + case Bytecodes::_lreturn: + case Bytecodes::_freturn: + case Bytecodes::_dreturn: + case Bytecodes::_areturn: + case Bytecodes::_return: + assert(strcmp(Bytecodes::format(op), "b") == 0, "wrong bytecode format"); + _bytecode.push(op); + break; + + // bi + case Bytecodes::_ldc: + case Bytecodes::_iload: + case Bytecodes::_lload: + case Bytecodes::_fload: + case Bytecodes::_dload: + case Bytecodes::_aload: + case Bytecodes::_istore: + case Bytecodes::_lstore: + case Bytecodes::_fstore: + case Bytecodes::_dstore: + case Bytecodes::_astore: + assert(strcmp(Bytecodes::format(op), "bi") == 0, "wrong bytecode format"); + assert((char) index == index, "index does not fit in 8-bit"); + _bytecode.push(op); + _bytecode.push(index); + break; + + // bii + case Bytecodes::_ldc2_w: + case Bytecodes::_checkcast: + assert(strcmp(Bytecodes::format(op), "bii") == 0, "wrong bytecode format"); + assert((short) index == index, "index does not fit in 16-bit"); + _bytecode.push(op); + _bytecode.push(index >> 8); + _bytecode.push(index); + break; + + // bjj + case Bytecodes::_invokestatic: + case Bytecodes::_invokespecial: + case Bytecodes::_invokevirtual: + assert(strcmp(Bytecodes::format(op), "bjj") == 0, "wrong bytecode format"); + assert((short) index == index, "index does not fit in 16-bit"); + _bytecode.push(op); + _bytecode.push(index >> 8); + _bytecode.push(index); + break; + + default: + ShouldNotReachHere(); + } +} + + +void MethodHandleCompiler::emit_load(BasicType bt, int index) { + if (index <= 3) { + switch (bt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::cast(Bytecodes::_iload_0 + index)); break; + case T_LONG: emit_bc(Bytecodes::cast(Bytecodes::_lload_0 + index)); break; + case T_FLOAT: emit_bc(Bytecodes::cast(Bytecodes::_fload_0 + index)); break; + case T_DOUBLE: emit_bc(Bytecodes::cast(Bytecodes::_dload_0 + index)); break; + case T_OBJECT: emit_bc(Bytecodes::cast(Bytecodes::_aload_0 + index)); break; + default: + ShouldNotReachHere(); + } + } + else { + switch (bt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::_iload, index); break; + case T_LONG: emit_bc(Bytecodes::_lload, index); break; + case T_FLOAT: emit_bc(Bytecodes::_fload, index); break; + case T_DOUBLE: emit_bc(Bytecodes::_dload, index); break; + case T_OBJECT: emit_bc(Bytecodes::_aload, index); break; + default: + ShouldNotReachHere(); + } + } + stack_push(bt); +} + +void MethodHandleCompiler::emit_store(BasicType bt, int index) { + if (index <= 3) { + switch (bt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::cast(Bytecodes::_istore_0 + index)); break; + case T_LONG: emit_bc(Bytecodes::cast(Bytecodes::_lstore_0 + index)); break; + case T_FLOAT: emit_bc(Bytecodes::cast(Bytecodes::_fstore_0 + index)); break; + case T_DOUBLE: emit_bc(Bytecodes::cast(Bytecodes::_dstore_0 + index)); break; + case T_OBJECT: emit_bc(Bytecodes::cast(Bytecodes::_astore_0 + index)); break; + default: + ShouldNotReachHere(); + } + } + else { + switch (bt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::_istore, index); break; + case T_LONG: emit_bc(Bytecodes::_lstore, index); break; + case T_FLOAT: emit_bc(Bytecodes::_fstore, index); break; + case T_DOUBLE: emit_bc(Bytecodes::_dstore, index); break; + case T_OBJECT: emit_bc(Bytecodes::_astore, index); break; + default: + ShouldNotReachHere(); + } + } + stack_pop(bt); +} + + +void MethodHandleCompiler::emit_load_constant(ArgToken arg) { + BasicType bt = arg.basic_type(); + switch (bt) { + case T_INT: { + jint value = arg.get_jint(); + if (-1 <= value && value <= 5) + emit_bc(Bytecodes::cast(Bytecodes::_iconst_0 + value)); + else + emit_bc(Bytecodes::_ldc, cpool_int_put(value)); + break; + } + case T_LONG: { + jlong value = arg.get_jlong(); + if (0 <= value && value <= 1) + emit_bc(Bytecodes::cast(Bytecodes::_lconst_0 + (int) value)); + else + emit_bc(Bytecodes::_ldc2_w, cpool_long_put(value)); + break; + } + case T_FLOAT: { + jfloat value = arg.get_jfloat(); + if (value == 0.0 || value == 1.0 || value == 2.0) + emit_bc(Bytecodes::cast(Bytecodes::_fconst_0 + (int) value)); + else + emit_bc(Bytecodes::_ldc, cpool_float_put(value)); + break; + } + case T_DOUBLE: { + jdouble value = arg.get_jdouble(); + if (value == 0.0 || value == 1.0) + emit_bc(Bytecodes::cast(Bytecodes::_dconst_0 + (int) value)); + else + emit_bc(Bytecodes::_ldc2_w, cpool_double_put(value)); + break; + } + case T_OBJECT: { + Handle value = arg.object(); + if (value.is_null()) + emit_bc(Bytecodes::_aconst_null); + else + emit_bc(Bytecodes::_ldc, cpool_object_put(value)); + break; + } + default: + ShouldNotReachHere(); + } + stack_push(bt); +} + + +MethodHandleWalker::ArgToken +MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, + const ArgToken& src, TRAPS) { + + BasicType srctype = src.basic_type(); + int index = src.index(); + + switch (op) { + case Bytecodes::_i2l: + case Bytecodes::_i2f: + case Bytecodes::_i2d: + case Bytecodes::_i2b: + case Bytecodes::_i2c: + case Bytecodes::_i2s: + + case Bytecodes::_l2i: + case Bytecodes::_l2f: + case Bytecodes::_l2d: + + case Bytecodes::_f2i: + case Bytecodes::_f2l: + case Bytecodes::_f2d: + + case Bytecodes::_d2i: + case Bytecodes::_d2l: + case Bytecodes::_d2f: + emit_load(srctype, index); + stack_pop(srctype); // pop the src type + emit_bc(op); + stack_push(type); // push the dest value + if (srctype != type) + index = new_local_index(type); + emit_store(type, index); + break; + + case Bytecodes::_checkcast: + emit_load(srctype, index); + emit_bc(op, cpool_klass_put(tk)); + emit_store(srctype, index); + break; + + default: + ShouldNotReachHere(); + } + + return make_parameter(type, tk, index, THREAD); +} + + +// ----------------------------------------------------------------------------- +// MethodHandleCompiler +// + +static jvalue zero_jvalue; + +// Emit bytecodes for the given invoke instruction. +MethodHandleWalker::ArgToken +MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, + Bytecodes::Code op, bool tailcall, + int argc, MethodHandleWalker::ArgToken* argv, + TRAPS) { + if (m == NULL) { + // Get the intrinsic methodOop. + m = vmIntrinsics::method_for(iid); + } + + klassOop klass = m->method_holder(); + symbolOop name = m->name(); + symbolOop signature = m->signature(); + + // This generated adapter method should be in the same class as the + // DMH target method (for accessability reasons). + if (tailcall) { + _target_klass = klass; + } + + // instanceKlass* ik = instanceKlass::cast(klass); + // tty->print_cr("MethodHandleCompiler::make_invoke: %s %s.%s%s", Bytecodes::name(op), ik->external_name(), name->as_C_string(), signature->as_C_string()); + + // Inline the method. + InvocationCounter* ic = m->invocation_counter(); + ic->set_carry(); + + for (int i = 0; i < argc; i++) { + ArgToken arg = argv[i]; + TokenType tt = arg.token_type(); + BasicType bt = arg.basic_type(); + + switch (tt) { + case tt_parameter: + case tt_temporary: + emit_load(bt, arg.index()); + break; + case tt_constant: + emit_load_constant(arg); + break; + case tt_illegal: + // Sentinel. + assert(i == (argc - 1), "sentinel must be last entry"); + break; + case tt_void: + default: + ShouldNotReachHere(); + } + } + + // Populate constant pool. + int name_index = cpool_symbol_put(name); + int signature_index = cpool_symbol_put(signature); + int name_and_type_index = cpool_name_and_type_put(name_index, signature_index); + int klass_index = cpool_klass_put(klass); + int methodref_index = cpool_methodref_put(klass_index, name_and_type_index); + + // Generate invoke. + switch (op) { + case Bytecodes::_invokestatic: + case Bytecodes::_invokespecial: + case Bytecodes::_invokevirtual: + emit_bc(op, methodref_index); + break; + case Bytecodes::_invokeinterface: + Unimplemented(); + break; + default: + ShouldNotReachHere(); + } + + // If tailcall, we have walked all the way to a direct method handle. + // Otherwise, make a recursive call to some helper routine. + BasicType rbt = m->result_type(); + ArgToken ret; + if (tailcall) { + if (rbt != _rtype) { + if (rbt == T_VOID) { + // push a zero of the right sort + ArgToken zero; + if (_rtype == T_OBJECT) { + zero = make_oop_constant(NULL, CHECK_(zero)); + } else { + zero = make_prim_constant(_rtype, &zero_jvalue, CHECK_(zero)); + } + emit_load_constant(zero); + } else if (_rtype == T_VOID) { + // We'll emit a _return with something on the stack. + // It's OK to ignore what's on the stack. + } else { + tty->print_cr("*** rbt=%d != rtype=%d", rbt, _rtype); + assert(false, "IMPLEMENT ME"); + } + } + switch (_rtype) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::_ireturn); break; + case T_LONG: emit_bc(Bytecodes::_lreturn); break; + case T_FLOAT: emit_bc(Bytecodes::_freturn); break; + case T_DOUBLE: emit_bc(Bytecodes::_dreturn); break; + case T_VOID: emit_bc(Bytecodes::_return); break; + case T_OBJECT: + if (_rklass.not_null() && _rklass() != SystemDictionary::Object_klass()) + emit_bc(Bytecodes::_checkcast, cpool_klass_put(_rklass())); + emit_bc(Bytecodes::_areturn); + break; + default: ShouldNotReachHere(); + } + ret = ArgToken(); // Dummy return value. + } + else { + stack_push(rbt); // The return value is already pushed onto the stack. + int index = new_local_index(rbt); + switch (rbt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: case T_LONG: case T_FLOAT: case T_DOUBLE: + case T_OBJECT: + emit_store(rbt, index); + ret = ArgToken(tt_temporary, rbt, index); + break; + case T_VOID: + ret = ArgToken(tt_void); + break; + default: + ShouldNotReachHere(); + } + } + + return ret; +} + +MethodHandleWalker::ArgToken +MethodHandleCompiler::make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, + const MethodHandleWalker::ArgToken& base, + const MethodHandleWalker::ArgToken& offset, + TRAPS) { + Unimplemented(); + return ArgToken(); +} + + +int MethodHandleCompiler::cpool_primitive_put(BasicType bt, jvalue* con) { + jvalue con_copy; + assert(bt < T_OBJECT, ""); + if (type2aelembytes(bt) < jintSize) { + // widen to int + con_copy = (*con); + con = &con_copy; + switch (bt) { + case T_BOOLEAN: con->i = (con->z ? 1 : 0); break; + case T_BYTE: con->i = con->b; break; + case T_CHAR: con->i = con->c; break; + case T_SHORT: con->i = con->s; break; + default: ShouldNotReachHere(); + } + bt = T_INT; + } + +// for (int i = 1, imax = _constants.length(); i < imax; i++) { +// ConstantValue* con = _constants.at(i); +// if (con != NULL && con->is_primitive() && con->_type == bt) { +// bool match = false; +// switch (type2size[bt]) { +// case 1: if (pcon->_value.i == con->i) match = true; break; +// case 2: if (pcon->_value.j == con->j) match = true; break; +// } +// if (match) +// return i; +// } +// } + ConstantValue* cv = new ConstantValue(bt, *con); + int index = _constants.append(cv); + + // long and double entries take 2 slots, we add another empty entry. + if (type2size[bt] == 2) + (void) _constants.append(NULL); + + return index; +} + + +constantPoolHandle MethodHandleCompiler::get_constant_pool(TRAPS) const { + constantPoolHandle nullHandle; + bool is_conc_safe = true; + constantPoolOop cpool_oop = oopFactory::new_constantPool(_constants.length(), is_conc_safe, CHECK_(nullHandle)); + constantPoolHandle cpool(THREAD, cpool_oop); + + // Fill the real constant pool skipping the zero element. + for (int i = 1; i < _constants.length(); i++) { + ConstantValue* cv = _constants.at(i); + switch (cv->tag()) { + case JVM_CONSTANT_Utf8: cpool->symbol_at_put( i, cv->symbol_oop() ); break; + case JVM_CONSTANT_Integer: cpool->int_at_put( i, cv->get_jint() ); break; + case JVM_CONSTANT_Float: cpool->float_at_put( i, cv->get_jfloat() ); break; + case JVM_CONSTANT_Long: cpool->long_at_put( i, cv->get_jlong() ); break; + case JVM_CONSTANT_Double: cpool->double_at_put( i, cv->get_jdouble() ); break; + case JVM_CONSTANT_Class: cpool->klass_at_put( i, cv->klass_oop() ); break; + case JVM_CONSTANT_Methodref: cpool->method_at_put( i, cv->first_index(), cv->second_index()); break; + case JVM_CONSTANT_NameAndType: cpool->name_and_type_at_put(i, cv->first_index(), cv->second_index()); break; + case JVM_CONSTANT_Object: cpool->object_at_put( i, cv->object_oop() ); break; + default: ShouldNotReachHere(); + } + + switch (cv->tag()) { + case JVM_CONSTANT_Long: + case JVM_CONSTANT_Double: + i++; // Skip empty entry. + assert(_constants.at(i) == NULL, "empty entry"); + break; + } + } + + // Set the constant pool holder to the target method's class. + cpool->set_pool_holder(_target_klass()); + + return cpool; +} + + +methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { + methodHandle nullHandle; + // Create a method that holds the generated bytecode. invokedynamic + // has no receiver, normal MH calls do. + int flags_bits; + if (for_invokedynamic()) + flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_STATIC); + else + flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL); + + bool is_conc_safe = true; + methodOop m_oop = oopFactory::new_method(bytecode_length(), + accessFlags_from(flags_bits), + 0, 0, 0, is_conc_safe, CHECK_(nullHandle)); + methodHandle m(THREAD, m_oop); + m_oop = NULL; // oop not GC safe + + constantPoolHandle cpool = get_constant_pool(CHECK_(nullHandle)); + m->set_constants(cpool()); + + m->set_name_index(_name_index); + m->set_signature_index(_signature_index); + + m->set_code((address) bytecode()); + + m->set_max_stack(_max_stack); + m->set_max_locals(max_locals()); + m->set_size_of_parameters(_num_params); + + typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array()); + m->set_exception_table(exception_handlers()); + + // Set the carry bit of the invocation counter to force inlining of + // the adapter. + InvocationCounter* ic = m->invocation_counter(); + ic->set_carry(); + + // Rewrite the method and set up the constant pool cache. + objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(nullHandle)); + objArrayHandle methods(THREAD, m_array); + methods->obj_at_put(0, m()); + Rewriter::rewrite(_target_klass(), cpool, methods, CHECK_(nullHandle)); // Use fake class. + +#ifndef PRODUCT + if (TraceMethodHandles) { + m->print(); + m->print_codes(); + } +#endif //PRODUCT + + return m; +} + + +#ifndef PRODUCT + +#if 0 +// MH printer for debugging. + +class MethodHandlePrinter : public MethodHandleWalker { +private: + outputStream* _out; + bool _verbose; + int _temp_num; + stringStream _strbuf; + const char* strbuf() { + const char* s = _strbuf.as_string(); + _strbuf.reset(); + return s; + } + ArgToken token(const char* str) { + return (ArgToken) str; + } + void start_params() { + _out->print("("); + } + void end_params() { + if (_verbose) _out->print("\n"); + _out->print(") => {"); + } + void put_type_name(BasicType type, klassOop tk, outputStream* s) { + const char* kname = NULL; + if (tk != NULL) + kname = Klass::cast(tk)->external_name(); + s->print("%s", (kname != NULL) ? kname : type2name(type)); + } + ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) { + const char* value = strbuf(); + if (!_verbose) return token(value); + // make an explicit binding for each separate value + _strbuf.print("%s%d", temp_name, ++_temp_num); + const char* temp = strbuf(); + _out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value); + return token(temp); + } + +public: + MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS) + : MethodHandleWalker(root, THREAD), + _out(out), + _verbose(verbose), + _temp_num(0) + { + start_params(); + } + virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { + if (argnum < 0) { + end_params(); + return NULL; + } + if (argnum == 0) { + _out->print(_verbose ? "\n " : ""); + } else { + _out->print(_verbose ? ",\n " : ", "); + } + if (argnum >= _temp_num) + _temp_num = argnum; + // generate an argument name + _strbuf.print("a%d", argnum); + const char* arg = strbuf(); + put_type_name(type, tk, _out); + _out->print(" %s", arg); + return token(arg); + } + virtual ArgToken make_oop_constant(oop con, TRAPS) { + if (con == NULL) + _strbuf.print("null"); + else + con->print_value_on(&_strbuf); + if (_strbuf.size() == 0) { // yuck + _strbuf.print("(a "); + put_type_name(T_OBJECT, con->klass(), &_strbuf); + _strbuf.print(")"); + } + return maybe_make_temp("constant", T_OBJECT, "k"); + } + virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { + java_lang_boxing_object::print(type, con, &_strbuf); + return maybe_make_temp("constant", type, "k"); + } + virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS) { + _strbuf.print("%s(%s", Bytecodes::name(op), (const char*)src); + if (tk != NULL) { + _strbuf.print(", "); + put_type_name(type, tk, &_strbuf); + } + _strbuf.print(")"); + return maybe_make_temp("convert", type, "v"); + } + virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS) { + _strbuf.print("%s(%s, %s", Bytecodes::name(op), (const char*)base, (const char*)offset); + if (tk != NULL) { + _strbuf.print(", "); + put_type_name(type, tk, &_strbuf); + } + _strbuf.print(")"); + return maybe_make_temp("fetch", type, "x"); + } + virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, + Bytecodes::Code op, bool tailcall, + int argc, ArgToken* argv, TRAPS) { + symbolOop name, sig; + if (m != NULL) { + name = m->name(); + sig = m->signature(); + } else { + name = vmSymbols::symbol_at(vmIntrinsics::name_for(iid)); + sig = vmSymbols::symbol_at(vmIntrinsics::signature_for(iid)); + } + _strbuf.print("%s %s%s(", Bytecodes::name(op), name->as_C_string(), sig->as_C_string()); + for (int i = 0; i < argc; i++) { + _strbuf.print("%s%s", (i > 0 ? ", " : ""), (const char*)argv[i]); + } + _strbuf.print(")"); + if (!tailcall) { + BasicType rt = char2type(sig->byte_at(sig->utf8_length()-1)); + if (rt == T_ILLEGAL) rt = T_OBJECT; // ';' at the end of '(...)L...;' + return maybe_make_temp("invoke", rt, "x"); + } else { + const char* ret = strbuf(); + _out->print(_verbose ? "\n return " : " "); + _out->print("%s", ret); + _out->print(_verbose ? "\n}\n" : " }"); + } + return ArgToken(); + } + + virtual void set_method_handle(oop mh) { + if (WizardMode && Verbose) { + tty->print("\n--- next target: "); + mh->print(); + } + } + + static void print(Handle root, bool verbose, outputStream* out, TRAPS) { + ResourceMark rm; + MethodHandlePrinter printer(root, verbose, out, CHECK); + printer.walk(CHECK); + out->print("\n"); + } + static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) { + EXCEPTION_MARK; + ResourceMark rm; + MethodHandlePrinter printer(root, verbose, out, THREAD); + if (!HAS_PENDING_EXCEPTION) + printer.walk(THREAD); + if (HAS_PENDING_EXCEPTION) { + oop ex = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + out->print("\n*** "); + if (ex != Universe::virtual_machine_error_instance()) + ex->print_on(out); + else + out->print("lose: %s", printer.lose_message()); + out->print("\n}\n"); + } + out->print("\n"); + } +}; +#endif // 0 + +extern "C" +void print_method_handle(oop mh) { + if (java_dyn_MethodHandle::is_instance(mh)) { + //MethodHandlePrinter::print(mh); + } else { + tty->print("*** not a method handle: "); + mh->print(); + } +} + +#endif // PRODUCT diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/methodHandleWalk.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/prims/methodHandleWalk.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -0,0 +1,407 @@ +/* + * Copyright 2008-2010 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. + * + */ + +// Low-level parser for method handle chains. +class MethodHandleChain : StackObj { +public: + typedef MethodHandles::EntryKind EntryKind; + +private: + Handle _root; // original target + Handle _method_handle; // current target + bool _is_last; // final guy in chain + bool _is_bound; // has a bound argument + BasicType _arg_type; // if is_bound, the bound argument type + int _arg_slot; // if is_bound or is_adapter, affected argument slot + jint _conversion; // conversion field of AMH or -1 + methodHandle _last_method; // if is_last, which method we target + Bytecodes::Code _last_invoke; // if is_last, type of invoke + const char* _lose_message; // saved argument to lose() + + void set_method_handle(Handle target, TRAPS); + void set_last_method(oop target, TRAPS); + static BasicType compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS); + + oop MethodHandle_type_oop() { return java_dyn_MethodHandle::type(method_handle_oop()); } + oop MethodHandle_vmtarget_oop() { return java_dyn_MethodHandle::vmtarget(method_handle_oop()); } + int MethodHandle_vmslots() { return java_dyn_MethodHandle::vmslots(method_handle_oop()); } + int DirectMethodHandle_vmindex() { return sun_dyn_DirectMethodHandle::vmindex(method_handle_oop()); } + oop BoundMethodHandle_argument_oop() { return sun_dyn_BoundMethodHandle::argument(method_handle_oop()); } + int BoundMethodHandle_vmargslot() { return sun_dyn_BoundMethodHandle::vmargslot(method_handle_oop()); } + int AdapterMethodHandle_conversion() { return sun_dyn_AdapterMethodHandle::conversion(method_handle_oop()); } + +public: + MethodHandleChain(Handle root, TRAPS) + : _root(root) + { set_method_handle(root, THREAD); } + + bool is_adapter() { return _conversion != -1; } + bool is_bound() { return _is_bound; } + bool is_last() { return _is_last; } + + void next(TRAPS) { + assert(!is_last(), ""); + set_method_handle(MethodHandle_vmtarget_oop(), THREAD); + } + + Handle method_handle() { return _method_handle; } + oop method_handle_oop() { return _method_handle(); } + oop method_type_oop() { return MethodHandle_type_oop(); } + oop vmtarget_oop() { return MethodHandle_vmtarget_oop(); } + + jint adapter_conversion() { assert(is_adapter(), ""); return _conversion; } + int adapter_conversion_op() { return MethodHandles::adapter_conversion_op(adapter_conversion()); } + BasicType adapter_conversion_src_type() + { return MethodHandles::adapter_conversion_src_type(adapter_conversion()); } + BasicType adapter_conversion_dest_type() + { return MethodHandles::adapter_conversion_dest_type(adapter_conversion()); } + int adapter_conversion_stack_move() + { return MethodHandles::adapter_conversion_stack_move(adapter_conversion()); } + int adapter_conversion_stack_pushes() + { return adapter_conversion_stack_move() / MethodHandles::stack_move_unit(); } + int adapter_conversion_vminfo() + { return MethodHandles::adapter_conversion_vminfo(adapter_conversion()); } + int adapter_arg_slot() { assert(is_adapter(), ""); return _arg_slot; } + oop adapter_arg_oop() { assert(is_adapter(), ""); return BoundMethodHandle_argument_oop(); } + + BasicType bound_arg_type() { assert(is_bound(), ""); return _arg_type; } + int bound_arg_slot() { assert(is_bound(), ""); return _arg_slot; } + oop bound_arg_oop() { assert(is_bound(), ""); return BoundMethodHandle_argument_oop(); } + + methodOop last_method_oop() { assert(is_last(), ""); return _last_method(); } + Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; } + + void lose(const char* msg, TRAPS); + const char* lose_message() { return _lose_message; } +}; + + +// Structure walker for method handles. +// Does abstract interpretation on top of low-level parsing. +// You supply the tokens shuffled by the abstract interpretation. +class MethodHandleWalker : StackObj { +public: + // Stack values: + enum TokenType { + tt_void, + tt_parameter, + tt_temporary, + tt_constant, + tt_illegal + }; + + // Argument token: + class ArgToken { + private: + TokenType _tt; + BasicType _bt; + jvalue _value; + Handle _handle; + + public: + ArgToken(TokenType tt = tt_illegal) : _tt(tt) {} + ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {} + + ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) { + _value.i = index; + } + + ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) { + _handle = value; + } + + TokenType token_type() const { return _tt; } + BasicType basic_type() const { return _bt; } + int index() const { return _value.i; } + Handle object() const { return _handle; } + + jint get_jint() const { return _value.i; } + jlong get_jlong() const { return _value.j; } + jfloat get_jfloat() const { return _value.f; } + jdouble get_jdouble() const { return _value.d; } + }; + + // Abstract interpretation state: + struct SlotState { + BasicType _type; + ArgToken _arg; + SlotState() : _type(), _arg() {} + }; + static SlotState make_state(BasicType type, ArgToken arg) { + SlotState ss; + ss._type = type; ss._arg = arg; + return ss; + } + +private: + MethodHandleChain _chain; + bool _for_invokedynamic; + int _local_index; + + GrowableArray _outgoing; // current outgoing parameter slots + int _outgoing_argc; // # non-empty outgoing slots + + // Replace a value of type old_type at slot (and maybe slot+1) with the new value. + // If old_type != T_VOID, remove the old argument at that point. + // If new_type != T_VOID, insert the new argument at that point. + // Insert or delete a second empty slot as needed. + void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg); + + SlotState* slot_state(int slot) { + if (slot < 0 || slot >= _outgoing.length()) + return NULL; + return _outgoing.adr_at(slot); + } + BasicType slot_type(int slot) { + SlotState* ss = slot_state(slot); + if (ss == NULL) + return T_ILLEGAL; + return ss->_type; + } + bool slot_has_argument(int slot) { + return slot_type(slot) < T_VOID; + } + +#ifdef ASSERT + int argument_count_slow(); +#endif + + // Return a bytecode for converting src to dest, if one exists. + Bytecodes::Code conversion_code(BasicType src, BasicType dest); + + void walk_incoming_state(TRAPS); + +public: + MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS) + : _chain(root, THREAD), + _for_invokedynamic(for_invokedynamic), + _outgoing(THREAD, 10), + _outgoing_argc(0) + { + _local_index = for_invokedynamic ? 0 : 1; + } + + MethodHandleChain& chain() { return _chain; } + + bool for_invokedynamic() const { return _for_invokedynamic; } + + int new_local_index(BasicType bt) { + //int index = _for_invokedynamic ? _local_index : _local_index - 1; + int index = _local_index; + _local_index += type2size[bt]; + return index; + } + + int max_locals() const { return _local_index; } + + // plug-in abstract interpretation steps: + virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0; + virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0; + virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0; + virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS ) = 0; + virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS ) = 0; + virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0; + + // For make_invoke, the methodOop can be NULL if the intrinsic ID + // is something other than vmIntrinsics::_none. + + // and in case anyone cares to related the previous actions to the chain: + virtual void set_method_handle(oop mh) { } + + void lose(const char* msg, TRAPS) { chain().lose(msg, THREAD); } + const char* lose_message() { return chain().lose_message(); } + + ArgToken walk(TRAPS); +}; + + +// An abstract interpreter for method handle chains. +// Produces an account of the semantics of a chain, in terms of a static IR. +// The IR happens to be JVM bytecodes. +class MethodHandleCompiler : public MethodHandleWalker { +private: + methodHandle _callee; + KlassHandle _rklass; // Return type for casting. + BasicType _rtype; + KlassHandle _target_klass; + Thread* _thread; + + // Fake constant pool entry. + class ConstantValue { + private: + int _tag; // Constant pool tag type. + JavaValue _value; + Handle _handle; + + public: + // Constructor for oop types. + ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) { + assert(tag == JVM_CONSTANT_Utf8 || + tag == JVM_CONSTANT_Class || + tag == JVM_CONSTANT_String || + tag == JVM_CONSTANT_Object, "must be oop type"); + } + + // Constructor for oop reference types. + ConstantValue(int tag, int index) : _tag(tag) { + assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type"); + _value.set_jint(index); + } + ConstantValue(int tag, int first_index, int second_index) : _tag(tag) { + assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type"); + _value.set_jint(first_index << 16 | second_index); + } + + // Constructor for primitive types. + ConstantValue(BasicType bt, jvalue con) { + _value.set_type(bt); + switch (bt) { + case T_INT: _tag = JVM_CONSTANT_Integer; _value.set_jint( con.i); break; + case T_LONG: _tag = JVM_CONSTANT_Long; _value.set_jlong( con.j); break; + case T_FLOAT: _tag = JVM_CONSTANT_Float; _value.set_jfloat( con.f); break; + case T_DOUBLE: _tag = JVM_CONSTANT_Double; _value.set_jdouble(con.d); break; + default: ShouldNotReachHere(); + } + } + + int tag() const { return _tag; } + symbolOop symbol_oop() const { return (symbolOop) _handle(); } + klassOop klass_oop() const { return (klassOop) _handle(); } + oop object_oop() const { return _handle(); } + int index() const { return _value.get_jint(); } + int first_index() const { return _value.get_jint() >> 16; } + int second_index() const { return _value.get_jint() & 0x0000FFFF; } + + bool is_primitive() const { return is_java_primitive(_value.get_type()); } + jint get_jint() const { return _value.get_jint(); } + jlong get_jlong() const { return _value.get_jlong(); } + jfloat get_jfloat() const { return _value.get_jfloat(); } + jdouble get_jdouble() const { return _value.get_jdouble(); } + }; + + // Fake constant pool. + GrowableArray _constants; + + // Accumulated compiler state: + GrowableArray _bytecode; + + int _cur_stack; + int _max_stack; + int _num_params; + int _name_index; + int _signature_index; + + void stack_push(BasicType bt) { + _cur_stack += type2size[bt]; + if (_cur_stack > _max_stack) _max_stack = _cur_stack; + } + void stack_pop(BasicType bt) { + _cur_stack -= type2size[bt]; + assert(_cur_stack >= 0, "sanity"); + } + + unsigned char* bytecode() const { return _bytecode.adr_at(0); } + int bytecode_length() const { return _bytecode.length(); } + + // Fake constant pool. + int cpool_oop_put(int tag, Handle con) { + if (con.is_null()) return 0; + ConstantValue* cv = new ConstantValue(tag, con); + return _constants.append(cv); + } + + int cpool_oop_reference_put(int tag, int first_index, int second_index) { + if (first_index == 0 && second_index == 0) return 0; + assert(first_index != 0 && second_index != 0, "no zero indexes"); + ConstantValue* cv = new ConstantValue(tag, first_index, second_index); + return _constants.append(cv); + } + + int cpool_primitive_put(BasicType type, jvalue* con); + + int cpool_int_put(jint value) { + jvalue con; con.i = value; + return cpool_primitive_put(T_INT, &con); + } + int cpool_long_put(jlong value) { + jvalue con; con.j = value; + return cpool_primitive_put(T_LONG, &con); + } + int cpool_float_put(jfloat value) { + jvalue con; con.f = value; + return cpool_primitive_put(T_FLOAT, &con); + } + int cpool_double_put(jdouble value) { + jvalue con; con.d = value; + return cpool_primitive_put(T_DOUBLE, &con); + } + + int cpool_object_put(Handle obj) { + return cpool_oop_put(JVM_CONSTANT_Object, obj); + } + int cpool_symbol_put(symbolOop sym) { + return cpool_oop_put(JVM_CONSTANT_Utf8, sym); + } + int cpool_klass_put(klassOop klass) { + return cpool_oop_put(JVM_CONSTANT_Class, klass); + } + int cpool_methodref_put(int class_index, int name_and_type_index) { + return cpool_oop_reference_put(JVM_CONSTANT_Methodref, class_index, name_and_type_index); + } + int cpool_name_and_type_put(int name_index, int signature_index) { + return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index); + } + + void emit_bc(Bytecodes::Code op, int index = 0); + void emit_load(BasicType bt, int index); + void emit_store(BasicType bt, int index); + void emit_load_constant(ArgToken arg); + + virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { + return ArgToken(tt_parameter, type, argnum); + } + virtual ArgToken make_oop_constant(oop con, TRAPS) { + Handle h(THREAD, con); + return ArgToken(tt_constant, T_OBJECT, h); + } + virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { + return ArgToken(tt_constant, type, *con); + } + + virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS); + virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS); + virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS); + + // Get a real constant pool. + constantPoolHandle get_constant_pool(TRAPS) const; + + // Get a real methodOop. + methodHandle get_method_oop(TRAPS) const; + +public: + MethodHandleCompiler(Handle root, methodHandle call_method, bool for_invokedynamic, TRAPS); + + // Compile the given MH chain into bytecode. + methodHandle compile(TRAPS); +}; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/methodHandles.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -132,8 +132,9 @@ } return m; } else { + assert(vmtarget->is_klass(), "must be class or interface"); decode_flags_result |= MethodHandles::_dmf_does_dispatch; - assert(vmtarget->is_klass(), "must be class or interface"); + decode_flags_result |= MethodHandles::_dmf_has_receiver; receiver_limit_result = (klassOop)vmtarget; Klass* tk = Klass::cast((klassOop)vmtarget); if (tk->is_interface()) { @@ -142,7 +143,7 @@ return klassItable::method_for_itable_index((klassOop)vmtarget, vmindex); } else { if (!tk->oop_is_instance()) - tk = instanceKlass::cast(SystemDictionary::object_klass()); + tk = instanceKlass::cast(SystemDictionary::Object_klass()); return ((instanceKlass*)tk)->method_at_vtable(vmindex); } } @@ -179,8 +180,10 @@ // short-circuits directly to the methodOop. // (It might be another argument besides a receiver also.) assert(target->is_method(), "must be a simple method"); + decode_flags_result |= MethodHandles::_dmf_binds_method; methodOop m = (methodOop) target; - decode_flags_result |= MethodHandles::_dmf_binds_method; + if (!m->is_static()) + decode_flags_result |= MethodHandles::_dmf_has_receiver; return m; } } @@ -233,8 +236,8 @@ BasicType recv_bt = char2type(sig->byte_at(1)); // Note: recv_bt might be T_ILLEGAL if byte_at(2) is ')' assert(sig->byte_at(0) == '(', "must be method sig"); - if (recv_bt == T_OBJECT || recv_bt == T_ARRAY) - decode_flags_result |= _dmf_has_receiver; +// if (recv_bt == T_OBJECT || recv_bt == T_ARRAY) +// decode_flags_result |= _dmf_has_receiver; } else { // non-static method decode_flags_result |= _dmf_has_receiver; @@ -261,14 +264,14 @@ return decode_MemberName(x, receiver_limit_result, decode_flags_result); } else if (java_dyn_MethodHandle::is_subclass(xk)) { return decode_MethodHandle(x, receiver_limit_result, decode_flags_result); - } else if (xk == SystemDictionary::reflect_method_klass()) { + } else if (xk == SystemDictionary::reflect_Method_klass()) { oop clazz = java_lang_reflect_Method::clazz(x); int slot = java_lang_reflect_Method::slot(x); klassOop k = java_lang_Class::as_klassOop(clazz); if (k != NULL && Klass::cast(k)->oop_is_instance()) return decode_methodOop(instanceKlass::cast(k)->method_with_idnum(slot), decode_flags_result); - } else if (xk == SystemDictionary::reflect_constructor_klass()) { + } else if (xk == SystemDictionary::reflect_Constructor_klass()) { oop clazz = java_lang_reflect_Constructor::clazz(x); int slot = java_lang_reflect_Constructor::slot(x); klassOop k = java_lang_Class::as_klassOop(clazz); @@ -325,7 +328,7 @@ }; void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { - if (target_oop->klass() == SystemDictionary::reflect_field_klass()) { + if (target_oop->klass() == SystemDictionary::reflect_Field_klass()) { oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() int mods = java_lang_reflect_Field::modifiers(target_oop); @@ -410,7 +413,7 @@ if (defc_klassOop == NULL) return; // a primitive; no resolution possible if (!Klass::cast(defc_klassOop)->oop_is_instance()) { if (!Klass::cast(defc_klassOop)->oop_is_array()) return; - defc_klassOop = SystemDictionary::object_klass(); + defc_klassOop = SystemDictionary::Object_klass(); } instanceKlassHandle defc(THREAD, defc_klassOop); defc_klassOop = NULL; // safety @@ -746,7 +749,7 @@ return NULL; // unformed MH } klassOop tklass = target->klass(); - if (Klass::cast(tklass)->is_subclass_of(SystemDictionary::object_klass())) { + if (Klass::cast(tklass)->is_subclass_of(SystemDictionary::Object_klass())) { return target; // target is another MH (or something else?) } } @@ -818,26 +821,26 @@ for (int i = 0; ; i++) { const char* test_name = always_null_names[i]; if (test_name == NULL) break; - if (name->equals(test_name, (int) strlen(test_name))) + if (name->equals(test_name)) return true; } return false; } bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) { - if (src == dst || dst == SystemDictionary::object_klass()) + if (src == dst || dst == SystemDictionary::Object_klass()) return false; // quickest checks Klass* srck = Klass::cast(src); Klass* dstk = Klass::cast(dst); if (dstk->is_interface()) { // interface receivers can safely be viewed as untyped, // because interface calls always include a dynamic check - //dstk = Klass::cast(SystemDictionary::object_klass()); + //dstk = Klass::cast(SystemDictionary::Object_klass()); return false; } if (srck->is_interface()) { // interface arguments must be viewed as untyped - //srck = Klass::cast(SystemDictionary::object_klass()); + //srck = Klass::cast(SystemDictionary::Object_klass()); return true; } if (is_always_null_type(src)) { @@ -850,7 +853,7 @@ } static oop object_java_mirror() { - return Klass::cast(SystemDictionary::object_klass())->java_mirror(); + return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); } bool MethodHandles::same_basic_type_for_arguments(BasicType src, @@ -1446,7 +1449,7 @@ break; } // check subrange of Integer.value, if necessary - if (argument == NULL || argument->klass() != SystemDictionary::int_klass()) { + if (argument == NULL || argument->klass() != SystemDictionary::Integer_klass()) { err = "bound integer argument must be of type java.lang.Integer"; break; } @@ -1469,7 +1472,7 @@ BasicType argbox = java_lang_boxing_object::basic_type(argument); if (argbox != ptype) { err = check_argument_type_change(T_OBJECT, (argument == NULL - ? SystemDictionary::object_klass() + ? SystemDictionary::Object_klass() : argument->klass()), ptype, ptype_klass(), argnum); assert(err != NULL, "this must be an error"); @@ -1487,8 +1490,9 @@ int target_pushes = decode_MethodHandle_stack_pushes(target()); assert(this_pushes == slots_pushed + target_pushes, "BMH stack motion must be correct"); // do not blow the stack; use a Java-based adapter if this limit is exceeded - if (slots_pushed + target_pushes > MethodHandlePushLimit) - err = "too many bound parameters"; + // FIXME + // if (slots_pushed + target_pushes > MethodHandlePushLimit) + // err = "too many bound parameters"; } } @@ -1518,6 +1522,11 @@ verify_vmslots(mh, CHECK); } + // Get bound type and required slots. + oop ptype_oop = java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum); + BasicType ptype = java_lang_Class::as_BasicType(ptype_oop); + int slots_pushed = type2size[ptype]; + // If (a) the target is a direct non-dispatched method handle, // or (b) the target is a dispatched direct method handle and we // are binding the receiver, cut out the middle-man. @@ -1529,7 +1538,7 @@ int decode_flags = 0; klassOop receiver_limit_oop = NULL; methodHandle m(THREAD, decode_method(target(), receiver_limit_oop, decode_flags)); if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "DMH failed to decode"); } - DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - 1); // pos. of 1st arg. + DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - slots_pushed); // pos. of 1st arg. assert(sun_dyn_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig"); if (argnum == 0 && (decode_flags & _dmf_has_receiver) != 0) { KlassHandle receiver_limit(THREAD, receiver_limit_oop); @@ -1554,10 +1563,6 @@ } // Next question: Is this a ref, int, or long bound value? - oop ptype_oop = java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum); - BasicType ptype = java_lang_Class::as_BasicType(ptype_oop); - int slots_pushed = type2size[ptype]; - MethodHandleEntry* me = NULL; if (ptype == T_OBJECT) { if (direct_to_method) me = MethodHandles::entry(_bound_ref_direct_mh); @@ -2170,7 +2175,7 @@ symbolOop name = vmSymbols::toString_name(), sig = vmSymbols::void_string_signature(); JavaCallArguments args(Handle(THREAD, JNIHandles::resolve_non_null(erased_jh))); JavaValue result(T_OBJECT); - JavaCalls::call_virtual(&result, SystemDictionary::object_klass(), name, sig, + JavaCalls::call_virtual(&result, SystemDictionary::Object_klass(), name, sig, &args, CHECK); Handle str(THREAD, (oop)result.get_jobject()); java_lang_String::print(str, tty); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/prims/nativeLookup.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -137,7 +137,7 @@ } // Otherwise call static method findNative in ClassLoader - KlassHandle klass (THREAD, SystemDictionary::classloader_klass()); + KlassHandle klass (THREAD, SystemDictionary::ClassLoader_klass()); Handle name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL); JavaValue result(T_LONG); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/arguments.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -2699,6 +2699,15 @@ } ScavengeRootsInCode = 1; } +#ifdef COMPILER2 + if (EnableInvokeDynamic && DoEscapeAnalysis) { + // TODO: We need to find rules for invokedynamic and EA. For now, + // simply disable EA by default. + if (FLAG_IS_DEFAULT(DoEscapeAnalysis)) { + DoEscapeAnalysis = false; + } + } +#endif if (PrintGCDetails) { // Turn on -verbose:gc options as well @@ -2722,6 +2731,15 @@ // Set flags based on ergonomics. set_ergonomics_flags(); +#ifdef _LP64 + // XXX JSR 292 currently does not support compressed oops. + if (EnableMethodHandles && UseCompressedOops) { + if (FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops)) { + UseCompressedOops = false; + } + } +#endif // _LP64 + // Check the GC selections again. if (!check_gc_consistency()) { return JNI_EINVAL; @@ -2756,9 +2774,16 @@ set_aggressive_opts_flags(); #ifdef CC_INTERP - // Biased locking is not implemented with c++ interpreter + // Clear flags not supported by the C++ interpreter + FLAG_SET_DEFAULT(ProfileInterpreter, false); FLAG_SET_DEFAULT(UseBiasedLocking, false); -#endif /* CC_INTERP */ + LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false)); +#endif // CC_INTERP + +#ifdef ZERO + // Clear flags not supported by Zero + FLAG_SET_DEFAULT(TaggedStackInterpreter, false); +#endif // ZERO #ifdef COMPILER2 if (!UseBiasedLocking || EmitSync != 0) { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/frame.cpp --- a/src/share/vm/runtime/frame.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/frame.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -769,9 +769,9 @@ class InterpretedArgumentOopFinder: public SignatureInfo { private: - OopClosure* _f; // Closure to invoke - int _offset; // TOS-relative offset, decremented with each argument - bool _is_static; // true if the callee is a static method + OopClosure* _f; // Closure to invoke + int _offset; // TOS-relative offset, decremented with each argument + bool _has_receiver; // true if the callee has a receiver frame* _fr; void set(int size, BasicType type) { @@ -786,9 +786,9 @@ } public: - InterpretedArgumentOopFinder(symbolHandle signature, bool is_static, frame* fr, OopClosure* f) : SignatureInfo(signature) { + InterpretedArgumentOopFinder(symbolHandle signature, bool has_receiver, frame* fr, OopClosure* f) : SignatureInfo(signature), _has_receiver(has_receiver) { // compute size of arguments - int args_size = ArgumentSizeComputer(signature).size() + (is_static ? 0 : 1); + int args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0); assert(!fr->is_interpreted_frame() || args_size <= fr->interpreter_frame_expression_stack_size(), "args cannot be on stack anymore"); @@ -796,11 +796,10 @@ _f = f; _fr = fr; _offset = args_size; - _is_static = is_static; } void oops_do() { - if (!_is_static) { + if (_has_receiver) { --_offset; oop_offset_do(); } @@ -912,7 +911,7 @@ int max_locals = m->is_native() ? m->size_of_parameters() : m->max_locals(); symbolHandle signature; - bool is_static = false; + bool has_receiver = false; // Process a callee's arguments if we are at a call site // (i.e., if we are at an invoke bytecode) @@ -922,7 +921,7 @@ Bytecode_invoke *call = Bytecode_invoke_at_check(m, bci); if (call != NULL) { signature = symbolHandle(thread, call->signature()); - is_static = call->is_invokestatic(); + has_receiver = call->has_receiver(); if (map->include_argument_oops() && interpreter_frame_expression_stack_size() > 0) { ResourceMark rm(thread); // is this right ??? @@ -936,7 +935,7 @@ // code in the interpreter calls a blocking runtime // routine which can cause this code to be executed). // (was bug gri 7/27/98) - oops_interpreted_arguments_do(signature, is_static, f); + oops_interpreted_arguments_do(signature, has_receiver, f); } } } @@ -950,7 +949,7 @@ mask = &oopmap_mask; #endif // ASSERT oops_interpreted_locals_do(f, max_locals, mask); - oops_interpreted_expressions_do(f, signature, is_static, + oops_interpreted_expressions_do(f, signature, has_receiver, m->max_stack(), max_locals, mask); } else { @@ -992,7 +991,7 @@ void frame::oops_interpreted_expressions_do(OopClosure *f, symbolHandle signature, - bool is_static, + bool has_receiver, int max_stack, int max_locals, InterpreterOopMap *mask) { @@ -1005,7 +1004,7 @@ // arguments in callee's locals. int args_size = 0; if (!signature.is_null()) { - args_size = ArgumentSizeComputer(signature).size() + (is_static ? 0 : 1); + args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0); } intptr_t *tos_addr = interpreter_frame_tos_at(args_size); @@ -1038,8 +1037,8 @@ } } -void frame::oops_interpreted_arguments_do(symbolHandle signature, bool is_static, OopClosure* f) { - InterpretedArgumentOopFinder finder(signature, is_static, this, f); +void frame::oops_interpreted_arguments_do(symbolHandle signature, bool has_receiver, OopClosure* f) { + InterpretedArgumentOopFinder finder(signature, has_receiver, this, f); finder.oops_do(); } @@ -1066,8 +1065,8 @@ class CompiledArgumentOopFinder: public SignatureInfo { protected: OopClosure* _f; - int _offset; // the current offset, incremented with each argument - bool _is_static; // true if the callee is a static method + int _offset; // the current offset, incremented with each argument + bool _has_receiver; // true if the callee has a receiver frame _fr; RegisterMap* _reg_map; int _arg_size; @@ -1087,24 +1086,24 @@ } public: - CompiledArgumentOopFinder(symbolHandle signature, bool is_static, OopClosure* f, frame fr, const RegisterMap* reg_map) + CompiledArgumentOopFinder(symbolHandle signature, bool has_receiver, OopClosure* f, frame fr, const RegisterMap* reg_map) : SignatureInfo(signature) { // initialize CompiledArgumentOopFinder _f = f; _offset = 0; - _is_static = is_static; + _has_receiver = has_receiver; _fr = fr; _reg_map = (RegisterMap*)reg_map; - _arg_size = ArgumentSizeComputer(signature).size() + (is_static ? 0 : 1); + _arg_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0); int arg_size; - _regs = SharedRuntime::find_callee_arguments(signature(), is_static, &arg_size); + _regs = SharedRuntime::find_callee_arguments(signature(), has_receiver, &arg_size); assert(arg_size == _arg_size, "wrong arg size"); } void oops_do() { - if (!_is_static) { + if (_has_receiver) { handle_oop_offset(); _offset++; } @@ -1112,9 +1111,9 @@ } }; -void frame::oops_compiled_arguments_do(symbolHandle signature, bool is_static, const RegisterMap* reg_map, OopClosure* f) { +void frame::oops_compiled_arguments_do(symbolHandle signature, bool has_receiver, const RegisterMap* reg_map, OopClosure* f) { ResourceMark rm; - CompiledArgumentOopFinder finder(signature, is_static, f, *this, reg_map); + CompiledArgumentOopFinder finder(signature, has_receiver, f, *this, reg_map); finder.oops_do(); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/frame.hpp --- a/src/share/vm/runtime/frame.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/frame.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -371,7 +371,7 @@ oop* oopmapreg_to_location(VMReg reg, const RegisterMap* regmap) const; // Oops-do's - void oops_compiled_arguments_do(symbolHandle signature, bool is_static, const RegisterMap* reg_map, OopClosure* f); + void oops_compiled_arguments_do(symbolHandle signature, bool has_receiver, const RegisterMap* reg_map, OopClosure* f); void oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache = true); private: @@ -379,9 +379,9 @@ int max_locals, InterpreterOopMap *mask); void oops_interpreted_expressions_do(OopClosure *f, symbolHandle signature, - bool is_static, int max_stack, int max_locals, + bool has_receiver, int max_stack, int max_locals, InterpreterOopMap *mask); - void oops_interpreted_arguments_do(symbolHandle signature, bool is_static, OopClosure* f); + void oops_interpreted_arguments_do(symbolHandle signature, bool has_receiver, OopClosure* f); // Iteration of oops void oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/jniHandles.cpp --- a/src/share/vm/runtime/jniHandles.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/jniHandles.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -144,7 +144,7 @@ EXCEPTION_MARK; // We will never reach the CATCH below since Exceptions::_throw will cause // the VM to exit if an exception is thrown during initialization - klassOop k = SystemDictionary::object_klass(); + klassOop k = SystemDictionary::Object_klass(); _deleted_handle = instanceKlass::cast(k)->allocate_permanent_instance(CATCH); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/os.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -280,7 +280,7 @@ string, CHECK); - KlassHandle group(THREAD, SystemDictionary::threadGroup_klass()); + KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); JavaCalls::call_special(&result, thread_group, group, diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/reflection.cpp --- a/src/share/vm/runtime/reflection.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/reflection.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -449,7 +449,7 @@ // sun/reflect/MagicAccessorImpl subclasses to succeed trivially. if ( JDK_Version::is_gte_jdk14x_version() && UseNewReflection - && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_magic_klass())) { + && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { return true; } @@ -541,7 +541,7 @@ // sun/reflect/MagicAccessorImpl subclasses to succeed trivially. if ( JDK_Version::is_gte_jdk14x_version() && UseNewReflection - && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_magic_klass())) { + && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { return true; } @@ -631,7 +631,7 @@ objArrayHandle Reflection::get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS) { // Allocate array holding parameter types (java.lang.Class instances) - objArrayOop m = oopFactory::new_objArray(SystemDictionary::class_klass(), parameter_count, CHECK_(objArrayHandle())); + objArrayOop m = oopFactory::new_objArray(SystemDictionary::Class_klass(), parameter_count, CHECK_(objArrayHandle())); objArrayHandle mirrors (THREAD, m); int index = 0; // Collect parameter types @@ -1308,7 +1308,7 @@ if (Klass::cast(klass)->oop_is_array() && which == MEMBER_DECLARED) return NULL; if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { - klass = SystemDictionary::object_klass(); + klass = SystemDictionary::Object_klass(); } instanceKlassHandle h_k(THREAD, klass); @@ -1375,13 +1375,13 @@ // Exclude primitive types if (java_lang_Class::is_primitive(mirror) || (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array() && (which == MEMBER_DECLARED))) { - klassOop klass = SystemDictionary::reflect_method_klass(); + klassOop klass = SystemDictionary::reflect_Method_klass(); return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array } klassOop klass = java_lang_Class::as_klassOop(mirror); if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { - klass = SystemDictionary::object_klass(); + klass = SystemDictionary::Object_klass(); } instanceKlassHandle h_k(THREAD, klass); @@ -1411,7 +1411,7 @@ } // Allocate result - klassOop klass = SystemDictionary::reflect_method_klass(); + klassOop klass = SystemDictionary::reflect_Method_klass(); objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); objArrayHandle h_result (THREAD, r); @@ -1462,7 +1462,7 @@ } } // Allocate result - klassOop klass = SystemDictionary::reflect_method_klass(); + klassOop klass = SystemDictionary::reflect_Method_klass(); objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); objArrayHandle h_result (THREAD, r); @@ -1523,7 +1523,7 @@ bool prim = java_lang_Class::is_primitive(mirror); Klass* k = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror)); if (prim || k->is_interface() || k->oop_is_array()) { - return oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), 0, CHECK_NULL); // Return empty array + return oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0, CHECK_NULL); // Return empty array } // Must be instanceKlass at this point diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/reflectionUtils.cpp --- a/src/share/vm/runtime/reflectionUtils.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/reflectionUtils.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -63,15 +63,15 @@ void FilteredFieldsMap::initialize() { int offset; offset = java_lang_Throwable::get_backtrace_offset(); - _filtered_fields->append(new FilteredField(SystemDictionary::throwable_klass(), offset)); + _filtered_fields->append(new FilteredField(SystemDictionary::Throwable_klass(), offset)); // The latest version of vm may be used with old jdk. if (JDK_Version::is_gte_jdk16x_version()) { // The following class fields do not exist in // previous version of jdk. offset = sun_reflect_ConstantPool::cp_oop_offset(); - _filtered_fields->append(new FilteredField(SystemDictionary::reflect_constant_pool_klass(), offset)); + _filtered_fields->append(new FilteredField(SystemDictionary::reflect_ConstantPool_klass(), offset)); offset = sun_reflect_UnsafeStaticFieldAccessorImpl::base_offset(); - _filtered_fields->append(new FilteredField(SystemDictionary::reflect_unsafe_static_field_accessor_impl_klass(), offset)); + _filtered_fields->append(new FilteredField(SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass(), offset)); } } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/sharedRuntime.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -802,7 +802,7 @@ #ifdef ASSERT // Check that the receiver klass is of the right subtype and that it is initialized for virtual calls - if (bc != Bytecodes::_invokestatic) { + if (bc != Bytecodes::_invokestatic && bc != Bytecodes::_invokedynamic) { assert(receiver.not_null(), "should have thrown exception"); KlassHandle receiver_klass (THREAD, receiver->klass()); klassOop rk = constants->klass_ref_at(bytecode_index, CHECK_(nullHandle)); @@ -860,7 +860,7 @@ if (JvmtiExport::can_hotswap_or_post_breakpoint()) { int retry_count = 0; while (!HAS_PENDING_EXCEPTION && callee_method->is_old() && - callee_method->method_holder() != SystemDictionary::object_klass()) { + callee_method->method_holder() != SystemDictionary::Object_klass()) { // If has a pending exception then there is no need to re-try to // resolve this method. // If the method has been redefined, we need to try again. @@ -1027,7 +1027,16 @@ frame stub_frame = thread->last_frame(); assert(stub_frame.is_runtime_frame(), "sanity check"); frame caller_frame = stub_frame.sender(®_map); - if (caller_frame.is_interpreted_frame() || caller_frame.is_entry_frame() ) { + + // MethodHandle invokes don't have a CompiledIC and should always + // simply redispatch to the callee_target. + address sender_pc = caller_frame.pc(); + CodeBlob* sender_cb = caller_frame.cb(); + nmethod* sender_nm = sender_cb->as_nmethod_or_null(); + + if (caller_frame.is_interpreted_frame() || + caller_frame.is_entry_frame() || + (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc))) { methodOop callee = thread->callee_target(); guarantee(callee != NULL && callee->is_method(), "bad handshake"); thread->set_vm_result(callee); @@ -1529,7 +1538,7 @@ oop SharedRuntime::wrong_method_type_is_for_single_argument(JavaThread* thr, oopDesc* required) { if (required == NULL) return NULL; - if (required->klass() == SystemDictionary::class_klass()) + if (required->klass() == SystemDictionary::Class_klass()) return required; if (required->is_klass()) return Klass::cast(klassOop(required))->java_mirror(); @@ -2136,7 +2145,7 @@ return regs.first(); } -VMRegPair *SharedRuntime::find_callee_arguments(symbolOop sig, bool is_static, int* arg_size) { +VMRegPair *SharedRuntime::find_callee_arguments(symbolOop sig, bool has_receiver, int* arg_size) { // This method is returning a data structure allocating as a // ResourceObject, so do not put any ResourceMarks in here. char *s = sig->as_C_string(); @@ -2148,7 +2157,7 @@ BasicType *sig_bt = NEW_RESOURCE_ARRAY( BasicType, 256 ); VMRegPair *regs = NEW_RESOURCE_ARRAY( VMRegPair, 256 ); int cnt = 0; - if (!is_static) { + if (has_receiver) { sig_bt[cnt++] = T_OBJECT; // Receiver is argument 0; not in signature } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/sharedRuntime.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -357,7 +357,7 @@ // Convert a sig into a calling convention register layout // and find interesting things about it. - static VMRegPair* find_callee_arguments(symbolOop sig, bool is_static, int *arg_size); + static VMRegPair* find_callee_arguments(symbolOop sig, bool has_receiver, int *arg_size); static VMReg name_for_receiver(); // "Top of Stack" slots that may be unused by the calling convention but must diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/statSampler.cpp --- a/src/share/vm/runtime/statSampler.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/statSampler.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -177,7 +177,7 @@ // public static String getProperty(String key, String def); JavaCalls::call_static(&result, - KlassHandle(THREAD, SystemDictionary::system_klass()), + KlassHandle(THREAD, SystemDictionary::System_klass()), vmSymbolHandles::getProperty_name(), vmSymbolHandles::string_string_signature(), key_str, diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/thread.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -973,7 +973,7 @@ return; } - KlassHandle group(this, SystemDictionary::threadGroup_klass()); + KlassHandle group(this, SystemDictionary::ThreadGroup_klass()); Handle threadObj(this, this->threadObj()); JavaCalls::call_special(&result, @@ -1468,7 +1468,7 @@ // so call ThreadGroup.uncaughtException() KlassHandle recvrKlass(THREAD, threadObj->klass()); CallInfo callinfo; - KlassHandle thread_klass(THREAD, SystemDictionary::thread_klass()); + KlassHandle thread_klass(THREAD, SystemDictionary::Thread_klass()); LinkResolver::resolve_virtual_call(callinfo, threadObj, recvrKlass, thread_klass, vmSymbolHandles::dispatchUncaughtException_name(), vmSymbolHandles::throwable_void_signature(), @@ -1484,7 +1484,7 @@ uncaught_exception, THREAD); } else { - KlassHandle thread_group(THREAD, SystemDictionary::threadGroup_klass()); + KlassHandle thread_group(THREAD, SystemDictionary::ThreadGroup_klass()); JavaValue result(T_VOID); JavaCalls::call_virtual(&result, group, thread_group, @@ -1505,7 +1505,7 @@ while (java_lang_Thread::threadGroup(threadObj()) != NULL && (count-- > 0)) { EXCEPTION_MARK; JavaValue result(T_VOID); - KlassHandle thread_klass(THREAD, SystemDictionary::thread_klass()); + KlassHandle thread_klass(THREAD, SystemDictionary::Thread_klass()); JavaCalls::call_virtual(&result, threadObj, thread_klass, vmSymbolHandles::exit_method_name(), @@ -1743,7 +1743,7 @@ // Check for pending async. exception if (_pending_async_exception != NULL) { // Only overwrite an already pending exception, if it is not a threadDeath. - if (!has_pending_exception() || !pending_exception()->is_a(SystemDictionary::threaddeath_klass())) { + if (!has_pending_exception() || !pending_exception()->is_a(SystemDictionary::ThreadDeath_klass())) { // We cannot call Exceptions::_throw(...) here because we cannot block set_pending_exception(_pending_async_exception, __FILE__, __LINE__); @@ -1852,14 +1852,14 @@ if (is_Compiler_thread()) return; // This is a change from JDK 1.1, but JDK 1.2 will also do it: - if (java_throwable->is_a(SystemDictionary::threaddeath_klass())) { + if (java_throwable->is_a(SystemDictionary::ThreadDeath_klass())) { java_lang_Thread::set_stillborn(threadObj()); } { // Actually throw the Throwable against the target Thread - however // only if there is no thread death exception installed already. - if (_pending_async_exception == NULL || !_pending_async_exception->is_a(SystemDictionary::threaddeath_klass())) { + if (_pending_async_exception == NULL || !_pending_async_exception->is_a(SystemDictionary::ThreadDeath_klass())) { // If the topmost frame is a runtime stub, then we are calling into // OptoRuntime from compiled code. Some runtime stubs (new, monitor_exit..) // must deoptimize the caller before continuing, as the compiled exception handler table @@ -3095,6 +3095,12 @@ warning("java.lang.ArithmeticException has not been initialized"); warning("java.lang.StackOverflowError has not been initialized"); } + + if (EnableInvokeDynamic) { + // JSR 292: An intialized java.dyn.InvokeDynamic is required in + // the compiler. + initialize_class(vmSymbolHandles::java_dyn_InvokeDynamic(), CHECK_0); + } } // See : bugid 4211085. diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/thread.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -772,6 +772,7 @@ volatile address _exception_pc; // PC where exception happened volatile address _exception_handler_pc; // PC for handler of exception volatile int _exception_stack_size; // Size of frame where exception happened + volatile int _is_method_handle_exception; // True if the current exception PC is at a MethodHandle call. // support for compilation bool _is_compiling; // is true if a compilation is active inthis thread (one compilation per thread possible) @@ -1107,11 +1108,13 @@ int exception_stack_size() const { return _exception_stack_size; } address exception_pc() const { return _exception_pc; } address exception_handler_pc() const { return _exception_handler_pc; } + int is_method_handle_exception() const { return _is_method_handle_exception; } void set_exception_oop(oop o) { _exception_oop = o; } void set_exception_pc(address a) { _exception_pc = a; } void set_exception_handler_pc(address a) { _exception_handler_pc = a; } void set_exception_stack_size(int size) { _exception_stack_size = size; } + void set_is_method_handle_exception(int value) { _is_method_handle_exception = value; } // Stack overflow support inline size_t stack_available(address cur_sp); @@ -1185,6 +1188,7 @@ static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc ); } static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); } static ByteSize exception_stack_size_offset() { return byte_offset_of(JavaThread, _exception_stack_size); } + static ByteSize is_method_handle_exception_offset() { return byte_offset_of(JavaThread, _is_method_handle_exception); } static ByteSize stack_guard_state_offset() { return byte_offset_of(JavaThread, _stack_guard_state ); } static ByteSize suspend_flags_offset() { return byte_offset_of(JavaThread, _suspend_flags ); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/vframe.cpp --- a/src/share/vm/runtime/vframe.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/vframe.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -124,7 +124,7 @@ static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) { if (obj.not_null()) { st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj()); - if (obj->klass() == SystemDictionary::class_klass()) { + if (obj->klass() == SystemDictionary::Class_klass()) { klassOop target_klass = java_lang_Class::as_klassOop(obj()); st->print_cr("(a java.lang.Class for %s)", instanceKlass::cast(target_klass)->external_name()); } else { @@ -430,7 +430,7 @@ // This is Method.invoke() -- skip it } else if (use_new_reflection && Klass::cast(method()->method_holder()) - ->is_subclass_of(SystemDictionary::reflect_method_accessor_klass())) { + ->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) { // This is an auxilary frame -- skip it } else { // This is non-excluded frame, we need to count it against the depth @@ -490,8 +490,8 @@ void vframeStreamCommon::skip_reflection_related_frames() { while (!at_end() && (JDK_Version::is_gte_jdk14x_version() && UseNewReflection && - (Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_method_accessor_klass()) || - Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_constructor_accessor_klass())))) { + (Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass()) || + Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_ConstructorAccessorImpl_klass())))) { next(); } } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/runtime/vmStructs.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -455,40 +455,38 @@ static_field(SystemDictionary, _shared_dictionary, Dictionary*) \ static_field(SystemDictionary, _system_loader_lock_obj, oop) \ static_field(SystemDictionary, _loader_constraints, LoaderConstraintTable*) \ - static_field(SystemDictionary, WK_KLASS(object_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(string_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(class_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(cloneable_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(classloader_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(serializable_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(system_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(throwable_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(threaddeath_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(error_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(exception_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(runtime_exception_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(classNotFoundException_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(noClassDefFoundError_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(linkageError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Object_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(String_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Class_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Cloneable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ClassLoader_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Serializable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(System_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Throwable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ThreadDeath_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Error_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Exception_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(RuntimeException_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ClassNotFoundException_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(NoClassDefFoundError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(LinkageError_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(ClassCastException_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(ArrayStoreException_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(virtualMachineError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(VirtualMachineError_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(OutOfMemoryError_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(protectionDomain_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(soft_reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(weak_reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(final_reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(phantom_reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(finalizer_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(thread_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(threadGroup_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(properties_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(stringBuffer_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(vector_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(hashtable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Reference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(SoftReference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(WeakReference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(FinalReference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Finalizer_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Thread_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Properties_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(StringBuffer_klass), klassOop) \ static_field(SystemDictionary, _box_klasses[0], klassOop) \ static_field(SystemDictionary, _java_system_loader, oop) \ \ diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/services/attachListener.cpp --- a/src/share/vm/services/attachListener.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/services/attachListener.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -437,7 +437,7 @@ string, CHECK); - KlassHandle group(THREAD, SystemDictionary::threadGroup_klass()); + KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); JavaCalls::call_special(&result, thread_group, group, diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/services/heapDumper.cpp --- a/src/share/vm/services/heapDumper.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/services/heapDumper.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -1274,7 +1274,7 @@ if (o->is_klass()) return; // skip classes as these emitted as HPROF_GC_CLASS_DUMP records - if (o->klass() == SystemDictionary::class_klass()) { + if (o->klass() == SystemDictionary::Class_klass()) { if (!java_lang_Class::is_primitive(o)) { return; } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/services/lowMemoryDetector.cpp --- a/src/share/vm/services/lowMemoryDetector.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/services/lowMemoryDetector.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -32,7 +32,7 @@ void LowMemoryDetector::initialize() { EXCEPTION_MARK; - instanceKlassHandle klass (THREAD, SystemDictionary::thread_klass()); + instanceKlassHandle klass (THREAD, SystemDictionary::Thread_klass()); instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); const char thread_name[] = "Low Memory Detector"; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/services/management.cpp --- a/src/share/vm/services/management.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/services/management.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -491,7 +491,7 @@ int num_flags = Arguments::num_jvm_flags(); int num_args = Arguments::num_jvm_args(); - instanceKlassHandle ik (THREAD, SystemDictionary::string_klass()); + instanceKlassHandle ik (THREAD, SystemDictionary::String_klass()); objArrayOop r = oopFactory::new_objArray(ik(), num_args + num_flags, CHECK_NULL); objArrayHandle result_h(THREAD, r); @@ -1321,7 +1321,7 @@ LoadedClassesEnumerator lce(THREAD); // Pass current Thread as parameter int num_classes = lce.num_loaded_classes(); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), num_classes, CHECK_0); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), num_classes, CHECK_0); objArrayHandle classes_ah(THREAD, r); for (int i = 0; i < num_classes; i++) { @@ -1481,7 +1481,7 @@ // last flag entry is always NULL, so subtract 1 int nFlags = (int) Flag::numFlags - 1; // allocate a temp array - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), nFlags, CHECK_0); objArrayHandle flags_ah(THREAD, r); int num_entries = 0; @@ -1497,7 +1497,7 @@ if (num_entries < nFlags) { // Return array of right length - objArrayOop res = oopFactory::new_objArray(SystemDictionary::string_klass(), num_entries, CHECK_0); + objArrayOop res = oopFactory::new_objArray(SystemDictionary::String_klass(), num_entries, CHECK_0); for(int i = 0; i < num_entries; i++) { res->obj_at_put(i, flags_ah->obj_at(i)); } @@ -1593,7 +1593,7 @@ objArrayHandle names_ah(THREAD, ta); // Make sure we have a String array klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass(); - if (element_klass != SystemDictionary::string_klass()) { + if (element_klass != SystemDictionary::String_klass()) { THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "Array element type is not String class", 0); } @@ -1747,7 +1747,7 @@ // Make sure we have a String array klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass(); - if (element_klass != SystemDictionary::string_klass()) { + if (element_klass != SystemDictionary::String_klass()) { THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "Array element type is not String class", 0); } @@ -1782,7 +1782,7 @@ num_threads += cycle->num_threads(); } - objArrayOop r = oopFactory::new_objArray(SystemDictionary::thread_klass(), num_threads, CHECK_NH); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NH); objArrayHandle threads_ah(THREAD, r); int index = 0; diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/services/serviceUtil.hpp --- a/src/share/vm/services/serviceUtil.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/services/serviceUtil.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -45,7 +45,7 @@ // instance if (o->is_instance()) { // instance objects are visible - if (o->klass() != SystemDictionary::class_klass()) { + if (o->klass() != SystemDictionary::Class_klass()) { return true; } if (java_lang_Class::is_primitive(o)) { diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/services/threadService.cpp --- a/src/share/vm/services/threadService.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/services/threadService.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -540,7 +540,7 @@ } Handle ThreadStackTrace::allocate_fill_stack_trace_element_array(TRAPS) { - klassOop k = SystemDictionary::stackTraceElement_klass(); + klassOop k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); instanceKlassHandle ik(THREAD, k); diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/utilities/constantTag.hpp --- a/src/share/vm/utilities/constantTag.hpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/utilities/constantTag.hpp Wed Jan 06 22:21:39 2010 -0800 @@ -36,7 +36,8 @@ JVM_CONSTANT_UnresolvedString = 102, // Temporary tag until actual use JVM_CONSTANT_StringIndex = 103, // Temporary tag while constructing constant pool JVM_CONSTANT_UnresolvedClassInError = 104, // Error tag due to resolution error - JVM_CONSTANT_InternalMax = 104 // Last implementation tag + JVM_CONSTANT_Object = 105, // Required for BoundMethodHandle arguments. + JVM_CONSTANT_InternalMax = 105 // Last implementation tag }; @@ -70,6 +71,8 @@ bool is_unresolved_string() const { return _tag == JVM_CONSTANT_UnresolvedString; } bool is_string_index() const { return _tag == JVM_CONSTANT_StringIndex; } + bool is_object() const { return _tag == JVM_CONSTANT_Object; } + bool is_klass_reference() const { return is_klass_index() || is_unresolved_klass(); } bool is_klass_or_reference() const{ return is_klass() || is_klass_reference(); } bool is_field_or_method() const { return is_field() || is_method() || is_interface_method(); } diff -r a5a6adfca6ec -r 9b9c1ee9b3f6 src/share/vm/utilities/exceptions.cpp --- a/src/share/vm/utilities/exceptions.cpp Wed Dec 23 03:12:16 2009 -0800 +++ b/src/share/vm/utilities/exceptions.cpp Wed Jan 06 22:21:39 2010 -0800 @@ -122,7 +122,7 @@ // Check for special boot-strapping/vm-thread handling if (special_exception(thread, file, line, h_exception)) return; - assert(h_exception->is_a(SystemDictionary::throwable_klass()), "exception is not a subclass of java/lang/Throwable"); + assert(h_exception->is_a(SystemDictionary::Throwable_klass()), "exception is not a subclass of java/lang/Throwable"); // set the pending exception thread->set_pending_exception(h_exception(), file, line); @@ -255,7 +255,7 @@ // Future: object initializer should take a cause argument if (h_cause() != NULL) { - assert(h_cause->is_a(SystemDictionary::throwable_klass()), + assert(h_cause->is_a(SystemDictionary::Throwable_klass()), "exception cause is not a subclass of java/lang/Throwable"); JavaValue result1(T_OBJECT); JavaCallArguments args1;