rewriter.hpp 7.5 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * 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.
 *
19 20 21
 * 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.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30 31
#ifndef SHARE_VM_INTERPRETER_REWRITER_HPP
#define SHARE_VM_INTERPRETER_REWRITER_HPP

#include "memory/allocation.hpp"
#include "runtime/handles.inline.hpp"
#include "utilities/growableArray.hpp"

D
duke 已提交
32 33 34
// The Rewriter adds caches to the constant pool and rewrites bytecode indices
// pointing into the constant pool for better interpreter performance.

35
class Rewriter: public StackObj {
D
duke 已提交
36
 private:
37 38
  instanceKlassHandle _klass;
  constantPoolHandle  _pool;
39
  Array<Method*>*     _methods;
40
  intArray            _cp_map;
41 42 43 44 45
  intStack            _cp_cache_map;        // for Methodref, Fieldref,
                                            // InterfaceMethodref and InvokeDynamic
  intArray            _reference_map;       // maps from cp index to resolved_refs index (or -1)
  intStack            _resolved_references_map;    // for strings, methodHandle, methodType
  intStack            _invokedynamic_references_map; // for invokedynamic resolved refs
46
  intArray            _method_handle_invokers;
47
  int                 _resolved_reference_limit;
48

49
  void init_maps(int length) {
50 51 52 53
    _cp_map.initialize(length, -1);
    // Choose an initial value large enough that we don't get frequent
    // calls to grow().
    _cp_cache_map.initialize(length / 2);
54 55 56 57 58 59
    // Also cache resolved objects, in another different cache.
    _reference_map.initialize(length, -1);
    _resolved_references_map.initialize(length / 2);
    _invokedynamic_references_map.initialize(length / 2);
    _resolved_reference_limit = -1;
    DEBUG_ONLY(_cp_cache_index_limit = -1);
60
  }
61 62 63 64 65 66 67 68 69 70

  int _cp_cache_index_limit;
  void record_map_limits() {
#ifdef ASSERT
    // Record initial size of the two arrays generated for the CP cache:
    _cp_cache_index_limit = _cp_cache_map.length();
#endif //ASSERT
    _resolved_reference_limit = _resolved_references_map.length();
  }

71 72
  int  cp_entry_to_cp_cache(int i) { assert(has_cp_cache(i), "oob"); return _cp_map[i]; }
  bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; }
73

74
  int add_cp_cache_entry(int cp_index) {
75
    assert(_pool->tag_at(cp_index).value() != JVM_CONSTANT_InvokeDynamic, "use indy version");
76
    assert(_cp_map[cp_index] == -1, "not twice on same cp_index");
77
    assert(_cp_cache_index_limit == -1, "do not add cache entries after first iteration");
78 79 80
    int cache_index = _cp_cache_map.append(cp_index);
    _cp_map.at_put(cp_index, cache_index);
    assert(cp_entry_to_cp_cache(cp_index) == cache_index, "");
81
    assert(cp_cache_entry_pool_index(cache_index) == cp_index, "");
82 83
    return cache_index;
  }
84 85 86 87 88 89 90 91 92 93

  // add a new CP cache entry beyond the normal cache (for invokedynamic only)
  int add_invokedynamic_cp_cache_entry(int cp_index) {
    assert(_pool->tag_at(cp_index).value() == JVM_CONSTANT_InvokeDynamic, "use non-indy version");
    assert(_cp_map[cp_index] == -1, "do not map from cp_index");
    assert(_cp_cache_index_limit >= 0, "add indy cache entries after first iteration");
    int cache_index = _cp_cache_map.append(cp_index);
    assert(cache_index >= _cp_cache_index_limit, "");
    // do not update _cp_map, since the mapping is one-to-many
    assert(cp_cache_entry_pool_index(cache_index) == cp_index, "");
94 95
    return cache_index;
  }
96

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
  // fix duplicated code later
  int  cp_entry_to_resolved_references(int cp_index) const {
    assert(has_entry_in_resolved_references(cp_index), "oob");
    return _reference_map[cp_index];
  }
  bool has_entry_in_resolved_references(int cp_index) const {
    return (uint)cp_index < (uint)_reference_map.length() && _reference_map[cp_index] >= 0;
  }

  // add a new entry to the resolved_references map
  int add_resolved_references_entry(int cp_index) {
    assert(_reference_map[cp_index] == -1, "not twice on same cp_index");
    assert(_resolved_reference_limit == -1, "do not add CP refs after first iteration");
    int ref_index = _resolved_references_map.append(cp_index);
    _reference_map.at_put(cp_index, ref_index);
    assert(cp_entry_to_resolved_references(cp_index) == ref_index, "");
    return ref_index;
  }

  // add a new entry to the resolved_references map (for invokedynamic only)
  int add_invokedynamic_resolved_references_entry(int cp_index, int cache_index) {
    assert(_resolved_reference_limit >= 0, "must add indy refs after first iteration");
    int ref_index = _resolved_references_map.append(cp_index);  // many-to-one
    assert(ref_index >= _resolved_reference_limit, "");
    _invokedynamic_references_map.at_put_grow(ref_index, cache_index, -1);
    return ref_index;
  }

  int resolved_references_entry_to_pool_index(int ref_index) {
    int cp_index = _resolved_references_map[ref_index];
    return cp_index;
  }

  // invokedynamic support - append the cpCache entry (encoded) in object map.
  // The resolved_references_map should still be in ascending order
  // The resolved_references has the invokedynamic call site objects appended after
  // the objects that are resolved in the constant pool.
  int add_callsite_entry(int main_cpc_entry) {
    int ref_index = _resolved_references_map.append(main_cpc_entry);
    return ref_index;
  }

139 140 141 142 143 144
  // Access the contents of _cp_cache_map to determine CP cache layout.
  int cp_cache_entry_pool_index(int cache_index) {
    int cp_index = _cp_cache_map[cache_index];
      return cp_index;
  }

145
  // All the work goes in here:
146
  Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS);
147 148 149

  void compute_index_maps();
  void make_constant_pool_cache(TRAPS);
150
  void scan_method(Method* m, bool reverse = false);
151
  void rewrite_Object_init(methodHandle m, TRAPS);
152
  void rewrite_member_reference(address bcp, int offset, bool reverse = false);
153
  void maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse = false);
154 155 156 157
  void rewrite_invokedynamic(address bcp, int offset, bool reverse = false);
  void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse = false);
  // Revert bytecodes in case of an exception.
  void restore_bytecodes();
D
duke 已提交
158

159
  static methodHandle rewrite_jsrs(methodHandle m, TRAPS);
D
duke 已提交
160
 public:
161
  // Driver routine:
D
duke 已提交
162
  static void rewrite(instanceKlassHandle klass, TRAPS);
163
  static void rewrite(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS);
164 165 166 167 168

  // Second pass, not gated by is_rewritten flag
  static void relocate_and_link(instanceKlassHandle klass, TRAPS);
  // JSR292 version to call with it's own methods.
  static void relocate_and_link(instanceKlassHandle klass,
169
                                Array<Method*>* methods, TRAPS);
170

D
duke 已提交
171
};
172 173

#endif // SHARE_VM_INTERPRETER_REWRITER_HPP