Спайдермонк и сборщик мусора - PullRequest
3 голосов
/ 07 марта 2012

Я встраиваю Spidermonkey в свое приложение C ++.Мне нужно реализовать некоторые пользовательские функции Javascript на нативном C ++, которые передают jsval.Мне нужно защитить jsval от случайного сбора мусора.Правильно ли мне сделать это:

(1) В процедуре инициализации:

static jsval vp; // a STATIC variable, value unknown
JSBool init((JSContext *cx, uintN argc, jsval *vp) {
   JS_AddValueRoot(cx,  &vp);
}

(2) В одной функции c ++, реализующей функцию Javascript setter ():

JSBool setter(JSContext *cx, uintN argc, jsval *vp) {
   ...
  vp=...;// set to some JSObject and hopefully makes any previous JSObject available for gc

}

(3) Во втором вызове функции C ++ в том же модуле компиляции, реализующем функцию get JavaScript ():

JSBool getter(JSContext *cx, uintN argc, jsval *vp) {
  jsval somethingelse = vp; //directly retrieve the static value stored by setter()
  ....
}

Мой сценарий Javascript использует вызовы функций следующим образом:

init();
setter(...);
some_other_function_call_that_causes_gc();
getter();
setter(...);
some_other_function_call_that_causes_gc();
getter();
....
some_other_function_call_that_causes_gc();
setter(...);
some_other_function_call_that_causes_gc();
getter();

Обратите внимание, что я никогда не вызываю JS_RemoveRoot (), поскольку static jsval vp является постоянным хранилищем для моего jsval, передаваемого между 2 вызовами функций.И я продолжаю устанавливать новые значения в статическую переменную gc с корневым доступом vp в моем setter (), предполагая, что любой предыдущий JSObject, сохраненный в jsval, будет доступен для сборки мусора.

Это правильные способы создания временных переменных с корневым доступом gcчто можно передать через вызов функции?В частности, это способ, которым мой setter () заменяет предыдущий JSObject правильным способом сделать существующий JSObject доступным для gc (т.е. без утечки памяти / сбоя).

EDIT: причина, по которой я считаю сборку мусорапроблема заключается в том, что:

https://developer.mozilla.org/En/SpiderMonkey/JSAPI_User_Guide

В разделе JSAPI Concepts, Javascript Values:

jsval сам по себе не защищает своего референта от мусорасборщик

https://developer.mozilla.org/en/SpiderMonkey_Garbage_Collection_Tips

Пример 3 говорит " Root по мере движения " и показывает, как jsval должен быть назначен корню.

Ответы [ 2 ]

0 голосов
/ 03 марта 2014

Ссылаясь на SpiderMonkey 17 и выше

jsval или любая другая вещь GC должна быть защищена , если есть вероятность запуска GC, когда вещь GC используется. Это необходимо, даже если jsval относится к уже защищенному хранилищу. GC SpiderMonkey - это движущаяся GC .

Используйте RootedValue для защиты на основе стека jsval и Heap<JS::Value> для кучи на основе jsval
(jsval совпадает с JS::Value). Используйте Handle<JS::Value> и MutableHandle<JS::Value> для аргументов функций.

Вот выдержка из комментариев RootingAPI:

 * A moving GC may change the physical location of GC allocated things, even
 * when they are rooted, updating all pointers to the thing to refer to its new
 * location. The GC must therefore know about all live pointers to a thing,
 * not just one of them, in order to behave correctly.
 *
 * For a code fragment such as:
 *
 * JSObject *obj = NewObject(cx);
 * DoSomething(cx);
 * ... = obj->lastProperty();
 *
 * If |DoSomething()| can trigger a GC, the stack location of |obj| must be
 * rooted to ensure that the GC does not move the JSObject referred to by
 * |obj| without updating |obj|'s location itself. This rooting must happen
 * regardless of whether there are other roots which ensure that the object
 * itself will not be collected.
 *
 * If |DoSomething()| cannot trigger a GC, and the same holds for all other
 * calls made between |obj|'s definitions and its last uses, then no rooting
 * is required.
 *
 * SpiderMonkey can trigger a GC at almost any time and in ways that are not
 * always clear. For example, the following innocuous-looking actions can
 * cause a GC: allocation of any new GC thing; JSObject::hasProperty;
 * JS_ReportError and friends; and ToNumber, among many others. The following
 * dangerous-looking actions cannot trigger a GC: js_malloc, cx->malloc_,
 * rt->malloc_, and friends and JS_ReportOutOfMemory.
0 голосов
/ 31 марта 2012

Нет необходимости добавлять рут для чего-то вроде jsval. Вам просто нужно сохранить ссылку на значение в вашем скрипте. SpiderMonkey GC основан на количестве ссылок, поэтому ваши jsvals не исчезнут до тех пор, пока они упоминаются в текущей области:

var x = 5;

callNativeFun (х);

function foo () {throw true; }

печать (nativeFunRef ());

// скрипт заканчивается здесь. X и FOO будут собирать мусор, так как будут вызывать сигнатуры функций jsNativeFun и nativeFunRef.

В приведенном выше примере кода глобальный объект поддерживает и x, и foo.

Пока содержимое указателя jsval определено в сценарии, оно никогда не достигнет GC. Убедитесь, что ваш двоичный код никогда не использует значение после окончания его жизни; то есть, когда вы закончили с этим в скрипте и вызываете delete для него или устанавливаете его значение как неопределенное по значению или по доверенности завершения области действия. Если вы предвидите какое-либо из этих негативных взаимодействий, вам следует установить корень GC для этого jsval.

...