Mercurial > hg > truffle
comparison src/share/vm/interpreter/rewriter.hpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | 1d7922586cf6 |
children | f6b0eb4e44cf |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
34 | 34 |
35 class Rewriter: public StackObj { | 35 class Rewriter: public StackObj { |
36 private: | 36 private: |
37 instanceKlassHandle _klass; | 37 instanceKlassHandle _klass; |
38 constantPoolHandle _pool; | 38 constantPoolHandle _pool; |
39 objArrayHandle _methods; | 39 Array<Method*>* _methods; |
40 intArray _cp_map; | 40 intArray _cp_map; |
41 intStack _cp_cache_map; | 41 intStack _cp_cache_map; // for Methodref, Fieldref, |
42 // InterfaceMethodref and InvokeDynamic | |
43 intArray _reference_map; // maps from cp index to resolved_refs index (or -1) | |
44 intStack _resolved_references_map; // for strings, methodHandle, methodType | |
45 intStack _invokedynamic_references_map; // for invokedynamic resolved refs | |
42 intArray _method_handle_invokers; | 46 intArray _method_handle_invokers; |
47 int _resolved_reference_limit; | |
43 | 48 |
44 void init_cp_map(int length) { | 49 void init_maps(int length) { |
45 _cp_map.initialize(length, -1); | 50 _cp_map.initialize(length, -1); |
46 // Choose an initial value large enough that we don't get frequent | 51 // Choose an initial value large enough that we don't get frequent |
47 // calls to grow(). | 52 // calls to grow(). |
48 _cp_cache_map.initialize(length / 2); | 53 _cp_cache_map.initialize(length / 2); |
54 // Also cache resolved objects, in another different cache. | |
55 _reference_map.initialize(length, -1); | |
56 _resolved_references_map.initialize(length / 2); | |
57 _invokedynamic_references_map.initialize(length / 2); | |
58 _resolved_reference_limit = -1; | |
59 DEBUG_ONLY(_cp_cache_index_limit = -1); | |
49 } | 60 } |
61 | |
62 int _cp_cache_index_limit; | |
63 void record_map_limits() { | |
64 #ifdef ASSERT | |
65 // Record initial size of the two arrays generated for the CP cache: | |
66 _cp_cache_index_limit = _cp_cache_map.length(); | |
67 #endif //ASSERT | |
68 _resolved_reference_limit = _resolved_references_map.length(); | |
69 } | |
70 | |
50 int cp_entry_to_cp_cache(int i) { assert(has_cp_cache(i), "oob"); return _cp_map[i]; } | 71 int cp_entry_to_cp_cache(int i) { assert(has_cp_cache(i), "oob"); return _cp_map[i]; } |
51 bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; } | 72 bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; } |
52 int maybe_add_cp_cache_entry(int i) { return has_cp_cache(i) ? _cp_map[i] : add_cp_cache_entry(i); } | 73 |
53 int add_cp_cache_entry(int cp_index) { | 74 int add_cp_cache_entry(int cp_index) { |
54 assert((cp_index & _secondary_entry_tag) == 0, "bad tag"); | 75 assert(_pool->tag_at(cp_index).value() != JVM_CONSTANT_InvokeDynamic, "use indy version"); |
55 assert(_cp_map[cp_index] == -1, "not twice on same cp_index"); | 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"); | |
56 int cache_index = _cp_cache_map.append(cp_index); | 78 int cache_index = _cp_cache_map.append(cp_index); |
57 _cp_map.at_put(cp_index, cache_index); | 79 _cp_map.at_put(cp_index, cache_index); |
58 assert(cp_entry_to_cp_cache(cp_index) == cache_index, ""); | 80 assert(cp_entry_to_cp_cache(cp_index) == cache_index, ""); |
81 assert(cp_cache_entry_pool_index(cache_index) == cp_index, ""); | |
59 return cache_index; | 82 return cache_index; |
60 } | 83 } |
61 int add_secondary_cp_cache_entry(int main_cpc_entry) { | 84 |
62 assert(main_cpc_entry < _cp_cache_map.length(), "must be earlier CP cache entry"); | 85 // add a new CP cache entry beyond the normal cache (for invokedynamic only) |
63 int cache_index = _cp_cache_map.append(main_cpc_entry | _secondary_entry_tag); | 86 int add_invokedynamic_cp_cache_entry(int cp_index) { |
87 assert(_pool->tag_at(cp_index).value() == JVM_CONSTANT_InvokeDynamic, "use non-indy version"); | |
88 assert(_cp_map[cp_index] == -1, "do not map from cp_index"); | |
89 assert(_cp_cache_index_limit >= 0, "add indy cache entries after first iteration"); | |
90 int cache_index = _cp_cache_map.append(cp_index); | |
91 assert(cache_index >= _cp_cache_index_limit, ""); | |
92 // do not update _cp_map, since the mapping is one-to-many | |
93 assert(cp_cache_entry_pool_index(cache_index) == cp_index, ""); | |
64 return cache_index; | 94 return cache_index; |
95 } | |
96 | |
97 // fix duplicated code later | |
98 int cp_entry_to_resolved_references(int cp_index) const { | |
99 assert(has_entry_in_resolved_references(cp_index), "oob"); | |
100 return _reference_map[cp_index]; | |
101 } | |
102 bool has_entry_in_resolved_references(int cp_index) const { | |
103 return (uint)cp_index < (uint)_reference_map.length() && _reference_map[cp_index] >= 0; | |
104 } | |
105 | |
106 // add a new entry to the resolved_references map | |
107 int add_resolved_references_entry(int cp_index) { | |
108 assert(_reference_map[cp_index] == -1, "not twice on same cp_index"); | |
109 assert(_resolved_reference_limit == -1, "do not add CP refs after first iteration"); | |
110 int ref_index = _resolved_references_map.append(cp_index); | |
111 _reference_map.at_put(cp_index, ref_index); | |
112 assert(cp_entry_to_resolved_references(cp_index) == ref_index, ""); | |
113 return ref_index; | |
114 } | |
115 | |
116 // add a new entry to the resolved_references map (for invokedynamic only) | |
117 int add_invokedynamic_resolved_references_entry(int cp_index, int cache_index) { | |
118 assert(_resolved_reference_limit >= 0, "must add indy refs after first iteration"); | |
119 int ref_index = _resolved_references_map.append(cp_index); // many-to-one | |
120 assert(ref_index >= _resolved_reference_limit, ""); | |
121 _invokedynamic_references_map.at_put_grow(ref_index, cache_index, -1); | |
122 return ref_index; | |
123 } | |
124 | |
125 int resolved_references_entry_to_pool_index(int ref_index) { | |
126 int cp_index = _resolved_references_map[ref_index]; | |
127 return cp_index; | |
128 } | |
129 | |
130 // invokedynamic support - append the cpCache entry (encoded) in object map. | |
131 // The resolved_references_map should still be in ascending order | |
132 // The resolved_references has the invokedynamic call site objects appended after | |
133 // the objects that are resolved in the constant pool. | |
134 int add_callsite_entry(int main_cpc_entry) { | |
135 int ref_index = _resolved_references_map.append(main_cpc_entry); | |
136 return ref_index; | |
65 } | 137 } |
66 | 138 |
67 // Access the contents of _cp_cache_map to determine CP cache layout. | 139 // Access the contents of _cp_cache_map to determine CP cache layout. |
68 int cp_cache_entry_pool_index(int cache_index) { | 140 int cp_cache_entry_pool_index(int cache_index) { |
69 int cp_index = _cp_cache_map[cache_index]; | 141 int cp_index = _cp_cache_map[cache_index]; |
70 if ((cp_index & _secondary_entry_tag) != 0) | |
71 return -1; | |
72 else | |
73 return cp_index; | 142 return cp_index; |
74 } | |
75 int cp_cache_secondary_entry_main_index(int cache_index) { | |
76 int cp_index = _cp_cache_map[cache_index]; | |
77 if ((cp_index & _secondary_entry_tag) == 0) | |
78 return -1; | |
79 else | |
80 return (cp_index - _secondary_entry_tag); | |
81 } | 143 } |
82 | 144 |
83 // All the work goes in here: | 145 // All the work goes in here: |
84 Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS); | 146 Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS); |
85 | 147 |
86 void compute_index_maps(); | 148 void compute_index_maps(); |
87 void make_constant_pool_cache(TRAPS); | 149 void make_constant_pool_cache(TRAPS); |
88 void scan_method(methodOop m, bool reverse = false); | 150 void scan_method(Method* m, bool reverse = false); |
89 void rewrite_Object_init(methodHandle m, TRAPS); | 151 void rewrite_Object_init(methodHandle m, TRAPS); |
90 void rewrite_member_reference(address bcp, int offset, bool reverse = false); | 152 void rewrite_member_reference(address bcp, int offset, bool reverse = false); |
91 void maybe_rewrite_invokehandle(address opc, int cp_index, bool reverse = false); | 153 void maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse = false); |
92 void rewrite_invokedynamic(address bcp, int offset, bool reverse = false); | 154 void rewrite_invokedynamic(address bcp, int offset, bool reverse = false); |
93 void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse = false); | 155 void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse = false); |
94 // Revert bytecodes in case of an exception. | 156 // Revert bytecodes in case of an exception. |
95 void restore_bytecodes(); | 157 void restore_bytecodes(); |
96 | 158 |
97 static methodHandle rewrite_jsrs(methodHandle m, TRAPS); | 159 static methodHandle rewrite_jsrs(methodHandle m, TRAPS); |
98 public: | 160 public: |
99 // Driver routine: | 161 // Driver routine: |
100 static void rewrite(instanceKlassHandle klass, TRAPS); | 162 static void rewrite(instanceKlassHandle klass, TRAPS); |
101 static void rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS); | 163 static void rewrite(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS); |
102 | |
103 enum { | |
104 _secondary_entry_tag = nth_bit(30) | |
105 }; | |
106 | 164 |
107 // Second pass, not gated by is_rewritten flag | 165 // Second pass, not gated by is_rewritten flag |
108 static void relocate_and_link(instanceKlassHandle klass, TRAPS); | 166 static void relocate_and_link(instanceKlassHandle klass, TRAPS); |
109 // JSR292 version to call with it's own methods. | 167 // JSR292 version to call with it's own methods. |
110 static void relocate_and_link(instanceKlassHandle klass, | 168 static void relocate_and_link(instanceKlassHandle klass, |
111 objArrayHandle methods, TRAPS); | 169 Array<Method*>* methods, TRAPS); |
112 | 170 |
113 }; | 171 }; |
114 | 172 |
115 #endif // SHARE_VM_INTERPRETER_REWRITER_HPP | 173 #endif // SHARE_VM_INTERPRETER_REWRITER_HPP |