1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)frame.c 8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11
12 /*
13 * Activation record handling.
14 *
15 * The routines curframe and nextframe cheat by using a global copy
16 * of the display. This means there can't be multiple instances of
17 * them active at the same time and nextframe won't work in arbitrary cases.
18 *
19 * This could be solved by putting the display copy into the FRAME structure,
20 * but I didn't feel like doing this. The idea is that they be used
21 * in looping through all frames, if I had generators I would use them.
22 */
23
24 #include "defs.h"
25 #include "runtime.h"
26 #include "machine.h"
27 #include "process.h"
28 #include "sym.h"
29 #include "object.h"
30 #include "mappings.h"
31 #include "process/pxinfo.h"
32 #include "frame.rep"
33 #include "process/process.rep"
34
35 /*
36 * Return a pointer to the current activation record.
37 * Return NIL if currently in the main program.
38 * The storage is static.
39 */
40
41 #define MAXDEPTH 7
42 #define dispblk(dp) ((dp - DISPLAY) / 2)
43
44 LOCAL ADDRESS *display[MAXDEPTH];
45 LOCAL int dispindex;
46
curframe()47 FRAME *curframe()
48 {
49 static FRAME frame;
50 FRAME *frp;
51 ADDRESS *dp, *disp;
52 int i;
53
54 frp = &frame;
55 dp = curdp();
56 disp = contents(dp);
57 if (dispblk(dp) <= MAINBLK) {
58 return NIL;
59 } else {
60 getframe(frp, disp);
61 for (i = 1; i < MAXDEPTH; i++) {
62 display[i] = dispval(i);
63 }
64 dispindex = dispblk(dp);
65 return frp;
66 }
67 }
68
69 /*
70 * Return a pointer to the next activation record up the stack.
71 * Return NIL if there is none.
72 * Writes over space pointed to by given argument.
73 */
74
nextframe(frp)75 FRAME *nextframe(frp)
76 FRAME *frp;
77 {
78 ADDRESS *fp;
79
80 if (dispblk(frp->save_dp) <= MAINBLK) {
81 return(NIL);
82 } else {
83 display[dispindex] = frp->save_disp;
84 dispindex = dispblk(frp->save_dp);
85 fp = display[dispindex];
86 getframe(frp, fp);
87 return(frp);
88 }
89 }
90
91 /*
92 * Return the frame associated with the given function.
93 */
94
findframe(f)95 FRAME *findframe(f)
96 SYM *f;
97 {
98 static FRAME frame;
99 FRAME *frp, *prevfrp;
100
101 frame.save_dp = curdp();
102 frame.save_disp = contents(frame.save_dp);
103 prevfrp = &frame;
104 for (frp = curframe(); frp != NIL; frp = nextframe(frp)) {
105 if (whatblock(entry(frp)) == f) {
106 return frp;
107 }
108 *prevfrp = *frp;
109 }
110 if (f == program) {
111 return prevfrp;
112 } else {
113 return NIL;
114 }
115 }
116
117 /*
118 * Get the activation record associated with the given display pointer.
119 */
120
getframe(frp,disp)121 LOCAL getframe(frp, disp)
122 FRAME *frp;
123 ADDRESS *disp;
124 {
125 if (disp == NIL) {
126 panic("bad disp in getframe");
127 }
128 dread(frp, disp, sizeof(FRAME));
129 frp->save_pc -= ENDOFF;
130 }
131
132 /*
133 * Return the address of the display in the px process for the given block.
134 */
135
dispval(b)136 ADDRESS *dispval(b)
137 int b;
138 {
139 ADDRESS *r;
140
141 dread(&r, (ADDRESS) (DISPLAY + 2*b), sizeof(r));
142 return r;
143 }
144
145 /*
146 * Return the current display pointer.
147 */
148
curdp()149 ADDRESS *curdp()
150 {
151 ADDRESS *r;
152
153 dread(&r, (ADDRESS) DP, sizeof(r));
154 return r;
155 }
156
157 /*
158 * Return the contents of the given display pointer.
159 */
160
contents(dp)161 ADDRESS *contents(dp)
162 ADDRESS *dp;
163 {
164 ADDRESS *r;
165
166 dread(&r, (ADDRESS) dp, sizeof(r));
167 return r;
168 }
169
170 /*
171 * Return the px stack address associated with a given frame pointer.
172 * Actually, to confuse the issue we want the stack address of the
173 * frame one up from the given one.
174 */
175
stkaddr(frp,b)176 ADDRESS stkaddr(frp, b)
177 FRAME *frp;
178 int b;
179 {
180 return (ADDRESS) display[b];
181 }
182