aoqi@0: /* aoqi@0: * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_CI_CIMETHOD_HPP aoqi@0: #define SHARE_VM_CI_CIMETHOD_HPP aoqi@0: aoqi@0: #include "ci/ciFlags.hpp" aoqi@0: #include "ci/ciInstanceKlass.hpp" aoqi@0: #include "ci/ciObject.hpp" aoqi@0: #include "ci/ciSignature.hpp" aoqi@0: #include "compiler/methodLiveness.hpp" aoqi@0: #include "prims/methodHandles.hpp" aoqi@0: #include "utilities/bitMap.hpp" aoqi@0: aoqi@0: class ciMethodBlocks; aoqi@0: class MethodLiveness; aoqi@0: class BitMap; aoqi@0: class Arena; aoqi@0: class BCEscapeAnalyzer; aoqi@0: aoqi@0: aoqi@0: // ciMethod aoqi@0: // aoqi@0: // This class represents a Method* in the HotSpot virtual aoqi@0: // machine. aoqi@0: class ciMethod : public ciMetadata { aoqi@0: friend class CompileBroker; aoqi@0: CI_PACKAGE_ACCESS aoqi@0: friend class ciEnv; aoqi@0: friend class ciExceptionHandlerStream; aoqi@0: friend class ciBytecodeStream; aoqi@0: friend class ciMethodHandle; aoqi@0: friend class ciReplay; aoqi@0: aoqi@0: private: aoqi@0: // General method information. aoqi@0: ciFlags _flags; aoqi@0: ciSymbol* _name; aoqi@0: ciInstanceKlass* _holder; aoqi@0: ciSignature* _signature; aoqi@0: ciMethodData* _method_data; aoqi@0: ciMethodBlocks* _method_blocks; aoqi@0: aoqi@0: // Code attributes. aoqi@0: int _code_size; aoqi@0: int _max_stack; aoqi@0: int _max_locals; aoqi@0: vmIntrinsics::ID _intrinsic_id; aoqi@0: int _handler_count; aoqi@0: int _interpreter_invocation_count; aoqi@0: int _interpreter_throwout_count; aoqi@0: int _instructions_size; aoqi@0: int _size_of_parameters; aoqi@0: aoqi@0: bool _uses_monitors; aoqi@0: bool _balanced_monitors; aoqi@0: bool _is_c1_compilable; aoqi@0: bool _is_c2_compilable; aoqi@0: bool _can_be_statically_bound; aoqi@0: aoqi@0: // Lazy fields, filled in on demand aoqi@0: address _code; aoqi@0: ciExceptionHandler** _exception_handlers; aoqi@0: aoqi@0: // Optional liveness analyzer. aoqi@0: MethodLiveness* _liveness; aoqi@0: #if defined(COMPILER2) || defined(SHARK) aoqi@0: ciTypeFlow* _flow; aoqi@0: BCEscapeAnalyzer* _bcea; aoqi@0: #endif aoqi@0: aoqi@0: ciMethod(methodHandle h_m); aoqi@0: ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor); aoqi@0: aoqi@0: Method* get_Method() const { aoqi@0: Method* m = (Method*)_metadata; aoqi@0: assert(m != NULL, "illegal use of unloaded method"); aoqi@0: return m; aoqi@0: } aoqi@0: aoqi@0: oop loader() const { return _holder->loader(); } aoqi@0: aoqi@0: const char* type_string() { return "ciMethod"; } aoqi@0: aoqi@0: void print_impl(outputStream* st); aoqi@0: aoqi@0: void load_code(); aoqi@0: aoqi@0: void check_is_loaded() const { assert(is_loaded(), "not loaded"); } aoqi@0: aoqi@0: bool ensure_method_data(methodHandle h_m); aoqi@0: aoqi@0: void code_at_put(int bci, Bytecodes::Code code) { aoqi@0: Bytecodes::check(code); aoqi@0: assert(0 <= bci && bci < code_size(), "valid bci"); aoqi@0: address bcp = _code + bci; aoqi@0: *bcp = code; aoqi@0: } aoqi@0: aoqi@0: // Check bytecode and profile data collected are compatible aoqi@0: void assert_virtual_call_type_ok(int bci); aoqi@0: void assert_call_type_ok(int bci); aoqi@0: aoqi@0: public: aoqi@0: // Basic method information. aoqi@0: ciFlags flags() const { check_is_loaded(); return _flags; } aoqi@0: ciSymbol* name() const { return _name; } aoqi@0: ciInstanceKlass* holder() const { return _holder; } aoqi@0: ciMethodData* method_data(); aoqi@0: ciMethodData* method_data_or_null(); aoqi@0: aoqi@0: // Signature information. aoqi@0: ciSignature* signature() const { return _signature; } aoqi@0: ciType* return_type() const { return _signature->return_type(); } aoqi@0: int arg_size_no_receiver() const { return _signature->size(); } aoqi@0: // Can only be used on loaded ciMethods aoqi@0: int arg_size() const { aoqi@0: check_is_loaded(); aoqi@0: return _signature->size() + (_flags.is_static() ? 0 : 1); aoqi@0: } aoqi@0: // Report the number of elements on stack when invoking this method. aoqi@0: // This is different than the regular arg_size because invokedynamic aoqi@0: // has an implicit receiver. aoqi@0: int invoke_arg_size(Bytecodes::Code code) const { aoqi@0: if (is_loaded()) { aoqi@0: return arg_size(); aoqi@0: } else { aoqi@0: int arg_size = _signature->size(); aoqi@0: // Add a receiver argument, maybe: aoqi@0: if (code != Bytecodes::_invokestatic && aoqi@0: code != Bytecodes::_invokedynamic) { aoqi@0: arg_size++; aoqi@0: } aoqi@0: return arg_size; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: // Method code and related information. aoqi@0: address code() { if (_code == NULL) load_code(); return _code; } aoqi@0: int code_size() const { check_is_loaded(); return _code_size; } aoqi@0: int max_stack() const { check_is_loaded(); return _max_stack; } aoqi@0: int max_locals() const { check_is_loaded(); return _max_locals; } aoqi@0: vmIntrinsics::ID intrinsic_id() const { check_is_loaded(); return _intrinsic_id; } aoqi@0: bool has_exception_handlers() const { check_is_loaded(); return _handler_count > 0; } aoqi@0: int exception_table_length() const { check_is_loaded(); return _handler_count; } aoqi@0: int interpreter_invocation_count() const { check_is_loaded(); return _interpreter_invocation_count; } aoqi@0: int interpreter_throwout_count() const { check_is_loaded(); return _interpreter_throwout_count; } aoqi@0: int size_of_parameters() const { check_is_loaded(); return _size_of_parameters; } aoqi@0: aoqi@0: // Code size for inlining decisions. aoqi@0: int code_size_for_inlining(); aoqi@0: aoqi@0: bool caller_sensitive() { return get_Method()->caller_sensitive(); } aoqi@0: bool force_inline() { return get_Method()->force_inline(); } aoqi@0: bool dont_inline() { return get_Method()->dont_inline(); } aoqi@0: aoqi@0: int comp_level(); aoqi@0: int highest_osr_comp_level(); aoqi@0: aoqi@0: Bytecodes::Code java_code_at_bci(int bci) { aoqi@0: address bcp = code() + bci; aoqi@0: return Bytecodes::java_code_at(NULL, bcp); aoqi@0: } aoqi@0: Bytecodes::Code raw_code_at_bci(int bci) { aoqi@0: address bcp = code() + bci; aoqi@0: return Bytecodes::code_at(NULL, bcp); aoqi@0: } aoqi@0: BCEscapeAnalyzer *get_bcea(); aoqi@0: ciMethodBlocks *get_method_blocks(); aoqi@0: aoqi@0: bool has_linenumber_table() const; // length unknown until decompression aoqi@0: u_char* compressed_linenumber_table() const; // not preserved by gc aoqi@0: aoqi@0: int line_number_from_bci(int bci) const; aoqi@0: aoqi@0: // Runtime information. aoqi@0: int vtable_index(); aoqi@0: #ifdef SHARK aoqi@0: int itable_index(); aoqi@0: #endif // SHARK aoqi@0: address native_entry(); aoqi@0: address interpreter_entry(); aoqi@0: aoqi@0: // Analysis and profiling. aoqi@0: // aoqi@0: // Usage note: liveness_at_bci and init_vars should be wrapped in ResourceMarks. aoqi@0: bool has_monitor_bytecodes() const { return _uses_monitors; } aoqi@0: bool has_balanced_monitors(); aoqi@0: aoqi@0: // Returns a bitmap indicating which locals are required to be aoqi@0: // maintained as live for deopt. raw_liveness_at_bci is always the aoqi@0: // direct output of the liveness computation while liveness_at_bci aoqi@0: // may mark all locals as live to improve support for debugging Java aoqi@0: // code by maintaining the state of as many locals as possible. aoqi@0: MethodLivenessResult raw_liveness_at_bci(int bci); aoqi@0: MethodLivenessResult liveness_at_bci(int bci); aoqi@0: aoqi@0: // Get the interpreters viewpoint on oop liveness. MethodLiveness is aoqi@0: // conservative in the sense that it may consider locals to be live which aoqi@0: // cannot be live, like in the case where a local could contain an oop or aoqi@0: // a primitive along different paths. In that case the local must be aoqi@0: // dead when those paths merge. Since the interpreter's viewpoint is aoqi@0: // used when gc'ing an interpreter frame we need to use its viewpoint aoqi@0: // during OSR when loading the locals. aoqi@0: aoqi@0: BitMap live_local_oops_at_bci(int bci); aoqi@0: aoqi@0: #ifdef COMPILER1 aoqi@0: const BitMap bci_block_start(); aoqi@0: #endif aoqi@0: aoqi@0: ciTypeFlow* get_flow_analysis(); aoqi@0: ciTypeFlow* get_osr_flow_analysis(int osr_bci); // alternate entry point aoqi@0: ciCallProfile call_profile_at_bci(int bci); aoqi@0: int interpreter_call_site_count(int bci); aoqi@0: aoqi@0: // Does type profiling provide a useful type at this point? aoqi@0: ciKlass* argument_profiled_type(int bci, int i); aoqi@0: ciKlass* parameter_profiled_type(int i); aoqi@0: ciKlass* return_profiled_type(int bci); aoqi@0: aoqi@0: ciField* get_field_at_bci( int bci, bool &will_link); aoqi@0: ciMethod* get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature); aoqi@0: // Given a certain calling environment, find the monomorphic target aoqi@0: // for the call. Return NULL if the call is not monomorphic in aoqi@0: // its calling environment. aoqi@0: ciMethod* find_monomorphic_target(ciInstanceKlass* caller, aoqi@0: ciInstanceKlass* callee_holder, aoqi@0: ciInstanceKlass* actual_receiver); aoqi@0: aoqi@0: // Given a known receiver klass, find the target for the call. aoqi@0: // Return NULL if the call has no target or is abstract. aoqi@0: ciMethod* resolve_invoke(ciKlass* caller, ciKlass* exact_receiver); aoqi@0: aoqi@0: // Find the proper vtable index to invoke this method. aoqi@0: int resolve_vtable_index(ciKlass* caller, ciKlass* receiver); aoqi@0: aoqi@0: // Compilation directives aoqi@0: bool should_exclude(); aoqi@0: bool should_inline(); aoqi@0: bool should_not_inline(); aoqi@0: bool should_print_assembly(); aoqi@0: bool break_at_execute(); aoqi@0: bool has_option(const char *option); aoqi@0: bool can_be_compiled(); aoqi@0: bool can_be_osr_compiled(int entry_bci); aoqi@0: void set_not_compilable(const char* reason = NULL); aoqi@0: bool has_compiled_code(); aoqi@0: void log_nmethod_identity(xmlStream* log); aoqi@0: bool is_not_reached(int bci); aoqi@0: bool was_executed_more_than(int times); aoqi@0: bool has_unloaded_classes_in_signature(); aoqi@0: bool is_klass_loaded(int refinfo_index, bool must_be_resolved) const; aoqi@0: bool check_call(int refinfo_index, bool is_static) const; aoqi@0: bool ensure_method_data(); // make sure it exists in the VM also aoqi@0: MethodCounters* ensure_method_counters(); aoqi@0: int instructions_size(); aoqi@0: int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC aoqi@0: aoqi@0: // Stack walking support aoqi@0: bool is_ignored_by_security_stack_walk() const; aoqi@0: aoqi@0: // JSR 292 support aoqi@0: bool is_method_handle_intrinsic() const; aoqi@0: bool is_compiled_lambda_form() const; aoqi@0: bool has_member_arg() const; aoqi@0: aoqi@0: // What kind of ciObject is this? aoqi@0: bool is_method() const { return true; } aoqi@0: aoqi@0: // Java access flags aoqi@0: bool is_public () const { return flags().is_public(); } aoqi@0: bool is_private () const { return flags().is_private(); } aoqi@0: bool is_protected () const { return flags().is_protected(); } aoqi@0: bool is_static () const { return flags().is_static(); } aoqi@0: bool is_final () const { return flags().is_final(); } aoqi@0: bool is_synchronized() const { return flags().is_synchronized(); } aoqi@0: bool is_native () const { return flags().is_native(); } aoqi@0: bool is_interface () const { return flags().is_interface(); } aoqi@0: bool is_abstract () const { return flags().is_abstract(); } aoqi@0: bool is_strict () const { return flags().is_strict(); } aoqi@0: aoqi@0: // Other flags aoqi@0: bool is_empty_method() const; aoqi@0: bool is_vanilla_constructor() const; aoqi@0: bool is_final_method() const { return is_final() || holder()->is_final(); } aoqi@0: bool has_loops () const; aoqi@0: bool has_jsrs () const; aoqi@0: bool is_accessor () const; aoqi@0: bool is_initializer () const; aoqi@0: bool can_be_statically_bound() const { return _can_be_statically_bound; } aoqi@0: bool is_boxing_method() const; aoqi@0: bool is_unboxing_method() const; aoqi@0: aoqi@0: // Replay data methods aoqi@0: void dump_name_as_ascii(outputStream* st); aoqi@0: void dump_replay_data(outputStream* st); aoqi@0: aoqi@0: // Print the bytecodes of this method. aoqi@0: void print_codes_on(outputStream* st); aoqi@0: void print_codes() { aoqi@0: print_codes_on(tty); aoqi@0: } aoqi@0: void print_codes_on(int from, int to, outputStream* st); aoqi@0: aoqi@0: // Print the name of this method in various incarnations. aoqi@0: void print_name(outputStream* st = tty); aoqi@0: void print_short_name(outputStream* st = tty); aoqi@0: }; aoqi@0: aoqi@0: #endif // SHARE_VM_CI_CIMETHOD_HPP