// ------------------------------------------------------------------ // ciMethod::uses_balanced_monitors // // Does this method use monitors in a strict stack-disciplined manner? bool ciMethod::has_balanced_monitors() { check_is_loaded(); if (_balanced_monitors) return true; // Analyze the method to see if monitors are used properly. VM_ENTRY_MARK; methodHandle method(THREAD, get_Method()); assert(method->has_monitor_bytecodes(), "should have checked this"); // Check to see if a previous compilation computed the // monitor-matching analysis. if (method->guaranteed_monitor_matching()) { _balanced_monitors = true; return true; } { EXCEPTION_MARK; ResourceMark rm(THREAD); GeneratePairingInfo gpi(method); gpi.compute_map(CATCH); if (!gpi.monitor_safe()) { return false; } method->set_guaranteed_monitor_matching(); _balanced_monitors = true; } return true; }
// ------------------------------------------------------------------ // ciMethod::resolve_vtable_index // // Given a known receiver klass, find the vtable index for the call. // Return Method::invalid_vtable_index if the vtable_index is unknown. int ciMethod::resolve_vtable_index(ciKlass* caller, ciKlass* receiver) { check_is_loaded(); int vtable_index = Method::invalid_vtable_index; // Only do lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail. if (!receiver->is_interface() && (!receiver->is_instance_klass() || receiver->as_instance_klass()->is_linked())) { VM_ENTRY_MARK; KlassHandle caller_klass (THREAD, caller->get_Klass()); KlassHandle h_recv (THREAD, receiver->get_Klass()); Symbol* h_name = name()->get_symbol(); Symbol* h_signature = signature()->get_symbol(); vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, h_recv, h_name, h_signature, caller_klass); if (vtable_index == Method::nonvirtual_vtable_index) { // A statically bound method. Return "no such index". vtable_index = Method::invalid_vtable_index; } } return vtable_index; }
// ------------------------------------------------------------------ // ciMethod::itable_index // // Get the position of this method's entry in the itable, if any. int ciMethod::itable_index() { check_is_loaded(); assert(holder()->is_linked(), "must be linked"); VM_ENTRY_MARK; Method* m = get_Method(); if (!m->has_itable_index()) return Method::nonvirtual_vtable_index; return m->itable_index(); }
// ------------------------------------------------------------------ // ciMethod::native_entry // // Get the address of this method's native code, if any. address ciMethod::native_entry() { check_is_loaded(); assert(flags().is_native(), "must be native method"); VM_ENTRY_MARK; Method* method = get_Method(); address entry = method->native_function(); assert(entry != NULL, "must be valid entry point"); return entry; }
// ------------------------------------------------------------------ // ciMethod::raw_liveness_at_bci // // Which local variables are live at a specific bci? MethodLivenessResult ciMethod::raw_liveness_at_bci(int bci) { check_is_loaded(); if (_liveness == NULL) { // Create the liveness analyzer. Arena* arena = CURRENT_ENV->arena(); _liveness = new (arena) MethodLiveness(arena, this); _liveness->compute_liveness(); } return _liveness->get_liveness_at(bci); }
// ------------------------------------------------------------------ // ciMethod::bci_block_start // // Marks all bcis where a new basic block starts const BitMap ciMethod::bci_block_start() { check_is_loaded(); if (_liveness == NULL) { // Create the liveness analyzer. Arena* arena = CURRENT_ENV->arena(); _liveness = new (arena) MethodLiveness(arena, this); _liveness->compute_liveness(); } return _liveness->get_bci_block_start(); }
// ------------------------------------------------------------------ // invokedynamic support // 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 { VM_ENTRY_MARK; bool flag2 = get_methodOop()->is_method_handle_invoke(); assert(flag == flag2, "consistent"); } #endif //ASSERT return flag; }
// ------------------------------------------------------------------ // ciMethod::resolve_invoke // // Given a known receiver klass, find the target for the call. // Return NULL if the call has no target or the target is abstract. ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver) { check_is_loaded(); VM_ENTRY_MARK; KlassHandle caller_klass (THREAD, caller->get_Klass()); KlassHandle h_recv (THREAD, exact_receiver->get_Klass()); KlassHandle h_resolved (THREAD, holder()->get_Klass()); Symbol* h_name = name()->get_symbol(); Symbol* h_signature = signature()->get_symbol(); methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail. if (h_recv->oop_is_array() || InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) { if (holder()->is_interface()) { m = LinkResolver::resolve_interface_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass); } else { m = LinkResolver::resolve_virtual_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass); } } if (m.is_null()) { // Return NULL only if there was a problem with lookup (uninitialized class, etc.) return NULL; } ciMethod* result = this; if (m() != get_Method()) { result = CURRENT_THREAD_ENV->get_method(m()); } // Don't return abstract methods because they aren't // optimizable or interesting. if (result->is_abstract()) { return NULL; } else { return result; } }
// ------------------------------------------------------------------ // ciMethod::itable_index // // Get the position of this method's entry in the itable, if any. int ciMethod::itable_index() { check_is_loaded(); assert(holder()->is_linked(), "must be linked"); VM_ENTRY_MARK; return klassItable::compute_itable_index(get_methodOop()); }
ciInstance* ciMethod::method_handle_type() { check_is_loaded(); VM_ENTRY_MARK; oop mtype = get_methodOop()->method_handle_type(); return CURRENT_THREAD_ENV->get_object(mtype)->as_instance(); }
// ------------------------------------------------------------------ // ciMethod::interpreter_entry // // Get the entry point for running this method in the interpreter. address ciMethod::interpreter_entry() { check_is_loaded(); VM_ENTRY_MARK; methodHandle mh(THREAD, get_Method()); return Interpreter::entry_for_method(mh); }
// ------------------------------------------------------------------ // ciMethod::vtable_index // // Get the position of this method's entry in the vtable, if any. int ciMethod::vtable_index() { check_is_loaded(); assert(holder()->is_linked(), "must be linked"); VM_ENTRY_MARK; return get_Method()->vtable_index(); }
// Basic method information. ciFlags flags() const { check_is_loaded(); return _flags; }
// ------------------------------------------------------------------ // ciMethod::find_monomorphic_target // // Given a certain calling environment, find the monomorphic target // for the call. Return NULL if the call is not monomorphic in // its calling environment, or if there are only abstract methods. // The returned method is never abstract. // Note: If caller uses a non-null result, it must inform dependencies // via assert_unique_concrete_method or assert_leaf_type. ciMethod* ciMethod::find_monomorphic_target(ciInstanceKlass* caller, ciInstanceKlass* callee_holder, ciInstanceKlass* actual_recv) { check_is_loaded(); if (actual_recv->is_interface()) { // %%% We cannot trust interface types, yet. See bug 6312651. return NULL; } ciMethod* root_m = resolve_invoke(caller, actual_recv); if (root_m == NULL) { // Something went wrong looking up the actual receiver method. return NULL; } assert(!root_m->is_abstract(), "resolve_invoke promise"); // Make certain quick checks even if UseCHA is false. // Is it private or final? if (root_m->can_be_statically_bound()) { return root_m; } if (actual_recv->is_leaf_type() && actual_recv == root_m->holder()) { // Easy case. There is no other place to put a method, so don't bother // to go through the VM_ENTRY_MARK and all the rest. return root_m; } // Array methods (clone, hashCode, etc.) are always statically bound. // If we were to see an array type here, we'd return root_m. // However, this method processes only ciInstanceKlasses. (See 4962591.) // The inline_native_clone intrinsic narrows Object to T[] properly, // so there is no need to do the same job here. if (!UseCHA) return NULL; VM_ENTRY_MARK; methodHandle target; { MutexLocker locker(Compile_lock); Klass* context = actual_recv->get_Klass(); target = Dependencies::find_unique_concrete_method(context, root_m->get_Method()); // %%% Should upgrade this ciMethod API to look for 1 or 2 concrete methods. } #ifndef PRODUCT if (TraceDependencies && target() != NULL && target() != root_m->get_Method()) { tty->print("found a non-root unique target method"); tty->print_cr(" context = %s", InstanceKlass::cast(actual_recv->get_Klass())->external_name()); tty->print(" method = "); target->print_short_name(tty); tty->cr(); } #endif //PRODUCT if (target() == NULL) { return NULL; } if (target() == root_m->get_Method()) { return root_m; } if (!root_m->is_public() && !root_m->is_protected()) { // If we are going to reason about inheritance, it's easiest // if the method in question is public, protected, or private. // If the answer is not root_m, it is conservatively correct // to return NULL, even if the CHA encountered irrelevant // methods in other packages. // %%% TO DO: Work out logic for package-private methods // with the same name but different vtable indexes. return NULL; } return CURRENT_THREAD_ENV->get_method(target()); }
int max_stack() const { check_is_loaded(); return _max_stack; }
bool ciMethod::is_method_handle_adapter() const { check_is_loaded(); VM_ENTRY_MARK; return get_methodOop()->is_method_handle_adapter(); }
// ------------------------------------------------------------------ // ciMethod::has_linenumber_table // // length unknown until decompression bool ciMethod::has_linenumber_table() const { check_is_loaded(); VM_ENTRY_MARK; return get_Method()->has_linenumber_table(); }
int exception_table_length() const { check_is_loaded(); return _handler_count; }
// Can only be used on loaded ciMethods int arg_size() const { check_is_loaded(); return _signature->size() + (_flags.is_static() ? 0 : 1); }
bool has_exception_handlers() const { check_is_loaded(); return _handler_count > 0; }
vmIntrinsics::ID intrinsic_id() const { check_is_loaded(); return _intrinsic_id; }
int max_locals() const { check_is_loaded(); return _max_locals; }
int nmethod_age() const { check_is_loaded(); return _nmethod_age; }
// ------------------------------------------------------------------ // ciMethod::compressed_linenumber_table u_char* ciMethod::compressed_linenumber_table() const { check_is_loaded(); VM_ENTRY_MARK; return get_Method()->compressed_linenumber_table(); }
int size_of_parameters() const { check_is_loaded(); return _size_of_parameters; }
// ------------------------------------------------------------------ // ciMethod::line_number_from_bci int ciMethod::line_number_from_bci(int bci) const { check_is_loaded(); VM_ENTRY_MARK; return get_Method()->line_number_from_bci(bci); }
int interpreter_invocation_count() const { check_is_loaded(); return _interpreter_invocation_count; }
int code_size() const { check_is_loaded(); return _code_size; }
// ------------------------------------------------------------------ // ciMethod::is_special_get_caller_class_method // bool ciMethod::is_ignored_by_security_stack_walk() const { check_is_loaded(); VM_ENTRY_MARK; return get_Method()->is_ignored_by_security_stack_walk(); }
int interpreter_throwout_count() const { check_is_loaded(); return _interpreter_throwout_count; }