annotate src/share/vm/runtime/relocator.cpp @ 1721:413ad0331a0c

6977924: Changes for 6975078 produce build error with certain gcc versions Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error. Reviewed-by: jcoomes, ysr, phh
author johnc
date Wed, 18 Aug 2010 10:59:06 -0700
parents c18cbe5936b8
children a4c7fe54bf3f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
2 * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_relocator.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 #define MAX_METHOD_LENGTH 65535
a61af66fc99e Initial load
duke
parents:
diff changeset
29
a61af66fc99e Initial load
duke
parents:
diff changeset
30 #define MAX_SHORT ((1 << 15) - 1)
a61af66fc99e Initial load
duke
parents:
diff changeset
31 #define MIN_SHORT (- (1 << 15))
a61af66fc99e Initial load
duke
parents:
diff changeset
32
a61af66fc99e Initial load
duke
parents:
diff changeset
33 // Encapsulates a code change request. There are 3 types.
a61af66fc99e Initial load
duke
parents:
diff changeset
34 // General instruction, jump instruction, and table/lookup switches
a61af66fc99e Initial load
duke
parents:
diff changeset
35 //
a61af66fc99e Initial load
duke
parents:
diff changeset
36 class ChangeItem : public ResourceObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
37 int _bci;
a61af66fc99e Initial load
duke
parents:
diff changeset
38 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
39 ChangeItem(int bci) { _bci = bci; }
a61af66fc99e Initial load
duke
parents:
diff changeset
40 virtual bool handle_code_change(Relocator *r) = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
41
a61af66fc99e Initial load
duke
parents:
diff changeset
42 // type info
a61af66fc99e Initial load
duke
parents:
diff changeset
43 virtual bool is_widen() { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
44 virtual bool is_jump_widen() { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
45 virtual bool is_switch_pad() { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
46
a61af66fc99e Initial load
duke
parents:
diff changeset
47 // accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
48 int bci() { return _bci; }
a61af66fc99e Initial load
duke
parents:
diff changeset
49 void relocate(int break_bci, int delta) { if (_bci > break_bci) { _bci += delta; } }
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51 virtual bool adjust(int bci, int delta) { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
52
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // debug
a61af66fc99e Initial load
duke
parents:
diff changeset
54 virtual void print() = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
55 };
a61af66fc99e Initial load
duke
parents:
diff changeset
56
a61af66fc99e Initial load
duke
parents:
diff changeset
57 class ChangeWiden : public ChangeItem {
a61af66fc99e Initial load
duke
parents:
diff changeset
58 int _new_ilen; // New length of instruction at bci
a61af66fc99e Initial load
duke
parents:
diff changeset
59 u_char* _inst_buffer; // New bytecodes
a61af66fc99e Initial load
duke
parents:
diff changeset
60 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
61 ChangeWiden(int bci, int new_ilen, u_char* inst_buffer) : ChangeItem(bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
62 _new_ilen = new_ilen;
a61af66fc99e Initial load
duke
parents:
diff changeset
63 _inst_buffer = inst_buffer;
a61af66fc99e Initial load
duke
parents:
diff changeset
64 }
a61af66fc99e Initial load
duke
parents:
diff changeset
65
a61af66fc99e Initial load
duke
parents:
diff changeset
66 // Callback to do instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
67 bool handle_code_change(Relocator *r) { return r->handle_widen(bci(), _new_ilen, _inst_buffer); };
a61af66fc99e Initial load
duke
parents:
diff changeset
68
a61af66fc99e Initial load
duke
parents:
diff changeset
69 bool is_widen() { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
70
a61af66fc99e Initial load
duke
parents:
diff changeset
71 void print() { tty->print_cr("ChangeWiden. bci: %d New_ilen: %d", bci(), _new_ilen); }
a61af66fc99e Initial load
duke
parents:
diff changeset
72 };
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 class ChangeJumpWiden : public ChangeItem {
a61af66fc99e Initial load
duke
parents:
diff changeset
75 int _delta; // New length of instruction at bci
a61af66fc99e Initial load
duke
parents:
diff changeset
76 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
77 ChangeJumpWiden(int bci, int delta) : ChangeItem(bci) { _delta = delta; }
a61af66fc99e Initial load
duke
parents:
diff changeset
78
a61af66fc99e Initial load
duke
parents:
diff changeset
79 // Callback to do instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
80 bool handle_code_change(Relocator *r) { return r->handle_jump_widen(bci(), _delta); };
a61af66fc99e Initial load
duke
parents:
diff changeset
81
a61af66fc99e Initial load
duke
parents:
diff changeset
82 bool is_jump_widen() { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // If the bci matches, adjust the delta in the change jump request.
a61af66fc99e Initial load
duke
parents:
diff changeset
85 bool adjust(int jump_bci, int delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
86 if (bci() == jump_bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
87 if (_delta > 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
88 _delta += delta;
a61af66fc99e Initial load
duke
parents:
diff changeset
89 else
a61af66fc99e Initial load
duke
parents:
diff changeset
90 _delta -= delta;
a61af66fc99e Initial load
duke
parents:
diff changeset
91 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
92 }
a61af66fc99e Initial load
duke
parents:
diff changeset
93 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
94 }
a61af66fc99e Initial load
duke
parents:
diff changeset
95
a61af66fc99e Initial load
duke
parents:
diff changeset
96 void print() { tty->print_cr("ChangeJumpWiden. bci: %d Delta: %d", bci(), _delta); }
a61af66fc99e Initial load
duke
parents:
diff changeset
97 };
a61af66fc99e Initial load
duke
parents:
diff changeset
98
a61af66fc99e Initial load
duke
parents:
diff changeset
99 class ChangeSwitchPad : public ChangeItem {
a61af66fc99e Initial load
duke
parents:
diff changeset
100 int _padding;
a61af66fc99e Initial load
duke
parents:
diff changeset
101 bool _is_lookup_switch;
a61af66fc99e Initial load
duke
parents:
diff changeset
102 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
103 ChangeSwitchPad(int bci, int padding, bool is_lookup_switch) : ChangeItem(bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
104 _padding = padding;
a61af66fc99e Initial load
duke
parents:
diff changeset
105 _is_lookup_switch = is_lookup_switch;
a61af66fc99e Initial load
duke
parents:
diff changeset
106 }
a61af66fc99e Initial load
duke
parents:
diff changeset
107
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // Callback to do instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
109 bool handle_code_change(Relocator *r) { return r->handle_switch_pad(bci(), _padding, _is_lookup_switch); };
a61af66fc99e Initial load
duke
parents:
diff changeset
110
a61af66fc99e Initial load
duke
parents:
diff changeset
111 bool is_switch_pad() { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
112 int padding() { return _padding; }
a61af66fc99e Initial load
duke
parents:
diff changeset
113 bool is_lookup_switch() { return _is_lookup_switch; }
a61af66fc99e Initial load
duke
parents:
diff changeset
114
a61af66fc99e Initial load
duke
parents:
diff changeset
115 void print() { tty->print_cr("ChangeSwitchPad. bci: %d Padding: %d IsLookupSwitch: %d", bci(), _padding, _is_lookup_switch); }
a61af66fc99e Initial load
duke
parents:
diff changeset
116 };
a61af66fc99e Initial load
duke
parents:
diff changeset
117
a61af66fc99e Initial load
duke
parents:
diff changeset
118 //-----------------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // Relocator code
a61af66fc99e Initial load
duke
parents:
diff changeset
120
a61af66fc99e Initial load
duke
parents:
diff changeset
121 Relocator::Relocator(methodHandle m, RelocatorListener* listener) {
a61af66fc99e Initial load
duke
parents:
diff changeset
122 set_method(m);
a61af66fc99e Initial load
duke
parents:
diff changeset
123 set_code_length(method()->code_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
124 set_code_array(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
125 // Allocate code array and copy bytecodes
a61af66fc99e Initial load
duke
parents:
diff changeset
126 if (!expand_code_array(0)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
127 // Should have at least MAX_METHOD_LENGTH available or the verifier
a61af66fc99e Initial load
duke
parents:
diff changeset
128 // would have failed.
a61af66fc99e Initial load
duke
parents:
diff changeset
129 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
131 set_compressed_line_number_table(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
132 set_compressed_line_number_table_size(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
133 _listener = listener;
a61af66fc99e Initial load
duke
parents:
diff changeset
134 }
a61af66fc99e Initial load
duke
parents:
diff changeset
135
a61af66fc99e Initial load
duke
parents:
diff changeset
136 // size is the new size of the instruction at bci. Hence, if size is less than the current
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // instruction sice, we will shrink the code.
a61af66fc99e Initial load
duke
parents:
diff changeset
138 methodHandle Relocator::insert_space_at(int bci, int size, u_char inst_buffer[], TRAPS) {
a61af66fc99e Initial load
duke
parents:
diff changeset
139 _changes = new GrowableArray<ChangeItem*> (10);
a61af66fc99e Initial load
duke
parents:
diff changeset
140 _changes->push(new ChangeWiden(bci, size, inst_buffer));
a61af66fc99e Initial load
duke
parents:
diff changeset
141
a61af66fc99e Initial load
duke
parents:
diff changeset
142 if (TraceRelocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
143 tty->print_cr("Space at: %d Size: %d", bci, size);
a61af66fc99e Initial load
duke
parents:
diff changeset
144 _method->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
145 _method->print_codes();
a61af66fc99e Initial load
duke
parents:
diff changeset
146 tty->print_cr("-------------------------------------------------");
a61af66fc99e Initial load
duke
parents:
diff changeset
147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
148
a61af66fc99e Initial load
duke
parents:
diff changeset
149 if (!handle_code_changes()) return methodHandle();
a61af66fc99e Initial load
duke
parents:
diff changeset
150
a61af66fc99e Initial load
duke
parents:
diff changeset
151 // Construct the new method
a61af66fc99e Initial load
duke
parents:
diff changeset
152 methodHandle new_method = methodOopDesc::clone_with_new_data(method(),
a61af66fc99e Initial load
duke
parents:
diff changeset
153 code_array(), code_length(),
a61af66fc99e Initial load
duke
parents:
diff changeset
154 compressed_line_number_table(),
a61af66fc99e Initial load
duke
parents:
diff changeset
155 compressed_line_number_table_size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
156 CHECK_(methodHandle()));
a61af66fc99e Initial load
duke
parents:
diff changeset
157 set_method(new_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
158
a61af66fc99e Initial load
duke
parents:
diff changeset
159 if (TraceRelocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
160 tty->print_cr("-------------------------------------------------");
a61af66fc99e Initial load
duke
parents:
diff changeset
161 tty->print_cr("new method");
a61af66fc99e Initial load
duke
parents:
diff changeset
162 _method->print_codes();
a61af66fc99e Initial load
duke
parents:
diff changeset
163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
164
a61af66fc99e Initial load
duke
parents:
diff changeset
165 return new_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
167
a61af66fc99e Initial load
duke
parents:
diff changeset
168
a61af66fc99e Initial load
duke
parents:
diff changeset
169 bool Relocator::handle_code_changes() {
a61af66fc99e Initial load
duke
parents:
diff changeset
170 assert(_changes != NULL, "changes vector must be initialized");
a61af66fc99e Initial load
duke
parents:
diff changeset
171
a61af66fc99e Initial load
duke
parents:
diff changeset
172 while (!_changes->is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
173 // Inv: everything is aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
174 ChangeItem* ci = _changes->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
175
a61af66fc99e Initial load
duke
parents:
diff changeset
176 if (TraceRelocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
177 ci->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
179
a61af66fc99e Initial load
duke
parents:
diff changeset
180 // Execute operation
a61af66fc99e Initial load
duke
parents:
diff changeset
181 if (!ci->handle_code_change(this)) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
182
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // Shuffel items up
a61af66fc99e Initial load
duke
parents:
diff changeset
184 for (int index = 1; index < _changes->length(); index++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
185 _changes->at_put(index-1, _changes->at(index));
a61af66fc99e Initial load
duke
parents:
diff changeset
186 }
a61af66fc99e Initial load
duke
parents:
diff changeset
187 _changes->pop();
a61af66fc99e Initial load
duke
parents:
diff changeset
188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
189 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
191
a61af66fc99e Initial load
duke
parents:
diff changeset
192
a61af66fc99e Initial load
duke
parents:
diff changeset
193 bool Relocator::is_opcode_lookupswitch(Bytecodes::Code bc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
194 switch (bc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
195 case Bytecodes::_tableswitch: return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
196 case Bytecodes::_lookupswitch: // not rewritten on ia64
a61af66fc99e Initial load
duke
parents:
diff changeset
197 case Bytecodes::_fast_linearswitch: // rewritten _lookupswitch
a61af66fc99e Initial load
duke
parents:
diff changeset
198 case Bytecodes::_fast_binaryswitch: return true; // rewritten _lookupswitch
a61af66fc99e Initial load
duke
parents:
diff changeset
199 default: ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
201 return true; // dummy
a61af66fc99e Initial load
duke
parents:
diff changeset
202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
203
a61af66fc99e Initial load
duke
parents:
diff changeset
204 // We need a special instruction size method, since lookupswitches and tableswitches might not be
a61af66fc99e Initial load
duke
parents:
diff changeset
205 // properly alligned during relocation
a61af66fc99e Initial load
duke
parents:
diff changeset
206 int Relocator::rc_instr_len(int bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
207 Bytecodes::Code bc= code_at(bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
208 switch (bc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // In the case of switch instructions, see if we have the original
a61af66fc99e Initial load
duke
parents:
diff changeset
210 // padding recorded.
a61af66fc99e Initial load
duke
parents:
diff changeset
211 case Bytecodes::_tableswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
212 case Bytecodes::_lookupswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
213 case Bytecodes::_fast_linearswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
214 case Bytecodes::_fast_binaryswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
215 {
a61af66fc99e Initial load
duke
parents:
diff changeset
216 int pad = get_orig_switch_pad(bci, is_opcode_lookupswitch(bc));
a61af66fc99e Initial load
duke
parents:
diff changeset
217 if (pad == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
218 return instruction_length_at(bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
220 // Otherwise, depends on the switch type.
a61af66fc99e Initial load
duke
parents:
diff changeset
221 switch (bc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
222 case Bytecodes::_tableswitch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
223 int lo = int_at(bci + 1 + pad + 4 * 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
224 int hi = int_at(bci + 1 + pad + 4 * 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
225 int n = hi - lo + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
226 return 1 + pad + 4*(3 + n);
a61af66fc99e Initial load
duke
parents:
diff changeset
227 }
a61af66fc99e Initial load
duke
parents:
diff changeset
228 case Bytecodes::_lookupswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
229 case Bytecodes::_fast_linearswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
230 case Bytecodes::_fast_binaryswitch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
231 int npairs = int_at(bci + 1 + pad + 4 * 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
232 return 1 + pad + 4*(2 + 2*npairs);
a61af66fc99e Initial load
duke
parents:
diff changeset
233 }
a61af66fc99e Initial load
duke
parents:
diff changeset
234 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
235 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
239 return instruction_length_at(bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 // If a change item is recorded for "pc", with type "ct", returns the
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // associated padding, else -1.
a61af66fc99e Initial load
duke
parents:
diff changeset
244 int Relocator::get_orig_switch_pad(int bci, bool is_lookup_switch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
245 for (int k = 0; k < _changes->length(); k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
246 ChangeItem* ci = _changes->at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
247 if (ci->is_switch_pad()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
248 ChangeSwitchPad* csp = (ChangeSwitchPad*)ci;
a61af66fc99e Initial load
duke
parents:
diff changeset
249 if (csp->is_lookup_switch() == is_lookup_switch && csp->bci() == bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
250 return csp->padding();
a61af66fc99e Initial load
duke
parents:
diff changeset
251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
252 }
a61af66fc99e Initial load
duke
parents:
diff changeset
253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
254 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
255 }
a61af66fc99e Initial load
duke
parents:
diff changeset
256
a61af66fc99e Initial load
duke
parents:
diff changeset
257
a61af66fc99e Initial load
duke
parents:
diff changeset
258 // Push a ChangeJumpWiden if it doesn't already exist on the work queue,
a61af66fc99e Initial load
duke
parents:
diff changeset
259 // otherwise adjust the item already there by delta. The calculation for
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // new_delta is wrong for this because it uses the offset stored in the
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // code stream itself which wasn't fixed when item was pushed on the work queue.
a61af66fc99e Initial load
duke
parents:
diff changeset
262 void Relocator::push_jump_widen(int bci, int delta, int new_delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
263 for (int j = 0; j < _changes->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
264 ChangeItem* ci = _changes->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
265 if (ci->adjust(bci, delta)) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
266 }
a61af66fc99e Initial load
duke
parents:
diff changeset
267 _changes->push(new ChangeJumpWiden(bci, new_delta));
a61af66fc99e Initial load
duke
parents:
diff changeset
268 }
a61af66fc99e Initial load
duke
parents:
diff changeset
269
a61af66fc99e Initial load
duke
parents:
diff changeset
270
a61af66fc99e Initial load
duke
parents:
diff changeset
271 // The current instruction of "c" is a jump; one of its offset starts
a61af66fc99e Initial load
duke
parents:
diff changeset
272 // at "offset" and is a short if "isShort" is "TRUE",
a61af66fc99e Initial load
duke
parents:
diff changeset
273 // and an integer otherwise. If the jump crosses "breakPC", change
a61af66fc99e Initial load
duke
parents:
diff changeset
274 // the span of the jump by "delta".
a61af66fc99e Initial load
duke
parents:
diff changeset
275 void Relocator::change_jump(int bci, int offset, bool is_short, int break_bci, int delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
276 int bci_delta = (is_short) ? short_at(offset) : int_at(offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
277 int targ = bci + bci_delta;
a61af66fc99e Initial load
duke
parents:
diff changeset
278
a61af66fc99e Initial load
duke
parents:
diff changeset
279 if ((bci <= break_bci && targ > break_bci) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
280 (bci > break_bci && targ <= break_bci)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
281 int new_delta;
a61af66fc99e Initial load
duke
parents:
diff changeset
282 if (bci_delta > 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
283 new_delta = bci_delta + delta;
a61af66fc99e Initial load
duke
parents:
diff changeset
284 else
a61af66fc99e Initial load
duke
parents:
diff changeset
285 new_delta = bci_delta - delta;
a61af66fc99e Initial load
duke
parents:
diff changeset
286
a61af66fc99e Initial load
duke
parents:
diff changeset
287 if (is_short && ((new_delta > MAX_SHORT) || new_delta < MIN_SHORT)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
288 push_jump_widen(bci, delta, new_delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
289 } else if (is_short) {
a61af66fc99e Initial load
duke
parents:
diff changeset
290 short_at_put(offset, new_delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
291 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
292 int_at_put(offset, new_delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
293 }
a61af66fc99e Initial load
duke
parents:
diff changeset
294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
296
a61af66fc99e Initial load
duke
parents:
diff changeset
297
a61af66fc99e Initial load
duke
parents:
diff changeset
298 // Changes all jumps crossing "break_bci" by "delta". May enqueue things
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // on "rc->changes"
a61af66fc99e Initial load
duke
parents:
diff changeset
300 void Relocator::change_jumps(int break_bci, int delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
301 int bci = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
302 Bytecodes::Code bc;
a61af66fc99e Initial load
duke
parents:
diff changeset
303 // Now, adjust any affected instructions.
a61af66fc99e Initial load
duke
parents:
diff changeset
304 while (bci < code_length()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
305 switch (bc= code_at(bci)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
306 case Bytecodes::_ifeq:
a61af66fc99e Initial load
duke
parents:
diff changeset
307 case Bytecodes::_ifne:
a61af66fc99e Initial load
duke
parents:
diff changeset
308 case Bytecodes::_iflt:
a61af66fc99e Initial load
duke
parents:
diff changeset
309 case Bytecodes::_ifge:
a61af66fc99e Initial load
duke
parents:
diff changeset
310 case Bytecodes::_ifgt:
a61af66fc99e Initial load
duke
parents:
diff changeset
311 case Bytecodes::_ifle:
a61af66fc99e Initial load
duke
parents:
diff changeset
312 case Bytecodes::_if_icmpeq:
a61af66fc99e Initial load
duke
parents:
diff changeset
313 case Bytecodes::_if_icmpne:
a61af66fc99e Initial load
duke
parents:
diff changeset
314 case Bytecodes::_if_icmplt:
a61af66fc99e Initial load
duke
parents:
diff changeset
315 case Bytecodes::_if_icmpge:
a61af66fc99e Initial load
duke
parents:
diff changeset
316 case Bytecodes::_if_icmpgt:
a61af66fc99e Initial load
duke
parents:
diff changeset
317 case Bytecodes::_if_icmple:
a61af66fc99e Initial load
duke
parents:
diff changeset
318 case Bytecodes::_if_acmpeq:
a61af66fc99e Initial load
duke
parents:
diff changeset
319 case Bytecodes::_if_acmpne:
a61af66fc99e Initial load
duke
parents:
diff changeset
320 case Bytecodes::_ifnull:
a61af66fc99e Initial load
duke
parents:
diff changeset
321 case Bytecodes::_ifnonnull:
a61af66fc99e Initial load
duke
parents:
diff changeset
322 case Bytecodes::_goto:
a61af66fc99e Initial load
duke
parents:
diff changeset
323 case Bytecodes::_jsr:
a61af66fc99e Initial load
duke
parents:
diff changeset
324 change_jump(bci, bci+1, true, break_bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
325 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
326 case Bytecodes::_goto_w:
a61af66fc99e Initial load
duke
parents:
diff changeset
327 case Bytecodes::_jsr_w:
a61af66fc99e Initial load
duke
parents:
diff changeset
328 change_jump(bci, bci+1, false, break_bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
329 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
330 case Bytecodes::_tableswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
331 case Bytecodes::_lookupswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
332 case Bytecodes::_fast_linearswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
333 case Bytecodes::_fast_binaryswitch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
334 int recPad = get_orig_switch_pad(bci, (bc != Bytecodes::_tableswitch));
a61af66fc99e Initial load
duke
parents:
diff changeset
335 int oldPad = (recPad != -1) ? recPad : align(bci+1) - (bci+1);
a61af66fc99e Initial load
duke
parents:
diff changeset
336 if (bci > break_bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
337 int new_bci = bci + delta;
a61af66fc99e Initial load
duke
parents:
diff changeset
338 int newPad = align(new_bci+1) - (new_bci+1);
a61af66fc99e Initial load
duke
parents:
diff changeset
339 // Do we need to check the padding?
a61af66fc99e Initial load
duke
parents:
diff changeset
340 if (newPad != oldPad) {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 if (recPad == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
342 _changes->push(new ChangeSwitchPad(bci, oldPad, (bc != Bytecodes::_tableswitch)));
a61af66fc99e Initial load
duke
parents:
diff changeset
343 }
a61af66fc99e Initial load
duke
parents:
diff changeset
344 }
a61af66fc99e Initial load
duke
parents:
diff changeset
345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
346
a61af66fc99e Initial load
duke
parents:
diff changeset
347 // Then the rest, which depend on the kind of switch.
a61af66fc99e Initial load
duke
parents:
diff changeset
348 switch (bc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
349 case Bytecodes::_tableswitch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
350 change_jump(bci, bci +1 + oldPad, false, break_bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
351 // We cannot use the Bytecode_tableswitch abstraction, since the padding might not be correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
352 int lo = int_at(bci + 1 + oldPad + 4 * 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
353 int hi = int_at(bci + 1 + oldPad + 4 * 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
354 int n = hi - lo + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
355 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
356 change_jump(bci, bci +1 + oldPad + 4*(k+3), false, break_bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
357 }
a61af66fc99e Initial load
duke
parents:
diff changeset
358 // Special next-bci calculation here...
a61af66fc99e Initial load
duke
parents:
diff changeset
359 bci += 1 + oldPad + (n+3)*4;
a61af66fc99e Initial load
duke
parents:
diff changeset
360 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
361 }
a61af66fc99e Initial load
duke
parents:
diff changeset
362 case Bytecodes::_lookupswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
363 case Bytecodes::_fast_linearswitch:
a61af66fc99e Initial load
duke
parents:
diff changeset
364 case Bytecodes::_fast_binaryswitch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
365 change_jump(bci, bci +1 + oldPad, false, break_bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
366 // We cannot use the Bytecode_lookupswitch abstraction, since the padding might not be correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
367 int npairs = int_at(bci + 1 + oldPad + 4 * 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
368 for (int k = 0; k < npairs; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
369 change_jump(bci, bci + 1 + oldPad + 4*(2 + 2*k + 1), false, break_bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
371 /* Special next-bci calculation here... */
a61af66fc99e Initial load
duke
parents:
diff changeset
372 bci += 1 + oldPad + (2 + (npairs*2))*4;
a61af66fc99e Initial load
duke
parents:
diff changeset
373 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
374 }
a61af66fc99e Initial load
duke
parents:
diff changeset
375 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
376 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
377 }
a61af66fc99e Initial load
duke
parents:
diff changeset
378 }
a61af66fc99e Initial load
duke
parents:
diff changeset
379 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
380 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
382 bci += rc_instr_len(bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
383 }
a61af66fc99e Initial load
duke
parents:
diff changeset
384 }
a61af66fc99e Initial load
duke
parents:
diff changeset
385
a61af66fc99e Initial load
duke
parents:
diff changeset
386 // The width of instruction at "pc" is changing by "delta". Adjust the
a61af66fc99e Initial load
duke
parents:
diff changeset
387 // exception table, if any, of "rc->mb".
a61af66fc99e Initial load
duke
parents:
diff changeset
388 void Relocator::adjust_exception_table(int bci, int delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
389 typeArrayOop table = method()->exception_table();
a61af66fc99e Initial load
duke
parents:
diff changeset
390 for (int index = 0; index < table->length(); index +=4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
391 if (table->int_at(index) > bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
392 table->int_at_put(index+0, table->int_at(index+0) + delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
393 table->int_at_put(index+1, table->int_at(index+1) + delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
394 } else if (bci < table->int_at(index+1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
395 table->int_at_put(index+1, table->int_at(index+1) + delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
396 }
a61af66fc99e Initial load
duke
parents:
diff changeset
397 if (table->int_at(index+2) > bci)
a61af66fc99e Initial load
duke
parents:
diff changeset
398 table->int_at_put(index+2, table->int_at(index+2) + delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
399 }
a61af66fc99e Initial load
duke
parents:
diff changeset
400 }
a61af66fc99e Initial load
duke
parents:
diff changeset
401
a61af66fc99e Initial load
duke
parents:
diff changeset
402
a61af66fc99e Initial load
duke
parents:
diff changeset
403 // The width of instruction at "bci" is changing by "delta". Adjust the line number table.
a61af66fc99e Initial load
duke
parents:
diff changeset
404 void Relocator::adjust_line_no_table(int bci, int delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
405 if (method()->has_linenumber_table()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
406 CompressedLineNumberReadStream reader(method()->compressed_linenumber_table());
a61af66fc99e Initial load
duke
parents:
diff changeset
407 CompressedLineNumberWriteStream writer(64); // plenty big for most line number tables
a61af66fc99e Initial load
duke
parents:
diff changeset
408 while (reader.read_pair()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
409 int adjustment = (reader.bci() > bci) ? delta : 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
410 writer.write_pair(reader.bci() + adjustment, reader.line());
a61af66fc99e Initial load
duke
parents:
diff changeset
411 }
a61af66fc99e Initial load
duke
parents:
diff changeset
412 writer.write_terminator();
a61af66fc99e Initial load
duke
parents:
diff changeset
413 set_compressed_line_number_table(writer.buffer());
a61af66fc99e Initial load
duke
parents:
diff changeset
414 set_compressed_line_number_table_size(writer.position());
a61af66fc99e Initial load
duke
parents:
diff changeset
415 }
a61af66fc99e Initial load
duke
parents:
diff changeset
416 }
a61af66fc99e Initial load
duke
parents:
diff changeset
417
a61af66fc99e Initial load
duke
parents:
diff changeset
418
a61af66fc99e Initial load
duke
parents:
diff changeset
419 // The width of instruction at "bci" is changing by "delta". Adjust the local variable table.
a61af66fc99e Initial load
duke
parents:
diff changeset
420 void Relocator::adjust_local_var_table(int bci, int delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
421 int localvariable_table_length = method()->localvariable_table_length();
a61af66fc99e Initial load
duke
parents:
diff changeset
422 if (localvariable_table_length > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
423 LocalVariableTableElement* table = method()->localvariable_table_start();
a61af66fc99e Initial load
duke
parents:
diff changeset
424 for (int i = 0; i < localvariable_table_length; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
425 u2 current_bci = table[i].start_bci;
a61af66fc99e Initial load
duke
parents:
diff changeset
426 if (current_bci > bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
427 table[i].start_bci = current_bci + delta;
a61af66fc99e Initial load
duke
parents:
diff changeset
428 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
429 u2 current_length = table[i].length;
a61af66fc99e Initial load
duke
parents:
diff changeset
430 if (current_bci + current_length > bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
431 table[i].length = current_length + delta;
a61af66fc99e Initial load
duke
parents:
diff changeset
432 }
a61af66fc99e Initial load
duke
parents:
diff changeset
433 }
a61af66fc99e Initial load
duke
parents:
diff changeset
434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
435 }
a61af66fc99e Initial load
duke
parents:
diff changeset
436 }
a61af66fc99e Initial load
duke
parents:
diff changeset
437
a61af66fc99e Initial load
duke
parents:
diff changeset
438
a61af66fc99e Initial load
duke
parents:
diff changeset
439 bool Relocator::expand_code_array(int delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
440 int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100);
a61af66fc99e Initial load
duke
parents:
diff changeset
441
a61af66fc99e Initial load
duke
parents:
diff changeset
442 if (length > MAX_METHOD_LENGTH) {
a61af66fc99e Initial load
duke
parents:
diff changeset
443 if (delta == 0 && code_length() <= MAX_METHOD_LENGTH) {
a61af66fc99e Initial load
duke
parents:
diff changeset
444 length = MAX_METHOD_LENGTH;
a61af66fc99e Initial load
duke
parents:
diff changeset
445 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
446 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
448 }
a61af66fc99e Initial load
duke
parents:
diff changeset
449
a61af66fc99e Initial load
duke
parents:
diff changeset
450 unsigned char* new_code_array = NEW_RESOURCE_ARRAY(unsigned char, length);
a61af66fc99e Initial load
duke
parents:
diff changeset
451 if (!new_code_array) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
452
a61af66fc99e Initial load
duke
parents:
diff changeset
453 // Expanding current array
a61af66fc99e Initial load
duke
parents:
diff changeset
454 if (code_array() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
455 memcpy(new_code_array, code_array(), code_length());
a61af66fc99e Initial load
duke
parents:
diff changeset
456 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
457 // Initial copy. Copy directly from methodOop
a61af66fc99e Initial load
duke
parents:
diff changeset
458 memcpy(new_code_array, method()->code_base(), code_length());
a61af66fc99e Initial load
duke
parents:
diff changeset
459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
460
a61af66fc99e Initial load
duke
parents:
diff changeset
461 set_code_array(new_code_array);
a61af66fc99e Initial load
duke
parents:
diff changeset
462 set_code_array_length(length);
a61af66fc99e Initial load
duke
parents:
diff changeset
463
a61af66fc99e Initial load
duke
parents:
diff changeset
464 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
465 }
a61af66fc99e Initial load
duke
parents:
diff changeset
466
a61af66fc99e Initial load
duke
parents:
diff changeset
467
a61af66fc99e Initial load
duke
parents:
diff changeset
468 // The instruction at "bci", whose size is "ilen", is changing size by
a61af66fc99e Initial load
duke
parents:
diff changeset
469 // "delta". Reallocate, move code, recalculate jumps, and enqueue
a61af66fc99e Initial load
duke
parents:
diff changeset
470 // change items as necessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
471 bool Relocator::relocate_code(int bci, int ilen, int delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
472 int next_bci = bci + ilen;
a61af66fc99e Initial load
duke
parents:
diff changeset
473 if (delta > 0 && code_length() + delta > code_array_length()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
474 // Expand allocated code space, if necessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
475 if (!expand_code_array(delta)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
476 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
477 }
a61af66fc99e Initial load
duke
parents:
diff changeset
478 }
a61af66fc99e Initial load
duke
parents:
diff changeset
479
a61af66fc99e Initial load
duke
parents:
diff changeset
480 // We require 4-byte alignment of code arrays.
a61af66fc99e Initial load
duke
parents:
diff changeset
481 assert(((intptr_t)code_array() & 3) == 0, "check code alignment");
a61af66fc99e Initial load
duke
parents:
diff changeset
482 // Change jumps before doing the copying; this routine requires aligned switches.
a61af66fc99e Initial load
duke
parents:
diff changeset
483 change_jumps(bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
484
a61af66fc99e Initial load
duke
parents:
diff changeset
485 // In case we have shrunken a tableswitch/lookupswitch statement, we store the last
a61af66fc99e Initial load
duke
parents:
diff changeset
486 // bytes that get overwritten. We have to copy the bytes after the change_jumps method
a61af66fc99e Initial load
duke
parents:
diff changeset
487 // has been called, since it is likly to update last offset in a tableswitch/lookupswitch
a61af66fc99e Initial load
duke
parents:
diff changeset
488 if (delta < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
489 assert(delta>=-3, "we cannot overwrite more than 3 bytes");
a61af66fc99e Initial load
duke
parents:
diff changeset
490 memcpy(_overwrite, addr_at(bci + ilen + delta), -delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
491 }
a61af66fc99e Initial load
duke
parents:
diff changeset
492
a61af66fc99e Initial load
duke
parents:
diff changeset
493 memmove(addr_at(next_bci + delta), addr_at(next_bci), code_length() - next_bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
494 set_code_length(code_length() + delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
495 // Also adjust exception tables...
a61af66fc99e Initial load
duke
parents:
diff changeset
496 adjust_exception_table(bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
497 // Line number tables...
a61af66fc99e Initial load
duke
parents:
diff changeset
498 adjust_line_no_table(bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
499 // And local variable table...
a61af66fc99e Initial load
duke
parents:
diff changeset
500 adjust_local_var_table(bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
501
a61af66fc99e Initial load
duke
parents:
diff changeset
502 // Relocate the pending change stack...
a61af66fc99e Initial load
duke
parents:
diff changeset
503 for (int j = 0; j < _changes->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
504 ChangeItem* ci = _changes->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
505 ci->relocate(bci, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
507
a61af66fc99e Initial load
duke
parents:
diff changeset
508 // Notify any listeners about code relocation
a61af66fc99e Initial load
duke
parents:
diff changeset
509 notify(bci, delta, code_length());
a61af66fc99e Initial load
duke
parents:
diff changeset
510
a61af66fc99e Initial load
duke
parents:
diff changeset
511 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
512 }
a61af66fc99e Initial load
duke
parents:
diff changeset
513
a61af66fc99e Initial load
duke
parents:
diff changeset
514 // relocate a general instruction. Called by ChangeWiden class
a61af66fc99e Initial load
duke
parents:
diff changeset
515 bool Relocator::handle_widen(int bci, int new_ilen, u_char inst_buffer[]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
516 int ilen = rc_instr_len(bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
517 if (!relocate_code(bci, ilen, new_ilen - ilen))
a61af66fc99e Initial load
duke
parents:
diff changeset
518 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
519
a61af66fc99e Initial load
duke
parents:
diff changeset
520 // Insert new bytecode(s)
a61af66fc99e Initial load
duke
parents:
diff changeset
521 for(int k = 0; k < new_ilen; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
522 code_at_put(bci + k, (Bytecodes::Code)inst_buffer[k]);
a61af66fc99e Initial load
duke
parents:
diff changeset
523 }
a61af66fc99e Initial load
duke
parents:
diff changeset
524
a61af66fc99e Initial load
duke
parents:
diff changeset
525 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
526 }
a61af66fc99e Initial load
duke
parents:
diff changeset
527
a61af66fc99e Initial load
duke
parents:
diff changeset
528 // handle jump_widen instruction. Called be ChangeJumpWiden class
a61af66fc99e Initial load
duke
parents:
diff changeset
529 bool Relocator::handle_jump_widen(int bci, int delta) {
a61af66fc99e Initial load
duke
parents:
diff changeset
530 int ilen = rc_instr_len(bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
531
a61af66fc99e Initial load
duke
parents:
diff changeset
532 Bytecodes::Code bc = code_at(bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
533 switch (bc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
534 case Bytecodes::_ifeq:
a61af66fc99e Initial load
duke
parents:
diff changeset
535 case Bytecodes::_ifne:
a61af66fc99e Initial load
duke
parents:
diff changeset
536 case Bytecodes::_iflt:
a61af66fc99e Initial load
duke
parents:
diff changeset
537 case Bytecodes::_ifge:
a61af66fc99e Initial load
duke
parents:
diff changeset
538 case Bytecodes::_ifgt:
a61af66fc99e Initial load
duke
parents:
diff changeset
539 case Bytecodes::_ifle:
a61af66fc99e Initial load
duke
parents:
diff changeset
540 case Bytecodes::_if_icmpeq:
a61af66fc99e Initial load
duke
parents:
diff changeset
541 case Bytecodes::_if_icmpne:
a61af66fc99e Initial load
duke
parents:
diff changeset
542 case Bytecodes::_if_icmplt:
a61af66fc99e Initial load
duke
parents:
diff changeset
543 case Bytecodes::_if_icmpge:
a61af66fc99e Initial load
duke
parents:
diff changeset
544 case Bytecodes::_if_icmpgt:
a61af66fc99e Initial load
duke
parents:
diff changeset
545 case Bytecodes::_if_icmple:
a61af66fc99e Initial load
duke
parents:
diff changeset
546 case Bytecodes::_if_acmpeq:
a61af66fc99e Initial load
duke
parents:
diff changeset
547 case Bytecodes::_if_acmpne:
a61af66fc99e Initial load
duke
parents:
diff changeset
548 case Bytecodes::_ifnull:
a61af66fc99e Initial load
duke
parents:
diff changeset
549 case Bytecodes::_ifnonnull: {
a61af66fc99e Initial load
duke
parents:
diff changeset
550 const int goto_length = Bytecodes::length_for(Bytecodes::_goto);
a61af66fc99e Initial load
duke
parents:
diff changeset
551
a61af66fc99e Initial load
duke
parents:
diff changeset
552 // If 'if' points to the next bytecode after goto, it's already handled.
a61af66fc99e Initial load
duke
parents:
diff changeset
553 // it shouldn't be.
a61af66fc99e Initial load
duke
parents:
diff changeset
554 assert (short_at(bci+1) != ilen+goto_length, "if relocation already handled");
a61af66fc99e Initial load
duke
parents:
diff changeset
555 assert(ilen == 3, "check length");
a61af66fc99e Initial load
duke
parents:
diff changeset
556
a61af66fc99e Initial load
duke
parents:
diff changeset
557 // Convert to 0 if <cond> goto 6
a61af66fc99e Initial load
duke
parents:
diff changeset
558 // 3 _goto 11
a61af66fc99e Initial load
duke
parents:
diff changeset
559 // 6 _goto_w <wide delta offset>
a61af66fc99e Initial load
duke
parents:
diff changeset
560 // 11 <else code>
a61af66fc99e Initial load
duke
parents:
diff changeset
561 const int goto_w_length = Bytecodes::length_for(Bytecodes::_goto_w);
a61af66fc99e Initial load
duke
parents:
diff changeset
562 const int add_bci = goto_length + goto_w_length;
a61af66fc99e Initial load
duke
parents:
diff changeset
563
a61af66fc99e Initial load
duke
parents:
diff changeset
564 if (!relocate_code(bci, 3, /*delta*/add_bci)) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
565
a61af66fc99e Initial load
duke
parents:
diff changeset
566 // if bytecode points to goto_w instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
567 short_at_put(bci + 1, ilen + goto_length);
a61af66fc99e Initial load
duke
parents:
diff changeset
568
a61af66fc99e Initial load
duke
parents:
diff changeset
569 int cbci = bci + ilen;
a61af66fc99e Initial load
duke
parents:
diff changeset
570 // goto around
a61af66fc99e Initial load
duke
parents:
diff changeset
571 code_at_put(cbci, Bytecodes::_goto);
a61af66fc99e Initial load
duke
parents:
diff changeset
572 short_at_put(cbci + 1, add_bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
573 // goto_w <wide delta>
a61af66fc99e Initial load
duke
parents:
diff changeset
574 cbci = cbci + goto_length;
a61af66fc99e Initial load
duke
parents:
diff changeset
575 code_at_put(cbci, Bytecodes::_goto_w);
a61af66fc99e Initial load
duke
parents:
diff changeset
576 if (delta > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
577 delta += 2; // goto_w is 2 bytes more than "if" code
a61af66fc99e Initial load
duke
parents:
diff changeset
578 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
579 delta -= ilen+goto_length; // branch starts at goto_w offset
a61af66fc99e Initial load
duke
parents:
diff changeset
580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
581 int_at_put(cbci + 1, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
582 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
583
a61af66fc99e Initial load
duke
parents:
diff changeset
584 }
a61af66fc99e Initial load
duke
parents:
diff changeset
585 case Bytecodes::_goto:
a61af66fc99e Initial load
duke
parents:
diff changeset
586 case Bytecodes::_jsr:
a61af66fc99e Initial load
duke
parents:
diff changeset
587 assert(ilen == 3, "check length");
a61af66fc99e Initial load
duke
parents:
diff changeset
588
a61af66fc99e Initial load
duke
parents:
diff changeset
589 if (!relocate_code(bci, 3, 2)) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
590 if (bc == Bytecodes::_goto)
a61af66fc99e Initial load
duke
parents:
diff changeset
591 code_at_put(bci, Bytecodes::_goto_w);
a61af66fc99e Initial load
duke
parents:
diff changeset
592 else
a61af66fc99e Initial load
duke
parents:
diff changeset
593 code_at_put(bci, Bytecodes::_jsr_w);
a61af66fc99e Initial load
duke
parents:
diff changeset
594
a61af66fc99e Initial load
duke
parents:
diff changeset
595 // If it's a forward jump, add 2 for the widening.
a61af66fc99e Initial load
duke
parents:
diff changeset
596 if (delta > 0) delta += 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
597 int_at_put(bci + 1, delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
598 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
599
a61af66fc99e Initial load
duke
parents:
diff changeset
600 default: ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
601 }
a61af66fc99e Initial load
duke
parents:
diff changeset
602
a61af66fc99e Initial load
duke
parents:
diff changeset
603 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
605
a61af66fc99e Initial load
duke
parents:
diff changeset
606 // handle lookup/table switch instructions. Called be ChangeSwitchPad class
a61af66fc99e Initial load
duke
parents:
diff changeset
607 bool Relocator::handle_switch_pad(int bci, int old_pad, bool is_lookup_switch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
608 int ilen = rc_instr_len(bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
609 int new_pad = align(bci+1) - (bci+1);
a61af66fc99e Initial load
duke
parents:
diff changeset
610 int pad_delta = new_pad - old_pad;
a61af66fc99e Initial load
duke
parents:
diff changeset
611 if (pad_delta != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
612 int len;
a61af66fc99e Initial load
duke
parents:
diff changeset
613 if (!is_lookup_switch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
614 int low = int_at(bci+1+old_pad+4);
a61af66fc99e Initial load
duke
parents:
diff changeset
615 int high = int_at(bci+1+old_pad+8);
a61af66fc99e Initial load
duke
parents:
diff changeset
616 len = high-low+1 + 3; // 3 for default, hi, lo.
a61af66fc99e Initial load
duke
parents:
diff changeset
617 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
618 int npairs = int_at(bci+1+old_pad+4);
a61af66fc99e Initial load
duke
parents:
diff changeset
619 len = npairs*2 + 2; // 2 for default, npairs.
a61af66fc99e Initial load
duke
parents:
diff changeset
620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
621 // Because "relocateCode" does a "changeJumps" loop,
a61af66fc99e Initial load
duke
parents:
diff changeset
622 // which parses instructions to determine their length,
a61af66fc99e Initial load
duke
parents:
diff changeset
623 // we need to call that before messing with the current
a61af66fc99e Initial load
duke
parents:
diff changeset
624 // instruction. Since it may also overwrite the current
a61af66fc99e Initial load
duke
parents:
diff changeset
625 // instruction when moving down, remember the possibly
a61af66fc99e Initial load
duke
parents:
diff changeset
626 // overwritten part.
a61af66fc99e Initial load
duke
parents:
diff changeset
627
a61af66fc99e Initial load
duke
parents:
diff changeset
628 // Move the code following the instruction...
a61af66fc99e Initial load
duke
parents:
diff changeset
629 if (!relocate_code(bci, ilen, pad_delta)) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
630
a61af66fc99e Initial load
duke
parents:
diff changeset
631 if (pad_delta < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
632 // Move the shrunken instruction down.
a61af66fc99e Initial load
duke
parents:
diff changeset
633 memmove(addr_at(bci + 1 + new_pad),
a61af66fc99e Initial load
duke
parents:
diff changeset
634 addr_at(bci + 1 + old_pad),
a61af66fc99e Initial load
duke
parents:
diff changeset
635 len * 4 + pad_delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
636 memmove(addr_at(bci + 1 + new_pad + len*4 + pad_delta),
a61af66fc99e Initial load
duke
parents:
diff changeset
637 _overwrite, -pad_delta);
a61af66fc99e Initial load
duke
parents:
diff changeset
638 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
639 assert(pad_delta > 0, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
640 // Move the expanded instruction up.
a61af66fc99e Initial load
duke
parents:
diff changeset
641 memmove(addr_at(bci +1 + new_pad),
a61af66fc99e Initial load
duke
parents:
diff changeset
642 addr_at(bci +1 + old_pad),
a61af66fc99e Initial load
duke
parents:
diff changeset
643 len * 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
645 }
a61af66fc99e Initial load
duke
parents:
diff changeset
646 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
647 }