1692
|
1 /*
|
1972
|
2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
1692
|
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
|
1972
|
26 #ifndef SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP
|
|
27 #define SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP
|
|
28
|
|
29 #include "ci/ciMethod.hpp"
|
|
30 #include "code/debugInfoRec.hpp"
|
|
31 #include "shark/sharkBuilder.hpp"
|
|
32 #include "shark/sharkFunction.hpp"
|
|
33 #include "shark/sharkStateScanner.hpp"
|
|
34
|
1692
|
35 // Class hierarchy:
|
|
36 // - SharkStateScanner
|
|
37 // - SharkCacherDecacher
|
|
38 // - SharkDecacher
|
|
39 // - SharkJavaCallDecacher
|
|
40 // - SharkVMCallDecacher
|
|
41 // - SharkTrapDecacher
|
|
42 // - SharkCacher
|
|
43 // - SharkJavaCallCacher
|
|
44 // - SharkVMCallCacher
|
|
45 // - SharkFunctionEntryCacher
|
|
46 // - SharkNormalEntryCacher
|
|
47 // - SharkOSREntryCacher
|
|
48
|
|
49 class SharkCacherDecacher : public SharkStateScanner {
|
|
50 protected:
|
|
51 SharkCacherDecacher(SharkFunction* function)
|
|
52 : SharkStateScanner(function) {}
|
|
53
|
|
54 // Helper
|
|
55 protected:
|
|
56 static int adjusted_offset(SharkValue* value, int offset) {
|
|
57 if (value->is_two_word())
|
|
58 offset--;
|
|
59 return offset;
|
|
60 }
|
|
61 };
|
|
62
|
|
63 class SharkDecacher : public SharkCacherDecacher {
|
|
64 protected:
|
|
65 SharkDecacher(SharkFunction* function, int bci)
|
|
66 : SharkCacherDecacher(function), _bci(bci) {}
|
|
67
|
|
68 private:
|
|
69 int _bci;
|
|
70
|
|
71 protected:
|
|
72 int bci() const {
|
|
73 return _bci;
|
|
74 }
|
|
75
|
|
76 private:
|
|
77 int _pc_offset;
|
|
78 OopMap* _oopmap;
|
|
79 GrowableArray<ScopeValue*>* _exparray;
|
|
80 GrowableArray<MonitorValue*>* _monarray;
|
|
81 GrowableArray<ScopeValue*>* _locarray;
|
|
82
|
|
83 private:
|
|
84 int pc_offset() const {
|
|
85 return _pc_offset;
|
|
86 }
|
|
87 OopMap* oopmap() const {
|
|
88 return _oopmap;
|
|
89 }
|
|
90 GrowableArray<ScopeValue*>* exparray() const {
|
|
91 return _exparray;
|
|
92 }
|
|
93 GrowableArray<MonitorValue*>* monarray() const {
|
|
94 return _monarray;
|
|
95 }
|
|
96 GrowableArray<ScopeValue*>* locarray() const {
|
|
97 return _locarray;
|
|
98 }
|
|
99
|
|
100 // Callbacks
|
|
101 protected:
|
|
102 void start_frame();
|
|
103
|
|
104 void start_stack(int stack_depth);
|
|
105 void process_stack_slot(int index, SharkValue** value, int offset);
|
|
106
|
|
107 void start_monitors(int num_monitors);
|
|
108 void process_monitor(int index, int box_offset, int obj_offset);
|
|
109
|
|
110 void process_oop_tmp_slot(llvm::Value** value, int offset);
|
|
111 void process_method_slot(llvm::Value** value, int offset);
|
|
112 void process_pc_slot(int offset);
|
|
113
|
|
114 void start_locals();
|
|
115 void process_local_slot(int index, SharkValue** value, int offset);
|
|
116
|
|
117 void end_frame();
|
|
118
|
|
119 // oopmap and debuginfo helpers
|
|
120 private:
|
|
121 static int oopmap_slot_munge(int offset) {
|
|
122 return SharkStack::oopmap_slot_munge(offset);
|
|
123 }
|
|
124 static VMReg slot2reg(int offset) {
|
|
125 return SharkStack::slot2reg(offset);
|
|
126 }
|
|
127 static Location slot2loc(int offset, Location::Type type) {
|
|
128 return Location::new_stk_loc(type, offset * wordSize);
|
|
129 }
|
|
130 static LocationValue* slot2lv(int offset, Location::Type type) {
|
|
131 return new LocationValue(slot2loc(offset, type));
|
|
132 }
|
|
133 static Location::Type location_type(SharkValue** addr, bool maybe_two_word) {
|
|
134 // low addresses this end
|
|
135 // Type 32-bit 64-bit
|
|
136 // ----------------------------------------------------
|
|
137 // stack[0] local[3] jobject oop oop
|
|
138 // stack[1] local[2] NULL normal lng
|
|
139 // stack[2] local[1] jlong normal invalid
|
|
140 // stack[3] local[0] jint normal normal
|
|
141 //
|
|
142 // high addresses this end
|
|
143
|
|
144 SharkValue *value = *addr;
|
|
145 if (value) {
|
|
146 if (value->is_jobject())
|
|
147 return Location::oop;
|
|
148 #ifdef _LP64
|
|
149 if (value->is_two_word())
|
|
150 return Location::invalid;
|
|
151 #endif // _LP64
|
|
152 return Location::normal;
|
|
153 }
|
|
154 else {
|
|
155 if (maybe_two_word) {
|
|
156 value = *(addr - 1);
|
|
157 if (value && value->is_two_word()) {
|
|
158 #ifdef _LP64
|
|
159 if (value->is_jlong())
|
|
160 return Location::lng;
|
|
161 if (value->is_jdouble())
|
|
162 return Location::dbl;
|
|
163 ShouldNotReachHere();
|
|
164 #else
|
|
165 return Location::normal;
|
|
166 #endif // _LP64
|
|
167 }
|
|
168 }
|
|
169 return Location::invalid;
|
|
170 }
|
|
171 }
|
|
172
|
|
173 // Stack slot helpers
|
|
174 protected:
|
|
175 virtual bool stack_slot_needs_write(int index, SharkValue* value) = 0;
|
|
176 virtual bool stack_slot_needs_oopmap(int index, SharkValue* value) = 0;
|
|
177 virtual bool stack_slot_needs_debuginfo(int index, SharkValue* value) = 0;
|
|
178
|
|
179 static Location::Type stack_location_type(int index, SharkValue** addr) {
|
|
180 return location_type(addr, *addr == NULL);
|
|
181 }
|
|
182
|
|
183 // Local slot helpers
|
|
184 protected:
|
|
185 virtual bool local_slot_needs_write(int index, SharkValue* value) = 0;
|
|
186 virtual bool local_slot_needs_oopmap(int index, SharkValue* value) = 0;
|
|
187 virtual bool local_slot_needs_debuginfo(int index, SharkValue* value) = 0;
|
|
188
|
|
189 static Location::Type local_location_type(int index, SharkValue** addr) {
|
|
190 return location_type(addr, index > 0);
|
|
191 }
|
|
192
|
|
193 // Writer helper
|
|
194 protected:
|
|
195 void write_value_to_frame(const llvm::Type* type,
|
|
196 llvm::Value* value,
|
|
197 int offset);
|
|
198 };
|
|
199
|
|
200 class SharkJavaCallDecacher : public SharkDecacher {
|
|
201 public:
|
|
202 SharkJavaCallDecacher(SharkFunction* function, int bci, ciMethod* callee)
|
|
203 : SharkDecacher(function, bci), _callee(callee) {}
|
|
204
|
|
205 private:
|
|
206 ciMethod* _callee;
|
|
207
|
|
208 protected:
|
|
209 ciMethod* callee() const {
|
|
210 return _callee;
|
|
211 }
|
|
212
|
|
213 // Stack slot helpers
|
|
214 protected:
|
|
215 bool stack_slot_needs_write(int index, SharkValue* value) {
|
|
216 return value && (index < callee()->arg_size() || value->is_jobject());
|
|
217 }
|
|
218 bool stack_slot_needs_oopmap(int index, SharkValue* value) {
|
|
219 return value && value->is_jobject() && index >= callee()->arg_size();
|
|
220 }
|
|
221 bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
222 return index >= callee()->arg_size();
|
|
223 }
|
|
224
|
|
225 // Local slot helpers
|
|
226 protected:
|
|
227 bool local_slot_needs_write(int index, SharkValue* value) {
|
|
228 return value && value->is_jobject();
|
|
229 }
|
|
230 bool local_slot_needs_oopmap(int index, SharkValue* value) {
|
|
231 return value && value->is_jobject();
|
|
232 }
|
|
233 bool local_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
234 return true;
|
|
235 }
|
|
236 };
|
|
237
|
|
238 class SharkVMCallDecacher : public SharkDecacher {
|
|
239 public:
|
|
240 SharkVMCallDecacher(SharkFunction* function, int bci)
|
|
241 : SharkDecacher(function, bci) {}
|
|
242
|
|
243 // Stack slot helpers
|
|
244 protected:
|
|
245 bool stack_slot_needs_write(int index, SharkValue* value) {
|
|
246 return value && value->is_jobject();
|
|
247 }
|
|
248 bool stack_slot_needs_oopmap(int index, SharkValue* value) {
|
|
249 return value && value->is_jobject();
|
|
250 }
|
|
251 bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
252 return true;
|
|
253 }
|
|
254
|
|
255 // Local slot helpers
|
|
256 protected:
|
|
257 bool local_slot_needs_write(int index, SharkValue* value) {
|
|
258 return value && value->is_jobject();
|
|
259 }
|
|
260 bool local_slot_needs_oopmap(int index, SharkValue* value) {
|
|
261 return value && value->is_jobject();
|
|
262 }
|
|
263 bool local_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
264 return true;
|
|
265 }
|
|
266 };
|
|
267
|
|
268 class SharkTrapDecacher : public SharkDecacher {
|
|
269 public:
|
|
270 SharkTrapDecacher(SharkFunction* function, int bci)
|
|
271 : SharkDecacher(function, bci) {}
|
|
272
|
|
273 // Stack slot helpers
|
|
274 protected:
|
|
275 bool stack_slot_needs_write(int index, SharkValue* value) {
|
|
276 return value != NULL;
|
|
277 }
|
|
278 bool stack_slot_needs_oopmap(int index, SharkValue* value) {
|
|
279 return value && value->is_jobject();
|
|
280 }
|
|
281 bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
282 return true;
|
|
283 }
|
|
284
|
|
285 // Local slot helpers
|
|
286 protected:
|
|
287 bool local_slot_needs_write(int index, SharkValue* value) {
|
|
288 return value != NULL;
|
|
289 }
|
|
290 bool local_slot_needs_oopmap(int index, SharkValue* value) {
|
|
291 return value && value->is_jobject();
|
|
292 }
|
|
293 bool local_slot_needs_debuginfo(int index, SharkValue* value) {
|
|
294 return true;
|
|
295 }
|
|
296 };
|
|
297
|
|
298 class SharkCacher : public SharkCacherDecacher {
|
|
299 protected:
|
|
300 SharkCacher(SharkFunction* function)
|
|
301 : SharkCacherDecacher(function) {}
|
|
302
|
|
303 // Callbacks
|
|
304 protected:
|
|
305 void process_stack_slot(int index, SharkValue** value, int offset);
|
|
306
|
|
307 void process_oop_tmp_slot(llvm::Value** value, int offset);
|
|
308 virtual void process_method_slot(llvm::Value** value, int offset);
|
|
309
|
|
310 virtual void process_local_slot(int index, SharkValue** value, int offset);
|
|
311
|
|
312 // Stack slot helper
|
|
313 protected:
|
|
314 virtual bool stack_slot_needs_read(int index, SharkValue* value) = 0;
|
|
315
|
|
316 // Local slot helper
|
|
317 protected:
|
|
318 virtual bool local_slot_needs_read(int index, SharkValue* value) {
|
|
319 return value && value->is_jobject();
|
|
320 }
|
|
321
|
|
322 // Writer helper
|
|
323 protected:
|
|
324 llvm::Value* read_value_from_frame(const llvm::Type* type, int offset);
|
|
325 };
|
|
326
|
|
327 class SharkJavaCallCacher : public SharkCacher {
|
|
328 public:
|
|
329 SharkJavaCallCacher(SharkFunction* function, ciMethod* callee)
|
|
330 : SharkCacher(function), _callee(callee) {}
|
|
331
|
|
332 private:
|
|
333 ciMethod* _callee;
|
|
334
|
|
335 protected:
|
|
336 ciMethod* callee() const {
|
|
337 return _callee;
|
|
338 }
|
|
339
|
|
340 // Stack slot helper
|
|
341 protected:
|
|
342 bool stack_slot_needs_read(int index, SharkValue* value) {
|
|
343 return value && (index < callee()->return_type()->size() ||
|
|
344 value->is_jobject());
|
|
345 }
|
|
346 };
|
|
347
|
|
348 class SharkVMCallCacher : public SharkCacher {
|
|
349 public:
|
|
350 SharkVMCallCacher(SharkFunction* function)
|
|
351 : SharkCacher(function) {}
|
|
352
|
|
353 // Stack slot helper
|
|
354 protected:
|
|
355 bool stack_slot_needs_read(int index, SharkValue* value) {
|
|
356 return value && value->is_jobject();
|
|
357 }
|
|
358 };
|
|
359
|
|
360 class SharkFunctionEntryCacher : public SharkCacher {
|
|
361 public:
|
|
362 SharkFunctionEntryCacher(SharkFunction* function, llvm::Value* method)
|
|
363 : SharkCacher(function), _method(method) {}
|
|
364
|
|
365 private:
|
|
366 llvm::Value* _method;
|
|
367
|
|
368 private:
|
|
369 llvm::Value* method() const {
|
|
370 return _method;
|
|
371 }
|
|
372
|
|
373 // Method slot callback
|
|
374 protected:
|
|
375 void process_method_slot(llvm::Value** value, int offset);
|
|
376
|
|
377 // Stack slot helper
|
|
378 protected:
|
|
379 bool stack_slot_needs_read(int index, SharkValue* value) {
|
|
380 ShouldNotReachHere(); // entry block shouldn't have stack
|
|
381 }
|
|
382
|
|
383 // Local slot helper
|
|
384 protected:
|
|
385 bool local_slot_needs_read(int index, SharkValue* value) {
|
|
386 return value != NULL;
|
|
387 }
|
|
388 };
|
|
389
|
|
390 class SharkNormalEntryCacher : public SharkFunctionEntryCacher {
|
|
391 public:
|
|
392 SharkNormalEntryCacher(SharkFunction* function, llvm::Value* method)
|
|
393 : SharkFunctionEntryCacher(function, method) {}
|
|
394 };
|
|
395
|
|
396 class SharkOSREntryCacher : public SharkFunctionEntryCacher {
|
|
397 public:
|
|
398 SharkOSREntryCacher(SharkFunction* function,
|
|
399 llvm::Value* method,
|
|
400 llvm::Value* osr_buf)
|
|
401 : SharkFunctionEntryCacher(function, method),
|
|
402 _osr_buf(
|
|
403 builder()->CreateBitCast(
|
|
404 osr_buf,
|
|
405 llvm::PointerType::getUnqual(
|
|
406 llvm::ArrayType::get(
|
|
407 SharkType::intptr_type(),
|
|
408 max_locals() + max_monitors() * 2)))) {}
|
|
409
|
|
410 private:
|
|
411 llvm::Value* _osr_buf;
|
|
412
|
|
413 private:
|
|
414 llvm::Value* osr_buf() const {
|
|
415 return _osr_buf;
|
|
416 }
|
|
417
|
|
418 // Callbacks
|
|
419 protected:
|
|
420 void process_monitor(int index, int box_offset, int obj_offset);
|
|
421 void process_local_slot(int index, SharkValue** value, int offset);
|
|
422
|
|
423 // Helper
|
|
424 private:
|
|
425 llvm::Value* CreateAddressOfOSRBufEntry(int offset, const llvm::Type* type);
|
|
426 };
|
1972
|
427
|
|
428 #endif // SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP
|