1692
|
1 /*
|
|
2 * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
|
|
3 * Copyright 2008, 2009 Red Hat, Inc.
|
|
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
5 *
|
|
6 * This code is free software; you can redistribute it and/or modify it
|
|
7 * under the terms of the GNU General Public License version 2 only, as
|
|
8 * published by the Free Software Foundation.
|
|
9 *
|
|
10 * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
13 * version 2 for more details (a copy is included in the LICENSE file that
|
|
14 * accompanied this code).
|
|
15 *
|
|
16 * You should have received a copy of the GNU General Public License version
|
|
17 * 2 along with this work; if not, write to the Free Software Foundation,
|
|
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
19 *
|
|
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
21 * or visit www.oracle.com if you need additional information or have any
|
|
22 * questions.
|
|
23 *
|
|
24 */
|
|
25
|
|
26 // Class hierarchy:
|
|
27 // - SharkStateScanner
|
|
28 // - SharkCacherDecacher
|
|
29 // - SharkDecacher
|
|
30 // - SharkJavaCallDecacher
|
|
31 // - SharkVMCallDecacher
|
|
32 // - SharkTrapDecacher
|
|
33 // - SharkCacher
|
|
34 // - SharkJavaCallCacher
|
|
35 // - SharkVMCallCacher
|
|
36 // - SharkFunctionEntryCacher
|
|
37 // - SharkNormalEntryCacher
|
|
38 // - SharkOSREntryCacher
|
|
39
|
|
40 class SharkCacherDecacher : public SharkStateScanner {
|
|
41 protected:
|
|
42 SharkCacherDecacher(SharkFunction* function)
|
|
43 : SharkStateScanner(function) {}
|
|
44
|
|
45 // Helper
|
|
46 protected:
|
|
47 static int adjusted_offset(SharkValue* value, int offset) {
|
|
48 if (value->is_two_word())
|
|
49 offset--;
|
|
50 return offset;
|
|
51 }
|
|
52 };
|
|
53
|
|
54 class SharkDecacher : public SharkCacherDecacher {
|
|
55 protected:
|
|
56 SharkDecacher(SharkFunction* function, int bci)
|
|
57 : SharkCacherDecacher(function), _bci(bci) {}
|
|
58
|
|
59 private:
|
|
60 int _bci;
|
|
61
|
|
62 protected:
|
|
63 int bci() const {
|
|
64 return _bci;
|
|
65 }
|
|
66
|
|
67 private:
|
|
68 int _pc_offset;
|
|
69 OopMap* _oopmap;
|
|
70 GrowableArray<ScopeValue*>* _exparray;
|
|
71 GrowableArray<MonitorValue*>* _monarray;
|
|
72 GrowableArray<ScopeValue*>* _locarray;
|
|
73
|
|
74 private:
|
|
75 int pc_offset() const {
|
|
76 return _pc_offset;
|
|
77 }
|
|
78 OopMap* oopmap() const {
|
|
79 return _oopmap;
|
|
80 }
|
|
81 GrowableArray<ScopeValue*>* exparray() const {
|
|
82 return _exparray;
|
|
83 }
|
|
84 GrowableArray<MonitorValue*>* monarray() const {
|
|
85 return _monarray;
|
|
86 }
|
|
87 GrowableArray<ScopeValue*>* locarray() const {
|
|
88 return _locarray;
|
|
89 }
|
|
90
|
|
91 // Callbacks
|
|
92 protected:
|
|
93 void start_frame();
|
|
94
|
|
95 void start_stack(int stack_depth);
|
|
96 void process_stack_slot(int index, SharkValue** value, int offset);
|
|
97
|
|
98 void start_monitors(int num_monitors);
|
|
99 void process_monitor(int index, int box_offset, int obj_offset);
|
|
100
|
|
101 void process_oop_tmp_slot(llvm::Value** value, int offset);
|
|
102 void process_method_slot(llvm::Value** value, int offset);
|
|
103 void process_pc_slot(int offset);
|
|
104
|
|
105 void start_locals();
|
|
106 void process_local_slot(int index, SharkValue** value, int offset);
|
|
107
|
|
108 void end_frame();
|
|
109
|
|
110 // oopmap and debuginfo helpers
|
|
111 private:
|
|
112 static int oopmap_slot_munge(int offset) {
|
|
113 return SharkStack::oopmap_slot_munge(offset);
|
|
114 }
|
|
115 static VMReg slot2reg(int offset) {
|
|
116 return SharkStack::slot2reg(offset);
|
|
117 }
|
|
118 static Location slot2loc(int offset, Location::Type type) {
|
|
119 return Location::new_stk_loc(type, offset * wordSize);
|
|
120 }
|
|
121 static LocationValue* slot2lv(int offset, Location::Type type) {
|
|
122 return new LocationValue(slot2loc(offset, type));
|
|
123 }
|
|
124 static Location::Type location_type(SharkValue** addr, bool maybe_two_word) {
|
|
125 // low addresses this end
|
|
126 // Type 32-bit 64-bit
|
|
127 // ----------------------------------------------------
|
|
128 // stack[0] local[3] jobject oop oop
|
|
129 // stack[1] local[2] NULL normal lng
|
|
130 // stack[2] local[1] jlong normal invalid
|
|
131 // stack[3] local[0] jint normal normal
|
|
132 //
|
|
133 // high addresses this end
|
|
134
|
|
135 SharkValue *value = *addr;
|
|
136 if (value) {
|
|
137 if (value->is_jobject())
|
|
138 return Location::oop;
|
|
139 #ifdef _LP64
|
|
140 if (value->is_two_word())
|
|
141 return Location::invalid;
|
|
142 #endif // _LP64
|
|
143 return Location::normal;
|
|
144 }
|
|
145 else {
|
|
146 if (maybe_two_word) {
|
|
147 value = *(addr - 1);
|
|
148 if (value && value->is_two_word()) {
|
|
149 #ifdef _LP64
|
|
150 if (value->is_jlong())
|
|
151 return Location::lng;
|
|
152 if (value->is_jdouble())
|
|
153 return Location::dbl;
|
|
154 ShouldNotReachHere();
|
|
155 #else
|
|
156 return Location::normal;
|
|
157 #endif // _LP64
|
|
158 }
|
|
159 }
|
|
160 return Location::invalid;
|
|
161 }
|
|
162 }
|
|
163
|
|
164 // Stack slot helpers
|
|
165 protected:
|
|
166 virtual bool stack_slot_needs_write(int index, SharkValue* value) = 0;
|
|
167 virtual bool stack_slot_needs_oopmap(int index, SharkValue* value) = 0;
|
|
168 virtual bool stack_slot_needs_debuginfo(int index, SharkValue* value) = 0;
|
|
169
|
|
170 static Location::Type stack_location_type(int index, SharkValue** addr) {
|
|
171 return location_type(addr, *addr == NULL);
|
|
172 }
|
|
173
|
|
174 // Local slot helpers
|
|
175 protected:
|
|
176 virtual bool local_slot_needs_write(int index, SharkValue* value) = 0;
|
|
177 virtual bool local_slot_needs_oopmap(int index, SharkValue* value) = 0;
|
|
178 virtual bool local_slot_needs_debuginfo(int index, SharkValue* value) = 0;
|
|
179
|
|
180 static Location::Type local_location_type(int index, SharkValue** addr) {
|
|
181 return location_type(addr, index > 0);
|
|
182 }
|
|
183
|
|
184 // Writer helper
|
|
185 protected:
|
|
186 void write_value_to_frame(const llvm::Type* type,
|
|
187 llvm::Value* value,
|
|
188 int offset);
|
|
189 };
|
|
190
|
|
191 class SharkJavaCallDecacher : public SharkDecacher {
|
|
192 public:
|
|
193 SharkJavaCallDecacher(SharkFunction* function, int bci, ciMethod* callee)
|
|
194 : SharkDecacher(function, bci), _callee(callee) {}
|
|
195
|
|
196 private:
|
|
197 ciMethod* _callee;
|
|
198
|
|
199 protected:
|
|
200 ciMethod* callee() const {
|
|
201 return _callee;
|
|
202 }
|
|
203
|
|
204 // Stack slot helpers
|
|
205 protected:
|
|
206 bool stack_slot_needs_write(int index, SharkValue* value) {
|
|
207 return value && (index < callee()->arg_size() || value->is_jobject());
|
|
208 }
|
|
209 bool stack_slot_needs_oopmap(int index, SharkValue* value) {
|
|
210 return value && value->is_jobject() && index >= callee()->arg_size();
|
|
211 }
|
|
212 bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
213 return index >= callee()->arg_size();
|
|
214 }
|
|
215
|
|
216 // Local slot helpers
|
|
217 protected:
|
|
218 bool local_slot_needs_write(int index, SharkValue* value) {
|
|
219 return value && value->is_jobject();
|
|
220 }
|
|
221 bool local_slot_needs_oopmap(int index, SharkValue* value) {
|
|
222 return value && value->is_jobject();
|
|
223 }
|
|
224 bool local_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
225 return true;
|
|
226 }
|
|
227 };
|
|
228
|
|
229 class SharkVMCallDecacher : public SharkDecacher {
|
|
230 public:
|
|
231 SharkVMCallDecacher(SharkFunction* function, int bci)
|
|
232 : SharkDecacher(function, bci) {}
|
|
233
|
|
234 // Stack slot helpers
|
|
235 protected:
|
|
236 bool stack_slot_needs_write(int index, SharkValue* value) {
|
|
237 return value && value->is_jobject();
|
|
238 }
|
|
239 bool stack_slot_needs_oopmap(int index, SharkValue* value) {
|
|
240 return value && value->is_jobject();
|
|
241 }
|
|
242 bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
243 return true;
|
|
244 }
|
|
245
|
|
246 // Local slot helpers
|
|
247 protected:
|
|
248 bool local_slot_needs_write(int index, SharkValue* value) {
|
|
249 return value && value->is_jobject();
|
|
250 }
|
|
251 bool local_slot_needs_oopmap(int index, SharkValue* value) {
|
|
252 return value && value->is_jobject();
|
|
253 }
|
|
254 bool local_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
255 return true;
|
|
256 }
|
|
257 };
|
|
258
|
|
259 class SharkTrapDecacher : public SharkDecacher {
|
|
260 public:
|
|
261 SharkTrapDecacher(SharkFunction* function, int bci)
|
|
262 : SharkDecacher(function, bci) {}
|
|
263
|
|
264 // Stack slot helpers
|
|
265 protected:
|
|
266 bool stack_slot_needs_write(int index, SharkValue* value) {
|
|
267 return value != NULL;
|
|
268 }
|
|
269 bool stack_slot_needs_oopmap(int index, SharkValue* value) {
|
|
270 return value && value->is_jobject();
|
|
271 }
|
|
272 bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
273 return true;
|
|
274 }
|
|
275
|
|
276 // Local slot helpers
|
|
277 protected:
|
|
278 bool local_slot_needs_write(int index, SharkValue* value) {
|
|
279 return value != NULL;
|
|
280 }
|
|
281 bool local_slot_needs_oopmap(int index, SharkValue* value) {
|
|
282 return value && value->is_jobject();
|
|
283 }
|
|
284 bool local_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
285 return true;
|
|
286 }
|
|
287 };
|
|
288
|
|
289 class SharkCacher : public SharkCacherDecacher {
|
|
290 protected:
|
|
291 SharkCacher(SharkFunction* function)
|
|
292 : SharkCacherDecacher(function) {}
|
|
293
|
|
294 // Callbacks
|
|
295 protected:
|
|
296 void process_stack_slot(int index, SharkValue** value, int offset);
|
|
297
|
|
298 void process_oop_tmp_slot(llvm::Value** value, int offset);
|
|
299 virtual void process_method_slot(llvm::Value** value, int offset);
|
|
300
|
|
301 virtual void process_local_slot(int index, SharkValue** value, int offset);
|
|
302
|
|
303 // Stack slot helper
|
|
304 protected:
|
|
305 virtual bool stack_slot_needs_read(int index, SharkValue* value) = 0;
|
|
306
|
|
307 // Local slot helper
|
|
308 protected:
|
|
309 virtual bool local_slot_needs_read(int index, SharkValue* value) {
|
|
310 return value && value->is_jobject();
|
|
311 }
|
|
312
|
|
313 // Writer helper
|
|
314 protected:
|
|
315 llvm::Value* read_value_from_frame(const llvm::Type* type, int offset);
|
|
316 };
|
|
317
|
|
318 class SharkJavaCallCacher : public SharkCacher {
|
|
319 public:
|
|
320 SharkJavaCallCacher(SharkFunction* function, ciMethod* callee)
|
|
321 : SharkCacher(function), _callee(callee) {}
|
|
322
|
|
323 private:
|
|
324 ciMethod* _callee;
|
|
325
|
|
326 protected:
|
|
327 ciMethod* callee() const {
|
|
328 return _callee;
|
|
329 }
|
|
330
|
|
331 // Stack slot helper
|
|
332 protected:
|
|
333 bool stack_slot_needs_read(int index, SharkValue* value) {
|
|
334 return value && (index < callee()->return_type()->size() ||
|
|
335 value->is_jobject());
|
|
336 }
|
|
337 };
|
|
338
|
|
339 class SharkVMCallCacher : public SharkCacher {
|
|
340 public:
|
|
341 SharkVMCallCacher(SharkFunction* function)
|
|
342 : SharkCacher(function) {}
|
|
343
|
|
344 // Stack slot helper
|
|
345 protected:
|
|
346 bool stack_slot_needs_read(int index, SharkValue* value) {
|
|
347 return value && value->is_jobject();
|
|
348 }
|
|
349 };
|
|
350
|
|
351 class SharkFunctionEntryCacher : public SharkCacher {
|
|
352 public:
|
|
353 SharkFunctionEntryCacher(SharkFunction* function, llvm::Value* method)
|
|
354 : SharkCacher(function), _method(method) {}
|
|
355
|
|
356 private:
|
|
357 llvm::Value* _method;
|
|
358
|
|
359 private:
|
|
360 llvm::Value* method() const {
|
|
361 return _method;
|
|
362 }
|
|
363
|
|
364 // Method slot callback
|
|
365 protected:
|
|
366 void process_method_slot(llvm::Value** value, int offset);
|
|
367
|
|
368 // Stack slot helper
|
|
369 protected:
|
|
370 bool stack_slot_needs_read(int index, SharkValue* value) {
|
|
371 ShouldNotReachHere(); // entry block shouldn't have stack
|
|
372 }
|
|
373
|
|
374 // Local slot helper
|
|
375 protected:
|
|
376 bool local_slot_needs_read(int index, SharkValue* value) {
|
|
377 return value != NULL;
|
|
378 }
|
|
379 };
|
|
380
|
|
381 class SharkNormalEntryCacher : public SharkFunctionEntryCacher {
|
|
382 public:
|
|
383 SharkNormalEntryCacher(SharkFunction* function, llvm::Value* method)
|
|
384 : SharkFunctionEntryCacher(function, method) {}
|
|
385 };
|
|
386
|
|
387 class SharkOSREntryCacher : public SharkFunctionEntryCacher {
|
|
388 public:
|
|
389 SharkOSREntryCacher(SharkFunction* function,
|
|
390 llvm::Value* method,
|
|
391 llvm::Value* osr_buf)
|
|
392 : SharkFunctionEntryCacher(function, method),
|
|
393 _osr_buf(
|
|
394 builder()->CreateBitCast(
|
|
395 osr_buf,
|
|
396 llvm::PointerType::getUnqual(
|
|
397 llvm::ArrayType::get(
|
|
398 SharkType::intptr_type(),
|
|
399 max_locals() + max_monitors() * 2)))) {}
|
|
400
|
|
401 private:
|
|
402 llvm::Value* _osr_buf;
|
|
403
|
|
404 private:
|
|
405 llvm::Value* osr_buf() const {
|
|
406 return _osr_buf;
|
|
407 }
|
|
408
|
|
409 // Callbacks
|
|
410 protected:
|
|
411 void process_monitor(int index, int box_offset, int obj_offset);
|
|
412 void process_local_slot(int index, SharkValue** value, int offset);
|
|
413
|
|
414 // Helper
|
|
415 private:
|
|
416 llvm::Value* CreateAddressOfOSRBufEntry(int offset, const llvm::Type* type);
|
|
417 };
|