11.11.2014 Views

Design of CMU Common Lisp.pdf - Common Lisp.net

Design of CMU Common Lisp.pdf - Common Lisp.net

Design of CMU Common Lisp.pdf - Common Lisp.net

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter 9<br />

Type checking<br />

We need to do a pretty good job <strong>of</strong> guessing when a type check will ultimately need to be done. Generic<br />

arithmetic, for example: In the absence <strong>of</strong> declarations, we will use the safe variant, but if we don’t know this,<br />

we will generate a check for NUMBER anyway. We need to look at the fast-safe templates and guess if any <strong>of</strong><br />

them could apply.<br />

We compute a function type from the VOP arguments and assertions on those arguments. This can be<br />

used with Valid-Function-Use to see which templates do or might apply to a particular call. If we guess that<br />

a safe implementation will be used, then we mark the continuation so as to force a safe implementation to be<br />

chosen. [This will happen if ICR optimize doesn’t run to completion, so the ICR optimization after type check<br />

generation can discover new type information. Since we won’t redo type check at that point, there could be a<br />

call that has applicable unsafe templates, but isn’t type checkable.]<br />

[### A better and more general optimization <strong>of</strong> structure type checks: in type check conversion, we look<br />

at the *original derived* type <strong>of</strong> the continuation: if the difference between the proven type and the asserted<br />

type is a simple type check, then check for the negation <strong>of</strong> the difference. e.g. if we want a FOO and we know<br />

we’ve got (OR FOO NULL), then test for (NOT NULL). This is a very important optimization for linked lists <strong>of</strong><br />

structures, but can also apply in other situations.]<br />

If after ICR phases, we have a continuation with check-type set in a context where it seems likely a check will<br />

be emitted, and the type is too hairy to be easily checked (i.e. no CHECK-xxx VOP), then we do a transformation<br />

on the ICR equivalent to:<br />

(... (the hair ) ...)<br />

==><br />

(... (funcall \#’(lambda (\#:val)<br />

(if (typep \#:val ’hair)<br />

\#:val<br />

(%type-check-error \#:val ’hair)))<br />

)<br />

...)<br />

This way, we guarantee that VMR conversion never has to emit type checks for hairy types.<br />

[Actually, we need to do a MV-bind and several type checks when there is a MV continuation. And some<br />

values types are just too hairy to check. We really can’t check any assertion for a non-fixed number <strong>of</strong> values,<br />

since there isn’t any efficient way to bind arbitrary numbers <strong>of</strong> values. (could be done with MV-call <strong>of</strong> a morearg<br />

function, I guess...) ]<br />

[Perhaps only use CHECK-xxx VOPs for types equivalent to a ptype? Exceptions for CONS and SYMBOL?<br />

Anyway, no point in going to trouble to implement and emit rarely used CHECK-xxx vops.]<br />

One potential lose in converting a type check to explicit conditionals rather than to a CHECK-xxx VOP is<br />

that VMR code motion optimizations won’t be able to do anything. This shouldn’t be much <strong>of</strong> an issue, though,<br />

since type constraint propagation has already done global optimization <strong>of</strong> type checks.<br />

This phase is optional, but should be done if anything is more important than compile speed.<br />

Type check is responsible for reconciling the continuation asserted and derived types, emitting type checks<br />

if appropriate. If the derived type is a subtype <strong>of</strong> the asserted type, then we don’t need to do anything.<br />

28

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!