nodejs c++启动过程1

原创 2013年12月02日 20:12:58

在main文件中调用以下代码

// 创建一个句柄作用域 ( 在栈上 ) 
HandleScope handle_scope; 

// 创建一个新的上下文对象
Persistent<Context> context = Context::New(); 

// 进入上一步创建的上下文,用于编译执行 helloworld 
Context::Scope context_scope(context); 


Isolate

在main文件之前,会首先实例化一个引擎,在isolate文件中中:

struct StaticInitializer {
  StaticInitializer() {
    Isolate::EnsureDefaultIsolate();
  }
} static_initializer;


默认初始化了一个引擎实例,进入函数EnsureDefaultIsolate



void Isolate::EnsureDefaultIsolate() {

// 初始化一个锁,Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();在文件中已经被初始化过了

// lock是一个scopedLock,在执行完成EnsureDefaultIsolate的时候,析构lock会离开临界区
  ScopedLock lock(process_wide_mutex_);

// 默认没有引擎实例
  if (default_isolate_ == NULL) {

// 创建局部存储,存储各个线程的引擎实例地址
    isolate_key_ = Thread::CreateThreadLocalKey();

// 创建存储threadid
    thread_id_key_ = Thread::CreateThreadLocalKey();

// 创建储存开辟的数据块位置
    per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey();

// 存储数据块表
    thread_data_table_ = new Isolate::ThreadDataTable();

// 定义默认的引擎
    default_isolate_ = new Isolate();
  }
  // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
  // because a non-null thread data may be already set.
  if (Thread::GetThreadLocal(isolate_key_) == NULL) {

// 存储当前引擎
    Thread::SetThreadLocal(isolate_key_, default_isolate_);
  }
}


然后再main文件中:

第一步:HandleScope初始化

// 获取当前线程的引擎实例

 i::Isolate* isolate = i::Isolate::Current();
  API_ENTRY_CHECK(isolate, "HandleScope::HandleScope");


// Introduce an alias for the handle scope data to allow non-friends
  // to access the HandleScope data.
  v8::ImplementationUtilities::HandleScopeData* current =
      isolate->handle_scope_data();
  isolate_ = isolate;
  prev_next_ = current->next;
  prev_limit_ = current->limit;
  is_closed_ = false;
  current->level++;


第二部:Context::New();


Persistent<Context> v8::Context::New(
    v8::ExtensionConfiguration* extensions,
    v8::Handle<ObjectTemplate> global_template,
    v8::Handle<Value> global_object) {
  i::Isolate::EnsureDefaultIsolate();
  i::Isolate* isolate = i::Isolate::Current();
// 会调用初始化快照函数i::Snapshot::Initialize(),迅速初始化引擎,具体见2-1
  EnsureInitializedForIsolate(isolate, "v8::Context::New()");
  LOG_API(isolate, "Context::New");
  ON_BAILOUT(isolate, "v8::Context::New()", return Persistent<Context>());

// context的初始化见博客3
  // Enter V8 via an ENTER_V8 scope.
  i::Handle<i::Context> env;
  {
    ENTER_V8(isolate);
    v8::Handle<ObjectTemplate> proxy_template = global_template;
    i::Handle<i::FunctionTemplateInfo> proxy_constructor;
    i::Handle<i::FunctionTemplateInfo> global_constructor;


    if (!global_template.IsEmpty()) {
      // Make sure that the global_template has a constructor.
      global_constructor =
          EnsureConstructor(Utils::OpenHandle(*global_template));


      // Create a fresh template for the global proxy object.
      proxy_template = ObjectTemplate::New();
      proxy_constructor =
          EnsureConstructor(Utils::OpenHandle(*proxy_template));


      // Set the global template to be the prototype template of
      // global proxy template.
      proxy_constructor->set_prototype_template(
          *Utils::OpenHandle(*global_template));


      // Migrate security handlers from global_template to
      // proxy_template.  Temporarily removing access check
      // information from the global template.
      if (!global_constructor->access_check_info()->IsUndefined()) {
        proxy_constructor->set_access_check_info(
            global_constructor->access_check_info());
        proxy_constructor->set_needs_access_check(
            global_constructor->needs_access_check());
        global_constructor->set_needs_access_check(false);
        global_constructor->set_access_check_info(
            isolate->heap()->undefined_value());
      }
    }


    // Create the environment.
    env = isolate->bootstrapper()->CreateEnvironment(
        isolate,
        Utils::OpenHandle(*global_object, true),
        proxy_template,
        extensions);


    // Restore the access check info on the global template.
    if (!global_template.IsEmpty()) {
      ASSERT(!global_constructor.is_null());
      ASSERT(!proxy_constructor.is_null());
      global_constructor->set_access_check_info(
          proxy_constructor->access_check_info());
      global_constructor->set_needs_access_check(
          proxy_constructor->needs_access_check());
    }
    isolate->runtime_profiler()->Reset();
  }
  // Leave V8.


  if (env.is_null()) {
    return Persistent<Context>();
  }
  return Persistent<Context>(Utils::ToLocal(env));
}


2-1 i::Snapshot::Initialize()

若依赖的项目是v8_snapshot则引擎会从快照中直接初始化,执行以下逻辑
// 快照数据二进制格式
SnapshotByteSource source(raw_data_, raw_size_);
//反序列号读取数据
    Deserializer deserializer(&source);
// 设置数据
    ReserveSpaceForLinkedInSnapshot(&deserializer);
// V8::Initialize(&deserializer); 见2-1-1
    return V8::Initialize(&deserializer);


2-1-1V8::Initialize(&deserializer);

bool V8::Initialize(Deserializer* des) {
  FlagList::EnforceFlagImplications();

//初始化,会调用InitializeOncePerProcess();初始化一次一次的函数,见2-2
  InitializeOncePerProcess();


  // The current thread may not yet had entered an isolate to run.
  // Note the Isolate::Current() may be non-null because for various
  // initialization purposes an initializing thread may be assigned an isolate
  // but not actually enter it.
  if (i::Isolate::CurrentPerIsolateThreadData() == NULL) {
// 会调用引擎的Enter函数见2-1-1-1
    i::Isolate::EnterDefaultIsolate();
  }


  ASSERT(i::Isolate::CurrentPerIsolateThreadData() != NULL);
  ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id().Equals(
           i::ThreadId::Current()));
  ASSERT(i::Isolate::CurrentPerIsolateThreadData()->isolate() ==
         i::Isolate::Current());


  if (IsDead()) return false;


  Isolate* isolate = Isolate::Current();
  if (isolate->IsInitialized()) return true;


  is_running_ = true;
  has_been_set_up_ = true;
  has_fatal_error_ = false;
  has_been_disposed_ = false;

// 引擎又一个初始化,见下一篇博客
  return isolate->Init(des);
}

2-1-1-1 Isolate::Enter() 

void Isolate::Enter() {
  Isolate* current_isolate = NULL;
// 首次进入的时候,data不存在
  PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
  if (current_data != NULL) {
    current_isolate = current_data->isolate_;
    ASSERT(current_isolate != NULL);
    if (current_isolate == this) {
      ASSERT(Current() == this);
      ASSERT(entry_stack_ != NULL);
      ASSERT(entry_stack_->previous_thread_data == NULL ||
             entry_stack_->previous_thread_data->thread_id().Equals(
                 ThreadId::Current()));
      // Same thread re-enters the isolate, no need to re-init anything.
// 多次进入,只需要count加1
      entry_stack_->entry_count++;
      return;
    }
  }


  // Threads can have default isolate set into TLS as Current but not yet have
  // PerIsolateThreadData for it, as it requires more advanced phase of the
  // initialization. For example, a thread might be the one that system used for
  // static initializers - in this case the default isolate is set in TLS but
  // the thread did not yet Enter the isolate. If PerisolateThreadData is not
  // there, use the isolate set in TLS.
  if (current_isolate == NULL) {
    current_isolate = Isolate::UncheckedCurrent();
  }

// 创建一段PerIsolateThreadData
  PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
  ASSERT(data != NULL);
  ASSERT(data->isolate_ == this);

// 进入引擎线程
  EntryStackItem* item = new EntryStackItem(current_data,
                                            current_isolate,
                                            entry_stack_);
  entry_stack_ = item;

// 设置PerIsolateThreadData到TLS中
  SetIsolateThreadLocals(this, data);


  // In case it's the first time some thread enters the isolate.
// 设置当前引擎的线程id
  set_thread_id(data->thread_id());
}

2-2 InitializeOncePerProcess();


void V8::InitializeOncePerProcess() {
// 调用InitializeOncePerProcessImpl 见2-3
  CallOnce(&init_once, &InitializeOncePerProcessImpl);
}

2-3 InitializeOncePerProcessImpl

void V8::InitializeOncePerProcessImpl() {

// 有v8类调到os类的初始化,初始化随机数种子,sampler等等

  OS::SetUp();


  use_crankshaft_ = FLAG_crankshaft;


  if (Serializer::enabled()) {
    use_crankshaft_ = false;
  }


// 会调用void CpuFeatures::Probe() ,里面有个VirtualMemory类,是自己分配的内存2-4

//这里会创建类Assembler,对js的二进制执行码进行优化

  CPU::SetUp();
  if (!CPU::SupportsCrankshaft()) {
    use_crankshaft_ = false;
  }

// 在cpu二进制执行码初始化后,调用这个后续初始化

// 一些数学函数的优化,需要二进制码优化

  OS::PostSetUp();

// TODO:下面的还没读
  RuntimeProfiler::GlobalSetUp();


  ElementsAccessor::InitializeOncePerProcess();


  if (FLAG_stress_compaction) {
    FLAG_force_marking_deque_overflows = true;
    FLAG_gc_global = true;
    FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
  }


  LOperand::SetUpCaches();
  SetUpJSCallerSavedCodeData();
  SamplerRegistry::SetUp();
  ExternalReference::SetUp();
}



2-4 VirtualMemory

创建类的时候初始化一个内存地址ReserveRegion(size),调用RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS);,设置这段地址内存为保留和不允许访问

然后再调用提交内存,CommitRegion(void* base, size_t size, bool is_executable) ,即调用VirtualAlloc(base, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE),使得申请的内存是是可执行可读写的,然后调用UpdateAllocatedSpaceLimits,告诉可以使用的内存范围







相关文章推荐

nodejs 启动过程2

水电费是否 2-5 Isolate::Init bool Isolate::Init(Deserializer* des) {   ASSERT(state_ != INITIALIZED);  ...

c++编译过程(1) vc命令行编

  • 2012年03月15日 08:17
  • 46.79MB
  • 下载

编译原理(六) LL(1)文法分析法(分析过程的C++实现)

前情了解快速通道算法分析预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a行事的。如下图所示,对于任何(X,a),总控程序每次都执行下述三种可能的动作之一: 若X = a =...

C++愤恨者札记1——类对象作为函数参数的数据传递过程

C++愤恨者札记1——类对象作为函数参数的数据传递过程     C++繁杂的机制,加上枯燥的教科书,再加上无法回避地要使用它,注定要造就一批C++愤恨者。本文作为C++愤恨者札记系列第一篇,从汇...
  • tms_li
  • tms_li
  • 2012年07月20日 08:07
  • 8542

BBS客户端学习过程【1】(总体规划+部分实现)PS:送上《Visual C++网络编程开发与实践》光盘资料

前天晚上,在微信上随意的一个回复引起了女朋友的不满。现在已经冷战(确切的说是他晾我)2天了。我很爱我的女朋友,但是现在我不知道怎么做.......希望她能明白我。好了,不煽情了,接着上部分分享我的BB...

c++模板类(1) 理解编译器的编译模板过程

如何组织编写模板程序 前言 常遇到询问使用模板到底是否容易的问题,我的回答是:“模板的使用是容易的,但组织编写却不容易”。看看我们几乎每天都能遇到的模板类吧,如STL, ATL, WTL,...

深入探索c/c++函数(1)---全局函数调用的基本过程

在c/c++等许多程序设计语言中,可以将一段经常需要使用的代码封装起来,在需要使用时可以直接调用,这就是程序中的函数,函数内封装了对数据和逻辑的处理。通过函数调用来执行函数体,下面根据代码进行分析。 ...

c++ primer -- 基于过程的程序设计(1)

1.所有的函数都使用在程序运行栈(run-time stack)中分配的存储区。该存储区一直保持与该函数相关联,直到函数结束为止。那时,存储区将自动释放以便重新使用。该函数的整个存储区被称为活动记录(...

c++服务器 拆包粘包 过程(1)

做了这么长时间的服务器,
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:nodejs c++启动过程1
举报原因:
原因补充:

(最多只允许输入30个字)