Сообщение Re[3]: protect variables от 09.03.2016 1:35
Изменено 09.03.2016 1:49 Evgeny.Panasyuk
CS>аргументы или перменные — не важно.
CS>Они все на стеке лежат если рассматривать идеальную "C машину".
Не идеальную, а простую.
CS>Практика показывает что не всегда на стеке, а например в регистрах.
CS>Не сильно хочется влазить в специфику процессоров или компиляторов. Сейчас оно компилируется всем что шевелится, т.е. чистый и незамутнённый C/C++.
CS>Но если без этого никак то придётся наверное.
Даже если будешь некроссплатформенно сканировать регистры и стек, то проблема с консервативностью всё равно останется
CS>В принципе я могу текущую VM* положить в TLS если это поможет. Чтобы не таскать параметр для PROTECT например.
Либо через TLS, либо через быструю маску по адресу — проблема доп параметра решается. Ещё есть какие-нибудь барьеры для использовании RAII обёрток?
P.S. В SpiderMonkey используются именно RAII обёртки:
All GC thing pointers stored on the stack (i.e., local variables and parameters to functions) must use the JS::Rooted<T> class.
...
SpiderMonkey makes it easy to remember to use JS::Rooted<T> types instead of a raw pointer because all of the API methods that may GC take a JS::Handle<T>, as described below.
...
All GC thing pointers that are parameters to a function must be wrapped in JS::Handle<T>. A JS::Handle<T> is a reference to a JS::Rooted<T>. All JS::Handle<T> are created implicitly by referencing a JS::Rooted<T>: It is not valid to create a JS::Handle<T> manually. Like JS::Rooted<T>, a JS::Handle<T> can be used as if it were the underlying pointer.
Since only a JS::Rooted<T> will cast to a JS::Handle<T>, the compiler will enforce correct rooting of any parameters passed to a function that may trigger GC. JS::Handle<T> exists because creating and destroying a JS::Rooted<T> is not free (though it only costs a few cycles). Thus, it makes more sense to only root the GC thing once and reuse it through an indirect reference. Like a reference, a JS::Handle is immutable: it can only ever refer to the JS::Rooted<T> that it was created for.
CS>аргументы или перменные — не важно.
CS>Они все на стеке лежат если рассматривать идеальную "C машину".
Не идеальную, а простую.
CS>Практика показывает что не всегда на стеке, а например в регистрах.
CS>Не сильно хочется влазить в специфику процессоров или компиляторов. Сейчас оно компилируется всем что шевелится, т.е. чистый и незамутнённый C/C++.
CS>Но если без этого никак то придётся наверное.
Даже если будешь некроссплатформенно сканировать регистры и стек, то проблема с консервативностью всё равно останется
CS>В принципе я могу текущую VM* положить в TLS если это поможет. Чтобы не таскать параметр для PROTECT например.
Либо через TLS, либо через быструю маску по адресу — проблема доп параметра решается. Ещё есть какие-нибудь барьеры для использовании RAII обёрток?
P.S. В SpiderMonkey используются именно RAII обёртки:
Вот релевантный код — там например строится интрузивный стек из Rooted.All GC thing pointers stored on the stack (i.e., local variables and parameters to functions) must use the JS::Rooted<T> class.
...
SpiderMonkey makes it easy to remember to use JS::Rooted<T> types instead of a raw pointer because all of the API methods that may GC take a JS::Handle<T>, as described below.
...
All GC thing pointers that are parameters to a function must be wrapped in JS::Handle<T>. A JS::Handle<T> is a reference to a JS::Rooted<T>. All JS::Handle<T> are created implicitly by referencing a JS::Rooted<T>: It is not valid to create a JS::Handle<T> manually. Like JS::Rooted<T>, a JS::Handle<T> can be used as if it were the underlying pointer.
Since only a JS::Rooted<T> will cast to a JS::Handle<T>, the compiler will enforce correct rooting of any parameters passed to a function that may trigger GC. JS::Handle<T> exists because creating and destroying a JS::Rooted<T> is not free (though it only costs a few cycles). Thus, it makes more sense to only root the GC thing once and reuse it through an indirect reference. Like a reference, a JS::Handle is immutable: it can only ever refer to the JS::Rooted<T> that it was created for.