V8内存管理参数的返回值

时间:2015-07-10 09:29:14

标签: c++ garbage-collection v8

我对V8如何管理其内存感到困惑。

问题:

据我所知,V8基本上使用Handle来引用内存中的实例,而使用HandleScope,可以自动轻松地管理所有本地句柄。但我无法理解为什么FunctionCallbackInfo不使用Handle来保持返回值:

void MyMethod(const FunctionCallbackInfo<Value>& args) 
{
    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope(isolate);

    cout<<"totally "<<args.Length()<<" arguments"<<endl;

    int result = AddOpeation(args[0]->Int32Value(), args[1]->Int32Value());
    char *s = new char [10];
    ZeroMemory(s, 10);
    _itoa_s(result, s, 9, 10);
    args.GetReturnValue().Set(String::NewFromUtf8(isolate, s)); // I'm confused by this line of code !!!
    delete [] s;
}

以下是 FunctionCallbackInfo :: GetReturnValue

的实现
template<typename T>
ReturnValue<T> FunctionCallbackInfo<T>::GetReturnValue() const {
    return ReturnValue<T>(&implicit_args_[kReturnValueIndex]);
}

这是 ReturnValue :: Set

的实现
template<typename T>
template<typename S>
void ReturnValue<T>::Set(const Handle<S> handle) {
   TYPE_CHECK(T, S);
   if (V8_UNLIKELY(handle.IsEmpty())) {
      *value_ = GetDefaultValue();
   } else {
   *value_ = *reinterpret_cast<internal::Object**>(*handle);
}

以下是 ReturnValue :: value _

的定义
  ...
  V8_INLINE void SetInternal(internal::Object* value) { *value_ = value; }
  V8_INLINE internal::Object* GetDefaultValue();
  V8_INLINE explicit ReturnValue(internal::Object** slot);
  internal::Object** value_;

问题:

回到我的代码 - 函数MyMethod,因为 ReturnValue :: value _ 不是句柄,一旦HandleScope被销毁就可以安全地访问ReturnValue :: value_吗?

我猜:

如果我创建了两个类的实例:

HandleScope s0(...);
LocalHandle<FunctionCallbackInfo> h0 = ...;    
...
{
    HandleScope s1(...);
    LocalHandle<MyType> h1 = ...;
    h0.ptr = *h1; // Suppose ptr is a member field defined in FunctionCallbackInfo
}

S1将在S0之前被销毁,此时,因为s0仍然存在,h0也是如此,并且* h1是h0的成员字段,因此V8 GC不会清理* h1或h0.ptr引用的内存。

我的猜测合理吗?

1 个答案:

答案 0 :(得分:0)

v8::HandleScope将销毁作用域出口上的所有本地句柄。我想没有办法通知句柄范围哪个句柄是结果而不应该被销毁。但v8::EscapableHandleScope允许这样做:

void MyMethod(const FunctionCallbackInfo<Value>& args) 
{
    Isolate* isolate = Isolate::GetCurrent();
    EscapableHandleScope scope(isolate);

    int result = AddOpeation(args[0]->Int32Value(), args[1]->Int32Value());
    char s[10];
    _itoa_s(result, s, 9, 10);
    Local<String> result = String::NewFromUtf8(isolate, s);
    args.GetReturnValue().Set(scope.Escape(result));
}

请参阅V8指南中Handles and Garbage Collection部分的底部。