[armedbear-devel] Objects sharing structure at compile time, get "destructured" in our FASL format

Alessio Stalla alessiostalla at gmail.com
Sun May 16 09:38:22 UTC 2010


On Sun, May 16, 2010 at 5:28 AM, Tobias C. Rittweiler <tcr at freebits.de> wrote:
> Erik Huelsmann <ehuels at gmail.com> writes:
>
>> The other day, Alessio and I were talking about how unfortunate it is
>> that we use the reader to create relatively simple structures, such as
>> lists in our Java classes. To illustrate:
>>
>> (defun foo ()
>>   (let ((x '(1 2 3)))
>>     x))
>>
>> In the above definition, if being file-compiled, the litteral list (1
>> 2 3) gets serialized into a string which is - at load time - converted
>> back to an object like this:
>>
>>    LispObject theObject = Lisp.readObjectFromString("(1 2 3)");
>>
>> In our minds, it would be faster to generate:
>>
>>   LispObject theObject = new Cons(new Fixnum(1), new Cons(new
>> Fixnum(2), new Cons(new Fixnum(3)))));
>>
>> Because that eliminates the need to set up a stream, reading from a
>> string, running all the characters through the reader, including
>> running of dispatch functions, etc.
>>
>>
>> While that would be a nice optimization, I've run into a correctness
>> issue investigating our current serialization.
>>
>> Now consider the following macro:
>>
>> (defmacro foo (x)
>>   `(defun bar ()
>>      (let ((a ,x)
>>          (b ,x))
>>        (eq a b))))
>>
>> (foo '(1 2 3))
>>
>> This macro can be used to generate an example of 2 objects sharing
>> structure to the extreme: they are the same object. The same object is
>> supposed to be assigned to A and B. In the interpreter, the result of
>> a function call to BAR returns T. However, after filecompiling the
>> above forms and loading the resulting fasl, the outcome of BAR is NIL.
>>
>> Suddenly, the forms are not the same anymore. The answer to that is
>> too simple: the object assigned to A and B is being read for A and B
>> separately with a readObjectFromString call, like this:
>>
>>   LispObject theObjectA = Lisp.readObjectFromString("(1 2 3)");
>>   LispObject theObjectB = Lisp.readObjectFromString("(1 2 3)");
>>
>> The above is clearly wrong. The solution to this case is very simple:
>> we should detect "duplicates" being serialized by the
>> DECLARE-OBJECT-AS-STRING function.
>
> Why wrong? Literal coalescing is optional behaviour as far as I
> remember.

Literal coalescing is this: (cons '(1 2 3) '(1 2 3)) those two
different '(1 2 3) constant objects can be coalesced to a single
object at the discretion of the compiler (only in file compilation,
iirc).

However, Erik talked about cases when the same literal object is
present more than once in the source, like in:

(let ((foo '(1 2 3)))
  (compile nil `(lambda () (eq ',foo ',foo))))

Clearly, in the second case the equality of the constant object must
be preserved.

Alessio




More information about the armedbear-devel mailing list