duke@435: /* jrose@1934: * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_INTERPRETER_REWRITER_HPP stefank@2314: #define SHARE_VM_INTERPRETER_REWRITER_HPP stefank@2314: stefank@2314: #include "memory/allocation.hpp" stefank@2314: #include "runtime/handles.inline.hpp" stefank@2314: #include "utilities/growableArray.hpp" stefank@2314: duke@435: // The Rewriter adds caches to the constant pool and rewrites bytecode indices duke@435: // pointing into the constant pool for better interpreter performance. duke@435: jrose@1161: class Rewriter: public StackObj { duke@435: private: jrose@1161: instanceKlassHandle _klass; jrose@1161: constantPoolHandle _pool; jrose@1161: objArrayHandle _methods; jrose@1161: intArray _cp_map; jrose@1161: intStack _cp_cache_map; jrose@2015: bool _have_invoke_dynamic; jrose@1161: jrose@1161: void init_cp_map(int length) { jrose@1161: _cp_map.initialize(length, -1); jrose@1161: // Choose an initial value large enough that we don't get frequent jrose@1161: // calls to grow(). jrose@1161: _cp_cache_map.initialize(length / 2); jrose@1161: } jrose@1161: int cp_entry_to_cp_cache(int i) { assert(has_cp_cache(i), "oob"); return _cp_map[i]; } jrose@1161: bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; } jrose@1161: int maybe_add_cp_cache_entry(int i) { return has_cp_cache(i) ? _cp_map[i] : add_cp_cache_entry(i); } jrose@1161: int add_cp_cache_entry(int cp_index) { jrose@1494: assert((cp_index & _secondary_entry_tag) == 0, "bad tag"); jrose@1161: assert(_cp_map[cp_index] == -1, "not twice on same cp_index"); jrose@1161: int cache_index = _cp_cache_map.append(cp_index); jrose@1161: _cp_map.at_put(cp_index, cache_index); jrose@1161: assert(cp_entry_to_cp_cache(cp_index) == cache_index, ""); jrose@1161: return cache_index; jrose@1161: } jrose@1494: int add_secondary_cp_cache_entry(int main_cpc_entry) { jrose@1494: assert(main_cpc_entry < _cp_cache_map.length(), "must be earlier CP cache entry"); jrose@1494: int cache_index = _cp_cache_map.append(main_cpc_entry | _secondary_entry_tag); jrose@1494: return cache_index; jrose@1494: } jrose@1161: jrose@2015: // Access the contents of _cp_cache_map to determine CP cache layout. jrose@2015: int cp_cache_entry_pool_index(int cache_index) { jrose@2015: int cp_index = _cp_cache_map[cache_index]; jrose@2015: if ((cp_index & _secondary_entry_tag) != 0) jrose@2015: return -1; jrose@2015: else jrose@2015: return cp_index; jrose@2015: } jrose@2015: int cp_cache_secondary_entry_main_index(int cache_index) { jrose@2015: int cp_index = _cp_cache_map[cache_index]; jrose@2015: if ((cp_index & _secondary_entry_tag) == 0) jrose@2015: return -1; jrose@2015: else jrose@2015: return (cp_index - _secondary_entry_tag); jrose@2015: } jrose@2015: jrose@1161: // All the work goes in here: twisti@1573: Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS); jrose@1161: jrose@1161: void compute_index_maps(); jrose@1161: void make_constant_pool_cache(TRAPS); coleenp@2945: void scan_method(methodOop m, bool reverse = false); jrose@1161: void rewrite_Object_init(methodHandle m, TRAPS); coleenp@2945: void rewrite_member_reference(address bcp, int offset, bool reverse = false); coleenp@2945: void rewrite_invokedynamic(address bcp, int offset, bool reverse = false); coleenp@2945: void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse = false); coleenp@2945: // Revert bytecodes in case of an exception. coleenp@2945: void restore_bytecodes(); duke@435: coleenp@2945: static methodHandle rewrite_jsrs(methodHandle m, TRAPS); duke@435: public: jrose@1161: // Driver routine: duke@435: static void rewrite(instanceKlassHandle klass, TRAPS); twisti@1573: static void rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS); jrose@1494: jrose@1494: enum { jrose@1494: _secondary_entry_tag = nth_bit(30) jrose@1494: }; coleenp@2945: coleenp@2945: // Second pass, not gated by is_rewritten flag coleenp@2945: static void relocate_and_link(instanceKlassHandle klass, TRAPS); coleenp@2945: // JSR292 version to call with it's own methods. coleenp@2945: static void relocate_and_link(instanceKlassHandle klass, coleenp@2945: objArrayHandle methods, TRAPS); coleenp@2945: duke@435: }; stefank@2314: stefank@2314: #endif // SHARE_VM_INTERPRETER_REWRITER_HPP