关闭

nodejs c++启动过程1

标签: nodejs
729人阅读 评论(0) 收藏 举报
分类:

在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,告诉可以使用的内存范围







0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:53206次
    • 积分:1103
    • 等级:
    • 排名:千里之外
    • 原创:59篇
    • 转载:10篇
    • 译文:0篇
    • 评论:1条
    文章分类
    最新评论