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