|
244 | 244 |
|
245 | 245 | ;;; Heap allocation |
246 | 246 |
|
247 | | -(define (emit-alloc cg size size-align post-align allocreg spare-regs) |
| 247 | +(define (heap-exhausted-bitset spare-regs protect-regs) |
| 248 | + (let* ((prot-bits (register-bitset protect-regs))) |
| 249 | + ;; Protected registers are distinct from live registers for the |
| 250 | + ;; purposes of heap_exhausted, so we include them in the spare |
| 251 | + ;; register set. |
| 252 | + (logior (logior (register-bitset spare-regs) prot-bits) |
| 253 | + (ash prot-bits general-register-count)))) |
| 254 | + |
| 255 | +(define (emit-alloc cg size size-align post-align allocreg spare-regs |
| 256 | + protect-regs) |
248 | 257 | (let* ((again-label (gen-label)) |
249 | 258 | (exhausted-label (gen-label))) |
250 | 259 | (flush-labels-and-jumps cg) |
|
260 | 269 | (codegen-push-out-of-line cg |
261 | 270 | (lambda () |
262 | 271 | (emit-raw-label cg exhausted-label) |
263 | | - (emit-mov cg (register-bitset (cons allocreg spare-regs)) %closure) |
| 272 | + (emit-mov cg (heap-exhausted-bitset (cons allocreg spare-regs) |
| 273 | + protect-regs) %closure) |
264 | 274 | (emit cg "call heap_exhausted") |
265 | 275 | (emit-restore-%closure cg) |
266 | 276 | (emit-jump cg again-label))))) |
267 | 277 |
|
268 | 278 | (define gc-label (make-label-for 'gc direct-function-label-prefix)) |
269 | 279 |
|
270 | 280 | (define (codegen-helpers cg) |
271 | | - (labels ((for-live-registers (regs op) |
| 281 | + (labels ((for-registers (regs bit-offset negated-cond op) |
272 | 282 | (dolist (reg regs) |
273 | 283 | (let* ((l (gen-label))) |
274 | | - (emit-test cg (register-bit reg) %closure) |
275 | | - (emit-branch cg "nz" l) |
| 284 | + (emit-test cg (ash (register-bit reg) bit-offset) %closure) |
| 285 | + (emit-branch cg negated-cond l) |
276 | 286 | (funcall op cg reg) |
277 | 287 | (emit-raw-label cg l))))) |
278 | 288 | (emit cg ".text") |
|
281 | 291 | ;; Push live registers onto the stack, guided by the bitset in |
282 | 292 | ;; %closure. This preserves their values, and also means that |
283 | 293 | ;; they get treated as part of the root set by the GC. |
284 | | - (for-live-registers general-registers (function emit-push)) |
285 | | - (emit-push cg %closure) |
| 294 | + (for-registers general-registers 0 "nz" (function emit-push)) |
| 295 | + |
| 296 | + ;; Push protected registers onto the stack. These are preserved, |
| 297 | + ;; but not seen or touched by the GC. |
| 298 | + (for-registers general-registers general-register-count "z" |
| 299 | + (function emit-push)) |
286 | 300 |
|
287 | | - ;; The stack-bottom argument skips the live reg bitset, so that it |
288 | | - ;; doesn't get exposed to the GC. |
289 | | - (emit-lea cg (indexed-operand %sp 1) %closure) |
| 301 | + ;; Preserve the register bitset |
290 | 302 | (emit-push cg %closure) |
| 303 | + |
| 304 | + ;; Work out the stack-bottom argument, skipping the live reg |
| 305 | + ;; bitset and any protected register values |
| 306 | + (emit-lea cg (indexed-operand %sp 1) %a) |
| 307 | + (for-registers general-registers general-register-count "z" |
| 308 | + (lambda (cg reg) (emit-add cg value-size %a))) |
| 309 | + (emit-push cg %a) |
291 | 310 | (emit cg "call ~A" gc-label) |
292 | 311 |
|
293 | | - ;; Restore live registers |
| 312 | + ;; Restore register bitset |
294 | 313 | (emit-pop cg %closure) |
295 | | - (for-live-registers (reverse general-registers) (function emit-pop)) |
| 314 | + |
| 315 | + (let* ((rev-gen-regs (reverse general-registers))) |
| 316 | + ;; Restore protected registers |
| 317 | + (for-registers rev-gen-regs general-register-count "z" |
| 318 | + (function emit-pop)) |
| 319 | + |
| 320 | + ;; Restore live registers |
| 321 | + (for-registers rev-gen-regs 0 "nz" (function emit-pop))) |
296 | 322 |
|
297 | 323 | (emit cg "ret"))) |
298 | 324 |
|
|
301 | 327 | (define-operator (raw-alloc (size reg-imm)) ((temp-regs alloc)) |
302 | 328 | (emit-alloc cg (emit-scale-number cg value-scale size) value-scale |
303 | 329 | (compiler-constant-value (attr-ref attrs 'tag-bits)) |
304 | | - alloc spare-regs) |
| 330 | + alloc spare-regs (if (number? size) () (list size))) |
305 | 331 | (emit-mov cg alloc result) |
306 | 332 | result) |
307 | 333 |
|
|
312 | 338 | ;; enclosed by a lambda that does the initialization. |
313 | 339 | (define-operator (alloc-closure) () |
314 | 340 | (emit-alloc cg (* value-size (1+ (attr-ref attrs 'length))) |
315 | | - value-scale closure-tag-bits result spare-regs) |
| 341 | + value-scale closure-tag-bits result spare-regs ()) |
316 | 342 | (emit-mov cg (attr-ref attrs 'label) (mem-operand result)) |
317 | 343 | (emit-add cg closure-tag result) |
318 | 344 | result) |
|
393 | 419 | ;;; Conses |
394 | 420 |
|
395 | 421 | (define-operator (cons (a reg-imm) (d reg-imm)) ((temp-regs alloc)) |
396 | | - (emit-alloc cg (* 2 value-size) value-scale pair-tag-bits alloc spare-regs) |
| 422 | + (emit-alloc cg (* 2 value-size) value-scale pair-tag-bits alloc spare-regs ()) |
397 | 423 | (emit-mov cg a (mem-operand alloc)) |
398 | 424 | (emit-mov cg d (indexed-operand alloc 1)) |
399 | 425 | (emit-lea cg (offset-operand alloc pair-tag) result) |
|
413 | 439 | ;;; Boxes |
414 | 440 |
|
415 | 441 | (define-operator (raw-make-box (val reg-imm)) ((temp-regs alloc)) |
416 | | - (emit-alloc cg value-size value-scale box-tag-bits alloc spare-regs) |
| 442 | + (emit-alloc cg value-size value-scale box-tag-bits alloc spare-regs ()) |
417 | 443 | (emit-mov cg val (mem-operand alloc)) |
418 | 444 | (emit-lea cg (offset-operand alloc box-tag) result) |
419 | 445 | result) |
|
435 | 461 |
|
436 | 462 | (define-operator (raw-make-symbol (str reg-imm) (id reg-imm)) |
437 | 463 | ((temp-regs alloc)) |
438 | | - (emit-alloc cg (* 2 value-size) value-scale symbol-tag-bits alloc spare-regs) |
| 464 | + (emit-alloc cg (* 2 value-size) value-scale symbol-tag-bits alloc spare-regs |
| 465 | + ()) |
439 | 466 | (emit-mov cg str (mem-operand alloc)) |
440 | 467 | (emit-mov cg id (indexed-operand alloc 1)) |
441 | 468 | (emit-lea cg (offset-operand alloc symbol-tag) result) |
|
547 | 574 | (emit-mov cg len %c) |
548 | 575 | (emit-scale-number cg scale len) |
549 | 576 | (emit-add cg value-size len) |
550 | | - (emit-alloc cg len scale tag-bits alloc (list* %di spare-regs)) |
| 577 | + (emit-alloc cg len scale tag-bits alloc (list* %di spare-regs) (list len)) |
551 | 578 | (emit-mov cg alloc %di) |
552 | 579 | (emit-mov cg %c (mem-operand alloc)) |
553 | 580 | (emit-add cg value-size %di) |
|
0 commit comments