void mixinOopDesc::customize_for(klassOop klass) { objArrayOop array = methods(); for (int index = 1; index <= array->length(); index++) { methodOop m = methodOop(array->obj_at(index)); m->customize_for(klass, this); } }
void mixinOopDesc::uncustomize_methods() { objArrayOop array = methods(); for (int index = 1; index <= array->length(); index++) { methodOop m = methodOop(array->obj_at(index)); m->uncustomize_for(this); } }
// size is the new size of the instruction at bci. Hence, if size is less than the current // instruction sice, we will shrink the code. methodHandle Relocator::insert_space_at(int bci, int size, u_char inst_buffer[], TRAPS) { _changes = new GrowableArray<ChangeItem*> (10); _changes->push(new ChangeWiden(bci, size, inst_buffer)); if (TraceRelocator) { tty->print_cr("Space at: %d Size: %d", bci, size); _method->print(); _method->print_codes(); tty->print_cr("-------------------------------------------------"); } if (!handle_code_changes()) return methodOop(NULL); // Construct the new method methodHandle new_method = methodOopDesc::clone_with_new_data(method(), code_array(), code_length(), compressed_line_number_table(), compressed_line_number_table_size(), CHECK_(methodOop(NULL))); set_method(new_method); if (TraceRelocator) { tty->print_cr("-------------------------------------------------"); tty->print_cr("new method"); _method->print_codes(); } return new_method; }
SimpleScopeDesc(nmethod* code,address pc) { PcDesc* pc_desc = code->pc_desc_at(pc); assert(pc_desc != NULL, "Must be able to find matching PcDesc"); DebugInfoReadStream buffer(code, pc_desc->scope_decode_offset()); int ignore_sender = buffer.read_int(); _method = methodOop(buffer.read_oop()); _bci = buffer.read_bci(); }
SimpleScopeDesc(nmethod* code,address pc,bool at_call) { PcDesc* pc_desc = code->pc_desc_at(pc, at_call); assert(pc_desc != NULL, "Must be able to find matching PcDesc"); u_char* buffer = code->scopes_data_begin() + pc_desc->scope_decode_offset(); CompressedReadStream::raw_read_int(buffer); _method = methodOop(code->oop_at(CompressedReadStream::raw_read_int(buffer))); _bci = CompressedReadStream::raw_read_int(buffer); }
bool mixinOopDesc::includes_method(methodOop method) { objArrayOop array = methods(); for (int index = 1; index <= array->length(); index++) { methodOop m = methodOop(array->obj_at(index)); if (m == method) return true; } return false; }
// 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 vframeStream::fill_from_compiled_frame(nmethod* code, int decode_offset) { _mode = compiled_mode; _code = code; // Decode first part of scopeDesc u_char* buffer = code->scopes_data_begin() + decode_offset; _sender_decode_offset = CompressedReadStream::raw_read_int(buffer); _method = methodOop(_code->oop_at(CompressedReadStream::raw_read_int(buffer))); _bci = CompressedReadStream::raw_read_int(buffer); assert(_method->is_method(), "checking type of decoded method"); }
methodOop frame::method() const { assert(is_interpreted_frame(), "must be interpreter frame"); // First we will check the interpreter frame is valid by checking the frame size. // The interpreter guarantees hp is valid if the frame is at least 4 in size. // (return address, link, receiver, hcode pointer) if (frame_size() < minimum_size_for_deoptimized_frame) return NULL; u_char* h = hp(); if (!Universe::old_gen.contains(h)) return NULL; memOop obj = as_memOop(Universe::object_start((oop*) h)); return obj->is_method() ? methodOop(obj) : NULL; }
symbolOop InterpretedIC::selector() const { oop fw = first_word(); if (fw->is_symbol()) { return symbolOop(fw); } else if (fw->is_method()) { return methodOop(fw)->selector(); } else { jumpTableEntry* e = jump_table_entry(); nmethod* nm = e->method(); assert(nm != NULL, "must have an nmethod"); return nm->key.selector(); } }
void pp(void* p) { Command c("pp"); FlagSetting fl(PrintVMMessages, true); if (p == NULL) { lprintf("0x0"); return; } if (Universe::is_heap((oop*) p)) { memOop obj = as_memOop(Universe::object_start((oop*) p)); obj->print(); if (obj->is_method()) { int bci = methodOop(obj)->bci_from((u_char*) p); prettyPrinter::print(methodOop(obj), NULL, bci); } return; } if (oop(p)->is_smi() || oop(p)->is_mark()) { oop(p)->print(); return; } }
methodOop ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) { if (is_secondary_entry()) { if (!is_f1_null()) return f2_as_vfinal_method(); return NULL; } // Decode the action of set_method and set_interface_call Bytecodes::Code invoke_code = bytecode_1(); if (invoke_code != (Bytecodes::Code)0) { oop f1 = _f1; if (f1 != NULL) { switch (invoke_code) { case Bytecodes::_invokeinterface: assert(f1->is_klass(), ""); return klassItable::method_for_itable_index(klassOop(f1), f2_as_index()); case Bytecodes::_invokestatic: case Bytecodes::_invokespecial: assert(!has_appendix(), ""); assert(f1->is_method(), ""); return methodOop(f1); } } } invoke_code = bytecode_2(); if (invoke_code != (Bytecodes::Code)0) { switch (invoke_code) { case Bytecodes::_invokevirtual: if (is_vfinal()) { // invokevirtual methodOop m = f2_as_vfinal_method(); assert(m->is_method(), ""); return m; } else { int holder_index = cpool->uncached_klass_ref_index_at(constant_pool_index()); if (cpool->tag_at(holder_index).is_klass()) { klassOop klass = cpool->resolved_klass_at(holder_index); if (!Klass::cast(klass)->oop_is_instance()) klass = SystemDictionary::Object_klass(); return instanceKlass::cast(klass)->method_at_vtable(f2_as_index()); } } break; case Bytecodes::_invokehandle: case Bytecodes::_invokedynamic: return f2_as_vfinal_method(); } } return NULL; }
void do_object(oop obj) { if (obj->is_klass() && obj->blueprint()->oop_is_instanceKlass()) { instanceKlass* ik = instanceKlass::cast((klassOop)obj); int i; mark_and_move_for_policy(OP_favor_startup, ik->name(), _move_ro); if (ik->super() != NULL) { do_object(ik->super()); } objArrayOop interfaces = ik->local_interfaces(); mark_and_move_for_policy(OP_favor_startup, interfaces, _move_ro); for(i = 0; i < interfaces->length(); i++) { klassOop k = klassOop(interfaces->obj_at(i)); mark_and_move_for_policy(OP_favor_startup, k->klass_part()->name(), _move_ro); do_object(k); } objArrayOop methods = ik->methods(); for(i = 0; i < methods->length(); i++) { methodOop m = methodOop(methods->obj_at(i)); mark_and_move_for_policy(OP_favor_startup, m->constMethod(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->exception_table(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->stackmap_data(), _move_ro); // We don't move the name symbolOop here because it may invalidate // method ordering, which is dependent on the address of the name // symbolOop. It will get promoted later with the other symbols. // Method name is rarely accessed during classloading anyway. // mark_and_move_for_policy(OP_balanced, m->name(), _move_ro); mark_and_move_for_policy(OP_favor_startup, m->signature(), _move_ro); } mark_and_move_for_policy(OP_favor_startup, ik->transitive_interfaces(), _move_ro); mark_and_move_for_policy(OP_favor_startup, ik->fields(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, ik->secondary_supers(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, ik->method_ordering(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, ik->class_annotations(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, ik->fields_annotations(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, ik->methods_annotations(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, ik->methods_parameter_annotations(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, ik->methods_default_annotations(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, ik->inner_classes(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, ik->secondary_supers(), _move_ro); } }
void mixinOopDesc::add_method(methodOop method) { objArrayOop old_array = methods(); symbolOop selector = method->selector(); // Find out if a method with the same selector exists. for (int index = 1; index <= old_array->length(); index++) { assert(old_array->obj_at(index)->is_method(), "must be method"); methodOop m = methodOop(old_array->obj_at(index)); if (m->selector() == selector) { objArrayOop new_array = old_array->copy(); new_array->obj_at_put(index, method); set_methods(new_array); return; } } // Extend the array set_methods(old_array->copy_add(method)); }
void do_object(oop obj) { // Mark symbols refered to by method objects. if (obj->is_method()) { methodOop m = methodOop(obj); mark_object(m->name()); mark_object(m->signature()); } // Mark symbols referenced by klass objects which are read-only. else if (obj->is_klass()) { if (obj->blueprint()->oop_is_instanceKlass()) { instanceKlass* ik = instanceKlass::cast((klassOop)obj); mark_object(ik->name()); mark_object(ik->generic_signature()); mark_object(ik->source_file_name()); mark_object(ik->source_debug_extension()); typeArrayOop inner_classes = ik->inner_classes(); if (inner_classes != NULL) { int length = inner_classes->length(); for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) { int ioff = i + instanceKlass::inner_class_inner_name_offset; int index = inner_classes->ushort_at(ioff); if (index != 0) { mark_object(ik->constants()->symbol_at(index)); } } } ik->field_names_and_sigs_iterate(&mark_all); } } // Mark symbols referenced by other constantpool entries. if (obj->is_constantPool()) { constantPoolOop(obj)->shared_symbols_iterate(&mark_all); } }
void do_object(oop obj) { if (obj->is_klass() && obj->blueprint()->oop_is_instanceKlass()) { instanceKlass* ik = instanceKlass::cast((klassOop)obj); int i; mark_and_move_for_policy(OP_favor_startup, ik->as_klassOop(), _move_rw); if (ik->super() != NULL) { do_object(ik->super()); } objArrayOop interfaces = ik->local_interfaces(); for(i = 0; i < interfaces->length(); i++) { klassOop k = klassOop(interfaces->obj_at(i)); mark_and_move_for_policy(OP_favor_startup, k, _move_rw); do_object(k); } objArrayOop methods = ik->methods(); mark_and_move_for_policy(OP_favor_startup, methods, _move_rw); for(i = 0; i < methods->length(); i++) { methodOop m = methodOop(methods->obj_at(i)); mark_and_move_for_policy(OP_favor_startup, m, _move_rw); mark_and_move_for_policy(OP_favor_startup, ik->constants(), _move_rw); // idempotent mark_and_move_for_policy(OP_balanced, ik->constants()->cache(), _move_rw); // idempotent mark_and_move_for_policy(OP_balanced, ik->constants()->tags(), _move_rw); // idempotent } mark_and_move_for_policy(OP_favor_startup, ik->as_klassOop()->klass(), _move_rw); mark_and_move_for_policy(OP_favor_startup, ik->constants()->klass(), _move_rw); // Although Java mirrors are marked in MarkReadWriteObjects, // apparently they were never moved into shared spaces since // MoveMarkedObjects skips marked instance oops. This may // be a bug in the original implementation or simply the vestige // of an abandoned experiment. Nevertheless we leave a hint // here in case this capability is ever correctly implemented. // // mark_and_move_for_policy(OP_favor_runtime, ik->java_mirror(), _move_rw); } }
inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) { _mode = compiled_mode; // Range check to detect ridiculous offsets. if (decode_offset == DebugInformationRecorder::serialized_null || decode_offset < 0 || decode_offset >= nm()->scopes_data_size()) { // 6379830 AsyncGetCallTrace sometimes feeds us wild frames. // If we attempt to read nmethod::scopes_data at serialized_null (== 0), // or if we read some at other crazy offset, // we will decode garbage and make wild references into the heap, // leading to crashes in product mode. // (This isn't airtight, of course, since there are internal // offsets which are also crazy.) #ifdef ASSERT if (WizardMode) { tty->print_cr("Error in fill_from_frame: pc_desc for " INTPTR_FORMAT " not found or invalid at %d", _frame.pc(), decode_offset); nm()->print(); nm()->method()->print_codes(); nm()->print_code(); nm()->print_pcs(); } #endif // Provide a cheap fallback in product mode. (See comment above.) found_bad_method_frame(); fill_from_compiled_native_frame(); return; } // Decode first part of scopeDesc DebugInfoReadStream buffer(nm(), decode_offset); _sender_decode_offset = buffer.read_int(); _method = methodOop(buffer.read_oop()); _bci = buffer.read_bci(); assert(_method->is_method(), "checking type of decoded method"); }
bool frame::follow_roots_interpreted_float_frame() { methodOop m = methodOop(hp()); assert(m->is_method(), "must be method"); // Return if this activation has no floats (the marker is conservative) if (!m->has_float_temporaries()) return false; // Iterator from stack pointer to end of float section oop* end = (oop*) addr_at(m->float_section_start_offset() - m->float_section_size()); for (oop* p = sp(); p <= end; p++) { MarkSweep::follow_root(p); } // Skip the float section and magic_value // Iterate from just before the float section to the first temp for (oop* q = (oop*) addr_at(m->float_section_start_offset() + 2); q <= temp_addr(0); q++) { MarkSweep::follow_root(q); } // The receiver MarkSweep::follow_root(receiver_addr()); return true; }
int oop_size(oop obj) const { return object_size(methodOop(obj)->size_of_codes()); }
methodOop method() const { assert(selector_or_method()->is_method(), "Wrong lookup type"); return methodOop(selector_or_method()); }
bool is_block_type() const { return selector_or_method()->is_method() && methodOop(selector_or_method())->is_blockMethod(); }
methodOop mixinOopDesc::method_at(int index) const { return methodOop(methods()->obj_at(index)); }
void instanceKlassKlass::oop_verify_on(oop obj, outputStream* st) { klassKlass::oop_verify_on(obj, st); if (!obj->partially_loaded()) { Thread *thread = Thread::current(); instanceKlass* ik = instanceKlass::cast(klassOop(obj)); // Avoid redundant verifies if (ik->_verify_count == Universe::verify_count()) return; ik->_verify_count = Universe::verify_count(); // Verify that klass is present in SystemDictionary if (ik->is_loaded()) { symbolHandle h_name (thread, ik->name()); Handle h_loader (thread, ik->class_loader()); SystemDictionary::verify_obj_klass_present(obj, h_name, h_loader); } // Verify static fields VerifyFieldClosure blk; ik->iterate_static_fields(&blk); // Verify vtables if (ik->is_linked()) { ResourceMark rm(thread); // $$$ This used to be done only for m/s collections. Doing it // always seemed a valid generalization. (DLD -- 6/00) ik->vtable()->verify(st); } // Verify oop map cache if (ik->oop_map_cache() != NULL) { ik->oop_map_cache()->verify(); } // Verify first subklass if (ik->subklass_oop() != NULL) { guarantee(ik->subklass_oop()->is_perm(), "should be in permspace"); guarantee(ik->subklass_oop()->is_klass(), "should be klass"); } // Verify siblings klassOop super = ik->super(); Klass* sib = ik->next_sibling(); int sib_count = 0; while (sib != NULL) { if (sib == ik) { fatal1("subclass cycle of length %d", sib_count); } if (sib_count >= 100000) { fatal1("suspiciously long subclass list %d", sib_count); } guarantee(sib->as_klassOop()->is_klass(), "should be klass"); guarantee(sib->as_klassOop()->is_perm(), "should be in permspace"); guarantee(sib->super() == super, "siblings should have same superklass"); sib = sib->next_sibling(); } // Verify implementor field if (ik->implementor() != NULL) { guarantee(ik->is_interface(), "only interfaces should have implementor set"); guarantee(ik->nof_implementors() == 1, "should only have one implementor"); klassOop im = ik->implementor(); guarantee(im->is_perm(), "should be in permspace"); guarantee(im->is_klass(), "should be klass"); guarantee(!Klass::cast(klassOop(im))->is_interface(), "implementors cannot be interfaces"); } // Verify local interfaces objArrayOop local_interfaces = ik->local_interfaces(); guarantee(local_interfaces->is_perm(), "should be in permspace"); guarantee(local_interfaces->is_objArray(), "should be obj array"); int j; for (j = 0; j < local_interfaces->length(); j++) { oop e = local_interfaces->obj_at(j); guarantee(e->is_klass() && Klass::cast(klassOop(e))->is_interface(), "invalid local interface"); } // Verify transitive interfaces objArrayOop transitive_interfaces = ik->transitive_interfaces(); guarantee(transitive_interfaces->is_perm(), "should be in permspace"); guarantee(transitive_interfaces->is_objArray(), "should be obj array"); for (j = 0; j < transitive_interfaces->length(); j++) { oop e = transitive_interfaces->obj_at(j); guarantee(e->is_klass() && Klass::cast(klassOop(e))->is_interface(), "invalid transitive interface"); } // Verify methods objArrayOop methods = ik->methods(); guarantee(methods->is_perm(), "should be in permspace"); guarantee(methods->is_objArray(), "should be obj array"); for (j = 0; j < methods->length(); j++) { guarantee(methods->obj_at(j)->is_method(), "non-method in methods array"); } for (j = 0; j < methods->length() - 1; j++) { methodOop m1 = methodOop(methods->obj_at(j)); methodOop m2 = methodOop(methods->obj_at(j + 1)); guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly"); } // Verify method ordering typeArrayOop method_ordering = ik->method_ordering(); guarantee(method_ordering->is_perm(), "should be in permspace"); guarantee(method_ordering->is_typeArray(), "should be type array"); int length = method_ordering->length(); if (jvmdi::enabled()) { guarantee(length == methods->length(), "invalid method ordering length"); jlong sum = 0; for (j = 0; j < length; j++) { int original_index = method_ordering->int_at(j); guarantee(original_index >= 0 && original_index < length, "invalid method ordering index"); sum += original_index; } // Verify sum of indices 0,1,...,length-1 guarantee(sum == ((jlong)length*(length-1))/2, "invalid method ordering sum"); } else { guarantee(length == 0, "invalid method ordering length"); } // Verify JNI static field/method identifiers if (ik->jni_ids() != NULL) { ik->jni_ids()->verify(ik->as_klassOop()); } // Verify other fields if (ik->array_klasses() != NULL) { guarantee(ik->array_klasses()->is_perm(), "should be in permspace"); guarantee(ik->array_klasses()->is_klass(), "should be klass"); } guarantee(ik->fields()->is_perm(), "should be in permspace"); guarantee(ik->fields()->is_typeArray(), "should be type array"); guarantee(ik->constants()->is_perm(), "should be in permspace"); guarantee(ik->constants()->is_constantPool(), "should be constant pool"); guarantee(ik->inner_classes()->is_perm(), "should be in permspace"); guarantee(ik->inner_classes()->is_typeArray(), "should be type array"); if (ik->source_file_name() != NULL) { guarantee(ik->source_file_name()->is_perm(), "should be in permspace"); guarantee(ik->source_file_name()->is_symbol(), "should be symbol"); } if (ik->source_debug_extension() != NULL) { guarantee(ik->source_debug_extension()->is_perm(), "should be in permspace"); guarantee(ik->source_debug_extension()->is_symbol(), "should be symbol"); } if (ik->protection_domain() != NULL) { guarantee(ik->protection_domain()->is_oop(), "should be oop"); } if (ik->signers() != NULL) { guarantee(ik->signers()->is_objArray(), "should be obj array"); } } }
// 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); }
// 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); }
void InterpretedIC::update_inline_cache(InterpretedIC* ic, frame* f, Bytecodes::Code send_code, klassOop klass, LookupResult result) { // update inline cache if (ic->is_empty() && ic->send_type() != Bytecodes::megamorphic_send) { // fill ic for the first time Bytecodes::Code new_send_code = Bytecodes::halt; if (result.is_entry()) { methodOop method = result.method(); if (UseAccessMethods && Bytecodes::has_access_send_code(send_code) && method->is_accessMethod()) { // access method found ==> switch to access send new_send_code = Bytecodes::access_send_code_for(send_code); ic->set(new_send_code, method, klass); } else if (UsePredictedMethods && Bytecodes::has_predicted_send_code(send_code) && method->is_special_primitiveMethod()) { // predictable method found ==> switch to predicted send // NB: ic of predicted send should be empty so that the compiler knows whether another type occurred or not // i.e., {predicted + empty} --> 1 class, {predicted + nonempty} --> 2 klasses (polymorphic) // but: this actually doesn't work (yet?) since the interpreter fills the ic on any failure (e.g. overflow) new_send_code = method->special_primitive_code(); method = methodOop(ic->selector()); // ic must stay empty klass = NULL; // ic must stay empty ic->set(new_send_code, method, klass); } else { // jump table entry found ==> switch to compiled send new_send_code = Bytecodes::compiled_send_code_for(send_code); ic->set(new_send_code, oop(result.entry()->entry_point()), klass); } } else { // methodOop found methodOop method = result.method(); if (UseAccessMethods && Bytecodes::has_access_send_code(send_code) && method->is_accessMethod()) { // access method found ==> switch to access send new_send_code = Bytecodes::access_send_code_for(send_code); } else if (UsePredictedMethods && Bytecodes::has_predicted_send_code(send_code) && method->is_special_primitiveMethod()) { // predictable method found ==> switch to predicted send // NB: ic of predicted send should be empty so that the compiler knows whether another type occurred or not // i.e., {predicted + empty} --> 1 class, {predicted + nonempty} --> 2 klasses (polymorphic) // but: this actually doesn't work (yet?) since the interpreter fills the ic on any failure (e.g. overflow) new_send_code = method->special_primitive_code(); method = methodOop(ic->selector()); // ic must stay empty klass = NULL; // ic must stay empty } else if (UsePrimitiveMethods && method->is_primitiveMethod()) { // primitive method found ==> switch to primitive send new_send_code = Bytecodes::primitive_send_code_for(send_code); Unimplemented(); // take this out when all primitive send bytecodes implemented } else { // normal interpreted send ==> do not change new_send_code = send_code; assert(new_send_code == Bytecodes::original_send_code_for(send_code), "bytecode should not change"); } assert(new_send_code != Bytecodes::halt, "new_send_code not set"); ic->set(new_send_code, method, klass); } } else { // ic not empty switch (ic->send_type()) { // monomorphic send case Bytecodes::accessor_send : // fall through case Bytecodes::predicted_send : // fall through case Bytecodes::compiled_send : // fall through case Bytecodes::interpreted_send: { // switch to polymorphic send with 2 entries objArrayOop pic = Interpreter_PICs::allocate(2); Interpreter_PICs::set_first(pic, ic->first_word(), ic->second_word()); Interpreter_PICs::set_second(pic, result.value(), klass); ic->set(Bytecodes::polymorphic_send_code_for(send_code), ic->selector(), pic); break; } // polymorphic send case Bytecodes::polymorphic_send: { objArrayOop old_pic = ic->pic_array(); objArrayOop new_pic = Interpreter_PICs::extend(old_pic); // add an entry to the PIC if appropriate if (new_pic == NULL) { // switch to megamorphic send if (Bytecodes::is_super_send(send_code)) { ic->set(Bytecodes::megamorphic_send_code_for(send_code), result.value(), klass); } else { ic->set(Bytecodes::megamorphic_send_code_for(send_code), ic->selector(), NULL); } } else { // still a polymorphic send, add entry and set ic to new_pic Interpreter_PICs::set_last(new_pic, result.value(), klass); ic->set(send_code, ic->selector(), new_pic); } // recycle old pic Interpreter_PICs::deallocate(old_pic); break; } // megamorphic send case Bytecodes::megamorphic_send: { if (Bytecodes::is_super_send(send_code)) { ic->set(send_code, result.value(), klass); } break; } default: ShouldNotReachHere(); } } // redo send (reset instruction pointer) f->set_hp(ic->send_code_addr()); }
void MethodIterator::dispatch(MethodClosure* blk) { bool oldFailState = blk->in_prim_failure_block(); blk->set_prim_failure(_interval->in_prim_failure_block()); CodeIterator iter(_interval->method(), _interval->begin_bci()); int lastArgNo = _interval->method()->number_of_arguments() - 1; blk->set_method(_interval->method()); int next_bci = _interval->begin_bci(); while (next_bci < _interval->end_bci() && !blk->aborting()) { iter.set_bci(next_bci); blk->set_bci(iter.bci()); next_bci = iter.next_bci(); blk->set_next_bci(next_bci); switch(iter.code()) { case Bytecodes::push_temp_0: blk->push_temporary(0); break; case Bytecodes::push_temp_1: blk->push_temporary(1); break; case Bytecodes::push_temp_2: blk->push_temporary(2); break; case Bytecodes::push_temp_3: blk->push_temporary(3); break; case Bytecodes::push_temp_4: blk->push_temporary(4); break; case Bytecodes::push_temp_5: blk->push_temporary(5); break; case Bytecodes::unimplemented_06: unknown_code(Bytecodes::unimplemented_06); break; case Bytecodes::push_temp_n: blk->push_temporary(255 - iter.byte_at(1)); break; case Bytecodes::push_arg_1: blk->push_argument(lastArgNo); break; case Bytecodes::push_arg_2: blk->push_argument(lastArgNo - 1); break; case Bytecodes::push_arg_3: blk->push_argument(lastArgNo - 2); break; case Bytecodes::push_arg_n: blk->push_argument(lastArgNo - iter.byte_at(1)); break; case Bytecodes::allocate_temp_1: blk->allocate_temporaries(1); break; case Bytecodes::allocate_temp_2: blk->allocate_temporaries(2); break; case Bytecodes::allocate_temp_3: blk->allocate_temporaries(3); break; case Bytecodes::allocate_temp_n: blk->allocate_temporaries(map0to256(iter.byte_at(1))); break; case Bytecodes::store_temp_0_pop: blk->store_temporary(0); blk->pop(); break; case Bytecodes::store_temp_1_pop: blk->store_temporary(1); blk->pop(); break; case Bytecodes::store_temp_2_pop: blk->store_temporary(2); blk->pop(); break; case Bytecodes::store_temp_3_pop: blk->store_temporary(3); blk->pop(); break; case Bytecodes::store_temp_4_pop: blk->store_temporary(4); blk->pop(); break; case Bytecodes::store_temp_5_pop: blk->store_temporary(5); blk->pop(); break; case Bytecodes::store_temp_n: blk->store_temporary(255 - iter.byte_at(1)); break; case Bytecodes::store_temp_n_pop: blk->store_temporary(255 - iter.byte_at(1)); blk->pop(); break; case Bytecodes::push_neg_n: blk->push_literal(as_smiOop(-(int) iter.byte_at(1))); break; case Bytecodes::push_succ_n: blk->push_literal(as_smiOop(iter.byte_at(1)+1)); break; case Bytecodes::push_literal: blk->push_literal(iter.oop_at(1)); break; case Bytecodes::push_tos: blk->push_tos(); break; case Bytecodes::push_self: blk->push_self(); break; case Bytecodes::push_nil: blk->push_literal(nilObj); break; case Bytecodes::push_true: blk->push_literal(trueObj); break; case Bytecodes::push_false: blk->push_literal(falseObj); break; case Bytecodes::unimplemented_20: unknown_code(Bytecodes::unimplemented_20); break; case Bytecodes::unimplemented_21: unknown_code(Bytecodes::unimplemented_21); break; case Bytecodes::unimplemented_22: unknown_code(Bytecodes::unimplemented_22); break; case Bytecodes::unimplemented_23: unknown_code(Bytecodes::unimplemented_23); break; case Bytecodes::unimplemented_24: unknown_code(Bytecodes::unimplemented_24); break; case Bytecodes::unimplemented_25: unknown_code(Bytecodes::unimplemented_25); break; case Bytecodes::unimplemented_26: unknown_code(Bytecodes::unimplemented_26); break; case Bytecodes::unimplemented_27: unknown_code(Bytecodes::unimplemented_27); break; case Bytecodes::return_instVar_name: { symbolOop name = symbolOop(iter.oop_at(1)); assert(name->is_symbol(), "must be symbol"); blk->push_instVar_name(name); blk->method_return(0); } break; case Bytecodes::push_classVar: { associationOop assoc = associationOop(iter.oop_at(1)); assert(assoc->is_association(), "must be association"); blk->push_classVar(assoc); } break; case Bytecodes::store_classVar_pop: { associationOop assoc = associationOop(iter.oop_at(1)); assert(assoc->is_association(), "must be association"); blk->store_classVar(assoc); blk->pop(); } break; case Bytecodes::store_classVar: { associationOop assoc = associationOop(iter.oop_at(1)); assert(assoc->is_association(), "must be association"); blk->store_classVar(assoc); } break; case Bytecodes::return_instVar: { smiOop offset = smiOop(iter.oop_at(1)); assert(offset->is_smi(), "must be smi"); blk->push_instVar(offset->value()); blk->method_return(0); } break; case Bytecodes::push_instVar: { smiOop offset = smiOop(iter.oop_at(1)); assert(offset->is_smi(), "must be smi"); blk->push_instVar(offset->value()); } break; case Bytecodes::store_instVar_pop: { smiOop offset = smiOop(iter.oop_at(1)); assert(offset->is_smi(), "must be smi"); blk->store_instVar(offset->value()); blk->pop(); } break; case Bytecodes::store_instVar:{ smiOop offset = smiOop(iter.oop_at(1)); assert(offset->is_smi(), "must be smi"); blk->store_instVar(offset->value()); } break; case Bytecodes::float_allocate: blk->allocate_temporaries(1 + iter.byte_at(1)*2); blk->float_allocate(iter.byte_at(2), iter.byte_at(3)); break; case Bytecodes::float_floatify_pop: blk->float_floatify(Floats::floatify, blk->float_at(iter.byte_at(1))); break; case Bytecodes::float_move: blk->float_move(blk->float_at(iter.byte_at(1)), blk->float_at(iter.byte_at(2))); break; case Bytecodes::float_set: blk->float_set(blk->float_at(iter.byte_at(1)), *(doubleOop*)iter.aligned_oop(2)); break; case Bytecodes::float_nullary_op: blk->float_nullary(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1))); break; case Bytecodes::float_unary_op: blk->float_unary(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1))); break; case Bytecodes::float_binary_op: blk->float_binary(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1))); break; case Bytecodes::float_unary_op_to_oop: blk->float_unaryToOop(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1))); break; case Bytecodes::float_binary_op_to_oop: blk->float_binaryToOop(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1))); break; case Bytecodes::unimplemented_39: unknown_code(Bytecodes::unimplemented_39); break; case Bytecodes::unimplemented_3a: unknown_code(Bytecodes::unimplemented_3a); break; case Bytecodes::unimplemented_3b: unknown_code(Bytecodes::unimplemented_3b); break; case Bytecodes::unimplemented_3c: unknown_code(Bytecodes::unimplemented_3c); break; case Bytecodes::push_instVar_name: { symbolOop name = symbolOop(iter.oop_at(1)); assert(name->is_symbol(), "must be symbol"); blk->push_instVar_name(name); } break; case Bytecodes::store_instVar_pop_name: { symbolOop name = symbolOop(iter.oop_at(1)); assert(name->is_symbol(), "must be symbol"); blk->store_instVar_name(name); blk->pop(); } break; case Bytecodes::store_instVar_name: { symbolOop name = symbolOop(iter.oop_at(1)); assert(name->is_symbol(), "must be symbol"); blk->store_instVar_name(name); } break; case Bytecodes::push_temp_0_context_0: blk->push_temporary(0, 0); break; case Bytecodes::push_temp_1_context_0: blk->push_temporary(1, 0); break; case Bytecodes::push_temp_2_context_0: blk->push_temporary(2, 0); break; case Bytecodes::push_temp_n_context_0: blk->push_temporary(iter.byte_at(1), 0); break; case Bytecodes::store_temp_0_context_0_pop: blk->store_temporary(0, 0); blk->pop(); break; case Bytecodes::store_temp_1_context_0_pop: blk->store_temporary(1, 0); blk->pop(); break; case Bytecodes::store_temp_2_context_0_pop: blk->store_temporary(2, 0); blk->pop(); break; case Bytecodes::store_temp_n_context_0_pop: blk->store_temporary(iter.byte_at(1), 0); blk->pop(); break; case Bytecodes::push_new_closure_context_0: blk->allocate_closure(context_as_scope, 0, methodOop(iter.oop_at(1))); break; case Bytecodes::push_new_closure_context_1: blk->allocate_closure(context_as_scope, 1, methodOop(iter.oop_at(1))); break; case Bytecodes::push_new_closure_context_2: blk->allocate_closure(context_as_scope, 2, methodOop(iter.oop_at(1))); break; case Bytecodes::push_new_closure_context_n: blk->allocate_closure(context_as_scope, iter.byte_at(1), methodOop(iter.oop_at(2))); break; case Bytecodes::install_new_context_method_0: blk->allocate_context(0, true); break; case Bytecodes::install_new_context_method_1: blk->allocate_context(1, true); break; case Bytecodes::install_new_context_method_2: blk->allocate_context(2, true); break; case Bytecodes::install_new_context_method_n: blk->allocate_context(iter.byte_at(1), true); break; case Bytecodes::push_temp_0_context_1: blk->push_temporary(0, 1); break; case Bytecodes::push_temp_1_context_1: blk->push_temporary(1, 1); break; case Bytecodes::push_temp_2_context_1: blk->push_temporary(2, 1); break; case Bytecodes::push_temp_n_context_1: blk->push_temporary(iter.byte_at(1), 1); break; case Bytecodes::store_temp_0_context_1_pop: blk->store_temporary(0, 1); blk->pop(); break; case Bytecodes::store_temp_1_context_1_pop: blk->store_temporary(1, 1); blk->pop(); break; case Bytecodes::store_temp_2_context_1_pop: blk->store_temporary(2, 1); blk->pop(); break; case Bytecodes::store_temp_n_context_1_pop: blk->store_temporary(iter.byte_at(1), 1); blk->pop(); break; case Bytecodes::push_new_closure_tos_0: blk->allocate_closure(tos_as_scope, 0, methodOop(iter.oop_at(1))); break; case Bytecodes::push_new_closure_tos_1: blk->allocate_closure(tos_as_scope, 1, methodOop(iter.oop_at(1))); break; case Bytecodes::push_new_closure_tos_2: blk->allocate_closure(tos_as_scope, 2, methodOop(iter.oop_at(1))); break; case Bytecodes::push_new_closure_tos_n: blk->allocate_closure(tos_as_scope, iter.byte_at(1), methodOop(iter.oop_at(2))); break; case Bytecodes::only_pop: blk->pop(); break; case Bytecodes::install_new_context_block_1: blk->allocate_context(1, false); break; case Bytecodes::install_new_context_block_2: blk->allocate_context(2, false); break; case Bytecodes::install_new_context_block_n: blk->allocate_context(iter.byte_at(1), false); break; case Bytecodes::push_temp_0_context_n: blk->push_temporary(0, iter.byte_at(1)); break; case Bytecodes::push_temp_1_context_n: blk->push_temporary(1, iter.byte_at(1)); break; case Bytecodes::push_temp_2_context_n: blk->push_temporary(2, iter.byte_at(1)); break; case Bytecodes::push_temp_n_context_n: blk->push_temporary(iter.byte_at(1), map0to256(iter.byte_at(2))); break; case Bytecodes::store_temp_0_context_n_pop: blk->store_temporary(0, iter.byte_at(1)); blk->pop(); break; case Bytecodes::store_temp_1_context_n_pop: blk->store_temporary(1, iter.byte_at(1)); blk->pop(); break; case Bytecodes::store_temp_2_context_n_pop: blk->store_temporary(2, iter.byte_at(1)); blk->pop(); break; case Bytecodes::store_temp_n_context_n_pop: blk->store_temporary(iter.byte_at(1), map0to256(iter.byte_at(2))); blk->pop(); break; case Bytecodes::set_self_via_context: blk->set_self_via_context(); break; case Bytecodes::copy_1_into_context: blk->copy_argument_into_context(lastArgNo - iter.byte_at(1), 0); break; case Bytecodes::copy_2_into_context: blk->copy_argument_into_context(lastArgNo - iter.byte_at(1), 0); blk->copy_argument_into_context(lastArgNo - iter.byte_at(2), 1); break; case Bytecodes::copy_n_into_context: { int len = map0to256(iter.byte_at(1)); for (int i = 0; i < len; i++) blk->copy_argument_into_context(lastArgNo - iter.byte_at(i + 2), i); break; } case Bytecodes::copy_self_into_context: blk->copy_self_into_context(); break; case Bytecodes::copy_self_1_into_context: blk->copy_self_into_context(); blk->copy_argument_into_context(lastArgNo - iter.byte_at(1), 1); break; case Bytecodes::copy_self_2_into_context: blk->copy_self_into_context(); blk->copy_argument_into_context(lastArgNo - iter.byte_at(1), 1); blk->copy_argument_into_context(lastArgNo - iter.byte_at(2), 2); break; case Bytecodes::copy_self_n_into_context: { blk->copy_self_into_context(); int len = map0to256(iter.byte_at(1)); for (int i = 0; i < len; i++) blk->copy_argument_into_context(lastArgNo - iter.byte_at(i + 2), i+1); break; } case Bytecodes::ifTrue_byte: { IfNode* node = MethodIterator::factory->new_IfNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), true, iter.byte_at(2), iter.byte_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->if_node(node); next_bci = node->end_bci(); break; } case Bytecodes::ifFalse_byte: { IfNode* node = MethodIterator::factory->new_IfNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), false, iter.byte_at(2), iter.byte_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->if_node(node); next_bci = node->end_bci(); break; } case Bytecodes::and_byte: { AndNode* node = MethodIterator::factory->new_AndNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.byte_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->cond_node(node); next_bci = node->end_bci(); break; } case Bytecodes::or_byte: { OrNode* node = MethodIterator::factory->new_OrNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.byte_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->cond_node(node); next_bci = node->end_bci(); break; } case Bytecodes::whileTrue_byte: // ignore since they are inside WhileNode expression body break; case Bytecodes::whileFalse_byte: // ignore since they are inside WhileNode expression body break; case Bytecodes::jump_else_byte: should_never_encounter(Bytecodes::jump_else_byte); break; case Bytecodes::jump_loop_byte: { WhileNode* node = MethodIterator::factory->new_WhileNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.byte_at(2), iter.byte_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->while_node(node); next_bci = node->end_bci(); break; } case Bytecodes::ifTrue_word: { IfNode* node = MethodIterator::factory->new_IfNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), true, iter.word_at(2), iter.byte_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->if_node(node); next_bci = node->end_bci(); break; } case Bytecodes::ifFalse_word: { IfNode* node = MethodIterator::factory->new_IfNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), false, iter.word_at(2), iter.byte_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->if_node(node); next_bci = node->end_bci(); break; } case Bytecodes::and_word: { AndNode* node = MethodIterator::factory->new_AndNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.word_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->cond_node(node); next_bci = node->end_bci(); break; } case Bytecodes::or_word: { OrNode* node = MethodIterator::factory->new_OrNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.word_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->cond_node(node); next_bci = node->end_bci(); break; } case Bytecodes::whileTrue_word: // Ignore since they are inside WhileNode expression body break; case Bytecodes::whileFalse_word: // Ignore since they are inside WhileNode expression body break; case Bytecodes::jump_else_word: should_never_encounter(Bytecodes::jump_else_word); break; case Bytecodes::jump_loop_word: { WhileNode* node = MethodIterator::factory->new_WhileNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.word_at(1 + oopSize), iter.word_at(1)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->while_node(node); next_bci = node->end_bci(); break; } case Bytecodes::interpreted_send_0: // fall through case Bytecodes::interpreted_send_1: // fall through case Bytecodes::interpreted_send_2: // fall through case Bytecodes::interpreted_send_n: // fall through case Bytecodes::compiled_send_0: // fall through case Bytecodes::compiled_send_1: // fall through case Bytecodes::compiled_send_2: // fall through case Bytecodes::compiled_send_n: // fall through case Bytecodes::primitive_send_0: // fall through case Bytecodes::primitive_send_1: // fall through case Bytecodes::primitive_send_2: // fall through case Bytecodes::primitive_send_n: // fall through case Bytecodes::polymorphic_send_0: // fall through case Bytecodes::polymorphic_send_1: // fall through case Bytecodes::polymorphic_send_2: // fall through case Bytecodes::polymorphic_send_n: // fall through case Bytecodes::megamorphic_send_0: // fall through case Bytecodes::megamorphic_send_1: // fall through case Bytecodes::megamorphic_send_2: // fall through case Bytecodes::megamorphic_send_n: // fall through blk->normal_send(iter.ic()); break; case Bytecodes::interpreted_send_0_pop: // fall through case Bytecodes::interpreted_send_1_pop: // fall through case Bytecodes::interpreted_send_2_pop: // fall through case Bytecodes::interpreted_send_n_pop: // fall through case Bytecodes::compiled_send_0_pop: // fall through case Bytecodes::compiled_send_1_pop: // fall through case Bytecodes::compiled_send_2_pop: // fall through case Bytecodes::compiled_send_n_pop: // fall through case Bytecodes::primitive_send_0_pop: // fall through case Bytecodes::primitive_send_1_pop: // fall through case Bytecodes::primitive_send_2_pop: // fall through case Bytecodes::primitive_send_n_pop: // fall through case Bytecodes::polymorphic_send_0_pop: // fall through case Bytecodes::polymorphic_send_1_pop: // fall through case Bytecodes::polymorphic_send_2_pop: // fall through case Bytecodes::polymorphic_send_n_pop: // fall through case Bytecodes::megamorphic_send_0_pop: // fall through case Bytecodes::megamorphic_send_1_pop: // fall through case Bytecodes::megamorphic_send_2_pop: // fall through case Bytecodes::megamorphic_send_n_pop: // fall through blk->normal_send(iter.ic()); blk->pop(); break; case Bytecodes::interpreted_send_self: // fall through case Bytecodes::compiled_send_self: // fall through case Bytecodes::primitive_send_self: // fall through case Bytecodes::polymorphic_send_self: // fall through case Bytecodes::megamorphic_send_self: // fall through blk->self_send(iter.ic()); break; case Bytecodes::interpreted_send_self_pop: // fall through case Bytecodes::compiled_send_self_pop: // fall through case Bytecodes::primitive_send_self_pop: // fall through case Bytecodes::polymorphic_send_self_pop: // fall through case Bytecodes::megamorphic_send_self_pop: // fall through blk->self_send(iter.ic()); blk->pop(); break; case Bytecodes::interpreted_send_super: // fall through case Bytecodes::compiled_send_super: // fall through case Bytecodes::primitive_send_super: // fall through case Bytecodes::polymorphic_send_super: // fall through case Bytecodes::megamorphic_send_super: // fall through blk->super_send(iter.ic()); break; case Bytecodes::interpreted_send_super_pop: // fall through case Bytecodes::compiled_send_super_pop: // fall through case Bytecodes::primitive_send_super_pop: // fall through case Bytecodes::polymorphic_send_super_pop: // fall through case Bytecodes::megamorphic_send_super_pop: // fall through blk->super_send(iter.ic()); blk->pop(); break; case Bytecodes::return_tos_pop_0: blk->method_return(0); break; case Bytecodes::return_tos_pop_1: blk->method_return(1); break; case Bytecodes::return_tos_pop_2: blk->method_return(2); break; case Bytecodes::return_tos_pop_n: blk->method_return(iter.byte_at(1)); break; case Bytecodes::return_self_pop_0: blk->push_self(); blk->method_return(0); break; case Bytecodes::return_self_pop_1: blk->push_self(); blk->method_return(1); break; case Bytecodes::return_self_pop_2: blk->push_self(); blk->method_return(2); break; case Bytecodes::return_self_pop_n: blk->push_self(); blk->method_return(iter.byte_at(1)); break; case Bytecodes::return_tos_zap_pop_n: blk->zap_scope(); blk->method_return(iter.byte_at(1)); break; case Bytecodes::return_self_zap_pop_n: blk->zap_scope(); blk->push_self(); blk->method_return(iter.byte_at(1)); break; case Bytecodes::non_local_return_tos_pop_n: blk->nonlocal_return(iter.byte_at(1)); break; case Bytecodes::non_local_return_self_pop_n: blk->push_self(); blk->nonlocal_return(iter.byte_at(1)); break; case Bytecodes::prim_call: // fall through case Bytecodes::prim_call_self: { primitive_desc* pdesc = primitives::lookup((fntype) iter.word_at(1)); PrimitiveCallNode* node = MethodIterator::factory->new_PrimitiveCallNode(_interval->method(), _interval, iter.bci(), iter.next_bci(), pdesc->has_receiver(), NULL, pdesc); // %hack: this assertion fails // assert(pdesc->has_receiver() == (iter.code() == Bytecodes::prim_call_self), "just checking"); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->primitive_call_node(node); next_bci = node->end_bci(); break; } case Bytecodes::predict_prim_call: blk->predict_prim_call(primitives::lookup((fntype) iter.word_at(1)), -1); break; case Bytecodes::prim_call_failure: // fall through case Bytecodes::prim_call_self_failure: { primitive_desc* pdesc = primitives::lookup((fntype) iter.word_at(1)); PrimitiveCallNode* node = MethodIterator::factory->new_PrimitiveCallNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), pdesc->has_receiver(), NULL, pdesc, iter.word_at(1 + oopSize)); assert(pdesc->has_receiver() == (iter.code() == Bytecodes::prim_call_self_failure), "just checking"); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->primitive_call_node(node); next_bci = node->end_bci(); break; } case Bytecodes::predict_prim_call_failure: blk->predict_prim_call( primitives::lookup((fntype) iter.word_at(1)), iter.next_bci() + iter.word_at(1 + oopSize)); break; case Bytecodes::dll_call_sync: { DLLCallNode* node = MethodIterator::factory->new_DLLCallNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.dll_cache()); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->dll_call_node(node); next_bci = node->end_bci(); break; } case Bytecodes::access_send_self: blk->self_send(iter.ic()); break; case Bytecodes::unimplemented_bc: unknown_code(Bytecodes::unimplemented_bc); break; case Bytecodes::prim_call_lookup: // fall through case Bytecodes::prim_call_self_lookup: { symbolOop name = symbolOop(iter.oop_at(1)); assert(name->is_symbol(), "name must be symbolOop"); PrimitiveCallNode* node = MethodIterator::factory->new_PrimitiveCallNode(_interval->method(), _interval, iter.bci(), iter.next_bci(), iter.code() == Bytecodes::prim_call_self_lookup, name, NULL); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->primitive_call_node(node); next_bci = node->end_bci(); break; } case Bytecodes::predict_prim_call_lookup: blk->predict_prim_call(primitives::lookup(symbolOop(iter.word_at(1))), -1); break; case Bytecodes::prim_call_failure_lookup: // fall through case Bytecodes::prim_call_self_failure_lookup: { symbolOop name = symbolOop(iter.oop_at(1)); assert(name->is_symbol(), "name must be symbolOop"); PrimitiveCallNode* node = MethodIterator::factory->new_PrimitiveCallNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.code() == Bytecodes::prim_call_self_failure_lookup, name, NULL, iter.word_at(1 + oopSize)); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->primitive_call_node(node); next_bci = node->end_bci(); break; } case Bytecodes::predict_prim_call_failure_lookup: blk->predict_prim_call( primitives::lookup(symbolOop(iter.word_at(1))), iter.bci() + iter.word_at(1 + oopSize)); break; case Bytecodes::dll_call_async: { DLLCallNode* node = MethodIterator::factory->new_DLLCallNode( _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.dll_cache()); assert(node->end_bci() <= _interval->end_bci(), "just checking"); blk->dll_call_node(node); next_bci = node->end_bci(); break; } case Bytecodes::unimplemented_c7: unknown_code(Bytecodes::unimplemented_c7); break; case Bytecodes::access_send_0: blk->normal_send(iter.ic()); break; case Bytecodes::unimplemented_cc: unknown_code(Bytecodes::unimplemented_cc); break; case Bytecodes::unimplemented_dc: unknown_code(Bytecodes::unimplemented_dc); break; case Bytecodes::special_primitive_send_1_hint: // ignore - only meaningfull for the interpreter break; case Bytecodes::unimplemented_de: unknown_code(Bytecodes::unimplemented_de); break; case Bytecodes::unimplemented_df: unknown_code(Bytecodes::unimplemented_df); break; case Bytecodes::smi_add : // fall through case Bytecodes::smi_sub : // fall through case Bytecodes::smi_mult : // fall through case Bytecodes::smi_div : // fall through case Bytecodes::smi_mod : // fall through case Bytecodes::smi_create_point : // fall through case Bytecodes::smi_equal : // fall through case Bytecodes::smi_not_equal : // fall through case Bytecodes::smi_less : // fall through case Bytecodes::smi_less_equal : // fall through case Bytecodes::smi_greater : // fall through case Bytecodes::smi_greater_equal : // fall through case Bytecodes::objArray_at : // fall through case Bytecodes::objArray_at_put : // fall through case Bytecodes::smi_and : // fall through case Bytecodes::smi_or : // fall through case Bytecodes::smi_xor : // fall through case Bytecodes::smi_shift : blk->normal_send(iter.ic()); break; case Bytecodes::double_equal: blk->double_equal(); break; case Bytecodes::double_tilde: blk->double_not_equal(); break; case Bytecodes::push_global: assert(iter.oop_at(1)->is_association(), "must be an association"); blk->push_global(associationOop(iter.oop_at(1))); break; case Bytecodes::store_global_pop: assert(iter.oop_at(1)->is_association(), "must be an association"); blk->store_global(associationOop(iter.oop_at(1))); blk->pop(); break; case Bytecodes::store_global: assert(iter.oop_at(1)->is_association(), "must be an association"); blk->store_global(associationOop(iter.oop_at(1))); break; case Bytecodes::push_classVar_name: { symbolOop name = symbolOop(iter.oop_at(1)); assert(name->is_symbol(), "must be symbol"); blk->push_classVar_name(name); } break; case Bytecodes::store_classVar_pop_name: { symbolOop name = symbolOop(iter.oop_at(1)); assert(name->is_symbol(), "must be symbol"); blk->store_classVar_name(name); blk->pop(); } break; case Bytecodes::store_classVar_name: { symbolOop name = symbolOop(iter.oop_at(1)); assert(name->is_symbol(), "must be symbol"); blk->store_classVar_name(name); } break; case Bytecodes::unimplemented_fa: unknown_code(Bytecodes::unimplemented_fa); break; case Bytecodes::unimplemented_fb: unknown_code(Bytecodes::unimplemented_fb); break; case Bytecodes::unimplemented_fc: unknown_code(Bytecodes::unimplemented_fc); break; case Bytecodes::unimplemented_fd: unknown_code(Bytecodes::unimplemented_fd); break; case Bytecodes::unimplemented_fe: unknown_code(Bytecodes::unimplemented_fe); break; case Bytecodes::halt: unknown_code(Bytecodes::halt); break; default: ShouldNotReachHere(); } } blk->set_prim_failure(oldFailState); }
bool methodKlass::oop_is_parsable(oop obj) const { assert(obj->is_method(), "must be method oop"); return methodOop(obj)->object_is_parsable(); }
int methodKlass::oop_size(oop obj) const { assert(obj->is_method(), "must be method oop"); return methodOop(obj)->object_size(); }
void InterpretedIC::cleanup() { if (is_empty()) return; // Nothing to cleanup switch (send_type()) { case Bytecodes::accessor_send: // fall through case Bytecodes::primitive_send: // fall through case Bytecodes::predicted_send: // fall through case Bytecodes::interpreted_send: { // check if the interpreted send should be replaced by a compiled send klassOop receiver_klass = klassOop(second_word()); assert(receiver_klass->is_klass(), "receiver klass must be a klass"); methodOop method = methodOop(first_word()); assert(method->is_method(), "first word in interpreter IC must be method"); if (!Bytecodes::is_super_send(send_code())) { // super sends cannot be handled since the sending method holder is unknown at this point. LookupKey key(receiver_klass, selector()); LookupResult result = lookupCache::lookup(&key); if (!result.matches(method)) { replace(result, receiver_klass); } } } break; case Bytecodes::compiled_send: { // check if the current compiled send is valid klassOop receiver_klass = klassOop(second_word()); assert(receiver_klass->is_klass(), "receiver klass must be a klass"); jumpTableEntry* entry = (jumpTableEntry*) first_word(); nmethod* nm = entry->method(); LookupResult result = lookupCache::lookup(&nm->key); if (!result.matches(nm)) { replace(result, receiver_klass); } } break; case Bytecodes::megamorphic_send: // Note that with the current definition of is_empty() // this will not be called for normal megamorphic sends // since they store only the selector. { klassOop receiver_klass = klassOop(second_word()); if (first_word()->is_smi()) { jumpTableEntry* entry = (jumpTableEntry*) first_word(); nmethod* nm = entry->method(); LookupResult result = lookupCache::lookup(&nm->key); if (!result.matches(nm)) { replace(result, receiver_klass); } } else { methodOop method = methodOop(first_word()); assert(method->is_method(), "first word in interpreter IC must be method"); if (!Bytecodes::is_super_send(send_code())) { // super sends cannot be handled since the sending method holder is unknown at this point. LookupKey key(receiver_klass, selector()); LookupResult result = lookupCache::lookup(&key); if (!result.matches(method)) { replace(result, receiver_klass); } } } } break; case Bytecodes::polymorphic_send: { // %implementation note: // when cleaning up we can always preserve the old pic since the // the only transitions are: // (compiled -> compiled) // (compiled -> interpreted) // (interpreted -> compiled) // in case of a super send we do not have to cleanup because // no nmethods are compiled for super sends. if (!Bytecodes::is_super_send(send_code())) { objArrayOop pic = pic_array(); for (int index = pic->length(); index > 0; index -= 2) { klassOop klass = klassOop(pic->obj_at(index)); assert(klass->is_klass(), "receiver klass must be klass"); oop first = pic->obj_at(index-1); if (first->is_smi()) { jumpTableEntry* entry = (jumpTableEntry*) first; nmethod* nm = entry->method(); LookupResult result = lookupCache::lookup(&nm->key); if (!result.matches(nm)) { pic->obj_at_put(index-1, result.value()); } } else { methodOop method = methodOop(first); assert(method->is_method(), "first word in interpreter IC must be method"); LookupKey key(klass, selector()); LookupResult result = lookupCache::lookup(&key); if (!result.matches(method)) { pic->obj_at_put(index-1, result.value()); } } } } } } }