void ObjArrayKlass::oop_oop_iterate_elements_specialized(objArrayOop a, OopClosureType* closure) { T* p = (T*)a->base(); T* const end = p + a->length(); for (;p < end; p++) { Devirtualizer<nv>::do_oop(closure, p); } }
static objArrayOop extend(objArrayOop old_pic) { int old_size = old_pic->length()/2; if (old_size >= size_of_largest_interpreterPIC) return NULL; objArrayOop result = allocate(old_size + 1); for (int index = 1; index <= old_size*2; index++) { result->obj_at_put(index, old_pic->obj_at(index)); } return result; }
// this function computes the vtable size (including the size needed for miranda // methods) and the number of miranda methods in this class // Note on Miranda methods: Let's say there is a class C that implements // interface I. Let's say there is a method m in I that neither C nor any // of its super classes implement (i.e there is no method of any access, with // the same name and signature as m), then m is a Miranda method which is // entered as a public abstract method in C's vtable. From then on it should // treated as any other public method in C for method over-ride purposes. void klassVtable::compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods, klassOop super, objArrayOop methods, AccessFlags class_flags, Handle classloader, Symbol* classname, objArrayOop local_interfaces, TRAPS ) { No_Safepoint_Verifier nsv; // set up default result values vtable_length = 0; num_miranda_methods = 0; // start off with super's vtable length instanceKlass* sk = (instanceKlass*)super->klass_part(); vtable_length = super == NULL ? 0 : sk->vtable_length(); // go thru each method in the methods table to see if it needs a new entry int len = methods->length(); for (int i = 0; i < len; i++) { assert(methods->obj_at(i)->is_method(), "must be a methodOop"); methodHandle mh(THREAD, methodOop(methods->obj_at(i))); if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, THREAD)) { vtable_length += vtableEntry::size(); // we need a new entry } } // compute the number of mirandas methods that must be added to the end num_miranda_methods = get_num_mirandas(super, methods, local_interfaces); vtable_length += (num_miranda_methods * vtableEntry::size()); if (Universe::is_bootstrapping() && vtable_length == 0) { // array classes don't have their superclass set correctly during // bootstrapping vtable_length = Universe::base_vtable_size(); } if (super == NULL && !Universe::is_bootstrapping() && vtable_length != Universe::base_vtable_size()) { // Someone is attempting to redefine java.lang.Object incorrectly. The // only way this should happen is from // SystemDictionary::resolve_from_stream(), which will detect this later // and throw a security exception. So don't assert here to let // the exception occur. vtable_length = Universe::base_vtable_size(); } assert(super != NULL || vtable_length == Universe::base_vtable_size(), "bad vtable size for class Object"); assert(vtable_length % vtableEntry::size() == 0, "bad vtable length"); assert(vtable_length >= Universe::base_vtable_size(), "vtable too small"); }
void flush_method_JNIid_cache() { for (int i = 0; i < _old_methods->length(); i++) { methodOop mop = (methodOop)_old_methods->obj_at(i); JNIid *mid = mop->jni_id(); if (mid != NULL) { // don't need to call JNIid::lock() since we are at a safepoint mid->set_resolved_method((methodOop)NULL, (klassOop)NULL); } } }
void ObjArrayKlass::oop_oop_iterate_range_specialized(objArrayOop a, OopClosureType* closure, int start, int end) { if (Devirtualizer<nv>::do_metadata(closure)) { Devirtualizer<nv>::do_klass(closure, a->klass()); } T* low = start == 0 ? cast_from_oop<T*>(a) : a->obj_at_addr<T>(start); T* high = (T*)a->base() + end; oop_oop_iterate_elements_specialized_bounded<nv, T>(a, closure, low, high); }
void check_methods_and_mark_as_old() { for (int i = 0; i < _old_methods->length(); i++) { methodOop old_method = (methodOop) _old_methods->obj_at(i); old_method->set_old_version(); if (jvmdi::enabled()) { methodOop new_method = (methodOop) _new_methods->obj_at(i); if (!MethodComparator::methods_EMCP(old_method, new_method)) { // Mark non-EMCP methods as such old_method->set_non_emcp_with_new_version(); } } } }
void constantPoolCacheOopDesc::adjust_method_entries(objArrayOop old_methods, objArrayOop new_methods) { for (int i = 0; i < old_methods->length(); i++) { methodOop old_method = (methodOop) old_methods->obj_at(i); if (! old_method->is_old_version()) continue; for (int j = 0; j < length(); j++) { if (entry_at(j)->is_method_entry()) { entry_at(j)->adjust_method_entry(old_method, (methodOop) new_methods->obj_at(i)); } } } }
extern "C" oop* setup_deoptimization_and_return_new_sp(oop* old_sp, int* old_fp, objArrayOop frame_array, int* current_frame) { ResourceMark rm; // Save all parameters for later use (check unpack_frame_array) ::old_sp = old_sp; ::old_fp = old_fp; ::frame_array = frame_array; ::cur_fp = current_frame; smiOop number_of_vframes = smiOop(frame_array->obj_at(StackChunkBuilder::number_of_vframes_index)); smiOop number_of_locals = smiOop(frame_array->obj_at(StackChunkBuilder::number_of_locals_index)); assert(number_of_vframes->is_smi(), "must be smi"); assert(number_of_locals->is_smi(), "must be smi"); new_sp = old_sp - frame::interpreter_stack_size(number_of_vframes->value(), number_of_locals->value()); return new_sp; }
inline void oop_pc_follow_contents_specialized(objArrayOop obj, int index, ParCompactionManager* cm) { const size_t len = size_t(obj->length()); const size_t beg_index = size_t(index); assert(beg_index < len || len == 0, "index too large"); const size_t stride = MIN2(len - beg_index, ObjArrayMarkingStride); const size_t end_index = beg_index + stride; T* const base = (T*)obj->base(); T* const beg = base + beg_index; T* const end = base + end_index; // Push the non-NULL elements of the next stride on the marking stack. for (T* e = beg; e < end; e++) { cm->mark_and_push<T>(e); } if (end_index < len) { cm->push_objarray(obj, end_index); // Push the continuation. } }
void ObjArrayKlass::oop_oop_iterate_elements_specialized_bounded( objArrayOop a, OopClosureType* closure, void* low, void* high) { T* const l = (T*)low; T* const h = (T*)high; T* p = (T*)a->base(); T* end = p + a->length(); if (p < l) { p = l; } if (end > h) { end = h; } for (;p < end; ++p) { Devirtualizer<nv>::do_oop(closure, p); } }
inline void trace_deoptimization_start() { if (TraceDeoptimization) { std->print("[Unpacking]"); if (nlr_through_unpacking) { std->print(" NLR %s", (nlr_home == (int) cur_fp) ? "inside" : "outside"); } std->cr(); std->print(" - array "); frame_array->print_value(); std->print_cr(" @ 0x%lx", old_fp); } }
inline size_t G1CMTask::scan_objArray(objArrayOop obj, MemRegion mr) { obj->oop_iterate(_cm_oop_closure, mr); return mr.word_size(); }
// Called from assembler in unpack_unoptimized_frames. // Based on the statics (old_sp, old_fp, and frame_array) this function unpacks // the array into interpreter frames. // Returning from this function should activate the most recent deoptimized frame. extern "C" void unpack_frame_array() { BlockScavenge bs; ResourceMark rm; int* pc_addr = (int*) new_sp - 1; assert(*pc_addr = -1, "just checking"); if (TraceDeoptimization) { std->print("[Unpacking]"); if (nlr_through_unpacking) { std->print(" NLR %s", (nlr_home == (int) cur_fp) ? "inside" : "outside"); } std->cr(); std->print(" - array "); frame_array->print_value(); std->print_cr(" @ 0x%lx", old_fp); } bool must_find_nlr_target = nlr_through_unpacking && nlr_home == (int) cur_fp; bool nlr_target_found = false; // For verification // link for the current frame int* link_addr = (int*) new_sp - 2; oop* current_sp = new_sp; int pos = 3; int length = frame_array->length(); bool first = true; frame current; // unpack one frame at at time from most recent to least recent do { oop receiver = frame_array->obj_at(pos++); methodOop method = methodOop(frame_array->obj_at(pos++)); assert(method->is_method(), "expecting method"); smiOop bci_obj = smiOop(frame_array->obj_at(pos++)); assert(bci_obj->is_smi(), "expecting smi"); int bci = bci_obj->value(); smiOop locals_obj = smiOop(frame_array->obj_at(pos++)); assert(locals_obj->is_smi(), "expecting smi"); int locals = locals_obj->value(); current = frame(current_sp, (int*) current_sp + locals + 2); // fill in the locals for (int index = 0; index < locals; index++) { current.set_temp(index, frame_array->obj_at(pos++)); } CodeIterator c(method, bci); char* current_pc; if (first) { // first vframe in the array if (nlr_through_unpacking) { // NLR is comming through unpacked vframes current_pc = c.interpreter_return_point(); // current_pc points to a normal return point in the interpreter. // To find the nlr return point we first compute the nlr offset. current_pc = ic_info_at(current_pc)->NLR_target(); current.set_hp(c.next_hp()); } else if (redo_the_send) { // Deoptimizing uncommon trap current_pc = (char*) redo_bytecode_after_deoptimization; current.set_hp(c.next_hp()); redo_send_offset = c.next_hp() - c.hp(); redo_the_send = false; } else { // Normal case current_pc = c.interpreter_return_point(true); current.set_hp(c.next_hp()); if (c.is_message_send()) { number_of_arguments_through_unpacking = c.ic()->nof_arguments(); } else if (c.is_primitive_call()) { number_of_arguments_through_unpacking = c.prim_cache()->number_of_parameters(); } else if (c.is_dll_call()) { // The callee should not pop the argument since a DLL call is like a c function call. // The continuation code for the DLL call will pop the arguments! number_of_arguments_through_unpacking = 0; } } } else { current_pc = c.interpreter_return_point(); current.set_hp(c.next_hp()); } current.set_receiver(receiver); current.patch_pc(current_pc); current.patch_fp(current.fp()); // Revive the contexts if (!method->is_blockMethod() && method->activation_has_context()) { contextOop con = contextOop(current.temp(0)); assert(con->is_context(), "must be context"); oop frame_oop = oop(current.fp()); con->set_parent(frame_oop); if (nlr_through_unpacking && nlr_home == (int) cur_fp) { if (nlr_home_context == con) { // This frame is the target of the NLR // set nlr_home to frame pointer of current frame nlr_home = (int) current.fp(); // compute number of arguments to pop nlr_home_id = ~method->number_of_arguments(); nlr_target_found = true; // std->print("target frame for NLR (%d, 0x%lx):",method->number_of_arguments(), nlr_home_id); } } } if (TraceDeoptimization) { frame v(current_sp, current.fp(), current_pc); v.print_for_deoptimization(std); } first = false; // Next pc current_sp += frame::interpreter_frame_size(locals); } while (pos <= length); if (must_find_nlr_target && !nlr_target_found) { fatal("Target for NLR not found when unpacking frame"); } assert (current_sp == old_sp, "We have not reached the end"); current.set_link(old_fp); }
// Called from assembler in unpack_unoptimized_frames. // Based on the statics (old_sp, old_fp, and frame_array) this function unpacks // the array into interpreter frames. // Returning from this function should activate the most recent deoptimized frame. extern "C" void unpack_frame_array() { BlockScavenge bs; ResourceMark rm; int* pc_addr = (int*) new_sp - 1; assert(*pc_addr = -1, "just checking"); trace_deoptimization_start(); bool must_find_nlr_target = nlr_through_unpacking && nlr_home == (int) cur_fp; bool nlr_target_found = false; // For verification // link for the current frame int* link_addr = (int*) new_sp - 2; oop* current_sp = new_sp; int pos = 3; int length = frame_array->length(); bool first = true; frame current; // unpack one frame at at time from most recent to least recent do { oop receiver = frame_array->obj_at(pos++); methodOop method = methodOop(frame_array->obj_at(pos++)); assert(method->is_method(), "expecting method"); smiOop bci_obj = smiOop(frame_array->obj_at(pos++)); assert(bci_obj->is_smi(), "expecting smi"); int bci = bci_obj->value(); smiOop locals_obj = smiOop(frame_array->obj_at(pos++)); assert(locals_obj->is_smi(), "expecting smi"); int locals = locals_obj->value(); current = frame(current_sp, (int*) current_sp + locals + 2); // fill in the locals for (int index = 0; index < locals; index++) { current.set_temp(index, frame_array->obj_at(pos++)); } CodeIterator c(method, bci); char* current_pc; if (first) { unpack_first_frame(current_pc, current, c); } else { current_pc = c.interpreter_return_point(); current.set_hp(c.next_hp()); } current.set_receiver(receiver); current.patch_pc(current_pc); current.patch_fp(current.fp()); // Revive the contexts if (!method->is_blockMethod() && method->activation_has_context()) { contextOop con = contextOop(current.temp(0)); assert(con->is_context(), "must be context"); oop frame_oop = oop(current.fp()); con->set_parent(frame_oop); if (nlr_through_unpacking && nlr_home == (int) cur_fp) { if (nlr_home_context == con) { // This frame is the target of the NLR // set nlr_home to frame pointer of current frame nlr_home = (int) current.fp(); // compute number of arguments to pop nlr_home_id = ~method->number_of_arguments(); nlr_target_found = true; // std->print("target frame for NLR (%d, 0x%lx):",method->number_of_arguments(), nlr_home_id); } } } trace_deoptimization_frame(current, current_sp, current_pc); first = false; // Next pc current_sp += frame::interpreter_frame_size(locals); } while (pos <= length); if (must_find_nlr_target && !nlr_target_found) { fatal("Target for NLR not found when unpacking frame"); } assert (current_sp == old_sp, "We have not reached the end"); current.set_link(old_fp); }
void ObjArrayKlass::oop_oop_iterate_range_specialized(objArrayOop a, OopClosureType* closure, int start, int end) { T* low = start == 0 ? cast_from_oop<T*>(a) : a->obj_at_addr<T>(start); T* high = (T*)a->base() + end; oop_oop_iterate_elements_specialized_bounded<nv, T>(a, closure, low, high); }
static void deallocate(objArrayOop pic) { int entry = (pic->length()/2) - 1; oop first = free_list()->obj_at(entry); pic->obj_at_put(1, first); free_list()->obj_at_put(entry, pic); }
static void set_first(objArrayOop pic, oop first, oop second) { pic->obj_at_put(1, first); pic->obj_at_put(2, second); }
static void set_last(objArrayOop pic, oop first, oop second) { int size = pic->length(); pic->obj_at_put(size--, second); pic->obj_at_put(size, first); }
static void set_second(objArrayOop pic, oop first, oop second) { pic->obj_at_put(3, first); pic->obj_at_put(4, second); }