aoqi@0: /* aoqi@0: * Copyright (c) 1998, 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_OPTO_RUNTIME_HPP aoqi@0: #define SHARE_VM_OPTO_RUNTIME_HPP aoqi@0: aoqi@0: #include "code/codeBlob.hpp" aoqi@0: #include "opto/machnode.hpp" aoqi@0: #include "opto/type.hpp" aoqi@0: #include "runtime/biasedLocking.hpp" aoqi@0: #include "runtime/rtmLocking.hpp" aoqi@0: #include "runtime/deoptimization.hpp" aoqi@0: #include "runtime/vframe.hpp" aoqi@0: aoqi@0: //------------------------------OptoRuntime------------------------------------ aoqi@0: // Opto compiler runtime routines aoqi@0: // aoqi@0: // These are all generated from Ideal graphs. They are called with the aoqi@0: // Java calling convention. Internally they call C++. They are made once at aoqi@0: // startup time and Opto compiles calls to them later. aoqi@0: // Things are broken up into quads: the signature they will be called with, aoqi@0: // the address of the generated code, the corresponding C++ code and an aoqi@0: // nmethod. aoqi@0: aoqi@0: // The signature (returned by "xxx_Type()") is used at startup time by the aoqi@0: // Generator to make the generated code "xxx_Java". Opto compiles calls aoqi@0: // to the generated code "xxx_Java". When the compiled code gets executed, aoqi@0: // it calls the C++ code "xxx_C". The generated nmethod is saved in the aoqi@0: // CodeCache. Exception handlers use the nmethod to get the callee-save aoqi@0: // register OopMaps. aoqi@0: class CallInfo; aoqi@0: aoqi@0: // aoqi@0: // NamedCounters are tagged counters which can be used for profiling aoqi@0: // code in various ways. Currently they are used by the lock coarsening code aoqi@0: // aoqi@0: aoqi@0: class NamedCounter : public CHeapObj { aoqi@0: public: aoqi@0: enum CounterTag { aoqi@0: NoTag, aoqi@0: LockCounter, aoqi@0: EliminatedLockCounter, aoqi@0: BiasedLockingCounter, aoqi@0: RTMLockingCounter aoqi@0: }; aoqi@0: aoqi@0: private: aoqi@0: const char * _name; aoqi@0: int _count; aoqi@0: CounterTag _tag; aoqi@0: NamedCounter* _next; aoqi@0: aoqi@0: public: aoqi@0: NamedCounter(const char *n, CounterTag tag = NoTag): aoqi@0: _name(n), aoqi@0: _count(0), aoqi@0: _next(NULL), aoqi@0: _tag(tag) {} aoqi@0: aoqi@0: const char * name() const { return _name; } aoqi@0: int count() const { return _count; } aoqi@0: address addr() { return (address)&_count; } aoqi@0: CounterTag tag() const { return _tag; } aoqi@0: void set_tag(CounterTag tag) { _tag = tag; } aoqi@0: aoqi@0: NamedCounter* next() const { return _next; } aoqi@0: void set_next(NamedCounter* next) { aoqi@0: assert(_next == NULL || next == NULL, "already set"); aoqi@0: _next = next; aoqi@0: } aoqi@0: aoqi@0: }; aoqi@0: aoqi@0: class BiasedLockingNamedCounter : public NamedCounter { aoqi@0: private: aoqi@0: BiasedLockingCounters _counters; aoqi@0: aoqi@0: public: aoqi@0: BiasedLockingNamedCounter(const char *n) : aoqi@0: NamedCounter(n, BiasedLockingCounter), _counters() {} aoqi@0: aoqi@0: BiasedLockingCounters* counters() { return &_counters; } aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class RTMLockingNamedCounter : public NamedCounter { aoqi@0: private: aoqi@0: RTMLockingCounters _counters; aoqi@0: aoqi@0: public: aoqi@0: RTMLockingNamedCounter(const char *n) : aoqi@0: NamedCounter(n, RTMLockingCounter), _counters() {} aoqi@0: aoqi@0: RTMLockingCounters* counters() { return &_counters; } aoqi@0: }; aoqi@0: aoqi@0: typedef const TypeFunc*(*TypeFunc_generator)(); aoqi@0: aoqi@0: class OptoRuntime : public AllStatic { aoqi@0: friend class Matcher; // allow access to stub names aoqi@0: aoqi@0: private: aoqi@0: // define stubs aoqi@0: static address generate_stub(ciEnv* ci_env, TypeFunc_generator gen, address C_function, const char *name, int is_fancy_jump, bool pass_tls, bool save_arguments, bool return_pc); aoqi@0: aoqi@0: // References to generated stubs aoqi@0: static address _new_instance_Java; aoqi@0: static address _new_array_Java; aoqi@0: static address _new_array_nozero_Java; aoqi@0: static address _multianewarray2_Java; aoqi@0: static address _multianewarray3_Java; aoqi@0: static address _multianewarray4_Java; aoqi@0: static address _multianewarray5_Java; aoqi@0: static address _multianewarrayN_Java; aoqi@0: static address _g1_wb_pre_Java; aoqi@0: static address _g1_wb_post_Java; aoqi@0: static address _vtable_must_compile_Java; aoqi@0: static address _complete_monitor_locking_Java; aoqi@0: static address _rethrow_Java; aoqi@0: aoqi@0: static address _slow_arraycopy_Java; aoqi@0: static address _register_finalizer_Java; aoqi@0: aoqi@0: # ifdef ENABLE_ZAP_DEAD_LOCALS aoqi@0: static address _zap_dead_Java_locals_Java; aoqi@0: static address _zap_dead_native_locals_Java; aoqi@0: # endif aoqi@0: aoqi@0: aoqi@0: // aoqi@0: // Implementation of runtime methods aoqi@0: // ================================= aoqi@0: aoqi@0: // Allocate storage for a Java instance. aoqi@0: static void new_instance_C(Klass* instance_klass, JavaThread *thread); aoqi@0: aoqi@0: // Allocate storage for a objArray or typeArray aoqi@0: static void new_array_C(Klass* array_klass, int len, JavaThread *thread); aoqi@0: static void new_array_nozero_C(Klass* array_klass, int len, JavaThread *thread); aoqi@0: aoqi@0: // Post-slow-path-allocation, pre-initializing-stores step for aoqi@0: // implementing ReduceInitialCardMarks aoqi@0: static void new_store_pre_barrier(JavaThread* thread); aoqi@0: aoqi@0: // Allocate storage for a multi-dimensional arrays aoqi@0: // Note: needs to be fixed for arbitrary number of dimensions aoqi@0: static void multianewarray2_C(Klass* klass, int len1, int len2, JavaThread *thread); aoqi@0: static void multianewarray3_C(Klass* klass, int len1, int len2, int len3, JavaThread *thread); aoqi@0: static void multianewarray4_C(Klass* klass, int len1, int len2, int len3, int len4, JavaThread *thread); aoqi@0: static void multianewarray5_C(Klass* klass, int len1, int len2, int len3, int len4, int len5, JavaThread *thread); aoqi@0: static void multianewarrayN_C(Klass* klass, arrayOopDesc* dims, JavaThread *thread); aoqi@0: static void g1_wb_pre_C(oopDesc* orig, JavaThread* thread); aoqi@0: static void g1_wb_post_C(void* card_addr, JavaThread* thread); aoqi@0: aoqi@0: public: aoqi@0: // Slow-path Locking and Unlocking aoqi@0: static void complete_monitor_locking_C(oopDesc* obj, BasicLock* lock, JavaThread* thread); aoqi@0: static void complete_monitor_unlocking_C(oopDesc* obj, BasicLock* lock); aoqi@0: aoqi@0: private: aoqi@0: aoqi@0: // Implicit exception support aoqi@0: static void throw_null_exception_C(JavaThread* thread); aoqi@0: aoqi@0: // Exception handling aoqi@0: static address handle_exception_C (JavaThread* thread); aoqi@0: static address handle_exception_C_helper(JavaThread* thread, nmethod*& nm); aoqi@0: static address rethrow_C (oopDesc* exception, JavaThread *thread, address return_pc ); aoqi@0: static void deoptimize_caller_frame (JavaThread *thread); aoqi@0: static void deoptimize_caller_frame (JavaThread *thread, bool doit); aoqi@0: static bool is_deoptimized_caller_frame (JavaThread *thread); aoqi@0: aoqi@0: // CodeBlob support aoqi@0: // =================================================================== aoqi@0: aoqi@0: static ExceptionBlob* _exception_blob; aoqi@0: static void generate_exception_blob(); aoqi@0: aoqi@0: static void register_finalizer(oopDesc* obj, JavaThread* thread); aoqi@0: aoqi@0: // zaping dead locals, either from Java frames or from native frames aoqi@0: # ifdef ENABLE_ZAP_DEAD_LOCALS aoqi@0: static void zap_dead_Java_locals_C( JavaThread* thread); aoqi@0: static void zap_dead_native_locals_C( JavaThread* thread); aoqi@0: aoqi@0: static void zap_dead_java_or_native_locals( JavaThread*, bool (*)(frame*)); aoqi@0: aoqi@0: public: aoqi@0: static int ZapDeadCompiledLocals_count; aoqi@0: aoqi@0: # endif aoqi@0: aoqi@0: aoqi@0: public: aoqi@0: aoqi@0: static bool is_callee_saved_register(MachRegisterNumbers reg); aoqi@0: aoqi@0: // One time only generate runtime code stubs. Returns true aoqi@0: // when runtime stubs have been generated successfully and aoqi@0: // false otherwise. aoqi@0: static bool generate(ciEnv* env); aoqi@0: aoqi@0: // Returns the name of a stub aoqi@0: static const char* stub_name(address entry); aoqi@0: aoqi@0: // access to runtime stubs entry points for java code aoqi@0: static address new_instance_Java() { return _new_instance_Java; } aoqi@0: static address new_array_Java() { return _new_array_Java; } aoqi@0: static address new_array_nozero_Java() { return _new_array_nozero_Java; } aoqi@0: static address multianewarray2_Java() { return _multianewarray2_Java; } aoqi@0: static address multianewarray3_Java() { return _multianewarray3_Java; } aoqi@0: static address multianewarray4_Java() { return _multianewarray4_Java; } aoqi@0: static address multianewarray5_Java() { return _multianewarray5_Java; } aoqi@0: static address multianewarrayN_Java() { return _multianewarrayN_Java; } aoqi@0: static address g1_wb_pre_Java() { return _g1_wb_pre_Java; } aoqi@0: static address g1_wb_post_Java() { return _g1_wb_post_Java; } aoqi@0: static address vtable_must_compile_stub() { return _vtable_must_compile_Java; } aoqi@0: static address complete_monitor_locking_Java() { return _complete_monitor_locking_Java; } aoqi@0: aoqi@0: static address slow_arraycopy_Java() { return _slow_arraycopy_Java; } aoqi@0: static address register_finalizer_Java() { return _register_finalizer_Java; } aoqi@0: aoqi@0: aoqi@0: # ifdef ENABLE_ZAP_DEAD_LOCALS aoqi@0: static address zap_dead_locals_stub(bool is_native) { return is_native aoqi@0: ? _zap_dead_native_locals_Java aoqi@0: : _zap_dead_Java_locals_Java; } aoqi@0: static MachNode* node_to_call_zap_dead_locals(Node* n, int block_num, bool is_native); aoqi@0: # endif aoqi@0: aoqi@0: static ExceptionBlob* exception_blob() { return _exception_blob; } aoqi@0: aoqi@0: // Leaf routines helping with method data update aoqi@0: static void profile_receiver_type_C(DataLayout* data, oopDesc* receiver); aoqi@0: aoqi@0: // Implicit exception support aoqi@0: static void throw_div0_exception_C (JavaThread* thread); aoqi@0: static void throw_stack_overflow_error_C(JavaThread* thread); aoqi@0: aoqi@0: // Exception handling aoqi@0: static address rethrow_stub() { return _rethrow_Java; } aoqi@0: aoqi@0: aoqi@0: // Type functions aoqi@0: // ====================================================== aoqi@0: aoqi@0: static const TypeFunc* new_instance_Type(); // object allocation (slow case) aoqi@0: static const TypeFunc* new_array_Type (); // [a]newarray (slow case) aoqi@0: static const TypeFunc* multianewarray_Type(int ndim); // multianewarray aoqi@0: static const TypeFunc* multianewarray2_Type(); // multianewarray aoqi@0: static const TypeFunc* multianewarray3_Type(); // multianewarray aoqi@0: static const TypeFunc* multianewarray4_Type(); // multianewarray aoqi@0: static const TypeFunc* multianewarray5_Type(); // multianewarray aoqi@0: static const TypeFunc* multianewarrayN_Type(); // multianewarray aoqi@0: static const TypeFunc* g1_wb_pre_Type(); aoqi@0: static const TypeFunc* g1_wb_post_Type(); aoqi@0: static const TypeFunc* complete_monitor_enter_Type(); aoqi@0: static const TypeFunc* complete_monitor_exit_Type(); aoqi@0: static const TypeFunc* uncommon_trap_Type(); aoqi@0: static const TypeFunc* athrow_Type(); aoqi@0: static const TypeFunc* rethrow_Type(); aoqi@0: static const TypeFunc* Math_D_D_Type(); // sin,cos & friends aoqi@0: static const TypeFunc* Math_DD_D_Type(); // mod,pow & friends aoqi@0: static const TypeFunc* modf_Type(); aoqi@0: static const TypeFunc* l2f_Type(); aoqi@0: static const TypeFunc* void_long_Type(); aoqi@0: aoqi@0: static const TypeFunc* flush_windows_Type(); aoqi@0: aoqi@0: // arraycopy routine types aoqi@0: static const TypeFunc* fast_arraycopy_Type(); // bit-blasters aoqi@0: static const TypeFunc* checkcast_arraycopy_Type(); aoqi@0: static const TypeFunc* generic_arraycopy_Type(); aoqi@0: static const TypeFunc* slow_arraycopy_Type(); // the full routine aoqi@0: aoqi@0: static const TypeFunc* array_fill_Type(); aoqi@0: aoqi@0: static const TypeFunc* aescrypt_block_Type(); aoqi@0: static const TypeFunc* cipherBlockChaining_aescrypt_Type(); aoqi@0: aoqi@0: static const TypeFunc* updateBytesCRC32_Type(); aoqi@0: aoqi@0: // leaf on stack replacement interpreter accessor types aoqi@0: static const TypeFunc* osr_end_Type(); aoqi@0: aoqi@0: // leaf methodData routine types aoqi@0: static const TypeFunc* profile_receiver_type_Type(); aoqi@0: aoqi@0: // leaf on stack replacement interpreter accessor types aoqi@0: static const TypeFunc* fetch_int_Type(); aoqi@0: static const TypeFunc* fetch_long_Type(); aoqi@0: static const TypeFunc* fetch_float_Type(); aoqi@0: static const TypeFunc* fetch_double_Type(); aoqi@0: static const TypeFunc* fetch_oop_Type(); aoqi@0: static const TypeFunc* fetch_monitor_Type(); aoqi@0: aoqi@0: static const TypeFunc* register_finalizer_Type(); aoqi@0: aoqi@0: // Dtrace support aoqi@0: static const TypeFunc* dtrace_method_entry_exit_Type(); aoqi@0: static const TypeFunc* dtrace_object_alloc_Type(); aoqi@0: aoqi@0: # ifdef ENABLE_ZAP_DEAD_LOCALS aoqi@0: static const TypeFunc* zap_dead_locals_Type(); aoqi@0: # endif aoqi@0: aoqi@0: private: aoqi@0: static NamedCounter * volatile _named_counters; aoqi@0: aoqi@0: public: aoqi@0: // helper function which creates a named counter labeled with the aoqi@0: // if they are available aoqi@0: static NamedCounter* new_named_counter(JVMState* jvms, NamedCounter::CounterTag tag); aoqi@0: aoqi@0: // dumps all the named counters aoqi@0: static void print_named_counters(); aoqi@0: aoqi@0: }; aoqi@0: aoqi@0: #endif // SHARE_VM_OPTO_RUNTIME_HPP