/* * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_VM_OPTO_RUNTIME_HPP #define SHARE_VM_OPTO_RUNTIME_HPP #include "code/codeBlob.hpp" #include "opto/machnode.hpp" #include "opto/optoreg.hpp" #include "opto/type.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/rtmLocking.hpp" #include "runtime/deoptimization.hpp" #include "runtime/vframe.hpp" //------------------------------OptoRuntime------------------------------------ // Opto compiler runtime routines // // These are all generated from Ideal graphs. They are called with the // Java calling convention. Internally they call C++. They are made once at // startup time and Opto compiles calls to them later. // Things are broken up into quads: the signature they will be called with, // the address of the generated code, the corresponding C++ code and an // nmethod. // The signature (returned by "xxx_Type()") is used at startup time by the // Generator to make the generated code "xxx_Java". Opto compiles calls // to the generated code "xxx_Java". When the compiled code gets executed, // it calls the C++ code "xxx_C". The generated nmethod is saved in the // CodeCache. Exception handlers use the nmethod to get the callee-save // register OopMaps. class CallInfo; // // NamedCounters are tagged counters which can be used for profiling // code in various ways. Currently they are used by the lock coarsening code // class NamedCounter : public CHeapObj { public: enum CounterTag { NoTag, LockCounter, EliminatedLockCounter, BiasedLockingCounter, RTMLockingCounter }; private: const char * _name; int _count; CounterTag _tag; NamedCounter* _next; public: NamedCounter(const char *n, CounterTag tag = NoTag): _name(n == NULL ? NULL : os::strdup(n)), _count(0), _next(NULL), _tag(tag) {} ~NamedCounter() { if (_name != NULL) { os::free((void*)_name); } } const char * name() const { return _name; } int count() const { return _count; } address addr() { return (address)&_count; } CounterTag tag() const { return _tag; } void set_tag(CounterTag tag) { _tag = tag; } NamedCounter* next() const { return _next; } void set_next(NamedCounter* next) { assert(_next == NULL || next == NULL, "already set"); _next = next; } }; class BiasedLockingNamedCounter : public NamedCounter { private: BiasedLockingCounters _counters; public: BiasedLockingNamedCounter(const char *n) : NamedCounter(n, BiasedLockingCounter), _counters() {} BiasedLockingCounters* counters() { return &_counters; } }; class RTMLockingNamedCounter : public NamedCounter { private: RTMLockingCounters _counters; public: RTMLockingNamedCounter(const char *n) : NamedCounter(n, RTMLockingCounter), _counters() {} RTMLockingCounters* counters() { return &_counters; } }; typedef const TypeFunc*(*TypeFunc_generator)(); class OptoRuntime : public AllStatic { friend class Matcher; // allow access to stub names private: // define stubs 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); // References to generated stubs static address _new_instance_Java; static address _new_array_Java; static address _new_array_nozero_Java; static address _multianewarray2_Java; static address _multianewarray3_Java; static address _multianewarray4_Java; static address _multianewarray5_Java; static address _multianewarrayN_Java; static address _g1_wb_pre_Java; static address _g1_wb_post_Java; static address _vtable_must_compile_Java; static address _complete_monitor_locking_Java; static address _rethrow_Java; static address _slow_arraycopy_Java; static address _register_finalizer_Java; # ifdef ENABLE_ZAP_DEAD_LOCALS static address _zap_dead_Java_locals_Java; static address _zap_dead_native_locals_Java; # endif // // Implementation of runtime methods // ================================= // Allocate storage for a Java instance. static void new_instance_C(Klass* instance_klass, JavaThread *thread); // Allocate storage for a objArray or typeArray static void new_array_C(Klass* array_klass, int len, JavaThread *thread); static void new_array_nozero_C(Klass* array_klass, int len, JavaThread *thread); // Post-slow-path-allocation, pre-initializing-stores step for // implementing ReduceInitialCardMarks static void new_store_pre_barrier(JavaThread* thread); // Allocate storage for a multi-dimensional arrays // Note: needs to be fixed for arbitrary number of dimensions static void multianewarray2_C(Klass* klass, int len1, int len2, JavaThread *thread); static void multianewarray3_C(Klass* klass, int len1, int len2, int len3, JavaThread *thread); static void multianewarray4_C(Klass* klass, int len1, int len2, int len3, int len4, JavaThread *thread); static void multianewarray5_C(Klass* klass, int len1, int len2, int len3, int len4, int len5, JavaThread *thread); static void multianewarrayN_C(Klass* klass, arrayOopDesc* dims, JavaThread *thread); static void g1_wb_pre_C(oopDesc* orig, JavaThread* thread); static void g1_wb_post_C(void* card_addr, JavaThread* thread); public: // Slow-path Locking and Unlocking static void complete_monitor_locking_C(oopDesc* obj, BasicLock* lock, JavaThread* thread); static void complete_monitor_unlocking_C(oopDesc* obj, BasicLock* lock, JavaThread* thread); private: // Implicit exception support static void throw_null_exception_C(JavaThread* thread); // Exception handling static address handle_exception_C (JavaThread* thread); static address handle_exception_C_helper(JavaThread* thread, nmethod*& nm); static address rethrow_C (oopDesc* exception, JavaThread *thread, address return_pc ); static void deoptimize_caller_frame (JavaThread *thread); static void deoptimize_caller_frame (JavaThread *thread, bool doit); static bool is_deoptimized_caller_frame (JavaThread *thread); // CodeBlob support // =================================================================== static ExceptionBlob* _exception_blob; static void generate_exception_blob(); static void register_finalizer(oopDesc* obj, JavaThread* thread); // zaping dead locals, either from Java frames or from native frames # ifdef ENABLE_ZAP_DEAD_LOCALS static void zap_dead_Java_locals_C( JavaThread* thread); static void zap_dead_native_locals_C( JavaThread* thread); static void zap_dead_java_or_native_locals( JavaThread*, bool (*)(frame*)); public: static int ZapDeadCompiledLocals_count; # endif public: static bool is_callee_saved_register(MachRegisterNumbers reg); // One time only generate runtime code stubs. Returns true // when runtime stubs have been generated successfully and // false otherwise. static bool generate(ciEnv* env); // Returns the name of a stub static const char* stub_name(address entry); // access to runtime stubs entry points for java code static address new_instance_Java() { return _new_instance_Java; } static address new_array_Java() { return _new_array_Java; } static address new_array_nozero_Java() { return _new_array_nozero_Java; } static address multianewarray2_Java() { return _multianewarray2_Java; } static address multianewarray3_Java() { return _multianewarray3_Java; } static address multianewarray4_Java() { return _multianewarray4_Java; } static address multianewarray5_Java() { return _multianewarray5_Java; } static address multianewarrayN_Java() { return _multianewarrayN_Java; } static address g1_wb_pre_Java() { return _g1_wb_pre_Java; } static address g1_wb_post_Java() { return _g1_wb_post_Java; } static address vtable_must_compile_stub() { return _vtable_must_compile_Java; } static address complete_monitor_locking_Java() { return _complete_monitor_locking_Java; } static address slow_arraycopy_Java() { return _slow_arraycopy_Java; } static address register_finalizer_Java() { return _register_finalizer_Java; } # ifdef ENABLE_ZAP_DEAD_LOCALS static address zap_dead_locals_stub(bool is_native) { return is_native ? _zap_dead_native_locals_Java : _zap_dead_Java_locals_Java; } static MachNode* node_to_call_zap_dead_locals(Node* n, int block_num, bool is_native); # endif static ExceptionBlob* exception_blob() { return _exception_blob; } // Leaf routines helping with method data update static void profile_receiver_type_C(DataLayout* data, oopDesc* receiver); // Implicit exception support static void throw_div0_exception_C (JavaThread* thread); static void throw_stack_overflow_error_C(JavaThread* thread); // Exception handling static address rethrow_stub() { return _rethrow_Java; } // Type functions // ====================================================== static const TypeFunc* new_instance_Type(); // object allocation (slow case) static const TypeFunc* new_array_Type (); // [a]newarray (slow case) static const TypeFunc* multianewarray_Type(int ndim); // multianewarray static const TypeFunc* multianewarray2_Type(); // multianewarray static const TypeFunc* multianewarray3_Type(); // multianewarray static const TypeFunc* multianewarray4_Type(); // multianewarray static const TypeFunc* multianewarray5_Type(); // multianewarray static const TypeFunc* multianewarrayN_Type(); // multianewarray static const TypeFunc* g1_wb_pre_Type(); static const TypeFunc* g1_wb_post_Type(); static const TypeFunc* complete_monitor_enter_Type(); static const TypeFunc* complete_monitor_exit_Type(); static const TypeFunc* uncommon_trap_Type(); static const TypeFunc* athrow_Type(); static const TypeFunc* rethrow_Type(); static const TypeFunc* Math_D_D_Type(); // sin,cos & friends static const TypeFunc* Math_DD_D_Type(); // mod,pow & friends static const TypeFunc* modf_Type(); static const TypeFunc* l2f_Type(); static const TypeFunc* void_long_Type(); static const TypeFunc* flush_windows_Type(); // arraycopy routine types static const TypeFunc* fast_arraycopy_Type(); // bit-blasters static const TypeFunc* checkcast_arraycopy_Type(); static const TypeFunc* generic_arraycopy_Type(); static const TypeFunc* slow_arraycopy_Type(); // the full routine static const TypeFunc* array_fill_Type(); static const TypeFunc* aescrypt_block_Type(); static const TypeFunc* cipherBlockChaining_aescrypt_Type(); static const TypeFunc* sha_implCompress_Type(); static const TypeFunc* digestBase_implCompressMB_Type(); static const TypeFunc* multiplyToLen_Type(); static const TypeFunc* squareToLen_Type(); static const TypeFunc* mulAdd_Type(); static const TypeFunc* ghash_processBlocks_Type(); static const TypeFunc* updateBytesCRC32_Type(); // leaf on stack replacement interpreter accessor types static const TypeFunc* osr_end_Type(); // leaf methodData routine types static const TypeFunc* profile_receiver_type_Type(); // leaf on stack replacement interpreter accessor types static const TypeFunc* fetch_int_Type(); static const TypeFunc* fetch_long_Type(); static const TypeFunc* fetch_float_Type(); static const TypeFunc* fetch_double_Type(); static const TypeFunc* fetch_oop_Type(); static const TypeFunc* fetch_monitor_Type(); static const TypeFunc* register_finalizer_Type(); // Dtrace support static const TypeFunc* dtrace_method_entry_exit_Type(); static const TypeFunc* dtrace_object_alloc_Type(); # ifdef ENABLE_ZAP_DEAD_LOCALS static const TypeFunc* zap_dead_locals_Type(); # endif private: static NamedCounter * volatile _named_counters; public: // helper function which creates a named counter labeled with the // if they are available static NamedCounter* new_named_counter(JVMState* jvms, NamedCounter::CounterTag tag); // dumps all the named counters static void print_named_counters(); }; #endif // SHARE_VM_OPTO_RUNTIME_HPP