From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Philipp Stephani
On 10/04/2015 02:41 AM, Philipp Stephani wrote:
>=C2=A0 =C2=A0 =C2=A0>
>=C2=A0 =C2=A0 =C2=A0>
>=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0 =C2=A0typedef struct emacs= _value_tag* emacs_value;
>=C2=A0 =C2=A0 =C2=A0>
>=C2=A0 =C2=A0 =C2=A0>
>=C2=A0 =C2=A0 =C2=A0> I think it's important that this is a poin= ter to a struct (for type
>=C2=A0 =C2=A0 =C2=A0> safety and size correctness) rather than just = an arbitrary type.
>
>=C2=A0 =C2=A0 =C2=A0A typedef is exactly as typesafe. The question of w= hether to use a
>=C2=A0 =C2=A0 =C2=A0struct or a typedef is aesthetic. I strongly prefer= a typedef, just like
>=C2=A0 =C2=A0 =C2=A0pthreads, and I believe that the people who advocat= e using structs
>=C2=A0 =C2=A0 =C2=A0directly are simply wrong.
>
>
> Ah, I'm not against the typedef, I'm just asking whether you w= ould make
> it part of the API contract that it's a typedef of a struct pointe= r, or
> whether it can be any type.
The problem with defining it as a pointer type is that NULL is now the
invalid sentinel value, which seems incompatible with both making this
thing literally a Lisp_Object and Qnil having all zero bits.
That's why I strongly prefer making emacs_value a _pointer_ to a
Lisp_Object, where we store the Lisp_Object in an array owned by the
emacs_env. This way, allocating local values is very cheap.
>=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0Modules can use make_global= _reference to allocate a global
>=C2=A0 =C2=A0 =C2=A0reference
>=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0(i.e., a GC root) for any e= macs_value; modules must then free
>=C2=A0 =C2=A0 =C2=A0these
>=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0references explicitly.
>=C2=A0 =C2=A0 =C2=A0>
>=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0All routines (except make_g= lobal_reference) that return
>=C2=A0 =C2=A0 =C2=A0emacs_value
>=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0values return local referen= ces.=C2=A0 It's up to modules to register
>=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0long-lived references expli= citly.
>=C2=A0 =C2=A0 =C2=A0>
>=C2=A0 =C2=A0 =C2=A0>
>=C2=A0 =C2=A0 =C2=A0> In which cases would global references be nece= ssary?
>
>=C2=A0 =C2=A0 =C2=A0Any time you want to hold onto a lisp value outside= the dynamic extent
>=C2=A0 =C2=A0 =C2=A0of your emacs_env.
>
>
> Isn't the dynamic extent of the emacs_env the whole program, start= ing
> from the module initializer?
Not necessarily. An emacs_env is valid only for the current call into
module code on the current thread. So if we call module-function-1, wait
for it to return, then call module-function-2, the two calls can have
different environments, and using local references from one might not be
valid on the other. (This approach opens up very important optimizations
in JNI, and it'd be good for us to use the same approach.) A global
reference is just an emacs_env in a heap-allocated object we register as
a GC root.
(To answer the question another way: global references are GC roots.)