2 % (c) Parade/AQUA Projects, Glasgow University, 1995
3 % Kevin Hammond, February 15th. 1995
5 % This is for GUM only.
7 %************************************************************************
9 \section[Unpack.lc]{Unpacking closures which have been exported to remote processors}
11 %************************************************************************
13 This module defines routines for unpacking closures in the parallel runtime
17 #ifdef PAR /* whole file */
20 EXTDATA_RO(FetchMe_info);
26 static globalAddr *PendingGABuffer; /* HWL; init in main; */
29 InitPendingGABuffer(size)
33 = (globalAddr *) stgMallocBytes((size-PACK_HDR_SIZE)*2*sizeof(globalAddr), "InitPendingGABuffer");
37 @CommonUp@ commons up two closures which we have discovered to be
38 variants of the same object. One is made an indirection to the other.
42 CommonUp(P_ src, P_ dst)
47 switch (INFO_TYPE(INFO_PTR(src))) {
48 case INFO_SPEC_RBH_TYPE:
49 bqe = (P_) SPEC_RBH_BQ(src);
51 case INFO_GEN_RBH_TYPE:
52 bqe = (P_) GEN_RBH_BQ(src);
54 case INFO_FETCHME_TYPE:
58 bqe = (P_) FMBQ_ENTRIES(src);
61 /* Don't common up anything else */
65 /* Note that UPD_IND does *not* awaken the bq */
67 ASSERT(!IS_BIG_MOTHER(INFO_PTR(dst)));
68 if (IS_MUTABLE(INFO_PTR(bqe)))
69 AwakenBlockingQueue(bqe);
74 @UnpackGraph@ unpacks the graph contained in a message buffer. It
75 returns a pointer to the new graph. The @gamap@ parameter is set to
76 point to an array of (oldGA,newGA) pairs which were created as a
77 result of unpacking the buffer; @nGAs@ is set to the number of GA
78 pairs which were created.
80 The format of graph in the pack buffer is as defined in @Pack.lc@.
84 UnpackGraph(buffer, gamap, nGAs)
89 W_ size, ptrs, nonptrs, vhs;
91 P_ bufptr = buffer + PACK_HDR_SIZE;
100 P_ graphroot, graph, parent;
101 W_ pptr = 0, pptrs = 0, pvhs;
106 InitPackBuffer(); /* in case it isn't already init'd */
108 gaga = PendingGABuffer;
112 /* Unpack the header */
117 graph = AllocateHeap(bufsize);
118 ASSERT(graph != NULL);
124 /* This is where we will ultimately save the closure's address */
127 /* First, unpack the next GA or PLC */
128 ga.weight = *bufptr++;
131 ga.loc.gc.gtid = *bufptr++;
132 ga.loc.gc.slot = *bufptr++;
134 ga.loc.plc = (P_) *bufptr++;
136 /* Now unpack the closure body, if there is one */
138 /* No more to unpack; just set closure to local address */
140 fprintf(stderr, "Unpacked PLC at %x \n", ga.loc.plc);
142 closure = ga.loc.plc;
143 } else if (isOffset(&ga)) {
144 /* No more to unpack; just set closure to cached address */
145 ASSERT(parent != NULL);
146 closure = (P_) buffer[ga.loc.gc.slot];
149 /* Now we have to build something. */
154 * Close your eyes. You don't want to see where we're looking. You
155 * can't get closure info until you've unpacked the variable header,
156 * but you don't know how big it is until you've got closure info.
157 * So...we trust that the closure in the buffer is organized the
158 * same way as they will be in the heap...at least up through the
159 * end of the variable header.
161 ip = get_closure_info(bufptr, &size, &ptrs, &nonptrs, &vhs);
163 /* Fill in the fixed header */
164 for (i = 0; i < FIXED_HS; i++)
165 graph[i] = *bufptr++;
167 if (INFO_TYPE(ip) == INFO_FETCHME_TYPE)
168 size = ptrs = nonptrs = vhs = 0;
170 /* Fill in the packed variable header */
171 for (i = 0; i < vhs; i++)
172 graph[FIXED_HS + i] = *bufptr++;
174 /* Pointers will be filled in later */
176 /* Fill in the packed non-pointers */
177 for (i = 0; i < nonptrs; i++)
178 graph[FIXED_HS + i + vhs + ptrs] = *bufptr++;
180 /* Indirections are never packed */
181 ASSERT(INFO_PTR(graph) != (W_) Ind_info_TO_USE);
183 /* Add to queue for processing */
187 * Common up the new closure with any existing closure having the same
191 if ((existing = GALAlookup(&ga)) == NULL) {
193 /* Just keep the new object */
195 fprintf(stderr, "Unpacking new (%x, %d, %x)\n",
196 ga.loc.gc.gtid, ga.loc.gc.slot, ga.weight);
199 newGA = setRemoteGA(graph, &ga, rtsTrue);
200 if (INFO_TYPE(ip) == INFO_FETCHME_TYPE)
201 FETCHME_GA(closure) = newGA;
203 /* Two closures, one global name. Someone loses */
204 oldip = (P_) INFO_PTR(existing);
206 if ((INFO_TYPE(oldip) == INFO_FETCHME_TYPE || IS_BLACK_HOLE(oldip)) &&
207 INFO_TYPE(ip) != INFO_FETCHME_TYPE) {
209 /* What we had wasn't worth keeping */
211 CommonUp(existing, graph);
215 * Either we already had something worthwhile by this name or
216 * the new thing is just another FetchMe. However, the thing we
217 * just unpacked has to be left as-is, or the child unpacking
218 * code will fail. Remember that the way pointer words are
219 * filled in depends on the info pointers of the parents being
220 * the same as when they were packed.
223 fprintf(stderr, "Unpacking old (%x, %d, %x), keeping %#lx\n",
224 ga.loc.gc.gtid, ga.loc.gc.slot, ga.weight, existing);
228 /* Pool the total weight in the stored ga */
229 (void) addWeight(&ga);
232 /* Sort out the global address mapping */
233 if ((IS_THUNK(ip) && IS_UPDATABLE(ip)) ||
234 (IS_MUTABLE(ip) && INFO_TYPE(ip) != INFO_FETCHME_TYPE)) {
235 /* Make up new GAs for single-copy closures */
236 globalAddr *newGA = MakeGlobal(closure, rtsTrue);
238 ASSERT(closure == graph);
240 /* Create an old GA to new GA mapping */
242 splitWeight(gaga, newGA);
243 ASSERT(gaga->weight == 1L << (BITS_IN(unsigned) - 1));
246 graph += FIXED_HS + (size < MIN_UPD_SIZE ? MIN_UPD_SIZE : size);
250 * Set parent pointer to point to chosen closure. If we're at the top of
251 * the graph (our parent is NULL), then we want to arrange to return the
252 * chosen closure to our caller (possibly in place of the allocated graph
258 parent[FIXED_HS + pvhs + pptr] = (W_) closure;
260 /* Save closure pointer for resolving offsets */
261 *slotptr = (W_) closure;
263 /* Locate next parent pointer */
265 while (pptr + 1 > pptrs) {
266 parent = DeQueueClosure();
271 (void) get_closure_info(parent, &size, &pptrs, &nonptrs, &pvhs);
275 } while (parent != NULL);
277 ASSERT(bufsize == 0 || graph - 1 <= SAVE_Hp);
279 *gamap = PendingGABuffer;
280 *nGAs = (gaga - PendingGABuffer) / 2;
282 /* ToDo: are we *certain* graphroot has been set??? WDP 95/07 */
288 #endif /* PAR -- whole file */