作用域和线程局部变量如何在 (V8) C++中工作?

How do scopes and thread locals work in (V8's) C++?

本文关键字:V8 C++ 工作 线程 局部变量 作用域      更新时间:2023-10-16

我对V8的作用域是如何工作的很感兴趣。

堆栈上的作用域对象如何在堆栈上找到其他作用域对象和上下文?

深入研究HandleScopes的工作方式,我发现它们依赖于线程本地程序。这让我想知道这些在C++中是如何工作的,我已经找到了实现,但仍然不知道发生了什么。

api.cc--HandleScope查找当前隔离

HandleScope::HandleScope() {
  i::Isolate* isolate = i::Isolate::Current();
  API_ENTRY_CHECK(isolate, "HandleScope::HandleScope");
  v8::ImplementationUtilities::HandleScopeData* current =
      isolate->handle_scope_data();
  isolate_ = isolate;
  prev_next_ = current->next;
  prev_limit_ = current->limit;
  is_closed_ = false;
  current->level++;
}

isolate.cc--静态方法将当前隔离作为线程本地

  // Returns the isolate inside which the current thread is running.
  INLINE(static Isolate* Current()) {
    const Thread::LocalStorageKey key = isolate_key();
    Isolate* isolate = reinterpret_cast<Isolate*>(
        Thread::GetExistingThreadLocal(key));
    if (!isolate) {
      EnsureDefaultIsolate();
      isolate = reinterpret_cast<Isolate*>(
          Thread::GetExistingThreadLocal(key));
    }
    ASSERT(isolate != NULL);
    return isolate;
  }

platform.h--调用一个低级别方法来检索线程本地

  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
    void* result = reinterpret_cast<void*>(
        InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
    ASSERT(result == GetThreadLocal(key));
    return result;
  }

平台-tls-win32.h——神奇的发生了

inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
  const intptr_t kTibInlineTlsOffset = 0xE10;
  const intptr_t kTibExtraTlsOffset = 0xF94;
  const intptr_t kMaxInlineSlots = 64;
  const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
  ASSERT(0 <= index && index < kMaxSlots);
  if (index < kMaxInlineSlots) {
    return static_cast<intptr_t>(__readfsdword(kTibInlineTlsOffset +
                                               kPointerSize * index));
  }
  intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
  ASSERT(extra != 0);
  return *reinterpret_cast<intptr_t*>(extra +
                                      kPointerSize * (index - kMaxInlineSlots));
}
  • 最后一种方法究竟是如何工作的
  • 它怎么知道往哪里看
  • 堆栈的结构是什么

您可以将InternalGetExistingThreadLocal视为TlsGetValue WinAPI调用的内联版本。

在Windows用户模式下,fs段寄存器允许代码访问线程信息块(TIB),其中包含线程特定信息,例如线程本地存储结构。

TIB的布局以及TLS存储在TIB内部的方式在DDK中公开(请参阅http://en.wikipedia.org/wiki/Win32_Thread_Information_Block用于TIB布局的快速概览)。

给定通过__readfsdword(offs)从TIB读取数据的这种知识和能力(相当于读取dword ptr fs:[offs]),可以在不调用TlsGetValue的情况下直接有效地访问TLS。