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

View File

@ -63,12 +63,12 @@ public class SystemDictionary {
javaSystemLoaderField = type.getOopField("_java_system_loader");
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:

View File

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

View File

@ -330,6 +330,14 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
// This is the sp before any possible extension (adapter/locals).
intptr_t* unextended_sp = interpreter_frame_sender_sp();
address sender_pc = this->sender_pc();
CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc);
assert(sender_cb, "sanity");
nmethod* sender_nm = sender_cb->as_nmethod_or_null();
if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) {
unextended_sp = (intptr_t*) at(link_offset);
}
// The interpreter and compiler(s) always save EBP/RBP in a known
// location on entry. We must record where that location is
// so this if EBP/RBP was live on callout from c2 we can find
@ -352,7 +360,7 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
#endif // AMD64
}
#endif /* COMPILER2 */
return frame(sp, unextended_sp, link(), sender_pc());
return frame(sp, unextended_sp, link(), sender_pc);
}
@ -375,6 +383,18 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {
intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset);
intptr_t* unextended_sp = sender_sp;
// If we are returning to a compiled method handle call site,
// the saved_fp will in fact be a saved value of the unextended SP.
// The simplest way to tell whether we are returning to such a call
// site is as follows:
CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc);
assert(sender_cb, "sanity");
nmethod* sender_nm = sender_cb->as_nmethod_or_null();
if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) {
unextended_sp = saved_fp;
}
if (map->update_map()) {
// Tell GC to use argument oopmaps for some runtime stubs that need it.
// For C1, the runtime stub might not have oop maps, so set this flag
@ -399,7 +419,7 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {
}
assert(sender_sp != sp(), "must have changed");
return frame(sender_sp, saved_fp, sender_pc);
return frame(sender_sp, unextended_sp, saved_fp, sender_pc);
}
frame frame::sender(RegisterMap* map) const {

View File

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

View File

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

View File

@ -43,11 +43,11 @@ ExceptionBlob* OptoRuntime::_exception_blob;
// This code is entered with a jmp.
//
// Arguments:
// rax,: exception oop
// rax: exception oop
// rdx: exception pc
//
// Results:
// rax,: exception oop
// rax: exception oop
// rdx: exception pc in caller or ???
// destination: exception handler of caller
//
@ -113,17 +113,17 @@ void OptoRuntime::generate_exception_blob() {
__ addptr(rsp, return_off * wordSize); // Epilog!
__ pop(rdx); // Exception pc
// rax: exception handler for given <exception oop/exception pc>
// rax,: exception handler for given <exception oop/exception pc>
// Restore SP from BP if the exception PC is a MethodHandle call.
__ cmpl(Address(rcx, JavaThread::is_method_handle_exception_offset()), 0);
__ cmovptr(Assembler::notEqual, rsp, rbp);
// We have a handler in rax, (could be deopt blob)
// rdx - throwing pc, deopt blob will need it.
__ push(rax);
// rcx contains handler address
__ get_thread(rcx); // TLS
// Get the exception
__ movptr(rax, Address(rcx, JavaThread::exception_oop_offset()));
// Get the exception pc in case we are deoptimized
@ -137,7 +137,7 @@ void OptoRuntime::generate_exception_blob() {
__ pop(rcx);
// rax,: exception oop
// rax: exception oop
// rcx: exception handler
// rdx: exception pc
__ jmp (rcx);

View File

@ -638,6 +638,10 @@ static void gen_i2c_adapter(MacroAssembler *masm,
__ movptr(rax, Address(rsp, 0));
// Must preserve original SP for loading incoming arguments because
// we need to align the outgoing SP for compiled code.
__ movptr(r11, rsp);
// Cut-out for having no stack args. Since up to 2 int/oop args are passed
// in registers, we will occasionally have no stack args.
int comp_words_on_stack = 0;
@ -661,6 +665,10 @@ static void gen_i2c_adapter(MacroAssembler *masm,
// as far as the placement of the call instruction
__ push(rax);
// Put saved SP in another register
const Register saved_sp = rax;
__ movptr(saved_sp, r11);
// Will jump to the compiled code just as if compiled code was doing it.
// Pre-load the register-jump target early, to schedule it better.
__ movptr(r11, Address(rbx, in_bytes(methodOopDesc::from_compiled_offset())));
@ -680,11 +688,7 @@ static void gen_i2c_adapter(MacroAssembler *masm,
assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(),
"scrambled load targets?");
// Load in argument order going down.
// int ld_off = (total_args_passed + comp_words_on_stack -i)*wordSize;
// base ld_off on r13 (sender_sp) as the stack alignment makes offsets from rsp
// unpredictable
int ld_off = ((total_args_passed - 1) - i)*Interpreter::stackElementSize();
int ld_off = (total_args_passed - i)*Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes();
// Point to interpreter value (vs. tag)
int next_off = ld_off - Interpreter::stackElementSize();
//
@ -699,10 +703,14 @@ static void gen_i2c_adapter(MacroAssembler *masm,
if (r_1->is_stack()) {
// Convert stack slot to an SP offset (+ wordSize to account for return address )
int st_off = regs[i].first()->reg2stack()*VMRegImpl::stack_slot_size + wordSize;
// We can use r13 as a temp here because compiled code doesn't need r13 as an input
// and if we end up going thru a c2i because of a miss a reasonable value of r13
// will be generated.
if (!r_2->is_valid()) {
// sign extend???
__ movl(rax, Address(r13, ld_off));
__ movptr(Address(rsp, st_off), rax);
__ movl(r13, Address(saved_sp, ld_off));
__ movptr(Address(rsp, st_off), r13);
} else {
//
// We are using two optoregs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE
@ -715,9 +723,9 @@ static void gen_i2c_adapter(MacroAssembler *masm,
// ld_off is MSW so get LSW
const int offset = (sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)?
next_off : ld_off;
__ movq(rax, Address(r13, offset));
__ movq(r13, Address(saved_sp, offset));
// st_off is LSW (i.e. reg.first())
__ movq(Address(rsp, st_off), rax);
__ movq(Address(rsp, st_off), r13);
}
} else if (r_1->is_Register()) { // Register argument
Register r = r_1->as_Register();
@ -732,16 +740,16 @@ static void gen_i2c_adapter(MacroAssembler *masm,
next_off : ld_off;
// this can be a misaligned move
__ movq(r, Address(r13, offset));
__ movq(r, Address(saved_sp, offset));
} else {
// sign extend and use a full word?
__ movl(r, Address(r13, ld_off));
__ movl(r, Address(saved_sp, ld_off));
}
} else {
if (!r_2->is_valid()) {
__ movflt(r_1->as_XMMRegister(), Address(r13, ld_off));
__ movflt(r_1->as_XMMRegister(), Address(saved_sp, ld_off));
} else {
__ movdbl(r_1->as_XMMRegister(), Address(r13, next_off));
__ movdbl(r_1->as_XMMRegister(), Address(saved_sp, next_off));
}
}
}
@ -3319,6 +3327,10 @@ void OptoRuntime::generate_exception_blob() {
// rax: exception handler
// Restore SP from BP if the exception PC is a MethodHandle call.
__ cmpl(Address(r15_thread, JavaThread::is_method_handle_exception_offset()), 0);
__ cmovptr(Assembler::notEqual, rsp, rbp);
// We have a handler in rax (could be deopt blob).
__ mov(r8, rax);

View File

@ -1488,7 +1488,10 @@ int AbstractInterpreter::layout_activation(methodOop method,
if (interpreter_frame != NULL) {
#ifdef ASSERT
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
if (!EnableMethodHandles)
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
// Probably, since deoptimization doesn't work yet.
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
#endif

View File

@ -449,8 +449,12 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
__ addptr(rax, stack_base);
__ subptr(rax, stack_size);
// Use the maximum number of pages we might bang.
const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages) ? StackShadowPages :
(StackRedPages+StackYellowPages);
// add in the red and yellow zone sizes
__ addptr(rax, (StackRedPages + StackYellowPages) * page_size);
__ addptr(rax, max_pages * page_size);
// check against the current stack bottom
__ cmpptr(rsp, rax);
@ -1502,8 +1506,10 @@ int AbstractInterpreter::layout_activation(methodOop method,
tempcount* Interpreter::stackElementWords() + popframe_extra_args;
if (interpreter_frame != NULL) {
#ifdef ASSERT
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(),
"Frame not properly walkable");
if (!EnableMethodHandles)
// @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
// Probably, since deoptimization doesn't work yet.
assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
#endif

View File

@ -268,22 +268,36 @@ static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CON
static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000));
static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
// Offset hacking within calls.
static int pre_call_FPU_size() {
if (Compile::current()->in_24_bit_fp_mode())
return 6; // fldcw
return 0;
}
static int preserve_SP_size() {
return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg)
}
// !!!!! Special hack to get all type of calls to specify the byte offset
// from the start of the call to the point where the return address
// will point.
int MachCallStaticJavaNode::ret_addr_offset() {
return 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 5 bytes from start of call to where return address points
int offset = 5 + pre_call_FPU_size(); // 5 bytes from start of call to where return address points
if (_method_handle_invoke)
offset += preserve_SP_size();
return offset;
}
int MachCallDynamicJavaNode::ret_addr_offset() {
return 10 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 10 bytes from start of call to where return address points
return 10 + pre_call_FPU_size(); // 10 bytes from start of call to where return address points
}
static int sizeof_FFree_Float_Stack_All = -1;
int MachCallRuntimeNode::ret_addr_offset() {
assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already");
return sizeof_FFree_Float_Stack_All + 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0);
return sizeof_FFree_Float_Stack_All + 5 + pre_call_FPU_size();
}
// Indicate if the safepoint node needs the polling page as an input.
@ -299,8 +313,16 @@ bool SafePointNode::needs_polling_address_input() {
// The address of the call instruction needs to be 4-byte aligned to
// ensure that it does not span a cache line so that it can be patched.
int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
if (Compile::current()->in_24_bit_fp_mode())
current_offset += 6; // skip fldcw in pre_call_FPU, if any
current_offset += pre_call_FPU_size(); // skip fldcw, if any
current_offset += 1; // skip call opcode byte
return round_to(current_offset, alignment_required()) - current_offset;
}
// The address of the call instruction needs to be 4-byte aligned to
// ensure that it does not span a cache line so that it can be patched.
int CallStaticJavaHandleNode::compute_padding(int current_offset) const {
current_offset += pre_call_FPU_size(); // skip fldcw, if any
current_offset += preserve_SP_size(); // skip mov rbp, rsp
current_offset += 1; // skip call opcode byte
return round_to(current_offset, alignment_required()) - current_offset;
}
@ -308,8 +330,7 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
// The address of the call instruction needs to be 4-byte aligned to
// ensure that it does not span a cache line so that it can be patched.
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const {
if (Compile::current()->in_24_bit_fp_mode())
current_offset += 6; // skip fldcw in pre_call_FPU, if any
current_offset += pre_call_FPU_size(); // skip fldcw, if any
current_offset += 5; // skip MOV instruction
current_offset += 1; // skip call opcode byte
return round_to(current_offset, alignment_required()) - current_offset;
@ -1460,6 +1481,10 @@ RegMask Matcher::modL_proj_mask() {
return RegMask();
}
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return EBP_REG_mask;
}
%}
//----------ENCODING BLOCK-----------------------------------------------------
@ -1772,10 +1797,13 @@ encode %{
enc_class pre_call_FPU %{
// If method sets FPU control word restore it here
debug_only(int off0 = cbuf.code_size());
if( Compile::current()->in_24_bit_fp_mode() ) {
MacroAssembler masm(&cbuf);
masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
}
debug_only(int off1 = cbuf.code_size());
assert(off1 - off0 == pre_call_FPU_size(), "correct size prediction");
%}
enc_class post_call_FPU %{
@ -1786,6 +1814,21 @@ encode %{
}
%}
enc_class preserve_SP %{
debug_only(int off0 = cbuf.code_size());
MacroAssembler _masm(&cbuf);
// RBP is preserved across all calls, even compiled calls.
// Use it to preserve RSP in places where the callee might change the SP.
__ movptr(rbp, rsp);
debug_only(int off1 = cbuf.code_size());
assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
%}
enc_class restore_SP %{
MacroAssembler _masm(&cbuf);
__ movptr(rsp, rbp);
%}
enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL
// CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
// who we intended to call.
@ -13406,6 +13449,7 @@ instruct cmovXX_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regX dst,
// compute_padding() functions will have to be adjusted.
instruct CallStaticJavaDirect(method meth) %{
match(CallStaticJava);
predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
effect(USE meth);
ins_cost(300);
@ -13420,6 +13464,30 @@ instruct CallStaticJavaDirect(method meth) %{
ins_alignment(4);
%}
// Call Java Static Instruction (method handle version)
// Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted.
instruct CallStaticJavaHandle(method meth, eBPRegP ebp) %{
match(CallStaticJava);
predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
effect(USE meth);
// EBP is saved by all callees (for interpreter stack correction).
// We use it here for a similar purpose, in {preserve,restore}_SP.
ins_cost(300);
format %{ "CALL,static/MethodHandle " %}
opcode(0xE8); /* E8 cd */
ins_encode( pre_call_FPU,
preserve_SP,
Java_Static_Call( meth ),
restore_SP,
call_epilog,
post_call_FPU );
ins_pipe( pipe_slow );
ins_pc_relative(1);
ins_alignment(4);
%}
// Call Java Dynamic Instruction
// Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted.

View File

@ -551,12 +551,19 @@ source %{
#define __ _masm.
static int preserve_SP_size() {
return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg)
}
// !!!!! Special hack to get all types of calls to specify the byte offset
// from the start of the call to the point where the return address
// will point.
int MachCallStaticJavaNode::ret_addr_offset()
{
return 5; // 5 bytes from start of call to where return address points
int offset = 5; // 5 bytes from start of call to where return address points
if (_method_handle_invoke)
offset += preserve_SP_size();
return offset;
}
int MachCallDynamicJavaNode::ret_addr_offset()
@ -587,6 +594,15 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const
return round_to(current_offset, alignment_required()) - current_offset;
}
// The address of the call instruction needs to be 4-byte aligned to
// ensure that it does not span a cache line so that it can be patched.
int CallStaticJavaHandleNode::compute_padding(int current_offset) const
{
current_offset += preserve_SP_size(); // skip mov rbp, rsp
current_offset += 1; // skip call opcode byte
return round_to(current_offset, alignment_required()) - current_offset;
}
// The address of the call instruction needs to be 4-byte aligned to
// ensure that it does not span a cache line so that it can be patched.
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
@ -2113,6 +2129,10 @@ RegMask Matcher::modL_proj_mask() {
return LONG_RDX_REG_mask;
}
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return PTR_RBP_REG_mask;
}
static Address build_address(int b, int i, int s, int d) {
Register index = as_Register(i);
Address::ScaleFactor scale = (Address::ScaleFactor)s;
@ -2608,6 +2628,21 @@ encode %{
RELOC_DISP32);
%}
enc_class preserve_SP %{
debug_only(int off0 = cbuf.code_size());
MacroAssembler _masm(&cbuf);
// RBP is preserved across all calls, even compiled calls.
// Use it to preserve RSP in places where the callee might change the SP.
__ movptr(rbp, rsp);
debug_only(int off1 = cbuf.code_size());
assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
%}
enc_class restore_SP %{
MacroAssembler _masm(&cbuf);
__ movptr(rsp, rbp);
%}
enc_class Java_Static_Call(method meth)
%{
// JAVA STATIC CALL
@ -12526,9 +12561,9 @@ instruct safePoint_poll(rFlagsReg cr)
// Call Java Static Instruction
// Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted.
instruct CallStaticJavaDirect(method meth)
%{
instruct CallStaticJavaDirect(method meth) %{
match(CallStaticJava);
predicate(!((CallStaticJavaNode*) n)->is_method_handle_invoke());
effect(USE meth);
ins_cost(300);
@ -12540,6 +12575,28 @@ instruct CallStaticJavaDirect(method meth)
ins_alignment(4);
%}
// Call Java Static Instruction (method handle version)
// Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted.
instruct CallStaticJavaHandle(method meth, rbp_RegP rbp) %{
match(CallStaticJava);
predicate(((CallStaticJavaNode*) n)->is_method_handle_invoke());
effect(USE meth);
// RBP is saved by all callees (for interpreter stack correction).
// We use it here for a similar purpose, in {preserve,restore}_SP.
ins_cost(300);
format %{ "call,static/MethodHandle " %}
opcode(0xE8); /* E8 cd */
ins_encode(preserve_SP,
Java_Static_Call(meth),
restore_SP,
call_epilog);
ins_pipe(pipe_slow);
ins_pc_relative(1);
ins_alignment(4);
%}
// Call Java Dynamic Instruction
// Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted.

View File

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

View File

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

View File

@ -425,7 +425,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
assert(exception.not_null(), "NULL exceptions should be handled by throw_exception");
assert(exception->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();
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_ciCPCache.cpp.incl"
// ciCPCache
// ------------------------------------------------------------------
// ciCPCache::get_f1_offset
size_t ciCPCache::get_f1_offset(int index) {
// Calculate the offset from the constantPoolCacheOop to the f1
// field.
ByteSize f1_offset =
constantPoolCacheOopDesc::entry_offset(index) +
ConstantPoolCacheEntry::f1_offset();
return in_bytes(f1_offset);
}
// ------------------------------------------------------------------
// ciCPCache::print
//
// Print debugging information about the cache.
void ciCPCache::print() {
Unimplemented();
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
// ciCPCache
//
// This class represents a constant pool cache.
//
// Note: This class is called ciCPCache as ciConstantPoolCache is used
// for something different.
class ciCPCache : public ciObject {
public:
ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {}
// What kind of ciObject is this?
bool is_cpcache() const { return true; }
// Get the offset in bytes from the oop to the f1 field of the
// requested entry.
size_t get_f1_offset(int index);
void print();
};

View File

@ -0,0 +1,46 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_ciCallSite.cpp.incl"
// ciCallSite
// ------------------------------------------------------------------
// ciCallSite::get_target
//
// Return the target MethodHandle of this CallSite.
ciMethodHandle* ciCallSite::get_target() const {
VM_ENTRY_MARK;
oop method_handle_oop = java_dyn_CallSite::target(get_oop());
return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle();
}
// ------------------------------------------------------------------
// ciCallSite::print
//
// Print debugging information about the CallSite.
void ciCallSite::print() {
Unimplemented();
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
// ciCallSite
//
// The class represents a java.dyn.CallSite object.
class ciCallSite : public ciInstance {
public:
ciCallSite(instanceHandle h_i) : ciInstance(h_i) {}
// What kind of ciObject is this?
bool is_call_site() const { return true; }
// Return the target MethodHandle of this CallSite.
ciMethodHandle* get_target() const;
void print();
};

View File

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

View File

@ -38,17 +38,9 @@ ciInstanceKlassKlass* ciEnv::_instance_klass_klass_instance;
ciTypeArrayKlassKlass* ciEnv::_type_array_klass_klass_instance;
ciObjArrayKlassKlass* ciEnv::_obj_array_klass_klass_instance;
ciInstanceKlass* ciEnv::_ArrayStoreException;
ciInstanceKlass* ciEnv::_Class;
ciInstanceKlass* ciEnv::_ClassCastException;
ciInstanceKlass* ciEnv::_Object;
ciInstanceKlass* ciEnv::_Throwable;
ciInstanceKlass* ciEnv::_Thread;
ciInstanceKlass* ciEnv::_OutOfMemoryError;
ciInstanceKlass* ciEnv::_String;
ciInstanceKlass* ciEnv::_StringBuffer;
ciInstanceKlass* ciEnv::_StringBuilder;
ciInstanceKlass* ciEnv::_Integer;
#define WK_KLASS_DEFN(name, ignore_s, ignore_o) ciInstanceKlass* ciEnv::_##name = NULL;
WK_KLASSES_DO(WK_KLASS_DEFN)
#undef WK_KLASS_DEFN
ciSymbol* ciEnv::_unloaded_cisymbol = NULL;
ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = NULL;
@ -442,12 +434,11 @@ ciKlass* ciEnv::get_klass_by_name(ciKlass* accessing_klass,
// ciEnv::get_klass_by_index_impl
//
// Implementation of get_klass_by_index.
ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor,
ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool,
int index,
bool& is_accessible) {
assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
bool& is_accessible,
ciInstanceKlass* accessor) {
EXCEPTION_CONTEXT;
constantPoolHandle cpool(THREAD, accessor->get_instanceKlass()->constants());
KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index));
symbolHandle klass_name;
if (klass.is_null()) {
@ -509,22 +500,21 @@ ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor,
// ciEnv::get_klass_by_index
//
// Get a klass from the constant pool.
ciKlass* ciEnv::get_klass_by_index(ciInstanceKlass* accessor,
ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool,
int index,
bool& is_accessible) {
GUARDED_VM_ENTRY(return get_klass_by_index_impl(accessor, index, is_accessible);)
bool& is_accessible,
ciInstanceKlass* accessor) {
GUARDED_VM_ENTRY(return get_klass_by_index_impl(cpool, index, is_accessible, accessor);)
}
// ------------------------------------------------------------------
// ciEnv::get_constant_by_index_impl
//
// Implementation of get_constant_by_index().
ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
int index) {
ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
int index,
ciInstanceKlass* accessor) {
EXCEPTION_CONTEXT;
instanceKlass* ik_accessor = accessor->get_instanceKlass();
assert(ik_accessor->is_linked(), "must be linked before accessing constant pool");
constantPoolOop cpool = ik_accessor->constants();
constantTag tag = cpool->tag_at(index);
if (tag.is_int()) {
return ciConstant(T_INT, (jint)cpool->int_at(index));
@ -552,7 +542,7 @@ ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
// 4881222: allow ldc to take a class type
bool ignore;
ciKlass* klass = get_klass_by_index_impl(accessor, index, ignore);
ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
record_out_of_memory_failure();
@ -561,6 +551,11 @@ ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
assert (klass->is_instance_klass() || klass->is_array_klass(),
"must be an instance or array klass ");
return ciConstant(T_OBJECT, klass);
} else if (tag.is_object()) {
oop obj = cpool->object_at(index);
assert(obj->is_instance(), "must be an instance");
ciObject* ciobj = get_object(obj);
return ciConstant(T_OBJECT, ciobj);
} else {
ShouldNotReachHere();
return ciConstant();
@ -597,9 +592,10 @@ bool ciEnv::is_unresolved_klass_impl(instanceKlass* accessor, int index) const {
// Pull a constant out of the constant pool. How appropriate.
//
// Implementation note: this query is currently in no way cached.
ciConstant ciEnv::get_constant_by_index(ciInstanceKlass* accessor,
int index) {
GUARDED_VM_ENTRY(return get_constant_by_index_impl(accessor, index); )
ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
int index,
ciInstanceKlass* accessor) {
GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, index, accessor);)
}
// ------------------------------------------------------------------
@ -609,7 +605,7 @@ ciConstant ciEnv::get_constant_by_index(ciInstanceKlass* accessor,
//
// Implementation note: this query is currently in no way cached.
bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor,
int index) const {
int index) const {
GUARDED_VM_ENTRY(return is_unresolved_string_impl(accessor->get_instanceKlass(), index); )
}
@ -620,7 +616,7 @@ bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor,
//
// Implementation note: this query is currently in no way cached.
bool ciEnv::is_unresolved_klass(ciInstanceKlass* accessor,
int index) const {
int index) const {
GUARDED_VM_ENTRY(return is_unresolved_klass_impl(accessor->get_instanceKlass(), index); )
}
@ -701,15 +697,12 @@ methodOop ciEnv::lookup_method(instanceKlass* accessor,
// ------------------------------------------------------------------
// ciEnv::get_method_by_index_impl
ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor,
int index, Bytecodes::Code bc) {
// Get the method's declared holder.
assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
constantPoolHandle cpool = accessor->get_instanceKlass()->constants();
ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
int index, Bytecodes::Code bc,
ciInstanceKlass* accessor) {
int holder_index = cpool->klass_ref_index_at(index);
bool holder_is_accessible;
ciKlass* holder = get_klass_by_index_impl(accessor, holder_index, holder_is_accessible);
ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
// Get the method's name and signature.
@ -735,6 +728,33 @@ ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor,
}
// ------------------------------------------------------------------
// ciEnv::get_fake_invokedynamic_method_impl
ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
int index, Bytecodes::Code bc) {
assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
// Get the CallSite from the constant pool cache.
ConstantPoolCacheEntry* cpc_entry = cpool->cache()->secondary_entry_at(index);
assert(cpc_entry != NULL && cpc_entry->is_secondary_entry(), "sanity");
Handle call_site = cpc_entry->f1();
// Call site might not be linked yet.
if (call_site.is_null()) {
ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass();
ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol();
return get_unloaded_method(mh_klass, ciSymbol::invoke_name(), sig_sym);
}
// Get the methodOop from the CallSite.
methodOop method_oop = (methodOop) java_dyn_CallSite::vmmethod(call_site());
assert(method_oop != NULL, "sanity");
assert(method_oop->is_method_handle_invoke(), "consistent");
return get_object(method_oop)->as_method();
}
// ------------------------------------------------------------------
// ciEnv::get_instance_klass_for_declared_method_holder
ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* method_holder) {
@ -757,15 +777,19 @@ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* m
}
// ------------------------------------------------------------------
// ciEnv::get_method_by_index
ciMethod* ciEnv::get_method_by_index(ciInstanceKlass* accessor,
int index, Bytecodes::Code bc) {
GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, bc);)
ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool,
int index, Bytecodes::Code bc,
ciInstanceKlass* accessor) {
if (bc == Bytecodes::_invokedynamic) {
GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc);)
} else {
GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);)
}
}
// ------------------------------------------------------------------
// ciEnv::name_buffer
char *ciEnv::name_buffer(int req_len) {

View File

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

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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());

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -86,7 +86,7 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with(NULL) {
bool ignore;
// This is not really a class reference; the index always refers to the
// field's type signature, as a symbol. Linkage checks do not apply.
_type = ciEnv::current(thread)->get_klass_by_index(klass, sig_index, ignore);
_type = ciEnv::current(thread)->get_klass_by_index(cpool, sig_index, ignore, klass);
} else {
_type = ciType::make(field_type);
}
@ -100,9 +100,9 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with(NULL) {
int holder_index = cpool->klass_ref_index_at(index);
bool holder_is_accessible;
ciInstanceKlass* declared_holder =
ciEnv::current(thread)->get_klass_by_index(klass, holder_index,
holder_is_accessible)
->as_instance_klass();
ciEnv::current(thread)->get_klass_by_index(cpool, holder_index,
holder_is_accessible,
klass)->as_instance_klass();
// The declared holder of this field may not have been loaded.
// Bail out with partial field information.
@ -168,8 +168,18 @@ void ciField::initialize_from(fieldDescriptor* fd) {
_holder = CURRENT_ENV->get_object(fd->field_holder())->as_instance_klass();
// Check to see if the field is constant.
if (_holder->is_initialized() &&
this->is_final() && this->is_static()) {
if (_holder->is_initialized() && this->is_final()) {
if (!this->is_static()) {
// A field can be constant if it's a final static field or if it's
// a final non-static field of a trusted class ({java,sun}.dyn).
if (_holder->is_in_package("java/dyn") || _holder->is_in_package("sun/dyn")) {
_is_constant = true;
return;
}
_is_constant = false;
return;
}
// This field just may be constant. The only cases where it will
// not be constant are:
//
@ -182,8 +192,8 @@ void ciField::initialize_from(fieldDescriptor* fd) {
// java.lang.System.out, and java.lang.System.err.
klassOop k = _holder->get_klassOop();
assert( SystemDictionary::system_klass() != NULL, "Check once per vm");
if( k == SystemDictionary::system_klass() ) {
assert( SystemDictionary::System_klass() != NULL, "Check once per vm");
if( k == SystemDictionary::System_klass() ) {
// Check offsets for case 2: System.in, System.out, or System.err
if( _offset == java_lang_System::in_offset_in_bytes() ||
_offset == java_lang_System::out_offset_in_bytes() ||

View File

@ -138,10 +138,18 @@ public:
// Get the constant value of this field.
ciConstant constant_value() {
assert(is_constant(), "illegal call to constant_value()");
assert(is_static() && is_constant(), "illegal call to constant_value()");
return _constant_value;
}
// Get the constant value of non-static final field in the given
// object.
ciConstant constant_value_of(ciObject* object) {
assert(!is_static() && is_constant(), "only if field is non-static constant");
assert(object->is_instance(), "must be instance");
return object->as_instance()->field_value(this);
}
// Check for link time errors. Accessing a field from a
// certain class via a certain bytecode may or may not be legal.
// This call checks to see if an exception may be raised by

View File

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

View File

@ -75,7 +75,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
_java_mirror = NULL;
if (is_shared()) {
if (h_k() != SystemDictionary::object_klass()) {
if (h_k() != SystemDictionary::Object_klass()) {
super();
}
java_mirror();
@ -232,8 +232,48 @@ bool ciInstanceKlass::is_java_lang_Object() {
// ------------------------------------------------------------------
// ciInstanceKlass::uses_default_loader
bool ciInstanceKlass::uses_default_loader() {
VM_ENTRY_MARK;
return loader() == NULL;
// Note: We do not need to resolve the handle or enter the VM
// in order to test null-ness.
return _loader == NULL;
}
// ------------------------------------------------------------------
// ciInstanceKlass::is_in_package
//
// Is this klass in the given package?
bool ciInstanceKlass::is_in_package(const char* packagename, int len) {
// To avoid class loader mischief, this test always rejects application classes.
if (!uses_default_loader())
return false;
GUARDED_VM_ENTRY(
return is_in_package_impl(packagename, len);
)
}
bool ciInstanceKlass::is_in_package_impl(const char* packagename, int len) {
ASSERT_IN_VM;
// If packagename contains trailing '/' exclude it from the
// prefix-test since we test for it explicitly.
if (packagename[len - 1] == '/')
len--;
if (!name()->starts_with(packagename, len))
return false;
// Test if the class name is something like "java/lang".
if ((len + 1) > name()->utf8_length())
return false;
// Test for trailing '/'
if ((char) name()->byte_at(len) != '/')
return false;
// Make sure it's not actually in a subpackage:
if (name()->index_of_at(len+1, "/", 1) >= 0)
return false;
return true;
}
// ------------------------------------------------------------------

View File

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

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -69,7 +69,7 @@ public:
ciKlass(KlassHandle k_h);
// What is the name of this klass?
ciSymbol* name() { return _name; }
ciSymbol* name() const { return _name; }
// What is its layout helper value?
jint layout_helper() { return _layout_helper; }

View File

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

View File

@ -38,6 +38,8 @@ class ciMethod : public ciObject {
CI_PACKAGE_ACCESS
friend class ciEnv;
friend class ciExceptionHandlerStream;
friend class ciBytecodeStream;
friend class ciMethodHandle;
private:
// General method information.
@ -213,7 +215,7 @@ class ciMethod : public ciObject {
bool check_call(int refinfo_index, bool is_static) const;
void build_method_data(); // make sure it exists in the VM also
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
bool is_method_handle_invoke();
bool is_method_handle_invoke() const;
ciInstance* method_handle_type();
// What kind of ciObject is this?
@ -251,4 +253,10 @@ class ciMethod : public ciObject {
// Print the name of this method in various incarnations.
void print_name(outputStream* st = tty);
void print_short_name(outputStream* st = tty);
methodOop get_method_handle_target() {
klassOop receiver_limit_oop = NULL;
int flags = 0;
return MethodHandles::decode_method(get_oop(), receiver_limit_oop, flags);
}
};

View File

@ -0,0 +1,52 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_ciMethodHandle.cpp.incl"
// ciMethodHandle
// ------------------------------------------------------------------
// ciMethodHandle::get_adapter
//
// Return an adapter for this MethodHandle.
ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
VM_ENTRY_MARK;
Handle h(get_oop());
methodHandle callee(_callee->get_methodOop());
MethodHandleCompiler mhc(h, callee, is_invokedynamic, THREAD);
methodHandle m = mhc.compile(CHECK_NULL);
return CURRENT_ENV->get_object(m())->as_method();
}
// ------------------------------------------------------------------
// ciMethodHandle::print_impl
//
// Implementation of the print method.
void ciMethodHandle::print_impl(outputStream* st) {
st->print(" type=");
get_oop()->print();
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
// ciMethodHandle
//
// The class represents a java.dyn.MethodHandle object.
class ciMethodHandle : public ciInstance {
private:
ciMethod* _callee;
// Return an adapter for this MethodHandle.
ciMethod* get_adapter(bool is_invokedynamic) const;
protected:
void print_impl(outputStream* st);
public:
ciMethodHandle(instanceHandle h_i) : ciInstance(h_i) {};
// What kind of ciObject is this?
bool is_method_handle() const { return true; }
ciMethod* callee() const { return _callee; }
void set_callee(ciMethod* m) { _callee = m; }
// Return an adapter for a MethodHandle call.
ciMethod* get_method_handle_adapter() const {
return get_adapter(false);
}
// Return an adapter for an invokedynamic call.
ciMethod* get_invokedynamic_adapter() const {
return get_adapter(true);
}
};

View File

@ -131,9 +131,12 @@ public:
// What kind of ciObject is this?
virtual bool is_null_object() const { return false; }
virtual bool is_call_site() const { return false; }
virtual bool is_cpcache() const { return false; }
virtual bool is_instance() { return false; }
virtual bool is_method() { return false; }
virtual bool is_method_data() { return false; }
virtual bool is_method_handle() const { return false; }
virtual bool is_array() { return false; }
virtual bool is_obj_array() { return false; }
virtual bool is_type_array() { return false; }
@ -185,6 +188,14 @@ public:
assert(is_null_object(), "bad cast");
return (ciNullObject*)this;
}
ciCallSite* as_call_site() {
assert(is_call_site(), "bad cast");
return (ciCallSite*) this;
}
ciCPCache* as_cpcache() {
assert(is_cpcache(), "bad cast");
return (ciCPCache*) this;
}
ciInstance* as_instance() {
assert(is_instance(), "bad cast");
return (ciInstance*)this;
@ -197,6 +208,10 @@ public:
assert(is_method_data(), "bad cast");
return (ciMethodData*)this;
}
ciMethodHandle* as_method_handle() {
assert(is_method_handle(), "bad cast");
return (ciMethodHandle*) this;
}
ciArray* as_array() {
assert(is_array(), "bad cast");
return (ciArray*)this;

View File

@ -144,39 +144,13 @@ void ciObjectFactory::init_shared_objects() {
ciEnv::_obj_array_klass_klass_instance =
get(Universe::objArrayKlassKlassObj())
->as_obj_array_klass_klass();
ciEnv::_ArrayStoreException =
get(SystemDictionary::ArrayStoreException_klass())
->as_instance_klass();
ciEnv::_Class =
get(SystemDictionary::class_klass())
->as_instance_klass();
ciEnv::_ClassCastException =
get(SystemDictionary::ClassCastException_klass())
->as_instance_klass();
ciEnv::_Object =
get(SystemDictionary::object_klass())
->as_instance_klass();
ciEnv::_Throwable =
get(SystemDictionary::throwable_klass())
->as_instance_klass();
ciEnv::_Thread =
get(SystemDictionary::thread_klass())
->as_instance_klass();
ciEnv::_OutOfMemoryError =
get(SystemDictionary::OutOfMemoryError_klass())
->as_instance_klass();
ciEnv::_String =
get(SystemDictionary::string_klass())
->as_instance_klass();
ciEnv::_StringBuffer =
get(SystemDictionary::stringBuffer_klass())
->as_instance_klass();
ciEnv::_StringBuilder =
get(SystemDictionary::StringBuilder_klass())
->as_instance_klass();
ciEnv::_Integer =
get(SystemDictionary::int_klass())
->as_instance_klass();
#define WK_KLASS_DEFN(name, ignore_s, opt) \
if (SystemDictionary::name() != NULL) \
ciEnv::_##name = get(SystemDictionary::name())->as_instance_klass();
WK_KLASSES_DO(WK_KLASS_DEFN)
#undef WK_KLASS_DEFN
for (int len = -1; len != _ci_objects->length(); ) {
len = _ci_objects->length();
@ -333,13 +307,21 @@ ciObject* ciObjectFactory::create_new_object(oop o) {
return new (arena()) ciMethodData(h_md);
} else if (o->is_instance()) {
instanceHandle h_i(THREAD, (instanceOop)o);
return new (arena()) ciInstance(h_i);
if (java_dyn_CallSite::is_instance(o))
return new (arena()) ciCallSite(h_i);
else if (java_dyn_MethodHandle::is_instance(o))
return new (arena()) ciMethodHandle(h_i);
else
return new (arena()) ciInstance(h_i);
} else if (o->is_objArray()) {
objArrayHandle h_oa(THREAD, (objArrayOop)o);
return new (arena()) ciObjArray(h_oa);
} else if (o->is_typeArray()) {
typeArrayHandle h_ta(THREAD, (typeArrayOop)o);
return new (arena()) ciTypeArray(h_ta);
} else if (o->is_constantPoolCache()) {
constantPoolCacheHandle h_cpc(THREAD, (constantPoolCacheOop) o);
return new (arena()) ciCPCache(h_cpc);
}
// The oop is of some type not supported by the compiler interface.
@ -576,7 +558,7 @@ ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) {
if (key->is_perm() && _non_perm_count == 0) {
return emptyBucket;
} else if (key->is_instance()) {
if (key->klass() == SystemDictionary::class_klass()) {
if (key->klass() == SystemDictionary::Class_klass()) {
// class mirror instances are always perm
return emptyBucket;
}

View File

@ -186,8 +186,9 @@ int ciBytecodeStream::get_klass_index() const {
// If this bytecode is a new, newarray, multianewarray, instanceof,
// or checkcast, get the referenced klass.
ciKlass* ciBytecodeStream::get_klass(bool& will_link) {
return CURRENT_ENV->get_klass_by_index(_holder, get_klass_index(),
will_link);
VM_ENTRY_MARK;
constantPoolHandle cpool(_method->get_methodOop()->constants());
return CURRENT_ENV->get_klass_by_index(cpool, get_klass_index(), will_link, _holder);
}
// ------------------------------------------------------------------
@ -213,7 +214,9 @@ int ciBytecodeStream::get_constant_index() const {
// If this bytecode is one of the ldc variants, get the referenced
// constant.
ciConstant ciBytecodeStream::get_constant() {
return CURRENT_ENV->get_constant_by_index(_holder, get_constant_index());
VM_ENTRY_MARK;
constantPoolHandle cpool(_method->get_methodOop()->constants());
return CURRENT_ENV->get_constant_by_index(cpool, get_constant_index(), _holder);
}
// ------------------------------------------------------------------
@ -264,9 +267,11 @@ ciField* ciBytecodeStream::get_field(bool& will_link) {
// There is no "will_link" result passed back. The user is responsible
// for checking linkability when retrieving the associated field.
ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() {
VM_ENTRY_MARK;
constantPoolHandle cpool(_method->get_methodOop()->constants());
int holder_index = get_field_holder_index();
bool ignore;
return CURRENT_ENV->get_klass_by_index(_holder, holder_index, ignore)
return CURRENT_ENV->get_klass_by_index(cpool, holder_index, ignore, _holder)
->as_instance_klass();
}
@ -277,9 +282,10 @@ ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() {
// referenced by the current bytecode. Used for generating
// deoptimization information.
int ciBytecodeStream::get_field_holder_index() {
VM_ENTRY_MARK;
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
return cpool->klass_ref_index_at(get_field_index());
GUARDED_VM_ENTRY(
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
return cpool->klass_ref_index_at(get_field_index());
)
}
// ------------------------------------------------------------------
@ -321,7 +327,9 @@ int ciBytecodeStream::get_method_index() {
//
// If this is a method invocation bytecode, get the invoked method.
ciMethod* ciBytecodeStream::get_method(bool& will_link) {
ciMethod* m = CURRENT_ENV->get_method_by_index(_holder, get_method_index(),cur_bc());
VM_ENTRY_MARK;
constantPoolHandle cpool(_method->get_methodOop()->constants());
ciMethod* m = CURRENT_ENV->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
will_link = m->is_loaded();
return m;
}
@ -338,11 +346,13 @@ ciMethod* ciBytecodeStream::get_method(bool& will_link) {
// There is no "will_link" result passed back. The user is responsible
// for checking linkability when retrieving the associated method.
ciKlass* ciBytecodeStream::get_declared_method_holder() {
VM_ENTRY_MARK;
constantPoolHandle cpool(_method->get_methodOop()->constants());
bool ignore;
// report as Dynamic for invokedynamic, which is syntactically classless
// report as InvokeDynamic for invokedynamic, which is syntactically classless
if (cur_bc() == Bytecodes::_invokedynamic)
return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_Dynamic(), false);
return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore);
return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false);
return CURRENT_ENV->get_klass_by_index(cpool, get_method_holder_index(), ignore, _holder);
}
// ------------------------------------------------------------------
@ -352,8 +362,7 @@ ciKlass* ciBytecodeStream::get_declared_method_holder() {
// referenced by the current bytecode. Used for generating
// deoptimization information.
int ciBytecodeStream::get_method_holder_index() {
VM_ENTRY_MARK;
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
constantPoolOop cpool = _method->get_methodOop()->constants();
return cpool->klass_ref_index_at(get_method_index());
}
@ -370,3 +379,31 @@ int ciBytecodeStream::get_method_signature_index() {
int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
return cpool->signature_ref_index_at(name_and_type_index);
}
// ------------------------------------------------------------------
// ciBytecodeStream::get_cpcache
ciCPCache* ciBytecodeStream::get_cpcache() {
VM_ENTRY_MARK;
// Get the constant pool.
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
constantPoolCacheOop cpcache = cpool->cache();
return CURRENT_ENV->get_object(cpcache)->as_cpcache();
}
// ------------------------------------------------------------------
// ciBytecodeStream::get_call_site
ciCallSite* ciBytecodeStream::get_call_site() {
VM_ENTRY_MARK;
// Get the constant pool.
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
constantPoolCacheOop cpcache = cpool->cache();
// Get the CallSite from the constant pool cache.
int method_index = get_method_index();
ConstantPoolCacheEntry* cpcache_entry = cpcache->secondary_entry_at(method_index);
oop call_site_oop = cpcache_entry->f1();
// Create a CallSite object and return it.
return CURRENT_ENV->get_object(call_site_oop)->as_call_site();
}

View File

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

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -59,6 +59,22 @@ int ciSymbol::byte_at(int i) {
GUARDED_VM_ENTRY(return get_symbolOop()->byte_at(i);)
}
// ------------------------------------------------------------------
// ciSymbol::starts_with
//
// Tests if the symbol starts with the given prefix.
bool ciSymbol::starts_with(const char* prefix, int len) const {
GUARDED_VM_ENTRY(return get_symbolOop()->starts_with(prefix, len);)
}
// ------------------------------------------------------------------
// ciSymbol::index_of
//
// Determines where the symbol contains the given substring.
int ciSymbol::index_of_at(int i, const char* str, int len) const {
GUARDED_VM_ENTRY(return get_symbolOop()->index_of_at(i, str, len);)
}
// ------------------------------------------------------------------
// ciSymbol::utf8_length
int ciSymbol::utf8_length() {

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@
// machine.
class ciSymbol : public ciObject {
CI_PACKAGE_ACCESS
// These friends all make direct use of get_symbolOop:
friend class ciEnv;
friend class ciInstanceKlass;
friend class ciSignature;
@ -38,13 +39,13 @@ private:
ciSymbol(symbolOop s) : ciObject(s) {}
ciSymbol(symbolHandle s); // for use with vmSymbolHandles
symbolOop get_symbolOop() { return (symbolOop)get_oop(); }
symbolOop get_symbolOop() const { return (symbolOop)get_oop(); }
const char* type_string() { return "ciSymbol"; }
void print_impl(outputStream* st);
int byte_at(int i);
// This is public in symbolOop but private here, because the base can move:
jbyte* base();
// Make a ciSymbol from a C string (implementation).
@ -55,6 +56,15 @@ public:
const char* as_utf8();
int utf8_length();
// Return the i-th utf8 byte, where i < utf8_length
int byte_at(int i);
// Tests if the symbol starts with the given prefix.
bool starts_with(const char* prefix, int len) const;
// Determines where the symbol contains the given substring.
int index_of_at(int i, const char* str, int len) const;
// What kind of ciObject is this?
bool is_symbol() { return true; }

View File

@ -111,7 +111,7 @@ ciType* ciType::make(BasicType t) {
// short, etc.
// Note: Bare T_ADDRESS means a raw pointer type, not a return_address.
assert((uint)t < T_CONFLICT+1, "range check");
if (t == T_OBJECT) return ciEnv::_Object; // java/lang/Object
if (t == T_OBJECT) return ciEnv::_Object_klass; // java/lang/Object
assert(_basic_types[t] != NULL, "domain check");
return _basic_types[t];
}

View File

@ -635,8 +635,15 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str,
ciMethod* method = str->get_method(will_link);
if (!will_link) {
// We weren't able to find the method.
ciKlass* unloaded_holder = method->holder();
trap(str, unloaded_holder, str->get_method_holder_index());
if (str->cur_bc() == Bytecodes::_invokedynamic) {
trap(str, NULL,
Deoptimization::make_trap_request
(Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret));
} else {
ciKlass* unloaded_holder = method->holder();
trap(str, unloaded_holder, str->get_method_holder_index());
}
} else {
ciSignature* signature = method->signature();
ciSignatureStream sigstr(signature);
@ -1292,8 +1299,8 @@ bool ciTypeFlow::StateVector::apply_one_bytecode(ciBytecodeStream* str) {
case Bytecodes::_invokeinterface: do_invoke(str, true); break;
case Bytecodes::_invokespecial: do_invoke(str, true); break;
case Bytecodes::_invokestatic: do_invoke(str, false); break;
case Bytecodes::_invokevirtual: do_invoke(str, true); break;
case Bytecodes::_invokedynamic: do_invoke(str, false); break;
case Bytecodes::_istore: store_local_int(str->get_index()); break;
case Bytecodes::_istore_0: store_local_int(0); break;

View File

@ -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); \

View File

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

View File

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

View File

@ -95,14 +95,14 @@ oop JavaAssertions::createAssertionStatusDirectives(TRAPS) {
int len;
typeArrayOop t;
len = OptionList::count(_packages);
objArrayOop pn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL);
objArrayOop pn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL);
objArrayHandle pkgNames (THREAD, pn);
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
typeArrayHandle pkgEnabled(THREAD, t);
fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL);
len = OptionList::count(_classes);
objArrayOop cn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL);
objArrayOop cn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL);
objArrayHandle classNames (THREAD, cn);
t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
typeArrayHandle classEnabled(THREAD, t);

View File

@ -68,9 +68,9 @@ Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
// and the char array it points to end up in the same cache line.
oop obj;
if (tenured) {
obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_permanent_instance(CHECK_NH);
obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_permanent_instance(CHECK_NH);
} else {
obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_instance(CHECK_NH);
obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_instance(CHECK_NH);
}
// Create the char array. The String object must be handlized here
@ -293,7 +293,7 @@ char* java_lang_String::as_utf8_string(oop java_string, int start, int len) {
bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
assert(SharedSkipVerify ||
java_string->klass() == SystemDictionary::string_klass(),
java_string->klass() == SystemDictionary::String_klass(),
"must be java_string");
typeArrayOop value = java_lang_String::value(java_string);
int offset = java_lang_String::offset(java_string);
@ -311,7 +311,7 @@ bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
void java_lang_String::print(Handle java_string, outputStream* st) {
oop obj = java_string();
assert(obj->klass() == SystemDictionary::string_klass(), "must be java_string");
assert(obj->klass() == SystemDictionary::String_klass(), "must be java_string");
typeArrayOop value = java_lang_String::value(obj);
int offset = java_lang_String::offset(obj);
int length = java_lang_String::length(obj);
@ -339,9 +339,9 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
// class is put into the system dictionary.
int computed_modifiers = k->compute_modifier_flags(CHECK_0);
k->set_modifier_flags(computed_modifiers);
if (SystemDictionary::class_klass_loaded()) {
if (SystemDictionary::Class_klass_loaded()) {
// Allocate mirror (java.lang.Class instance)
Handle mirror = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0);
Handle mirror = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0);
// Setup indirections
mirror->obj_field_put(klass_offset, k());
k->set_java_mirror(mirror());
@ -378,7 +378,7 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
// This should be improved by adding a field at the Java level or by
// introducing a new VM klass (see comment in ClassFileParser)
oop java_class = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0);
oop java_class = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0);
if (type != T_VOID) {
klassOop aklass = Universe::typeArrayKlassObj(type);
assert(aklass != NULL, "correct bootstrap");
@ -502,7 +502,7 @@ BasicType java_lang_Class::as_BasicType(oop java_class, klassOop* reference_klas
oop java_lang_Class::primitive_mirror(BasicType t) {
oop mirror = Universe::java_mirror(t);
assert(mirror != NULL && mirror->is_a(SystemDictionary::class_klass()), "must be a Class");
assert(mirror != NULL && mirror->is_a(SystemDictionary::Class_klass()), "must be a Class");
assert(java_lang_Class::is_primitive(mirror), "must be primitive");
return mirror;
}
@ -515,14 +515,14 @@ void java_lang_Class::compute_offsets() {
assert(!offsets_computed, "offsets should be initialized only once");
offsets_computed = true;
klassOop k = SystemDictionary::class_klass();
klassOop k = SystemDictionary::Class_klass();
// The classRedefinedCount field is only present starting in 1.5,
// so don't go fatal.
compute_optional_offset(classRedefinedCount_offset,
k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
// The field indicating parallelCapable (parallelLockMap) is only present starting in 7,
klassOop k1 = SystemDictionary::classloader_klass();
klassOop k1 = SystemDictionary::ClassLoader_klass();
compute_optional_offset(parallelCapable_offset,
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
}
@ -588,7 +588,7 @@ int java_lang_Thread::_park_event_offset = 0 ;
void java_lang_Thread::compute_offsets() {
assert(_group_offset == 0, "offsets should be initialized only once");
klassOop k = SystemDictionary::thread_klass();
klassOop k = SystemDictionary::Thread_klass();
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::char_array_signature());
compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature());
compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature());
@ -847,7 +847,7 @@ bool java_lang_ThreadGroup::is_vmAllowSuspension(oop java_thread_group) {
void java_lang_ThreadGroup::compute_offsets() {
assert(_parent_offset == 0, "offsets should be initialized only once");
klassOop k = SystemDictionary::threadGroup_klass();
klassOop k = SystemDictionary::ThreadGroup_klass();
compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature());
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
@ -1344,7 +1344,7 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t
// No-op if stack trace is disabled
if (!StackTraceInThrowable) return;
assert(throwable->is_a(SystemDictionary::throwable_klass()), "sanity check");
assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check");
oop backtrace = java_lang_Throwable::backtrace(throwable());
assert(backtrace != NULL, "backtrace not preallocated");
@ -1449,7 +1449,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4");
// Allocate java.lang.StackTraceElement instance
klassOop k = SystemDictionary::stackTraceElement_klass();
klassOop k = SystemDictionary::StackTraceElement_klass();
assert(k != NULL, "must be loaded in 1.4+");
instanceKlassHandle ik (THREAD, k);
if (ik->should_be_initialized()) {
@ -1487,7 +1487,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
void java_lang_reflect_AccessibleObject::compute_offsets() {
klassOop k = SystemDictionary::reflect_accessible_object_klass();
klassOop k = SystemDictionary::reflect_AccessibleObject_klass();
compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature());
}
@ -1502,7 +1502,7 @@ void java_lang_reflect_AccessibleObject::set_override(oop reflect, jboolean valu
}
void java_lang_reflect_Method::compute_offsets() {
klassOop k = SystemDictionary::reflect_method_klass();
klassOop k = SystemDictionary::reflect_Method_klass();
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature());
@ -1523,7 +1523,7 @@ void java_lang_reflect_Method::compute_offsets() {
Handle java_lang_reflect_Method::create(TRAPS) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
klassOop klass = SystemDictionary::reflect_method_klass();
klassOop klass = SystemDictionary::reflect_Method_klass();
// This class is eagerly initialized during VM initialization, since we keep a refence
// to one of the methods
assert(instanceKlass::cast(klass)->is_initialized(), "must be initialized");
@ -1665,7 +1665,7 @@ void java_lang_reflect_Method::set_annotation_default(oop method, oop value) {
}
void java_lang_reflect_Constructor::compute_offsets() {
klassOop k = SystemDictionary::reflect_constructor_klass();
klassOop k = SystemDictionary::reflect_Constructor_klass();
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature());
compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature());
@ -1789,7 +1789,7 @@ void java_lang_reflect_Constructor::set_parameter_annotations(oop method, oop va
}
void java_lang_reflect_Field::compute_offsets() {
klassOop k = SystemDictionary::reflect_field_klass();
klassOop k = SystemDictionary::reflect_Field_klass();
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature());
@ -1896,7 +1896,7 @@ void java_lang_reflect_Field::set_annotations(oop field, oop value) {
void sun_reflect_ConstantPool::compute_offsets() {
klassOop k = SystemDictionary::reflect_constant_pool_klass();
klassOop k = SystemDictionary::reflect_ConstantPool_klass();
// This null test can be removed post beta
if (k != NULL) {
compute_offset(_cp_oop_offset, k, vmSymbols::constantPoolOop_name(), vmSymbols::object_signature());
@ -1906,7 +1906,7 @@ void sun_reflect_ConstantPool::compute_offsets() {
Handle sun_reflect_ConstantPool::create(TRAPS) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
klassOop k = SystemDictionary::reflect_constant_pool_klass();
klassOop k = SystemDictionary::reflect_ConstantPool_klass();
instanceKlassHandle klass (THREAD, k);
// Ensure it is initialized
klass->initialize(CHECK_NH);
@ -1926,7 +1926,7 @@ void sun_reflect_ConstantPool::set_cp_oop(oop reflect, oop value) {
}
void sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() {
klassOop k = SystemDictionary::reflect_unsafe_static_field_accessor_impl_klass();
klassOop k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass();
// This null test can be removed post beta
if (k != NULL) {
compute_offset(_base_offset, k,
@ -2072,7 +2072,7 @@ void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream*
// Support for java_lang_ref_Reference
oop java_lang_ref_Reference::pending_list_lock() {
instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass());
char *addr = (((char *)ik->start_of_static_fields()) + static_lock_offset);
if (UseCompressedOops) {
return oopDesc::load_decode_heap_oop((narrowOop *)addr);
@ -2082,7 +2082,7 @@ oop java_lang_ref_Reference::pending_list_lock() {
}
HeapWord *java_lang_ref_Reference::pending_list_addr() {
instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass());
char *addr = (((char *)ik->start_of_static_fields()) + static_pending_offset);
// XXX This might not be HeapWord aligned, almost rather be char *.
return (HeapWord*)addr;
@ -2105,17 +2105,17 @@ jlong java_lang_ref_SoftReference::timestamp(oop ref) {
}
jlong java_lang_ref_SoftReference::clock() {
instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass());
instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass());
int offset = ik->offset_of_static_fields() + static_clock_offset;
return SystemDictionary::soft_reference_klass()->long_field(offset);
return SystemDictionary::SoftReference_klass()->long_field(offset);
}
void java_lang_ref_SoftReference::set_clock(jlong value) {
instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass());
instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass());
int offset = ik->offset_of_static_fields() + static_clock_offset;
SystemDictionary::soft_reference_klass()->long_field_put(offset, value);
SystemDictionary::SoftReference_klass()->long_field_put(offset, value);
}
@ -2403,6 +2403,10 @@ oop java_dyn_MethodType::ptype(oop mt, int idx) {
return ptypes(mt)->obj_at(idx);
}
int java_dyn_MethodType::ptype_count(oop mt) {
return ptypes(mt)->length();
}
// Support for java_dyn_MethodTypeForm
@ -2534,7 +2538,7 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
// the generated bytecodes for reflection, and if so, "magically"
// delegate to its parent to prevent class loading from occurring
// in places where applications using reflection didn't expect it.
klassOop delegating_cl_class = SystemDictionary::reflect_delegating_classloader_klass();
klassOop delegating_cl_class = SystemDictionary::reflect_DelegatingClassLoader_klass();
// This might be null in non-1.4 JDKs
if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) {
return parent(loader);
@ -2549,7 +2553,7 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
void java_lang_System::compute_offsets() {
assert(offset_of_static_fields == 0, "offsets should be initialized only once");
instanceKlass* ik = instanceKlass::cast(SystemDictionary::system_klass());
instanceKlass* ik = instanceKlass::cast(SystemDictionary::System_klass());
offset_of_static_fields = ik->offset_of_static_fields();
}

View File

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

View File

@ -60,10 +60,10 @@ oop SystemDictionary::java_system_loader() {
}
void SystemDictionary::compute_java_system_loader(TRAPS) {
KlassHandle system_klass(THREAD, WK_KLASS(classloader_klass));
KlassHandle system_klass(THREAD, WK_KLASS(ClassLoader_klass));
JavaValue result(T_OBJECT);
JavaCalls::call_static(&result,
KlassHandle(THREAD, WK_KLASS(classloader_klass)),
KlassHandle(THREAD, WK_KLASS(ClassLoader_klass)),
vmSymbolHandles::getSystemClassLoader_name(),
vmSymbolHandles::void_classloader_signature(),
CHECK);
@ -128,7 +128,7 @@ klassOop SystemDictionary::handle_resolution_exception(symbolHandle class_name,
// in which case we have to check whether the pending exception is a ClassNotFoundException,
// and if so convert it to a NoClassDefFoundError
// And chain the original ClassNotFoundException
if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass())) {
if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass())) {
ResourceMark rm(THREAD);
assert(klass_h() == NULL, "Should not have result with exception pending");
Handle e(THREAD, PENDING_EXCEPTION);
@ -359,7 +359,7 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass,
assert(class_loader() != NULL, "should not have non-null protection domain for null classloader");
KlassHandle system_loader(THREAD, SystemDictionary::classloader_klass());
KlassHandle system_loader(THREAD, SystemDictionary::ClassLoader_klass());
JavaCalls::call_special(&result,
class_loader,
system_loader,
@ -743,7 +743,7 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam
// Bootstrap goes through here to allow for an extra guarantee check
if (UnsyncloadClass || (class_loader.is_null())) {
if (k.is_null() && HAS_PENDING_EXCEPTION
&& PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) {
&& PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
MutexLocker mu(SystemDictionary_lock, THREAD);
klassOop check = find_class(d_index, d_hash, name, class_loader);
if (check != NULL) {
@ -1367,7 +1367,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_nam
JavaValue result(T_OBJECT);
KlassHandle spec_klass (THREAD, SystemDictionary::classloader_klass());
KlassHandle spec_klass (THREAD, SystemDictionary::ClassLoader_klass());
// Call public unsynchronized loadClass(String) directly for all class loaders
// for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will
@ -1944,13 +1944,13 @@ void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
assert(WK_KLASS(object_klass) == NULL, "preloaded classes should only be initialized once");
assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
// Preload commonly used klasses
WKID scan = FIRST_WKID;
// first do Object, String, Class
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(class_klass), scan, CHECK);
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK);
debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(class_klass)));
debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(Class_klass)));
// Fixup mirrors for classes loaded before java.lang.Class.
// These calls iterate over the objects currently in the perm gen
@ -1961,17 +1961,17 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
Universe::fixup_mirrors(CHECK);
// do a bunch more:
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(reference_klass), scan, CHECK);
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Reference_klass), scan, CHECK);
// Preload ref klasses and set reference types
instanceKlass::cast(WK_KLASS(reference_klass))->set_reference_type(REF_OTHER);
instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(reference_klass));
instanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass));
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(phantom_reference_klass), scan, CHECK);
instanceKlass::cast(WK_KLASS(soft_reference_klass))->set_reference_type(REF_SOFT);
instanceKlass::cast(WK_KLASS(weak_reference_klass))->set_reference_type(REF_WEAK);
instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK);
instanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
instanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK);
instanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
instanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
@ -1984,7 +1984,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
scan = WKID(meth_group_end+1);
}
WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
WKID indy_group_end = WK_KLASS_ENUM_NAME(Dynamic_klass);
WKID indy_group_end = WK_KLASS_ENUM_NAME(InvokeDynamic_klass);
initialize_wk_klasses_until(indy_group_start, scan, CHECK);
if (EnableInvokeDynamic) {
initialize_wk_klasses_through(indy_group_end, scan, CHECK);
@ -1996,14 +1996,14 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
_box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass);
_box_klasses[T_CHAR] = WK_KLASS(char_klass);
_box_klasses[T_FLOAT] = WK_KLASS(float_klass);
_box_klasses[T_DOUBLE] = WK_KLASS(double_klass);
_box_klasses[T_BYTE] = WK_KLASS(byte_klass);
_box_klasses[T_SHORT] = WK_KLASS(short_klass);
_box_klasses[T_INT] = WK_KLASS(int_klass);
_box_klasses[T_LONG] = WK_KLASS(long_klass);
_box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
_box_klasses[T_CHAR] = WK_KLASS(Character_klass);
_box_klasses[T_FLOAT] = WK_KLASS(Float_klass);
_box_klasses[T_DOUBLE] = WK_KLASS(Double_klass);
_box_klasses[T_BYTE] = WK_KLASS(Byte_klass);
_box_klasses[T_SHORT] = WK_KLASS(Short_klass);
_box_klasses[T_INT] = WK_KLASS(Integer_klass);
_box_klasses[T_LONG] = WK_KLASS(Long_klass);
//_box_klasses[T_OBJECT] = WK_KLASS(object_klass);
//_box_klasses[T_ARRAY] = WK_KLASS(object_klass);
@ -2014,11 +2014,11 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
#endif // KERNEL
{ // Compute whether we should use loadClass or loadClassInternal when loading classes.
methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature());
methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature());
_has_loadClassInternal = (method != NULL);
}
{ // Compute whether we should use checkPackageAccess or NOT
methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature());
methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature());
_has_checkPackageAccess = (method != NULL);
}
}
@ -2340,6 +2340,8 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
if (spe == NULL || spe->property_oop() == NULL) {
// Must create lots of stuff here, but outside of the SystemDictionary lock.
if (THREAD->is_Compiler_thread())
return NULL; // do not attempt from within compiler
Handle mt = compute_method_handle_type(signature(),
class_loader, protection_domain,
CHECK_NULL);
@ -2372,7 +2374,7 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
TRAPS) {
Handle empty;
int npts = ArgumentCount(signature()).size();
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty));
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty));
int arg = 0;
Handle rt; // the return type from the signature
for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {

View File

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

View File

@ -143,7 +143,7 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul
bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) {
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

View File

@ -1,5 +1,5 @@
/*
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -70,6 +70,7 @@ static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGN
void vmSymbols::initialize(TRAPS) {
assert((int)SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield");
assert((int)SID_LIMIT*5 > (1<<log2_SID_LIMIT), "make the bitfield smaller, please");
assert(vmIntrinsics::FLAG_LIMIT <= (1 << vmIntrinsics::log2_FLAG_LIMIT), "must fit in this bitfield");
if (!UseSharedSpaces) {
const char* string = &vm_symbol_bodies[0];
@ -271,6 +272,58 @@ vmSymbols::SID vmSymbols::find_sid(symbolOop symbol) {
return sid;
}
static vmIntrinsics::ID wrapper_intrinsic(BasicType type, bool unboxing) {
#define TYPE2(type, unboxing) ((int)(type)*2 + ((unboxing) ? 1 : 0))
switch (TYPE2(type, unboxing)) {
#define BASIC_TYPE_CASE(type, box, unbox) \
case TYPE2(type, false): return vmIntrinsics::box; \
case TYPE2(type, true): return vmIntrinsics::unbox
BASIC_TYPE_CASE(T_BOOLEAN, _Boolean_valueOf, _booleanValue);
BASIC_TYPE_CASE(T_BYTE, _Byte_valueOf, _byteValue);
BASIC_TYPE_CASE(T_CHAR, _Character_valueOf, _charValue);
BASIC_TYPE_CASE(T_SHORT, _Short_valueOf, _shortValue);
BASIC_TYPE_CASE(T_INT, _Integer_valueOf, _intValue);
BASIC_TYPE_CASE(T_LONG, _Long_valueOf, _longValue);
BASIC_TYPE_CASE(T_FLOAT, _Float_valueOf, _floatValue);
BASIC_TYPE_CASE(T_DOUBLE, _Double_valueOf, _doubleValue);
#undef BASIC_TYPE_CASE
}
#undef TYPE2
return vmIntrinsics::_none;
}
vmIntrinsics::ID vmIntrinsics::for_boxing(BasicType type) {
return wrapper_intrinsic(type, false);
}
vmIntrinsics::ID vmIntrinsics::for_unboxing(BasicType type) {
return wrapper_intrinsic(type, true);
}
vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest) {
#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d))
switch (SRC_DEST(src, dest)) {
case SRC_DEST(T_INT, T_FLOAT): return vmIntrinsics::_intBitsToFloat;
case SRC_DEST(T_FLOAT, T_INT): return vmIntrinsics::_floatToRawIntBits;
case SRC_DEST(T_LONG, T_DOUBLE): return vmIntrinsics::_longBitsToDouble;
case SRC_DEST(T_DOUBLE, T_LONG): return vmIntrinsics::_doubleToRawLongBits;
}
#undef SRC_DEST
return vmIntrinsics::_none;
}
methodOop vmIntrinsics::method_for(vmIntrinsics::ID id) {
if (id == _none) return NULL;
symbolOop cname = vmSymbols::symbol_at(class_for(id));
symbolOop mname = vmSymbols::symbol_at(name_for(id));
symbolOop msig = vmSymbols::symbol_at(signature_for(id));
if (cname == NULL || mname == NULL || msig == NULL) return NULL;
klassOop k = SystemDictionary::find_well_known_klass(cname);
if (k == NULL) return NULL;
return instanceKlass::cast(k)->find_method(mname, msig);
}
#define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0"
static const char* vm_intrinsic_name_bodies =
@ -330,15 +383,15 @@ inline bool match_F_RNY(jshort flags) {
}
// These are for forming case labels:
#define ID3(x, y, z) (( jint)(z) + \
((jint)(y) << vmSymbols::log2_SID_LIMIT) + \
((jint)(x) << (2*vmSymbols::log2_SID_LIMIT)) )
#define ID3(x, y, z) (( jlong)(z) + \
((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \
((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) )
#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n)
vmIntrinsics::ID vmIntrinsics::find_id(vmSymbols::SID holder,
vmSymbols::SID name,
vmSymbols::SID sig,
jshort flags) {
vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder,
vmSymbols::SID name,
vmSymbols::SID sig,
jshort flags) {
assert((int)vmSymbols::SID_LIMIT <= (1<<vmSymbols::log2_SID_LIMIT), "must fit");
// Let the C compiler build the decision tree.
@ -383,62 +436,50 @@ const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf,
}
// These are for friendly printouts of intrinsics:
// These are to get information about intrinsics.
#define ID4(x, y, z, f) ((ID3(x, y, z) << vmIntrinsics::log2_FLAG_LIMIT) | (jlong) (f))
static const jlong intrinsic_info_array[vmIntrinsics::ID_LIMIT+1] = {
#define VM_INTRINSIC_INFO(ignore_id, klass, name, sig, fcode) \
ID4(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig), vmIntrinsics::fcode),
0, VM_INTRINSICS_DO(VM_INTRINSIC_INFO,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE)
0
#undef VM_INTRINSIC_INFO
};
inline jlong intrinsic_info(vmIntrinsics::ID id) {
return intrinsic_info_array[vmIntrinsics::ID_from((int)id)];
}
vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) {
#ifndef PRODUCT
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
case id: return SID_ENUM(klass);
switch (id) {
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
}
#undef VM_INTRINSIC_CASE
#endif //PRODUCT
return vmSymbols::NO_SID;
jlong info = intrinsic_info(id);
int shift = 2*vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1021, "");
return vmSymbols::SID( (info >> shift) & mask );
}
vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) {
#ifndef PRODUCT
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
case id: return SID_ENUM(name);
switch (id) {
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
}
#undef VM_INTRINSIC_CASE
#endif //PRODUCT
return vmSymbols::NO_SID;
jlong info = intrinsic_info(id);
int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, "");
return vmSymbols::SID( (info >> shift) & mask );
}
vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) {
#ifndef PRODUCT
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
case id: return SID_ENUM(sig);
switch (id) {
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
}
#undef VM_INTRINSIC_CASE
#endif //PRODUCT
return vmSymbols::NO_SID;
jlong info = intrinsic_info(id);
int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, "");
return vmSymbols::SID( (info >> shift) & mask );
}
vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) {
#ifndef PRODUCT
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
case id: return fcode;
switch (id) {
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
}
#undef VM_INTRINSIC_CASE
#endif //PRODUCT
return F_none;
jlong info = intrinsic_info(id);
int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT);
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, "");
return Flags( (info >> shift) & mask );
}

View File

@ -219,7 +219,7 @@
template(base_name, "base") \
\
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
template(java_dyn_Dynamic, "java/dyn/Dynamic") \
template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") \
template(java_dyn_Linkage, "java/dyn/Linkage") \
template(java_dyn_CallSite, "java/dyn/CallSite") \
template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
@ -347,9 +347,14 @@
\
/* common signatures names */ \
template(void_method_signature, "()V") \
template(void_boolean_signature, "()Z") \
template(void_byte_signature, "()B") \
template(void_char_signature, "()C") \
template(void_short_signature, "()S") \
template(void_int_signature, "()I") \
template(void_long_signature, "()J") \
template(void_boolean_signature, "()Z") \
template(void_float_signature, "()F") \
template(void_double_signature, "()D") \
template(int_void_signature, "(I)V") \
template(int_int_signature, "(I)I") \
template(int_bool_signature, "(I)Z") \
@ -854,6 +859,46 @@
\
do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
/* (symbols invoke_name and invoke_signature defined above) */ \
do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \
do_name( checkSpreadArgument_name, "checkSpreadArgument") \
do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \
\
/* unboxing methods: */ \
do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \
do_name( booleanValue_name, "booleanValue") \
do_intrinsic(_byteValue, java_lang_Byte, byteValue_name, void_byte_signature, F_R) \
do_name( byteValue_name, "byteValue") \
do_intrinsic(_charValue, java_lang_Character, charValue_name, void_char_signature, F_R) \
do_name( charValue_name, "charValue") \
do_intrinsic(_shortValue, java_lang_Short, shortValue_name, void_short_signature, F_R) \
do_name( shortValue_name, "shortValue") \
do_intrinsic(_intValue, java_lang_Integer, intValue_name, void_int_signature, F_R) \
do_name( intValue_name, "intValue") \
do_intrinsic(_longValue, java_lang_Long, longValue_name, void_long_signature, F_R) \
do_name( longValue_name, "longValue") \
do_intrinsic(_floatValue, java_lang_Float, floatValue_name, void_float_signature, F_R) \
do_name( floatValue_name, "floatValue") \
do_intrinsic(_doubleValue, java_lang_Double, doubleValue_name, void_double_signature, F_R) \
do_name( doubleValue_name, "doubleValue") \
\
/* boxing methods: */ \
do_name( valueOf_name, "valueOf") \
do_intrinsic(_Boolean_valueOf, java_lang_Boolean, valueOf_name, Boolean_valueOf_signature, F_S) \
do_name( Boolean_valueOf_signature, "(Z)Ljava/lang/Boolean;") \
do_intrinsic(_Byte_valueOf, java_lang_Byte, valueOf_name, Byte_valueOf_signature, F_S) \
do_name( Byte_valueOf_signature, "(B)Ljava/lang/Byte;") \
do_intrinsic(_Character_valueOf, java_lang_Character, valueOf_name, Character_valueOf_signature, F_S) \
do_name( Character_valueOf_signature, "(C)Ljava/lang/Character;") \
do_intrinsic(_Short_valueOf, java_lang_Short, valueOf_name, Short_valueOf_signature, F_S) \
do_name( Short_valueOf_signature, "(S)Ljava/lang/Short;") \
do_intrinsic(_Integer_valueOf, java_lang_Integer, valueOf_name, Integer_valueOf_signature, F_S) \
do_name( Integer_valueOf_signature, "(I)Ljava/lang/Integer;") \
do_intrinsic(_Long_valueOf, java_lang_Long, valueOf_name, Long_valueOf_signature, F_S) \
do_name( Long_valueOf_signature, "(J)Ljava/lang/Long;") \
do_intrinsic(_Float_valueOf, java_lang_Float, valueOf_name, Float_valueOf_signature, F_S) \
do_name( Float_valueOf_signature, "(F)Ljava/lang/Float;") \
do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \
do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \
\
/*end*/
@ -984,7 +1029,12 @@ class vmIntrinsics: AllStatic {
F_Y, // !static ?native synchronized
F_RN, // !static native !synchronized
F_SN, // static native !synchronized
F_RNY // !static native synchronized
F_RNY, // !static native synchronized
FLAG_LIMIT
};
enum {
log2_FLAG_LIMIT = 4 // checked by an assert at start-up
};
public:
@ -996,15 +1046,32 @@ public:
static const char* name_at(ID id);
private:
static ID find_id_impl(vmSymbols::SID holder,
vmSymbols::SID name,
vmSymbols::SID sig,
jshort flags);
public:
// Given a method's class, name, signature, and access flags, report its ID.
static ID find_id(vmSymbols::SID holder,
vmSymbols::SID name,
vmSymbols::SID sig,
jshort flags);
jshort flags) {
ID id = find_id_impl(holder, name, sig, flags);
#ifdef ASSERT
// ID _none does not hold the following asserts.
if (id == _none) return id;
#endif
assert( class_for(id) == holder, "correct id");
assert( name_for(id) == name, "correct id");
assert(signature_for(id) == sig, "correct id");
return id;
}
static void verify_method(ID actual_id, methodOop m) PRODUCT_RETURN;
// No need for these in the product:
// Find out the symbols behind an intrinsic:
static vmSymbols::SID class_for(ID id);
static vmSymbols::SID name_for(ID id);
static vmSymbols::SID signature_for(ID id);
@ -1014,4 +1081,11 @@ public:
// Access to intrinsic methods:
static methodOop method_for(ID id);
// Wrapper object methods:
static ID for_boxing(BasicType type);
static ID for_unboxing(BasicType type);
// Raw conversion:
static ID for_raw_conversion(BasicType src, BasicType dest);
};

View File

@ -1,5 +1,5 @@
/*
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -102,6 +102,9 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
virtual bool is_compiled_by_c2() const { return false; }
virtual bool is_compiled_by_c1() const { return false; }
// Casting
nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
// Boundaries
address header_begin() const { return (address) this; }
address header_end() const { return ((address) this) + _header_size; };

View File

@ -281,6 +281,7 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
ciMethod* method,
int bci,
bool reexecute,
bool is_method_handle_invoke,
DebugToken* locals,
DebugToken* expressions,
DebugToken* monitors) {
@ -292,8 +293,9 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
int stream_offset = stream()->position();
last_pd->set_scope_decode_offset(stream_offset);
// Record reexecute bit into pcDesc
// Record flags into pcDesc.
last_pd->set_should_reexecute(reexecute);
last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
// serialize sender stream offest
stream()->write_int(sender_stream_offset);

View File

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

View File

@ -1170,7 +1170,7 @@ void nmethod::log_state_change() const {
}
// Common functionality for both make_not_entrant and make_zombie
bool nmethod::make_not_entrant_or_zombie(int state) {
bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
// If the method is already zombie there is nothing to do
@ -1724,9 +1724,9 @@ void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map
if (!method()->is_native()) {
SimpleScopeDesc ssd(this, fr.pc());
Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci());
bool is_static = call->is_invokestatic();
bool has_receiver = call->has_receiver();
symbolOop signature = call->signature();
fr.oops_compiled_arguments_do(signature, is_static, reg_map, f);
fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f);
}
}
@ -1763,6 +1763,14 @@ void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) {
"must end with a sentinel");
#endif //ASSERT
// Search for MethodHandle invokes and tag the nmethod.
for (int i = 0; i < count; i++) {
if (pcs[i].is_method_handle_invoke()) {
set_has_method_handle_invokes(true);
break;
}
}
int size = count * sizeof(PcDesc);
assert(scopes_pcs_size() >= size, "oob");
memcpy(scopes_pcs_begin(), pcs, size);
@ -2029,6 +2037,18 @@ bool nmethod::is_deopt_pc(address pc) {
}
// -----------------------------------------------------------------------------
// MethodHandle
bool nmethod::is_method_handle_return(address return_pc) {
if (!has_method_handle_invokes()) return false;
PcDesc* pd = pc_desc_at(return_pc);
if (pd == NULL)
return false;
return pd->is_method_handle_invoke();
}
// -----------------------------------------------------------------------------
// Verification

View File

@ -81,18 +81,19 @@ class PcDescCache VALUE_OBJ_CLASS_SPEC {
struct nmFlags {
friend class VMStructs;
unsigned int version:8; // version number (0 = first version)
unsigned int level:4; // optimization level
unsigned int age:4; // age (in # of sweep steps)
unsigned int version:8; // version number (0 = first version)
unsigned int level:4; // optimization level
unsigned int age:4; // age (in # of sweep steps)
unsigned int state:2; // {alive, zombie, unloaded)
unsigned int state:2; // {alive, zombie, unloaded)
unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap?
unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures
unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies
unsigned int markedForReclamation:1; // Used by NMethodSweeper
unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap?
unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures
unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies
unsigned int markedForReclamation:1; // Used by NMethodSweeper
unsigned int has_unsafe_access:1; // May fault due to unsafe access.
unsigned int has_unsafe_access:1; // May fault due to unsafe access.
unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes?
void clear();
};
@ -254,7 +255,7 @@ class nmethod : public CodeBlob {
const char* reloc_string_for(u_char* begin, u_char* end);
// Returns true if this thread changed the state of the nmethod or
// false if another thread performed the transition.
bool make_not_entrant_or_zombie(int state);
bool make_not_entrant_or_zombie(unsigned int state);
void inc_decompile_count();
// used to check that writes to nmFlags are done consistently.
@ -409,6 +410,9 @@ class nmethod : public CodeBlob {
bool has_unsafe_access() const { return flags.has_unsafe_access; }
void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; }
bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; }
void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; }
int level() const { return flags.level; }
void set_level(int newLevel) { check_safepoint(); flags.level = newLevel; }
@ -541,6 +545,9 @@ class nmethod : public CodeBlob {
address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
// MethodHandle
bool is_method_handle_return(address return_pc);
// jvmti support:
void post_compiled_method_load_event();

View File

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

View File

@ -1820,9 +1820,11 @@ void CompileBroker::print_times() {
CompileBroker::_t_standard_compilation.seconds(),
CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count);
tty->print_cr(" On stack replacement : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count);
compiler(CompLevel_fast_compile)->print_timers();
if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier)) {
compiler(CompLevel_highest_tier)->print_timers();
if (compiler(CompLevel_fast_compile)) {
compiler(CompLevel_fast_compile)->print_timers();
if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier))
compiler(CompLevel_highest_tier)->print_timers();
}
tty->cr();

View File

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

View File

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

View File

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

View File

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

View File

@ -102,7 +102,9 @@ methodHandle Bytecode_invoke::static_target(TRAPS) {
KlassHandle resolved_klass;
constantPoolHandle constants(THREAD, _method->constants());
if (adjusted_invoke_code() != Bytecodes::_invokeinterface) {
if (adjusted_invoke_code() == Bytecodes::_invokedynamic) {
LinkResolver::resolve_dynamic_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
} else if (adjusted_invoke_code() != Bytecodes::_invokeinterface) {
LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
} else {
LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));

View File

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

View File

@ -270,6 +270,8 @@ void BytecodePrinter::print_constant(int i, outputStream* st) {
st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name());
} else if (tag.is_unresolved_klass()) {
st->print_cr(" <unresolved klass at %d>", i);
} else if (tag.is_object()) {
st->print_cr(" " PTR_FORMAT, constants->object_at(i));
} else {
st->print_cr(" bad tag=%d at %d", tag.value(), i);
}

View File

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

View File

@ -323,7 +323,7 @@ address AbstractInterpreter::deopt_continue_after_entry(methodOop method, addres
// (NOT needed for the old calling convension)
if (!is_top_frame) {
int index = Bytes::get_native_u4(bcp+1);
method->constants()->cache()->entry_at(index)->set_parameter_size(callee_parameters);
method->constants()->cache()->secondary_entry_at(index)->set_parameter_size(callee_parameters);
}
break;
}

View File

@ -353,7 +353,7 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
assert(h_exception.not_null(), "NULL exceptions should be handled by athrow");
assert(h_exception->is_oop(), "just checking");
// Check that exception is a subclass of Throwable, otherwise we have a VerifyError
if (!(h_exception->is_a(SystemDictionary::throwable_klass()))) {
if (!(h_exception->is_a(SystemDictionary::Throwable_klass()))) {
if (ExitVMOnVerifyError) vm_exit(-1);
ShouldNotReachHere();
}
@ -585,7 +585,7 @@ IRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThre
Handle exception(thread, thread->vm_result());
assert(exception() != NULL, "vm result should be set");
thread->set_vm_result(NULL); // clear vm result before continuing (may cause memory leaks and assert failures)
if (!exception->is_a(SystemDictionary::threaddeath_klass())) {
if (!exception->is_a(SystemDictionary::ThreadDeath_klass())) {
exception = get_preinitialized_exception(
SystemDictionary::IllegalMonitorStateException_klass(),
CATCH);
@ -660,7 +660,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes
tty->print_cr("Resolving: klass: %s to method: %s", info.resolved_klass()->name()->as_C_string(), info.resolved_method()->name()->as_C_string());
}
if (info.resolved_method()->method_holder() ==
SystemDictionary::object_klass()) {
SystemDictionary::Object_klass()) {
// NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec
// (see also cpCacheOop.cpp for details)
methodHandle rm = info.resolved_method();
@ -1250,7 +1250,7 @@ IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* threa
methodHandle mh(thread, fr.interpreter_frame_method());
Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci);
ArgumentSizeComputer asc(invoke->signature());
int size_of_arguments = (asc.size() + (invoke->is_invokestatic() ? 0 : 1)); // receiver
int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver
Copy::conjoint_bytes(src_address, dest_address,
size_of_arguments * Interpreter::stackElementSize());
IRT_END

View File

@ -55,7 +55,7 @@ void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_kl
// we should pick the vtable index from the resolved method.
// Other than that case, there is no valid vtable index to specify.
int vtable_index = methodOopDesc::invalid_vtable_index;
if (resolved_method->method_holder() == SystemDictionary::object_klass()) {
if (resolved_method->method_holder() == SystemDictionary::Object_klass()) {
assert(resolved_method->vtable_index() == selected_method->vtable_index(), "sanity check");
vtable_index = resolved_method->vtable_index();
}
@ -75,6 +75,8 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass
_selected_method = selected_method;
_vtable_index = vtable_index;
if (CompilationPolicy::mustBeCompiled(selected_method)) {
// This path is unusual, mostly used by the '-Xcomp' stress test mode.
// Note: with several active threads, the mustBeCompiled may be true
// while canBeCompiled is false; remove assert
// assert(CompilationPolicy::canBeCompiled(selected_method), "cannot compile");
@ -82,6 +84,16 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass
// don't force compilation, resolve was on behalf of compiler
return;
}
if (instanceKlass::cast(selected_method->method_holder())->is_not_initialized()) {
// 'is_not_initialized' means not only '!is_initialized', but also that
// initialization has not been started yet ('!being_initialized')
// Do not force compilation of methods in uninitialized classes.
// Note that doing this would throw an assert later,
// in CompileBroker::compile_method.
// We sometimes use the link resolver to do reflective lookups
// even before classes are initialized.
return;
}
CompileBroker::compile_method(selected_method, InvocationEntryBci,
methodHandle(), 0, "mustBeCompiled", CHECK);
}
@ -181,7 +193,7 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass,
// We'll check for the method name first, as that's most likely
// to be false (so we'll short-circuit out of these tests).
if (sel_method->name() == vmSymbols::clone_name() &&
sel_klass() == SystemDictionary::object_klass() &&
sel_klass() == SystemDictionary::Object_klass() &&
resolved_klass->oop_is_array()) {
// We need to change "protected" to "public".
assert(flags.is_protected(), "clone not protected?");
@ -223,6 +235,18 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle& re
resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
}
void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) {
// The class is java.dyn.MethodHandle
resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
symbolHandle method_name = vmSymbolHandles::invoke_name();
symbolHandle method_signature(THREAD, pool->signature_ref_at(index));
KlassHandle current_klass (THREAD, pool->pool_holder());
resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
}
void LinkResolver::resolve_interface_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) {
// resolve klass

View File

@ -133,6 +133,7 @@ class LinkResolver: AllStatic {
// static resolving for all calls except interface calls
static void resolve_method (methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS);
static void resolve_dynamic_method (methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS);
static void resolve_interface_method(methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS);
// runtime/static resolving for fields

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -43,7 +43,7 @@ klassOop arrayKlass::java_super() const {
if (super() == NULL) return NULL; // bootstrap case
// Array klasses have primary supertypes which are not reported to Java.
// Example super chain: String[][] -> Object[][] -> Object[] -> Object
return SystemDictionary::object_klass();
return SystemDictionary::Object_klass();
}
@ -82,7 +82,7 @@ const Klass_vtbl& cplusplus_vtbl, int header_size, KlassHandle klass, TRAPS) {
k = arrayKlassHandle(THREAD, base_klass());
assert(!k()->is_parsable(), "not expecting parsability yet.");
k->set_super(Universe::is_bootstrapping() ? (klassOop)NULL : SystemDictionary::object_klass());
k->set_super(Universe::is_bootstrapping() ? (klassOop)NULL : SystemDictionary::Object_klass());
k->set_layout_helper(Klass::_lh_neutral_value);
k->set_dimension(1);
k->set_higher_dimension(NULL);
@ -117,9 +117,9 @@ objArrayOop arrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS) {
bool arrayKlass::compute_is_subtype_of(klassOop k) {
// An array is a subtype of Serializable, Clonable, and Object
return k == SystemDictionary::object_klass()
|| k == SystemDictionary::cloneable_klass()
|| k == SystemDictionary::serializable_klass();
return k == SystemDictionary::Object_klass()
|| k == SystemDictionary::Cloneable_klass()
|| k == SystemDictionary::Serializable_klass();
}

View File

@ -67,7 +67,7 @@ class arrayKlass: public Klass {
// Compiler/Interpreter offset
static ByteSize component_mirror_offset() { return byte_offset_of(arrayKlass, _component_mirror); }
virtual klassOop java_super() const;//{ return SystemDictionary::object_klass(); }
virtual klassOop java_super() const;//{ return SystemDictionary::Object_klass(); }
// Allocation
// Sizes points to the first dimension of the array, subsequent dimensions

View File

@ -258,6 +258,11 @@ public:
LocalVariableTableElement* localvariable_table_start() const;
// byte codes
void set_code(address code) {
if (code_size() > 0) {
memcpy(code_base(), code, code_size());
}
}
address code_base() const { return (address) (this+1); }
address code_end() const { return code_base() + code_size(); }
bool contains(address bcp) const { return code_base() <= bcp

View File

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

View File

@ -191,6 +191,16 @@ class constantPoolOopDesc : public oopDesc {
}
}
void object_at_put(int which, oop str) {
oop_store((volatile oop*) obj_at_addr(which), str);
release_tag_at_put(which, JVM_CONSTANT_Object);
if (UseConcMarkSweepGC) {
// In case the earlier card-mark was consumed by a concurrent
// marking thread before the tag was updated, redirty the card.
oop_store_without_check((volatile oop*) obj_at_addr(which), str);
}
}
// For temporary use while constructing constant pool
void string_index_at_put(int which, int string_index) {
tag_at_put(which, JVM_CONSTANT_StringIndex);
@ -228,7 +238,8 @@ class constantPoolOopDesc : public oopDesc {
tag.is_unresolved_klass() ||
tag.is_symbol() ||
tag.is_unresolved_string() ||
tag.is_string();
tag.is_string() ||
tag.is_object();
}
// Fetching constants
@ -291,6 +302,11 @@ class constantPoolOopDesc : public oopDesc {
return string_at_impl(h_this, which, CHECK_NULL);
}
oop object_at(int which) {
assert(tag_at(which).is_object(), "Corrupted constant pool");
return *obj_at_addr(which);
}
// A "pseudo-string" is an non-string oop that has found is way into
// a String entry.
// Under AnonymousClasses this can happen if the user patches a live

View File

@ -1556,13 +1556,13 @@ void GenerateOopMap::interp1(BytecodeStream *itr) {
case Bytecodes::_getfield: do_field(true, false, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_putfield: do_field(false, false, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_invokevirtual:
case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_invokevirtual:
case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_invokedynamic: do_method(true, false, itr->get_index_int(), itr->bci()); break;
case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_newarray:
case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break;
case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break;
case Bytecodes::_newarray:
case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break;
case Bytecodes::_checkcast: do_checkcast(); break;
case Bytecodes::_arraylength:
case Bytecodes::_instanceof: pp(rCTS, vCTS); break;
@ -1830,12 +1830,8 @@ void GenerateOopMap::do_jsr(int targ_bci) {
void GenerateOopMap::do_ldc(int idx, int bci) {
constantPoolOop cp = method()->constants();
constantTag tag = cp->tag_at(idx);
CellTypeState cts = (tag.is_string() || tag.is_unresolved_string() ||
tag.is_klass() || tag.is_unresolved_klass())
? CellTypeState::make_line_ref(bci) : valCTS;
constantPoolOop cp = method()->constants();
CellTypeState cts = cp->is_pointer_entry(idx) ? CellTypeState::make_line_ref(bci) : valCTS;
ppush1(cts);
}

View File

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

View File

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

View File

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

View File

@ -456,12 +456,12 @@ objArrayHandle methodOopDesc::resolved_checked_exceptions_impl(methodOop this_oo
return objArrayHandle(THREAD, Universe::the_empty_class_klass_array());
} else {
methodHandle h_this(THREAD, this_oop);
objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::class_klass(), length, CHECK_(objArrayHandle()));
objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::Class_klass(), length, CHECK_(objArrayHandle()));
objArrayHandle mirrors (THREAD, m_oop);
for (int i = 0; i < length; i++) {
CheckedExceptionElement* table = h_this->checked_exceptions_start(); // recompute on each iteration, not gc safe
klassOop k = h_this->constants()->klass_at(table[i].class_cp_index, CHECK_(objArrayHandle()));
assert(Klass::cast(k)->is_subclass_of(SystemDictionary::throwable_klass()), "invalid exception class");
assert(Klass::cast(k)->is_subclass_of(SystemDictionary::Throwable_klass()), "invalid exception class");
mirrors->obj_at_put(i, Klass::cast(k)->java_mirror());
}
return mirrors;
@ -1032,8 +1032,8 @@ bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) {
// We are loading classes eagerly. If a ClassNotFoundException or
// a LinkageError was generated, be sure to ignore it.
if (HAS_PENDING_EXCEPTION) {
if (PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass()) ||
PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) {
if (PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass()) ||
PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
CLEAR_PENDING_EXCEPTION;
} else {
return false;

View File

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

View File

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

View File

@ -99,7 +99,7 @@ klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHand
}
} else {
// The element type is already Object. Object[] has direct super of Object.
super_klass = KlassHandle(THREAD, SystemDictionary::object_klass());
super_klass = KlassHandle(THREAD, SystemDictionary::Object_klass());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,11 @@
# include "incls/_precompiled.incl"
# include "incls/_symbolOop.cpp.incl"
// ------------------------------------------------------------------
// symbolOopDesc::equals
//
// Compares the symbol with a string of the given length.
bool symbolOopDesc::equals(const char* str, int len) const {
int l = utf8_length();
if (l != len) return false;
@ -36,6 +41,48 @@ bool symbolOopDesc::equals(const char* str, int len) const {
return true;
}
// ------------------------------------------------------------------
// symbolOopDesc::starts_with
//
// Tests if the symbol starts with the specified prefix of the given
// length.
bool symbolOopDesc::starts_with(const char* prefix, int len) const {
if (len > utf8_length()) return false;
while (len-- > 0) {
if (prefix[len] != (char) byte_at(len))
return false;
}
assert(len == -1, "we should be at the beginning");
return true;
}
// ------------------------------------------------------------------
// symbolOopDesc::index_of
//
// Finds if the given string is a substring of this symbol's utf8 bytes.
// Return -1 on failure. Otherwise return the first index where str occurs.
int symbolOopDesc::index_of_at(int i, const char* str, int len) const {
assert(i >= 0 && i <= utf8_length(), "oob");
if (len <= 0) return 0;
char first_char = str[0];
address bytes = (address) ((symbolOopDesc*)this)->base();
address limit = bytes + utf8_length() - len; // inclusive limit
address scan = bytes + i;
if (scan > limit)
return -1;
for (;;) {
scan = (address) memchr(scan, first_char, (limit + 1 - scan));
if (scan == NULL)
return -1; // not found
assert(scan >= bytes+i && scan <= limit, "scan oob");
if (memcmp(scan, str, len) == 0)
return (int)(scan - bytes);
}
}
char* symbolOopDesc::as_C_string(char* buf, int size) const {
if (size > 0) {
int len = MIN2(size - 1, utf8_length());

View File

@ -1,5 +1,5 @@
/*
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -70,8 +70,21 @@ class symbolOopDesc : public oopDesc {
void set_utf8_length(int len) { _length = len; }
// Compares the symbol with a string
// Compares the symbol with a string.
bool equals(const char* str, int len) const;
bool equals(const char* str) const { return equals(str, (int) strlen(str)); }
// Tests if the symbol starts with the given prefix.
bool starts_with(const char* prefix, int len) const;
bool starts_with(const char* prefix) const {
return starts_with(prefix, (int) strlen(prefix));
}
// Tests if the symbol starts with the given prefix.
int index_of_at(int i, const char* str, int len) const;
int index_of_at(int i, const char* str) const {
return index_of_at(i, str, (int) strlen(str));
}
// Three-way compare for sorting; returns -1/0/1 if receiver is </==/> than arg
// note that the ordering is not alfabetical

View File

@ -180,6 +180,10 @@ const char* InlineTree::shouldNotInline(ciMethod *callee_method, ciMethod* calle
return NULL;
}
// Always inline MethodHandle methods.
if (callee_method->is_method_handle_invoke())
return NULL;
// First check all inlining restrictions which are required for correctness
if (callee_method->is_abstract()) return "abstract method";
// note: we allow ik->is_abstract()
@ -322,14 +326,17 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call
// stricter than callee_holder->is_initialized()
ciBytecodeStream iter(caller_method);
iter.force_bci(caller_bci);
int index = iter.get_index_int();
if( !caller_method->is_klass_loaded(index, true) ) {
return false;
}
// Try to do constant pool resolution if running Xcomp
Bytecodes::Code call_bc = iter.cur_bc();
if( !caller_method->check_call(index, call_bc == Bytecodes::_invokestatic) ) {
return false;
// An invokedynamic instruction does not have a klass.
if (call_bc != Bytecodes::_invokedynamic) {
int index = iter.get_index_int();
if (!caller_method->is_klass_loaded(index, true)) {
return false;
}
// Try to do constant pool resolution if running Xcomp
if( !caller_method->check_call(index, call_bc == Bytecodes::_invokestatic) ) {
return false;
}
}
}
// We will attempt to see if a class/field/etc got properly loaded. If it

View File

@ -1,5 +1,5 @@
/*
* Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -136,6 +136,8 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) {
}
// Mark the call node as virtual, sort of:
call->set_optimized_virtual(true);
if (method()->is_method_handle_invoke())
call->set_method_handle_invoke(true);
}
kit.set_arguments_for_java_call(call);
kit.set_edges_for_java_call(call, false, _separate_io_proj);
@ -145,6 +147,71 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) {
return kit.transfer_exceptions_into_jvms();
}
//---------------------------DynamicCallGenerator-----------------------------
// Internal class which handles all out-of-line invokedynamic calls.
class DynamicCallGenerator : public CallGenerator {
public:
DynamicCallGenerator(ciMethod* method)
: CallGenerator(method)
{
}
virtual JVMState* generate(JVMState* jvms);
};
JVMState* DynamicCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
if (kit.C->log() != NULL) {
kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci());
}
// Get the constant pool cache from the caller class.
ciMethod* caller_method = jvms->method();
ciBytecodeStream str(caller_method);
str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!");
ciCPCache* cpcache = str.get_cpcache();
// Get the offset of the CallSite from the constant pool cache
// pointer.
int index = str.get_method_index();
size_t call_site_offset = cpcache->get_f1_offset(index);
// Load the CallSite object from the constant pool cache.
const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
Node* cpcache_adr = kit.makecon(cpcache_ptr);
Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
// Load the target MethodHandle from the CallSite object.
Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT);
address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub();
CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci());
// invokedynamic is treated as an optimized invokevirtual.
call->set_optimized_virtual(true);
// Take extra care (in the presence of argument motion) not to trash the SP:
call->set_method_handle_invoke(true);
// Pass the target MethodHandle as first argument and shift the
// other arguments.
call->init_req(0 + TypeFunc::Parms, target_mh);
uint nargs = call->method()->arg_size();
for (uint i = 1; i < nargs; i++) {
Node* arg = kit.argument(i - 1);
call->init_req(i + TypeFunc::Parms, arg);
}
kit.set_edges_for_java_call(call);
Node* ret = kit.set_results_for_java_call(call);
kit.push_node(method()->return_type()->basic_type(), ret);
return kit.transfer_exceptions_into_jvms();
}
//--------------------------VirtualCallGenerator------------------------------
// Internal class which handles all out-of-line calls checking receiver type.
class VirtualCallGenerator : public CallGenerator {
private:
int _vtable_index;
@ -159,8 +226,6 @@ public:
virtual JVMState* generate(JVMState* jvms);
};
//--------------------------VirtualCallGenerator------------------------------
// Internal class which handles all out-of-line calls checking receiver type.
JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
Node* receiver = kit.argument(0);
@ -253,8 +318,14 @@ CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj
return new DirectCallGenerator(m, separate_io_proj);
}
CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) {
assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch");
return new DynamicCallGenerator(m);
}
CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
assert(!m->is_static(), "for_virtual_call mismatch");
assert(!m->is_method_handle_invoke(), "should be a direct call");
return new VirtualCallGenerator(m, vtable_index);
}
@ -576,6 +647,155 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
}
//------------------------PredictedDynamicCallGenerator-----------------------
// Internal class which handles all out-of-line calls checking receiver type.
class PredictedDynamicCallGenerator : public CallGenerator {
ciMethodHandle* _predicted_method_handle;
CallGenerator* _if_missed;
CallGenerator* _if_hit;
float _hit_prob;
public:
PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle,
CallGenerator* if_missed,
CallGenerator* if_hit,
float hit_prob)
: CallGenerator(if_missed->method()),
_predicted_method_handle(predicted_method_handle),
_if_missed(if_missed),
_if_hit(if_hit),
_hit_prob(hit_prob)
{}
virtual bool is_inline() const { return _if_hit->is_inline(); }
virtual bool is_deferred() const { return _if_hit->is_deferred(); }
virtual JVMState* generate(JVMState* jvms);
};
CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
CallGenerator* if_missed,
CallGenerator* if_hit,
float hit_prob) {
return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob);
}
JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
PhaseGVN& gvn = kit.gvn();
CompileLog* log = kit.C->log();
if (log != NULL) {
log->elem("predicted_dynamic_call bci='%d'", jvms->bci());
}
// Get the constant pool cache from the caller class.
ciMethod* caller_method = jvms->method();
ciBytecodeStream str(caller_method);
str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
ciCPCache* cpcache = str.get_cpcache();
// Get the offset of the CallSite from the constant pool cache
// pointer.
int index = str.get_method_index();
size_t call_site_offset = cpcache->get_f1_offset(index);
// Load the CallSite object from the constant pool cache.
const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
Node* cpcache_adr = kit.makecon(cpcache_ptr);
Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
// Load the target MethodHandle from the CallSite object.
Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT);
// Check if the MethodHandle is still the same.
const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true);
Node* predicted_mh = kit.makecon(predicted_mh_ptr);
Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh));
Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN);
kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff)));
Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff));
SafePointNode* slow_map = NULL;
JVMState* slow_jvms;
{ PreserveJVMState pjvms(&kit);
kit.set_control(slow_ctl);
if (!kit.stopped()) {
slow_jvms = _if_missed->generate(kit.sync_jvms());
assert(slow_jvms != NULL, "miss path must not fail to generate");
kit.add_exception_states_from(slow_jvms);
kit.set_map(slow_jvms->map());
if (!kit.stopped())
slow_map = kit.stop();
}
}
if (kit.stopped()) {
// Instance exactly does not matches the desired type.
kit.set_jvms(slow_jvms);
return kit.transfer_exceptions_into_jvms();
}
// Make the hot call:
JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
if (new_jvms == NULL) {
// Inline failed, so make a direct call.
assert(_if_hit->is_inline(), "must have been a failed inline");
CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
new_jvms = cg->generate(kit.sync_jvms());
}
kit.add_exception_states_from(new_jvms);
kit.set_jvms(new_jvms);
// Need to merge slow and fast?
if (slow_map == NULL) {
// The fast path is the only path remaining.
return kit.transfer_exceptions_into_jvms();
}
if (kit.stopped()) {
// Inlined method threw an exception, so it's just the slow path after all.
kit.set_jvms(slow_jvms);
return kit.transfer_exceptions_into_jvms();
}
// Finish the diamond.
kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
RegionNode* region = new (kit.C, 3) RegionNode(3);
region->init_req(1, kit.control());
region->init_req(2, slow_map->control());
kit.set_control(gvn.transform(region));
Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
iophi->set_req(2, slow_map->i_o());
kit.set_i_o(gvn.transform(iophi));
kit.merge_memory(slow_map->merged_memory(), region, 2);
uint tos = kit.jvms()->stkoff() + kit.sp();
uint limit = slow_map->req();
for (uint i = TypeFunc::Parms; i < limit; i++) {
// Skip unused stack slots; fast forward to monoff();
if (i == tos) {
i = kit.jvms()->monoff();
if( i >= limit ) break;
}
Node* m = kit.map()->in(i);
Node* n = slow_map->in(i);
if (m != n) {
const Type* t = gvn.type(m)->meet(gvn.type(n));
Node* phi = PhiNode::make(region, m, t);
phi->set_req(2, n);
kit.map()->set_req(i, gvn.transform(phi));
}
}
return kit.transfer_exceptions_into_jvms();
}
//-------------------------UncommonTrapCallGenerator-----------------------------
// Internal class which handles all out-of-line calls checking receiver type.
class UncommonTrapCallGenerator : public CallGenerator {

View File

@ -100,6 +100,7 @@ class CallGenerator : public ResourceObj {
// How to generate vanilla out-of-line call sites:
static CallGenerator* for_direct_call(ciMethod* m, bool separate_io_projs = false); // static, special
static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic
static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface
// How to generate a replace a direct call with an inline version
@ -116,6 +117,12 @@ class CallGenerator : public ResourceObj {
CallGenerator* if_hit,
float hit_prob);
// How to make a call that optimistically assumes a MethodHandle target:
static CallGenerator* for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
CallGenerator* if_missed,
CallGenerator* if_hit,
float hit_prob);
// How to make a call that gives up and goes back to the interpreter:
static CallGenerator* for_uncommon_trap(ciMethod* m,
Deoptimization::DeoptReason reason,

View File

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

View File

@ -224,6 +224,57 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
}
}
// Do MethodHandle calls.
if (call_method->is_method_handle_invoke()) {
if (jvms->method()->java_code_at_bci(jvms->bci()) != Bytecodes::_invokedynamic) {
GraphKit kit(jvms);
Node* n = kit.argument(0);
if (n->Opcode() == Op_ConP) {
const TypeOopPtr* oop_ptr = n->bottom_type()->is_oopptr();
ciObject* const_oop = oop_ptr->const_oop();
ciMethodHandle* method_handle = const_oop->as_method_handle();
// Set the actually called method to have access to the class
// and signature in the MethodHandleCompiler.
method_handle->set_callee(call_method);
// Get an adapter for the MethodHandle.
ciMethod* target_method = method_handle->get_method_handle_adapter();
CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
if (hit_cg != NULL && hit_cg->is_inline())
return hit_cg;
}
return CallGenerator::for_direct_call(call_method);
}
else {
// Get the MethodHandle from the CallSite.
ciMethod* caller_method = jvms->method();
ciBytecodeStream str(caller_method);
str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
ciCallSite* call_site = str.get_call_site();
ciMethodHandle* method_handle = call_site->get_target();
// Set the actually called method to have access to the class
// and signature in the MethodHandleCompiler.
method_handle->set_callee(call_method);
// Get an adapter for the MethodHandle.
ciMethod* target_method = method_handle->get_invokedynamic_adapter();
CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
if (hit_cg != NULL && hit_cg->is_inline()) {
CallGenerator* miss_cg = CallGenerator::for_dynamic_call(call_method);
return CallGenerator::for_predicted_dynamic_call(method_handle, miss_cg, hit_cg, prof_factor);
}
// If something failed, generate a normal dynamic call.
return CallGenerator::for_dynamic_call(call_method);
}
}
// There was no special inlining tactic, or it bailed out.
// Use a more generic tactic, like a simple call.
if (call_is_virtual) {
@ -299,7 +350,7 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl
// Interface classes can be loaded & linked and never get around to
// being initialized. Uncommon-trap for not-initialized static or
// v-calls. Let interface calls happen.
ciInstanceKlass* holder_klass = dest_method->holder();
ciInstanceKlass* holder_klass = dest_method->holder();
if (!holder_klass->is_initialized() &&
!holder_klass->is_interface()) {
uncommon_trap(Deoptimization::Reason_uninitialized,
@ -307,14 +358,6 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl
holder_klass);
return true;
}
if (dest_method->is_method_handle_invoke()
&& holder_klass->name() == ciSymbol::java_dyn_Dynamic()) {
// FIXME: NYI
uncommon_trap(Deoptimization::Reason_unhandled,
Deoptimization::Action_none,
holder_klass);
return true;
}
assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility");
return false;
@ -333,6 +376,7 @@ void Parse::do_call() {
bool is_virtual = bc() == Bytecodes::_invokevirtual;
bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface;
bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial;
bool is_invokedynamic = bc() == Bytecodes::_invokedynamic;
// Find target being called
bool will_link;
@ -341,7 +385,8 @@ void Parse::do_call() {
ciKlass* holder = iter().get_declared_method_holder();
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
int nargs = dest_method->arg_size();
int nargs = dest_method->arg_size();
if (is_invokedynamic) nargs -= 1;
// uncommon-trap when callee is unloaded, uninitialized or will not link
// bailout when too many arguments for register representation
@ -355,7 +400,7 @@ void Parse::do_call() {
return;
}
assert(holder_klass->is_loaded(), "");
assert(dest_method->is_static() == !has_receiver, "must match bc");
assert((dest_method->is_static() || is_invokedynamic) == !has_receiver , "must match bc");
// Note: this takes into account invokeinterface of methods declared in java/lang/Object,
// which should be invokevirtuals but according to the VM spec may be invokeinterfaces
assert(holder_klass->is_interface() || holder_klass->super() == NULL || (bc() != Bytecodes::_invokeinterface), "must match bc");

View File

@ -1916,7 +1916,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
Node *arg = call->in(i)->uncast();
if (at->isa_oopptr() != NULL &&
ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) {
ptnode_adr(arg->_idx)->escape_state() < PointsToNode::GlobalEscape) {
bool global_escapes = false;
bool fields_escapes = false;

View File

@ -981,14 +981,19 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth) {
case Bytecodes::_invokedynamic:
case Bytecodes::_invokeinterface:
{
bool is_static = (depth == 0);
bool ignore;
ciBytecodeStream iter(method());
iter.reset_to_bci(bci());
iter.next();
ciMethod* method = iter.get_method(ignore);
inputs = method->arg_size_no_receiver();
if (!is_static) inputs += 1;
// Add a receiver argument, maybe:
if (code != Bytecodes::_invokestatic &&
code != Bytecodes::_invokedynamic)
inputs += 1;
// (Do not use ciMethod::arg_size(), because
// it might be an unloaded method, which doesn't
// know whether it is static or not.)
int size = method->return_type()->size();
depth = size - inputs;
}

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