1 /* |
|
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
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 |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 package sun.jvm.hotspot.runtime.ia64; |
|
26 |
|
27 import java.util.*; |
|
28 // import sun.jvm.hotspot.asm.ia64.*; |
|
29 import sun.jvm.hotspot.code.*; |
|
30 import sun.jvm.hotspot.compiler.*; |
|
31 import sun.jvm.hotspot.debugger.*; |
|
32 import sun.jvm.hotspot.oops.*; |
|
33 import sun.jvm.hotspot.runtime.*; |
|
34 import sun.jvm.hotspot.types.*; |
|
35 import sun.jvm.hotspot.utilities.*; |
|
36 |
|
37 /** Specialization of and implementation of abstract methods of the |
|
38 Frame class for the ia64 family of CPUs. */ |
|
39 |
|
40 public class IA64Frame extends Frame { |
|
41 private static final boolean DEBUG = false; |
|
42 |
|
43 // All frames |
|
44 |
|
45 // Interpreter frames |
|
46 |
|
47 // Entry frames |
|
48 |
|
49 // Native frames |
|
50 |
|
51 // an additional field beyond sp and pc: |
|
52 // Address raw_fp; // frame pointer only 1.4.2 |
|
53 |
|
54 Address iframe; |
|
55 |
|
56 private IA64Frame() { |
|
57 } |
|
58 |
|
59 public IA64Frame(Address raw_sp, Address iframe, Address pc) { |
|
60 this.raw_sp = raw_sp; |
|
61 this.iframe = iframe; |
|
62 this.pc = pc; |
|
63 if (DEBUG) { |
|
64 System.err.println("IA64Frame(sp, iframe, pc): " + this); |
|
65 dumpStack(); |
|
66 } |
|
67 } |
|
68 |
|
69 public Object clone() { |
|
70 IA64Frame frame = new IA64Frame(); |
|
71 frame.raw_sp = raw_sp; |
|
72 frame.iframe = iframe; |
|
73 frame.pc = pc; |
|
74 return frame; |
|
75 } |
|
76 |
|
77 public boolean equals(Object arg) { |
|
78 if (arg == null) { |
|
79 return false; |
|
80 } |
|
81 |
|
82 if (!(arg instanceof IA64Frame)) { |
|
83 return false; |
|
84 } |
|
85 |
|
86 IA64Frame other = (IA64Frame) arg; |
|
87 |
|
88 return (AddressOps.equal(getSP(), other.getSP()) && |
|
89 AddressOps.equal(getIFRAME(), other.getIFRAME()) && |
|
90 AddressOps.equal(getPC(), other.getPC())); |
|
91 } |
|
92 |
|
93 public int hashCode() { |
|
94 if (iframe == null) { |
|
95 return 0; |
|
96 } |
|
97 |
|
98 return iframe.hashCode(); |
|
99 } |
|
100 |
|
101 public String toString() { |
|
102 return "sp: " + (getSP() == null? "null" : getSP().toString()) + |
|
103 ", iframe: " + (getIFRAME() == null? "null" : getIFRAME().toString()) + |
|
104 ", pc: " + (pc == null? "null" : pc.toString()); |
|
105 } |
|
106 |
|
107 // accessors for the instance variables |
|
108 public Address getFP() { return null; } |
|
109 public Address getIFRAME() { return iframe; } |
|
110 public Address getSP() { return raw_sp; } |
|
111 public Address getID() { return getFP(); } |
|
112 |
|
113 // FIXME: not implemented yet |
|
114 public boolean isSignalHandlerFrameDbg() { return false; } |
|
115 public int getSignalNumberDbg() { return 0; } |
|
116 public String getSignalNameDbg() { return null; } |
|
117 |
|
118 // FIXME: do sanity checks |
|
119 public boolean isInterpretedFrameValid() { |
|
120 return true; |
|
121 } |
|
122 |
|
123 public boolean isInterpretedFrame() { return iframe != null; } |
|
124 |
|
125 |
|
126 // FIXME: not applicable in current system |
|
127 // void patch_pc(Thread* thread, address pc); |
|
128 |
|
129 public Frame sender(RegisterMap regMap, CodeBlob cb) { |
|
130 |
|
131 if (iframe == null) { |
|
132 return null; |
|
133 } |
|
134 |
|
135 cInterpreter fr = new cInterpreter(iframe); |
|
136 |
|
137 if (fr.prev() == null) { |
|
138 Address wrapper = fr.wrapper(); |
|
139 if ( wrapper == null) { |
|
140 return null; |
|
141 } |
|
142 IA64JavaCallWrapper jcw = new IA64JavaCallWrapper(wrapper); |
|
143 Address iprev = jcw.getPrevIFrame(); |
|
144 if (iprev == null) { |
|
145 return null; |
|
146 } |
|
147 return new IA64Frame(null, iprev, null); |
|
148 } else { |
|
149 return new IA64Frame(null, fr.prev(), null); |
|
150 } |
|
151 |
|
152 /* |
|
153 IA64RegisterMap map = (IA64RegisterMap) regMap; |
|
154 |
|
155 if (Assert.ASSERTS_ENABLED) { |
|
156 Assert.that(map != null, "map must be set"); |
|
157 } |
|
158 |
|
159 // Default is we done have to follow them. The sender_for_xxx will |
|
160 // update it accordingly |
|
161 map.setIncludeArgumentOops(false); |
|
162 |
|
163 if (isEntryFrame()) return senderForEntryFrame(map); |
|
164 if (isInterpretedFrame()) return senderForInterpreterFrame(map); |
|
165 |
|
166 if (!VM.getVM().isCore()) { |
|
167 if(cb == null) { |
|
168 cb = VM.getVM().getCodeCache().findBlob(getPC()); |
|
169 } else { |
|
170 if (Assert.ASSERTS_ENABLED) { |
|
171 Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); |
|
172 } |
|
173 } |
|
174 |
|
175 if (cb != null) { |
|
176 return senderForCompiledFrame(map, cb); |
|
177 } |
|
178 } |
|
179 |
|
180 // Must be native-compiled frame, i.e. the marshaling code for native |
|
181 // methods that exists in the core system. |
|
182 return new IA64Frame(getSenderSP(), getLink(), getSenderPC()); |
|
183 |
|
184 */ |
|
185 } |
|
186 |
|
187 private Frame senderForEntryFrame(IA64RegisterMap map) { |
|
188 if (Assert.ASSERTS_ENABLED) { |
|
189 Assert.that(map != null, "map must be set"); |
|
190 } |
|
191 /* |
|
192 // Java frame called from C; skip all C frames and return top C |
|
193 // frame of that chunk as the sender |
|
194 IA64JavaCallWrapper jcw = (IA64JavaCallWrapper) getEntryFrameCallWrapper(); |
|
195 if (Assert.ASSERTS_ENABLED) { |
|
196 Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); |
|
197 Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); |
|
198 } |
|
199 IA64Frame fr = new IA64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), null); |
|
200 map.clear(); |
|
201 if (Assert.ASSERTS_ENABLED) { |
|
202 Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); |
|
203 } |
|
204 return fr; |
|
205 */ |
|
206 throw new RuntimeException("senderForEntryFrame NYI"); |
|
207 } |
|
208 |
|
209 private Frame senderForInterpreterFrame(IA64RegisterMap map) { |
|
210 /* |
|
211 Address sp = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); |
|
212 // We do not need to update the callee-save register mapping because above |
|
213 // us is either another interpreter frame or a converter-frame, but never |
|
214 // directly a compiled frame. |
|
215 return new IA64Frame(sp, getLink(), getSenderPC()); |
|
216 */ |
|
217 throw new RuntimeException("senderForInterpreterFrame NYI"); |
|
218 } |
|
219 |
|
220 private Frame senderForDeoptimizedFrame(IA64RegisterMap map, CodeBlob cb) { |
|
221 // FIXME |
|
222 throw new RuntimeException("Deoptimized frames not handled yet"); |
|
223 } |
|
224 |
|
225 private Frame senderForCompiledFrame(IA64RegisterMap map, CodeBlob cb) { |
|
226 // |
|
227 // NOTE: some of this code is (unfortunately) duplicated in IA64CurrentFrameGuess |
|
228 // |
|
229 |
|
230 if (Assert.ASSERTS_ENABLED) { |
|
231 Assert.that(map != null, "map must be set"); |
|
232 } |
|
233 |
|
234 throw new RuntimeException("senderForCompiledFrame NYI"); |
|
235 |
|
236 /* |
|
237 |
|
238 // frame owned by optimizing compiler |
|
239 Address sender_sp = null; |
|
240 |
|
241 if (VM.getVM().isClientCompiler()) { |
|
242 sender_sp = addressOfStackSlot(SENDER_SP_OFFSET); |
|
243 } else { |
|
244 if (Assert.ASSERTS_ENABLED) { |
|
245 Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use"); |
|
246 } |
|
247 sender_sp = getSP().addOffsetTo(cb.getFrameSize()); |
|
248 } |
|
249 |
|
250 // On Intel the return_address is always the word on the stack |
|
251 Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); |
|
252 |
|
253 if (map.getUpdateMap() && cb.getOopMaps() != null) { |
|
254 OopMapSet.updateRegisterMap(this, cb, map, true); |
|
255 } |
|
256 |
|
257 Address saved_fp = null; |
|
258 if (VM.getVM().isClientCompiler()) { |
|
259 saved_fp = getFP().getAddressAt(0); |
|
260 } else { |
|
261 int llink_offset = cb.getLinkOffset(); |
|
262 if (llink_offset >= 0) { |
|
263 // Restore base-pointer, since next frame might be an interpreter frame. |
|
264 Address fp_addr = getSP().addOffsetTo(VM.getVM().getAddressSize() * llink_offset); |
|
265 saved_fp = fp_addr.getAddressAt(0); |
|
266 } |
|
267 } |
|
268 |
|
269 sender_sp = null ; // sp_addr.getAddressAt(0); |
|
270 |
|
271 return new IA64Frame(sender_sp, saved_fp, sender_pc); |
|
272 |
|
273 */ |
|
274 } |
|
275 |
|
276 protected boolean hasSenderPD() { |
|
277 // FIXME |
|
278 return true; |
|
279 } |
|
280 |
|
281 public long frameSize() { |
|
282 throw new RuntimeException("frameSize NYI"); |
|
283 /* |
|
284 return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); |
|
285 */ |
|
286 } |
|
287 |
|
288 public Address getLink() { |
|
289 throw new RuntimeException("getLink NYI"); |
|
290 /* |
|
291 return addressOfStackSlot(LINK_OFFSET).getAddressAt(0); |
|
292 */ |
|
293 } |
|
294 |
|
295 // FIXME: not implementable yet |
|
296 //inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; } |
|
297 |
|
298 public Address getUnextendedSP() { return getSP(); } |
|
299 |
|
300 // Return address: |
|
301 /* |
|
302 public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); } |
|
303 */ |
|
304 |
|
305 public Address getSenderPC() { return null; } |
|
306 |
|
307 /* |
|
308 // return address of param, zero origin index. |
|
309 public Address getNativeParamAddr(int idx) { |
|
310 return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx); |
|
311 } |
|
312 */ |
|
313 |
|
314 public Address getSenderSP() { return null; } |
|
315 |
|
316 /* |
|
317 public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) { |
|
318 if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) { |
|
319 throw new RuntimeException("Should not reach here"); |
|
320 } |
|
321 |
|
322 return oopMapRegToLocation(reg, regMap); |
|
323 } |
|
324 |
|
325 */ |
|
326 |
|
327 public Address addressOfInterpreterFrameLocals() { |
|
328 if (iframe == null) { |
|
329 throw new RuntimeException("Not an Interpreter frame"); |
|
330 } |
|
331 cInterpreter fr = new cInterpreter(iframe); |
|
332 return fr.locals(); |
|
333 } |
|
334 |
|
335 private Address addressOfInterpreterFrameBCX() { |
|
336 if (iframe == null) { |
|
337 throw new RuntimeException("Not an Interpreter frame"); |
|
338 } |
|
339 cInterpreter fr = new cInterpreter(iframe); |
|
340 return fr.bcpAddr(); |
|
341 } |
|
342 |
|
343 public int getInterpreterFrameBCI() { |
|
344 // FIXME: this is not atomic with respect to GC and is unsuitable |
|
345 // for use in a non-debugging, or reflective, system. Need to |
|
346 // figure out how to express this. |
|
347 Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); |
|
348 Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); |
|
349 Method method = (Method)Metadata.instantiateWrapperFor(methodHandle); |
|
350 return bcpToBci(bcp, method); |
|
351 } |
|
352 |
|
353 public Address addressOfInterpreterFrameMDX() { |
|
354 return null; |
|
355 } |
|
356 |
|
357 // FIXME |
|
358 //inline int frame::interpreter_frame_monitor_size() { |
|
359 // return BasicObjectLock::size(); |
|
360 //} |
|
361 |
|
362 // expression stack |
|
363 // (the max_stack arguments are used by the GC; see class FrameClosure) |
|
364 |
|
365 public Address addressOfInterpreterFrameExpressionStack() { |
|
366 if (iframe == null) { |
|
367 throw new RuntimeException("Not an Interpreter frame"); |
|
368 } |
|
369 cInterpreter fr = new cInterpreter(iframe); |
|
370 return fr.stackBase(); |
|
371 } |
|
372 |
|
373 public int getInterpreterFrameExpressionStackDirection() { return -1; } |
|
374 |
|
375 // top of expression stack |
|
376 public Address addressOfInterpreterFrameTOS() { |
|
377 if (iframe == null) { |
|
378 throw new RuntimeException("Not an Interpreter frame"); |
|
379 } |
|
380 cInterpreter fr = new cInterpreter(iframe); |
|
381 // tos always points to first free element in c++ interpreter not tos |
|
382 return fr.stackBase().addOffsetTo(VM.getVM().getAddressSize()); |
|
383 } |
|
384 |
|
385 /** Expression stack from top down */ |
|
386 public Address addressOfInterpreterFrameTOSAt(int slot) { |
|
387 return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); |
|
388 } |
|
389 |
|
390 public Address getInterpreterFrameSenderSP() { |
|
391 if (Assert.ASSERTS_ENABLED) { |
|
392 Assert.that(isInterpretedFrame(), "interpreted frame expected"); |
|
393 } |
|
394 throw new RuntimeException("getInterpreterFrameSenderSP NYI"); |
|
395 } |
|
396 |
|
397 // Monitors |
|
398 public BasicObjectLock interpreterFrameMonitorBegin() { |
|
399 if (iframe == null) { |
|
400 throw new RuntimeException("Not an Interpreter frame"); |
|
401 } |
|
402 cInterpreter fr = new cInterpreter(iframe); |
|
403 return new BasicObjectLock(fr.monitorBase()); |
|
404 } |
|
405 |
|
406 public BasicObjectLock interpreterFrameMonitorEnd() { |
|
407 if (iframe == null) { |
|
408 throw new RuntimeException("Not an Interpreter frame"); |
|
409 } |
|
410 cInterpreter fr = new cInterpreter(iframe); |
|
411 // Monitors end is just above stack base (2 slots per monitor) |
|
412 Address result = fr.stackBase().addOffsetTo(2 * VM.getVM().getAddressSize()); |
|
413 /* |
|
414 if (Assert.ASSERTS_ENABLED) { |
|
415 // make sure the pointer points inside the frame |
|
416 Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer"); |
|
417 Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer"); |
|
418 } |
|
419 */ |
|
420 return new BasicObjectLock(result); |
|
421 } |
|
422 |
|
423 public int interpreterFrameMonitorSize() { |
|
424 return BasicObjectLock.size(); |
|
425 } |
|
426 |
|
427 // Method |
|
428 public Address addressOfInterpreterFrameMethod() { |
|
429 if (iframe == null) { |
|
430 throw new RuntimeException("Not an Interpreter frame"); |
|
431 } |
|
432 cInterpreter fr = new cInterpreter(iframe); |
|
433 return fr.methodAddr(); |
|
434 } |
|
435 |
|
436 // Constant pool cache |
|
437 public Address addressOfInterpreterFrameCPCache() { |
|
438 if (iframe == null) { |
|
439 throw new RuntimeException("Not an Interpreter frame"); |
|
440 } |
|
441 cInterpreter fr = new cInterpreter(iframe); |
|
442 return fr.constantsAddr(); |
|
443 } |
|
444 |
|
445 // Entry frames |
|
446 public JavaCallWrapper getEntryFrameCallWrapper() { |
|
447 throw new RuntimeException("getEntryFrameCallWrapper NYI"); |
|
448 } |
|
449 |
|
450 protected Address addressOfSavedOopResult() { |
|
451 throw new RuntimeException("public boolean isInterpretedFrame() NYI"); |
|
452 /* |
|
453 // offset is 2 for compiler2 and 3 for compiler1 |
|
454 return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) * |
|
455 VM.getVM().getAddressSize()); |
|
456 */ |
|
457 } |
|
458 |
|
459 protected Address addressOfSavedReceiver() { |
|
460 throw new RuntimeException("getEntryFrameCallWrapper NYI"); |
|
461 // return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize()); |
|
462 } |
|
463 |
|
464 private void dumpStack() { |
|
465 /* |
|
466 if (getFP() != null) { |
|
467 for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); |
|
468 AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize())); |
|
469 addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { |
|
470 System.out.println(addr + ": " + addr.getAddressAt(0)); |
|
471 } |
|
472 } else { |
|
473 for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); |
|
474 AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize())); |
|
475 addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { |
|
476 System.out.println(addr + ": " + addr.getAddressAt(0)); |
|
477 } |
|
478 } |
|
479 */ |
|
480 } |
|
481 } |
|