0
|
1 /*
|
|
2 * Copyright 2000-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 package sun.jvm.hotspot.runtime;
|
|
26
|
|
27 import java.io.*;
|
|
28 import java.util.*;
|
|
29 import sun.jvm.hotspot.*;
|
|
30 import sun.jvm.hotspot.code.*;
|
|
31 import sun.jvm.hotspot.compiler.*;
|
|
32 import sun.jvm.hotspot.c1.*;
|
|
33 import sun.jvm.hotspot.debugger.*;
|
|
34 import sun.jvm.hotspot.interpreter.*;
|
|
35 import sun.jvm.hotspot.oops.*;
|
|
36 import sun.jvm.hotspot.types.*;
|
|
37 import sun.jvm.hotspot.utilities.*;
|
|
38
|
|
39 /** <P> A frame represents a physical stack frame (an activation).
|
|
40 Frames can be C or Java frames, and the Java frames can be
|
|
41 interpreted or compiled. In contrast, vframes represent
|
|
42 source-level activations, so that one physical frame can
|
|
43 correspond to multiple source level frames because of inlining.
|
|
44 </P>
|
|
45
|
|
46 <P> NOTE that this is not a VMObject and does not wrap an Address
|
|
47 -- this is an actual port of the VM's Frame code to Java. </P>
|
|
48
|
|
49 <P> NOTE also that this is incomplete -- just trying to get
|
|
50 reading of interpreted frames working for now, so all non-core and
|
|
51 setter methods are removed for now. (FIXME) </P> */
|
|
52
|
|
53 public abstract class Frame implements Cloneable {
|
|
54 /** A raw stack pointer. The accessor getSP() will return a real (usable)
|
|
55 stack pointer (e.g. from Thread::last_Java_sp) */
|
|
56 protected Address raw_sp;
|
|
57
|
|
58 /** Program counter (the next instruction after the call) */
|
|
59 protected Address pc;
|
|
60 protected boolean deoptimized;
|
|
61
|
|
62 public Frame() {
|
|
63 deoptimized = false;
|
|
64 }
|
|
65
|
|
66 static {
|
|
67 VM.registerVMInitializedObserver(new Observer() {
|
|
68 public void update(Observable o, Object data) {
|
|
69 initialize(VM.getVM().getTypeDataBase());
|
|
70 }
|
|
71 });
|
|
72 }
|
|
73
|
|
74 /** Size of constMethodOopDesc for computing BCI from BCP (FIXME: hack) */
|
|
75 private static long constMethodOopDescSize;
|
|
76
|
|
77 private static synchronized void initialize(TypeDataBase db) {
|
|
78 Type constMethodOopType = db.lookupType("constMethodOopDesc");
|
|
79 // FIXME: not sure whether alignment here is correct or how to
|
|
80 // force it (round up to address size?)
|
|
81 constMethodOopDescSize = constMethodOopType.getSize();
|
|
82 }
|
|
83
|
|
84 protected int bcpToBci(Address bcp, ConstMethod cm) {
|
|
85 // bcp will be null for interpreter native methods
|
|
86 // in addition depending on where we catch the system the value can
|
|
87 // be a bcp or a bci.
|
|
88 if (bcp == null) return 0;
|
|
89 long bci = bcp.minus(null);
|
|
90 if (bci >= 0 && bci < cm.getCodeSize()) return (int) bci;
|
|
91 return (int) (bcp.minus(cm.getHandle()) - constMethodOopDescSize);
|
|
92 }
|
|
93
|
|
94 protected int bcpToBci(Address bcp, Method m) {
|
|
95 return bcpToBci(bcp, m.getConstMethod());
|
|
96 }
|
|
97
|
|
98 public abstract Object clone();
|
|
99
|
|
100 // Accessors
|
|
101
|
|
102 /** pc: Returns the pc at which this frame will continue normally.
|
|
103 It must point at the beginning of the next instruction to
|
|
104 execute. */
|
|
105 public Address getPC() { return pc; }
|
|
106 public void setPC(Address newpc) { pc = newpc; }
|
|
107 public boolean isDeoptimized() { return deoptimized; }
|
|
108
|
|
109 public abstract Address getSP();
|
|
110 public abstract Address getID();
|
|
111 public abstract Address getFP();
|
|
112
|
|
113 /** testers -- platform dependent */
|
|
114 public abstract boolean equals(Object arg);
|
|
115
|
|
116 /** type testers */
|
|
117 public boolean isInterpretedFrame() { return VM.getVM().getInterpreter().contains(getPC()); }
|
|
118 public boolean isJavaFrame() {
|
|
119 if (isInterpretedFrame()) return true;
|
|
120 if (!VM.getVM().isCore()) {
|
|
121 if (isCompiledFrame()) return true;
|
|
122 }
|
|
123 return false;
|
|
124 }
|
|
125
|
|
126 /** Java frame called from C? */
|
|
127 public boolean isEntryFrame() { return VM.getVM().getStubRoutines().returnsToCallStub(getPC()); }
|
|
128 public boolean isNativeFrame() {
|
|
129 if (!VM.getVM().isCore()) {
|
|
130 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());
|
|
131 return (cb != null && cb.isNativeMethod());
|
|
132 } else {
|
|
133 return false;
|
|
134 }
|
|
135 }
|
|
136
|
|
137 public boolean isCompiledFrame() {
|
|
138 if (Assert.ASSERTS_ENABLED) {
|
|
139 Assert.that(!VM.getVM().isCore(), "noncore builds only");
|
|
140 }
|
|
141 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());
|
|
142 return (cb != null && cb.isJavaMethod());
|
|
143 }
|
|
144
|
|
145 public boolean isGlueFrame() {
|
|
146 if (Assert.ASSERTS_ENABLED) {
|
|
147 Assert.that(!VM.getVM().isCore(), "noncore builds only");
|
|
148 }
|
|
149 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());
|
|
150 if (cb == null) {
|
|
151 return false;
|
|
152 }
|
|
153 if (cb.isRuntimeStub()) return true;
|
|
154 else return false;
|
|
155 }
|
|
156
|
|
157 /** oldest frame? (has no sender) FIXME: this is modified from the
|
|
158 C++ code to handle the debugging situation where we try to
|
|
159 traverse the stack for, for example, the signal thread, and
|
|
160 don't find any valid Java frames. Would really like to put the
|
|
161 second half of the conditional in some sort of debugging-only if
|
|
162 statement. */
|
|
163 // *** FIXME: THE CALL TO isJavaFrame() IS WAY TOO EXPENSIVE!!!!! ***
|
|
164 public boolean isFirstFrame() { return ((isEntryFrame() && entryFrameIsFirst()) ||
|
|
165 (!isJavaFrame() && !hasSenderPD())); }
|
|
166 /** same for Java frame */
|
|
167 public boolean isFirstJavaFrame() { throw new RuntimeException("not yet implemented"); }
|
|
168
|
|
169 /** This is an addition for debugging purposes on platforms which
|
|
170 have the notion of signals. */
|
|
171 public abstract boolean isSignalHandlerFrameDbg();
|
|
172
|
|
173 /** If this is a signal handler frame (again, on a platform with a
|
|
174 notion of signals), get the signal number. */
|
|
175 public abstract int getSignalNumberDbg();
|
|
176
|
|
177 /** If this is a signal handler frame (again, on a platform with a
|
|
178 notion of signals), get the name of the signal. */
|
|
179 public abstract String getSignalNameDbg();
|
|
180
|
|
181 /** performs sanity checks on interpreted frames. */
|
|
182 public abstract boolean isInterpretedFrameValid();
|
|
183
|
|
184 /** tells whether this frame is marked for deoptimization */
|
|
185 public boolean shouldBeDeoptimized() { throw new RuntimeException("not yet implemented"); }
|
|
186
|
|
187 /** tells whether this frame can be deoptimized */
|
|
188 public boolean canBeDeoptimized() { throw new RuntimeException("not yet implemented"); }
|
|
189
|
|
190 /** returns the sending frame */
|
|
191 public abstract Frame sender(RegisterMap map, CodeBlob nm);
|
|
192
|
|
193 /** equivalent to sender(map, null) */
|
|
194 public Frame sender(RegisterMap map) { return sender(map, null); }
|
|
195
|
|
196 /** returns the sender, but skips conversion frames */
|
|
197 public Frame realSender(RegisterMap map) {
|
|
198 if (!VM.getVM().isCore()) {
|
|
199 Frame result = sender(map);
|
|
200 while (result.isGlueFrame()) {
|
|
201 result = result.sender(map);
|
|
202 }
|
|
203 return result;
|
|
204 } else {
|
|
205 return sender(map);
|
|
206 }
|
|
207 }
|
|
208
|
|
209 /** Platform-dependent query indicating whether this frame has a
|
|
210 sender. Should return true if it is possible to call sender() at
|
|
211 all on this frame. (This is currently only needed for the
|
|
212 debugging system, if a stack trace is attempted for a Java
|
|
213 thread which has no Java frames, i.e., the signal thread; we
|
|
214 have to know to stop traversal at the bottom frame.) */
|
|
215 protected abstract boolean hasSenderPD();
|
|
216
|
|
217 //--------------------------------------------------------------------------------
|
|
218 // All frames:
|
|
219 // A low-level interface for vframes:
|
|
220
|
|
221 /** Returns the address of the requested "slot" on the stack. Slots
|
|
222 are as wide as addresses, so are 32 bits wide on a 32-bit
|
|
223 machine and 64 bits wide on a 64-bit machine. */
|
|
224 public Address addressOfStackSlot(int slot) { return getFP().addOffsetTo(slot * VM.getVM().getAddressSize()); }
|
|
225
|
|
226 /** Fetches the OopHandle at the requested slot */
|
|
227 public OopHandle getOopHandleAt(int slot) { return addressOfStackSlot(slot).getOopHandleAt(0); }
|
|
228 /** Fetches the OopHandle at the slot, adjusted for compiler frames */
|
|
229 // FIXME: looks like this is only used for compiled frames
|
|
230 // public OopHandle getOopHandleAtAdjusted(MethodOop method, int slot) { return addressOfStackSlot(slot).getOopHandleAt(0); }
|
|
231 // FIXME: Not yet implementable
|
|
232 // public void setOopHandleAt(int slot, OopHandle value) { addressOfStackSlot(slot).setOopHandleAt(0, value); }
|
|
233
|
|
234 /** Fetches the (Java) int at the requested slot */
|
|
235 public int getIntAt(int slot) { return addressOfStackSlot(slot).getJIntAt(0); }
|
|
236 // FIXME: Not yet implementable
|
|
237 // public void setIntAt(int slot, int value) { addressOfStackSlot(slot).setJIntAt(0, value); }
|
|
238
|
|
239 /** returns the frame size in stack slots */
|
|
240 public abstract long frameSize();
|
|
241
|
|
242 /** Link (i.e., the pointer to the previous frame) */
|
|
243 public abstract Address getLink();
|
|
244 // public abstract void setLink(Address addr);
|
|
245
|
|
246 /** Return address */
|
|
247 public abstract Address getSenderPC();
|
|
248 // FIXME: currently unimplementable
|
|
249 // public abstract void setSenderPC(Address addr);
|
|
250
|
|
251 /** The frame's original SP, before any extension by an interpreted
|
|
252 callee; used for packing debug info into vframeArray objects and
|
|
253 vframeArray lookup. */
|
|
254 public abstract Address getUnextendedSP();
|
|
255
|
|
256 /** Returns the stack pointer of the calling frame */
|
|
257 public abstract Address getSenderSP();
|
|
258
|
|
259 //--------------------------------------------------------------------------------
|
|
260 // Interpreter frames:
|
|
261 //
|
|
262
|
|
263 public abstract Address addressOfInterpreterFrameLocals();
|
|
264
|
|
265 public Address addressOfInterpreterFrameLocal(int slot) {
|
|
266 return addressOfInterpreterFrameLocals().getAddressAt(0).addOffsetTo(-slot * VM.getVM().getAddressSize());
|
|
267 }
|
|
268
|
|
269 // FIXME: not yet implementable
|
|
270 // void interpreter_frame_set_locals(intptr_t* locs);
|
|
271
|
|
272 // NOTE that the accessor "addressOfInterpreterFrameBCX" has
|
|
273 // necessarily been eliminated. The byte code pointer is inherently
|
|
274 // an interior pointer to a Method (the bytecodes follow the
|
|
275 // methodOopDesc data structure) and therefore acquisition of it in
|
|
276 // this system can not be allowed. All accesses to interpreter frame
|
|
277 // byte codes are via the byte code index (BCI).
|
|
278
|
|
279 /** Byte code index. In the underlying frame, what is actually
|
|
280 stored is a byte code pointer (BCP), which is converted to a BCI
|
|
281 and back by the GC when methods are moved. In this system,
|
|
282 interior pointers are not allowed, so we must make the access to
|
|
283 the interpreter frame's BCI atomic with respect to GC. This may
|
|
284 mean implementation with an underlying call through native code
|
|
285 into the VM or a magic sequence in the compiler. (FIXME) */
|
|
286 public abstract int getInterpreterFrameBCI();
|
|
287 // FIXME: not yet implementable
|
|
288 // public abstract void setInterpreterFrameBCI(int bci);
|
|
289
|
|
290 // FIXME: elided for now
|
|
291 // public abstract Address addressOfInterpreterCalleeReceiver(Symbol signature);
|
|
292
|
|
293 /** Find receiver for an invoke when arguments are just pushed on
|
|
294 stack (i.e., callee stack-frame is not setup) */
|
|
295 // FIXME: elided for now
|
|
296 // public OopHandle getInterpreterCalleeReceiver(SymbolOop signature) { return addressOfInterpreterCalleeReceiver(signature).getOopHandleAt(0); }
|
|
297
|
|
298 //--------------------------------------------------------------------------------
|
|
299 // Expression stack (may go up or down, direction == 1 or -1)
|
|
300 //
|
|
301
|
|
302 public abstract Address addressOfInterpreterFrameExpressionStack();
|
|
303 public abstract int getInterpreterFrameExpressionStackDirection();
|
|
304 public Address addressOfInterpreterFrameExpressionStackSlot(int slot) {
|
|
305 return addressOfInterpreterFrameExpressionStack().addOffsetTo(-slot * VM.getVM().getAddressSize());
|
|
306 }
|
|
307
|
|
308 /** Top of expression stack */
|
|
309 public abstract Address addressOfInterpreterFrameTOS();
|
|
310
|
|
311 /** Expression stack from top down */
|
|
312 public abstract Address addressOfInterpreterFrameTOSAt(int slot);
|
|
313
|
|
314 /** FIXME: is this portable? */
|
|
315 public int getInterpreterFrameExpressionStackSize() {
|
|
316 return (int) (1 + (getInterpreterFrameExpressionStackDirection() *
|
|
317 (addressOfInterpreterFrameTOS().minus(addressOfInterpreterFrameExpressionStack()))));
|
|
318 }
|
|
319
|
|
320 public abstract Address getInterpreterFrameSenderSP();
|
|
321 // FIXME: not yet implementable
|
|
322 // public abstract void setInterpreterFrameSenderSP(Address senderSP);
|
|
323
|
|
324 //--------------------------------------------------------------------------------
|
|
325 // BasicObjectLocks:
|
|
326 //
|
|
327
|
|
328 public abstract BasicObjectLock interpreterFrameMonitorBegin();
|
|
329 public abstract BasicObjectLock interpreterFrameMonitorEnd();
|
|
330 /** NOTE: this returns a size in BYTES in this system! */
|
|
331 public abstract int interpreterFrameMonitorSize();
|
|
332 public BasicObjectLock nextMonitorInInterpreterFrame(BasicObjectLock cur) {
|
|
333 return new BasicObjectLock(cur.address().addOffsetTo(interpreterFrameMonitorSize()));
|
|
334 }
|
|
335 public BasicObjectLock previousMonitorInInterpreterFrame(BasicObjectLock cur) {
|
|
336 return new BasicObjectLock(cur.address().addOffsetTo(-1 * interpreterFrameMonitorSize()));
|
|
337 }
|
|
338
|
|
339 // interpreter_frame_monitor_begin is higher in memory than interpreter_frame_monitor_end
|
|
340 // Interpreter_frame_monitor_begin points to one element beyond the oldest one,
|
|
341 // interpreter_frame_monitor_end points to the youngest one, or if there are none,
|
|
342 // it points to one beyond where the first element will be.
|
|
343 // interpreter_frame_monitor_size reports the allocation size of a monitor in the interpreter stack.
|
|
344 // this value is >= BasicObjectLock::size(), and may be rounded up
|
|
345
|
|
346 // FIXME: avoiding implementing this for now if possible
|
|
347 // public void interpreter_frame_set_monitor_end(BasicObjectLock* value);
|
|
348 // public void interpreter_frame_verify_monitor(BasicObjectLock* value) const;
|
|
349 //
|
|
350 // Tells whether the current interpreter_frame frame pointer
|
|
351 // corresponds to the old compiled/deoptimized fp
|
|
352 // The receiver used to be a top level frame
|
|
353 // public boolean interpreter_frame_equals_unpacked_fp(intptr_t* fp);
|
|
354
|
|
355 //--------------------------------------------------------------------------------
|
|
356 // Method and constant pool cache:
|
|
357 //
|
|
358
|
|
359 /** Current method */
|
|
360 public abstract Address addressOfInterpreterFrameMethod();
|
|
361
|
|
362 /** Current method */
|
|
363 public Method getInterpreterFrameMethod() {
|
|
364 return (Method) VM.getVM().getObjectHeap().newOop(addressOfInterpreterFrameMethod().getOopHandleAt(0));
|
|
365 }
|
|
366
|
|
367 /** Current method */
|
|
368 // FIXME: not yet implementable
|
|
369 // public void setInterpreterFrameMethod(Method method);
|
|
370
|
|
371 /** Constant pool cache */
|
|
372 public abstract Address addressOfInterpreterFrameCPCache();
|
|
373 /** Constant pool cache */
|
|
374 public ConstantPoolCache getInterpreterFrameCPCache() {
|
|
375 return (ConstantPoolCache) VM.getVM().getObjectHeap().newOop(addressOfInterpreterFrameCPCache().getOopHandleAt(0));
|
|
376 }
|
|
377
|
|
378 //--------------------------------------------------------------------------------
|
|
379 // Entry frames:
|
|
380 //
|
|
381
|
|
382 public abstract JavaCallWrapper getEntryFrameCallWrapper();
|
|
383
|
|
384 // FIXME: add
|
|
385 // inline intptr_t* entry_frame_argument_at(int offset) const;
|
|
386
|
|
387
|
|
388 /** Tells whether there is another chunk of Delta stack above */
|
|
389 public boolean entryFrameIsFirst() { return (getEntryFrameCallWrapper().getLastJavaSP() == null); }
|
|
390
|
|
391 //--------------------------------------------------------------------------------
|
|
392 // Safepoints:
|
|
393 //
|
|
394
|
|
395 protected abstract Address addressOfSavedOopResult();
|
|
396 protected abstract Address addressOfSavedReceiver();
|
|
397
|
|
398 public OopHandle getSavedOopResult() {
|
|
399 return addressOfSavedOopResult().getOopHandleAt(0);
|
|
400 }
|
|
401
|
|
402 // FIXME: not yet implementable
|
|
403 // public void setSavedOopResult(OopHandle obj);
|
|
404
|
|
405 public OopHandle getSavedReceiver() {
|
|
406 return addressOfSavedReceiver().getOopHandleAt(0);
|
|
407 }
|
|
408
|
|
409 // FIXME: not yet implementable
|
|
410 // public void setSavedReceiver(OopHandle obj);
|
|
411
|
|
412 //--------------------------------------------------------------------------------
|
|
413 // Oop traversals:
|
|
414 //
|
|
415
|
|
416 public void oopsInterpretedArgumentsDo(Symbol signature, boolean isStatic, AddressVisitor f) {
|
|
417 ArgumentOopFinder finder = new ArgumentOopFinder(signature, isStatic, this, f);
|
|
418 finder.oopsDo();
|
|
419 }
|
|
420
|
|
421 /** Conversion from an VMReg::Name to physical stack location */
|
|
422 public Address oopMapRegToLocation(VMReg reg, RegisterMap regMap) {
|
|
423 VMReg stack0 = VM.getVM().getVMRegImplInfo().getStack0();
|
|
424 if (reg.lessThan(stack0)) {
|
|
425 // If it is passed in a register, it got spilled in the stub frame.
|
|
426 return regMap.getLocation(reg);
|
|
427 } else {
|
|
428 long spOffset = VM.getVM().getAddressSize() * reg.minus(stack0);
|
|
429 return getUnextendedSP().addOffsetTo(spOffset);
|
|
430 }
|
|
431 }
|
|
432
|
|
433 public void oopsDo(AddressVisitor oopVisitor, RegisterMap map) {
|
|
434 if (isInterpretedFrame()) {
|
|
435 oopsInterpretedDo(oopVisitor, map);
|
|
436 } else if (isEntryFrame()) {
|
|
437 oopsEntryDo(oopVisitor, map);
|
|
438 } else if (VM.getVM().getCodeCache().contains(getPC())) {
|
|
439 oopsCodeBlobDo(oopVisitor, map);
|
|
440 } else {
|
|
441 Assert.that(false, "should not reach here");
|
|
442 }
|
|
443 }
|
|
444
|
|
445 //--------------------------------------------------------------------------------
|
|
446 // Printing code
|
|
447 //
|
|
448
|
|
449 public void printValue() {
|
|
450 printValueOn(System.out);
|
|
451 }
|
|
452
|
|
453 public void printValueOn(PrintStream tty) {
|
|
454 // FIXME;
|
|
455 }
|
|
456
|
|
457 public void print() {
|
|
458 printOn(System.out);
|
|
459 }
|
|
460
|
|
461 public void printOn(PrintStream tty) {
|
|
462 // FIXME;
|
|
463 }
|
|
464
|
|
465 public void interpreterFramePrintOn(PrintStream tty) {
|
|
466 // FIXME;
|
|
467 }
|
|
468
|
|
469 //--------------------------------------------------------------------------------
|
|
470 // Get/set typed locals from a frame.
|
|
471 // Respects platform dependent word-ordering.
|
|
472 //
|
|
473 // FIXME: avoiding implementing this for now if possible
|
|
474 //
|
|
475 // Currently these work only for interpreted frames.
|
|
476 // Todo: make these work for compiled frames.
|
|
477 //
|
|
478 // oop get_local_object(jint slot) const;
|
|
479 // jint get_local_int (jint slot) const;
|
|
480 // jlong get_local_long (jint slot) const;
|
|
481 // jfloat get_local_float (jint slot) const;
|
|
482 // jdouble get_local_double(jint slot) const;
|
|
483 //
|
|
484 // void set_local_object(jint slot, oop obj);
|
|
485 // void set_local_int (jint slot, jint i);
|
|
486 // void set_local_long (jint slot, jlong l);
|
|
487 // void set_local_float (jint slot, jfloat f);
|
|
488 // void set_local_double(jint slot, jdouble d);
|
|
489
|
|
490 // FIXME: add safepoint code, oops_do, etc.
|
|
491 // FIXME: NOT FINISHED
|
|
492
|
|
493
|
|
494
|
|
495
|
|
496
|
|
497 //--------------------------------------------------------------------------------
|
|
498 // Internals only below this point
|
|
499 //
|
|
500
|
|
501 // /** Helper method for better factored code in frame::sender */
|
|
502 // private frame sender_for_entry_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); }
|
|
503 // private frame sender_for_interpreter_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); }
|
|
504
|
|
505 //
|
|
506 // Oop iteration (FIXME: NOT FINISHED)
|
|
507 //
|
|
508
|
|
509
|
|
510 private static class InterpVisitor implements OopMapVisitor {
|
|
511 private AddressVisitor addressVisitor;
|
|
512
|
|
513 public InterpVisitor(AddressVisitor oopVisitor) {
|
|
514 setAddressVisitor(oopVisitor);
|
|
515 }
|
|
516
|
|
517 public void setAddressVisitor(AddressVisitor addressVisitor) {
|
|
518 this.addressVisitor = addressVisitor;
|
|
519 }
|
|
520
|
|
521 public void visitOopLocation(Address oopAddr) {
|
|
522 addressVisitor.visitAddress(oopAddr);
|
|
523 }
|
|
524
|
|
525 public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) {
|
|
526 if (VM.getVM().isClientCompiler()) {
|
|
527 Assert.that(false, "should not reach here");
|
|
528 } else if (VM.getVM().isServerCompiler() &&
|
|
529 VM.getVM().useDerivedPointerTable()) {
|
|
530 Assert.that(false, "FIXME: add derived pointer table");
|
|
531 }
|
|
532 }
|
|
533
|
|
534 public void visitValueLocation(Address valueAddr) {
|
|
535 }
|
|
536
|
|
537 public void visitDeadLocation(Address deadAddr) {
|
|
538 }
|
|
539 }
|
|
540
|
|
541 private void oopsInterpretedDo(AddressVisitor oopVisitor, RegisterMap map) {
|
|
542 if (Assert.ASSERTS_ENABLED) {
|
|
543 Assert.that(map != null, "map must be set");
|
|
544 }
|
|
545 Method m = getInterpreterFrameMethod();
|
|
546 int bci = getInterpreterFrameBCI();
|
|
547
|
|
548 // FIXME: Seeing this sometimes
|
|
549 if (VM.getVM().isDebugging()) {
|
|
550 if (bci < 0 || bci >= m.getCodeSize()) return;
|
|
551 }
|
|
552
|
|
553 if (Assert.ASSERTS_ENABLED) {
|
|
554 // Assert.that(VM.getVM().getUniverse().heap().isIn(m), "method must be valid oop");
|
|
555 Assert.that((m.isNative() && (bci == 0)) || ((bci >= 0) && (bci < m.getCodeSize())), "invalid bci value");
|
|
556 }
|
|
557
|
|
558 // Handle the monitor elements in the activation
|
|
559 // FIXME: monitor information not yet exposed
|
|
560 // for (
|
|
561 // BasicObjectLock* current = interpreter_frame_monitor_end();
|
|
562 // current < interpreter_frame_monitor_begin();
|
|
563 // current = next_monitor_in_interpreter_frame(current)
|
|
564 // ) {
|
|
565 //#ifdef ASSERT
|
|
566 // interpreter_frame_verify_monitor(current);
|
|
567 //#endif
|
|
568 // current->oops_do(f);
|
|
569 // }
|
|
570
|
|
571 // process fixed part
|
|
572 oopVisitor.visitAddress(addressOfInterpreterFrameMethod());
|
|
573 oopVisitor.visitAddress(addressOfInterpreterFrameCPCache());
|
|
574
|
|
575 // FIXME: expose interpreterFrameMirrorOffset
|
|
576 // if (m.isNative() && m.isStatic()) {
|
|
577 // oopVisitor.visitAddress(getFP().addOffsetTo(interpreterFrameMirrorOffset));
|
|
578 // }
|
|
579
|
|
580 int maxLocals = (int) (m.isNative() ? m.getSizeOfParameters() : m.getMaxLocals());
|
|
581 InterpreterFrameClosure blk = new InterpreterFrameClosure(this, maxLocals, (int) m.getMaxStack(), oopVisitor);
|
|
582
|
|
583 // process locals & expression stack
|
|
584 OopMapCacheEntry mask = m.getMaskFor(bci);
|
|
585 mask.iterateOop(blk);
|
|
586
|
|
587 // process a callee's arguments if we are at a call site
|
|
588 // (i.e., if we are at an invoke bytecode)
|
|
589 if (map.getIncludeArgumentOops() && !m.isNative()) {
|
|
590 BytecodeInvoke call = BytecodeInvoke.atCheck(m, bci);
|
|
591 if (call != null && getInterpreterFrameExpressionStackSize() > 0) {
|
|
592 // we are at a call site & the expression stack is not empty
|
|
593 // => process callee's arguments
|
|
594 //
|
|
595 // Note: The expression stack can be empty if an exception
|
|
596 // occured during method resolution/execution. In all
|
|
597 // cases we empty the expression stack completely be-
|
|
598 // fore handling the exception (the exception handling
|
|
599 // code in the interpreter calls a blocking runtime
|
|
600 // routine which can cause this code to be executed).
|
|
601 // (was bug gri 7/27/98)
|
|
602 oopsInterpretedArgumentsDo(call.signature(), call.isInvokestatic(), oopVisitor);
|
|
603 }
|
|
604 }
|
|
605 }
|
|
606
|
|
607 private void oopsEntryDo (AddressVisitor oopVisitor, RegisterMap regMap) {}
|
|
608 private void oopsCodeBlobDo (AddressVisitor oopVisitor, RegisterMap regMap) {
|
|
609 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());
|
|
610 if (Assert.ASSERTS_ENABLED) {
|
|
611 Assert.that(cb != null, "sanity check");
|
|
612 }
|
|
613 if (cb.getOopMaps() != null) {
|
|
614 OopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging());
|
|
615
|
|
616 // FIXME: add in traversal of argument oops (skipping this for
|
|
617 // now until we have the other stuff tested)
|
|
618
|
|
619 }
|
|
620
|
|
621 // FIXME: would add this in in non-debugging system
|
|
622
|
|
623 // If we see an activation belonging to a non_entrant nmethod, we mark it.
|
|
624 // if (cb->is_nmethod() && ((nmethod *)cb)->is_not_entrant()) {
|
|
625 // ((nmethod*)cb)->mark_as_seen_on_stack();
|
|
626 // }
|
|
627 }
|
|
628
|
|
629 // FIXME: implement the above routines, plus add
|
|
630 // oops_interpreted_arguments_do and oops_compiled_arguments_do
|
|
631 }
|
|
632
|
|
633 //
|
|
634 // Only used internally, to iterate through oop slots in interpreted
|
|
635 // frames
|
|
636 //
|
|
637 class InterpreterFrameClosure implements OffsetClosure {
|
|
638 // Used for debugging this code
|
|
639 private static final boolean DEBUG = false;
|
|
640
|
|
641 private Frame fr;
|
|
642 private AddressVisitor f;
|
|
643 private int maxLocals;
|
|
644 private int maxStack;
|
|
645
|
|
646 InterpreterFrameClosure(Frame fr, int maxLocals, int maxStack, AddressVisitor f) {
|
|
647 this.fr = fr;
|
|
648 this.maxLocals = maxLocals;
|
|
649 this.maxStack = maxStack;
|
|
650 this.f = f;
|
|
651 }
|
|
652
|
|
653 public void offsetDo(int offset) {
|
|
654 if (DEBUG) {
|
|
655 System.err.println("Visiting offset " + offset + ", maxLocals = " + maxLocals +
|
|
656 " for frame " + fr + ", method " +
|
|
657 fr.getInterpreterFrameMethod().getMethodHolder().getName().asString() +
|
|
658 fr.getInterpreterFrameMethod().getName().asString());
|
|
659 }
|
|
660 Address addr;
|
|
661 if (offset < maxLocals) {
|
|
662 addr = fr.addressOfInterpreterFrameLocal(offset);
|
|
663 if (Assert.ASSERTS_ENABLED) {
|
|
664 Assert.that(AddressOps.gte(addr, fr.getSP()), "must be inside the frame");
|
|
665 }
|
|
666 if (DEBUG) {
|
|
667 System.err.println(" Visiting local at addr " + addr);
|
|
668 }
|
|
669 f.visitAddress(addr);
|
|
670 } else {
|
|
671 addr = fr.addressOfInterpreterFrameExpressionStackSlot(offset - maxLocals);
|
|
672 if (DEBUG) {
|
|
673 System.err.println(" Address of expression stack slot: " + addr + ", TOS = " +
|
|
674 fr.addressOfInterpreterFrameTOS());
|
|
675 }
|
|
676 // In case of exceptions, the expression stack is invalid and the esp will be reset to express
|
|
677 // this condition. Therefore, we call f only if addr is 'inside' the stack (i.e., addr >= esp for Intel).
|
|
678 boolean inStack;
|
|
679 if (fr.getInterpreterFrameExpressionStackDirection() > 0) {
|
|
680 inStack = AddressOps.lte(addr, fr.addressOfInterpreterFrameTOS());
|
|
681 } else {
|
|
682 inStack = AddressOps.gte(addr, fr.addressOfInterpreterFrameTOS());
|
|
683 }
|
|
684 if (inStack) {
|
|
685 if (DEBUG) {
|
|
686 System.err.println(" In stack; visiting location.");
|
|
687 }
|
|
688 f.visitAddress(addr);
|
|
689 } else if (DEBUG) {
|
|
690 System.err.println(" *** WARNING: Address is out of bounds");
|
|
691 }
|
|
692 }
|
|
693 }
|
|
694 }
|
|
695
|
|
696 // Only used internally, to find arguments in interpreted frames
|
|
697 class ArgumentOopFinder extends SignatureInfo {
|
|
698 private AddressVisitor f;
|
|
699 private int offset;
|
|
700 private boolean isStatic;
|
|
701 private Frame fr;
|
|
702
|
|
703 protected void set(int size, int type) {
|
|
704 offset -= size;
|
|
705 if (type == BasicType.getTObject() || type == BasicType.getTArray()) oopOffsetDo();
|
|
706 }
|
|
707
|
|
708 private void oopOffsetDo() {
|
|
709 f.visitAddress(fr.addressOfInterpreterFrameTOSAt(offset));
|
|
710 }
|
|
711
|
|
712 public ArgumentOopFinder(Symbol signature, boolean isStatic, Frame fr, AddressVisitor f) {
|
|
713 super(signature);
|
|
714
|
|
715 // compute size of arguments
|
|
716 int argsSize = new ArgumentSizeComputer(signature).size() + (isStatic ? 0 : 1);
|
|
717 if (Assert.ASSERTS_ENABLED) {
|
|
718 Assert.that(!fr.isInterpretedFrame() ||
|
|
719 argsSize <= fr.getInterpreterFrameExpressionStackSize(), "args cannot be on stack anymore");
|
|
720 }
|
|
721 // initialize ArgumentOopFinder
|
|
722 this.f = f;
|
|
723 this.fr = fr;
|
|
724 this.offset = argsSize;
|
|
725 this.isStatic = isStatic;
|
|
726 }
|
|
727
|
|
728 public void oopsDo() {
|
|
729 if (!isStatic) {
|
|
730 --offset;
|
|
731 oopOffsetDo();
|
|
732 }
|
|
733 iterateParameters();
|
|
734 }
|
|
735 }
|