V8源码分析之d8源码注解(第五篇)

0x00 前言

没了你,我颓废了自己。心里那些苦,都只哽在喉咙里,一想起来就泪如雨下。 ----王国维

0x01 调用栈

Thread 1 "d8" received signal SIGINT, Interrupt.
0x00007ffff4a8ea44 in v8::base::LocalKeyToPthreadKey (local_key=32767) at ../../src/base/platform/platform-posix.cc:856
856	static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) {
(gdb) bt
#0  0x00007ffff4a8ea44 in v8::base::LocalKeyToPthreadKey (local_key=32767) at ../../src/base/platform/platform-posix.cc:856
#1  0x00007ffff4a8ea6a in v8::base::Thread::GetThreadLocal (key=3) at ../../src/base/platform/platform-posix.cc:952
#2  0x00007ffff6929720 in v8::internal::PerThreadAssertData::GetCurrent () at ../../src/common/assert-scope.cc:45
#3  0x00007ffff692ad2b in v8::internal::PerThreadAssertScope<(v8::internal::PerThreadAssertType)2, true>::IsAllowed () at ../../src/common/assert-scope.cc:91
#4  0x00007ffff6ac3a00 in v8::internal::HandleBase::IsDereferenceAllowed (this=0x7fffffffc360) at ../../src/handles/handles.cc:43
#5  0x000055555561a9c5 in v8::internal::HandleBase::location (this=0x7fffffffc360) at ../../src/handles/handles.h:59
#6  0x00007ffff689e560 in v8::internal::Handle<v8::internal::SeqOneByteString>::operator* (this=0x7fffffffc360) at ../../src/handles/handles.h:137
#7  0x00007ffff689e2b5 in v8::internal::Handle<v8::internal::SeqOneByteString>::operator-> (this=0x7fffffffc360) at ../../src/handles/handles.h:131
#8  0x00007ffff6aee3a3 in v8::internal::Factory::NewRawOneByteString (this=0x14e800000000, length=267, allocation=v8::internal::AllocationType::kYoung)
    at ../../src/heap/factory.cc:1085
#9  0x00007ffff6aee5cb in v8::internal::Factory::NewStringFromUtf8 (this=0x14e800000000, string=..., allocation=v8::internal::AllocationType::kYoung)
    at ../../src/heap/factory.cc:787
#10 0x00007ffff66d0f43 in v8::(anonymous namespace)::NewString (factory=0x14e800000000, type=v8::NewStringType::kNormal, string=...) at ../../src/api/api.cc:6248
#11 0x00007ffff66d0d97 in v8::String::NewFromUtf8 (isolate=0x14e800000000, 
    data=0x1426612c1000 "127.0.0.1\tlocalhost\n127.0.1.1\tubuntu\n127.0.0.1   chrome-infra-packages.appspot.com\n\n# The following lines are desirable for IPv6 capable hosts\n::1     ip6-localhost ip6-loopback\nfe00::0 ip6-localnet\nf"..., type=v8::NewStringType::kNormal, length=267) at ../../src/api/api.cc:6297
#12 0x00005555555f178e in v8::Shell::ReadFile (isolate=0x14e800000000, name=0x55555570aa30 "/etc/hosts") at ../../src/d8/d8.cc:2358
#13 0x00005555555f83e3 in v8::Shell::Read (args=...) at ../../src/d8/d8.cc:1412
#14 0x00007ffff6081f0f in Builtins_CallApiCallback () from /home/test/git/google/v8/out/x64.debug/libv8.so
#15 0x00007fffffffc768 in ?? ()
#16 0x00007fffffffc798 in ?? ()
#17 0x0000000000000001 in ?? ()
#18 0x0000000000000040 in ?? ()
#19 0x00007fffffffc7a0 in ?? ()
#20 0x00007fffffffc720 in ?? ()
#21 0x0000000000000006 in ?? ()
#22 0x00007fffffffc7f0 in ?? ()
#23 0x000014e800082c3e in ?? ()
#24 0x000014e8083c0119 in ?? ()
#25 0x000014e800000000 in ?? ()
#26 0x000014e808040305 in ?? ()
#27 0x000014e808040305 in ?? ()
#28 0x000014e808040305 in ?? ()
#29 0x000014e808040305 in ?? ()
#30 0x000014e80824fdbd in ?? ()
#31 0x000014e8083c0119 in ?? ()
#32 0x000014e808240ced in ?? ()
#33 0x000014e80824fec1 in ?? ()
#34 0x000014e80824fdbd in ?? ()
#35 0x000014e80824e125 in ?? ()
#36 0x000014e80836a2d9 in ?? ()
#37 0x0000000000000098 in ?? ()
#38 0x000014e80824fe59 in ?? ()
#39 0x000014e80824fec1 in ?? ()
#40 0x000014e808240ced in ?? ()
#41 0x00007fffffffc818 in ?? ()
#42 0x00007ffff60753da in Builtins_JSEntryTrampoline () from /home/test/git/google/v8/out/x64.debug/libv8.so
#43 0x000014e8083c0119 in ?? ()
#44 0x000014e80824fec1 in ?? ()
#45 0x0000000000000022 in ?? ()
#46 0x00007fffffffc880 in ?? ()
#47 0x00007ffff60751b8 in Builtins_JSEntry () from /home/test/git/google/v8/out/x64.debug/libv8.so

0x02 RunMain函数分析

路径

v8\src\d8\d8.cc

源码

int Shell::RunMain(Isolate* isolate, int argc, char* argv[], bool last_run) {
 //默认d8启动一个线程跑,options.num_isolates默认值为1
  for (int i = 1; i < options.num_isolates; ++i) {
    options.isolate_sources[i].StartExecuteInThread();
  }
  bool success = true;
  {
    SetWaitUntilDone(isolate, false);
    // 默认为null,不会走这个分支
    if (options.lcov_file) {
      debug::Coverage::SelectMode(isolate, debug::CoverageMode::kBlockCount);
    }
    //创建HandleScope类的实例对象scope
    //HandleScope类基于栈分配方式管理所有local句柄,相当于local句柄的作用域。
    //所有的本地句柄都由该作用域分配。
    //定义位于../../src/api/api.cc:1124
    HandleScope scope(isolate);
    //可以看见0x02小结的注解
    Local<Context> context = CreateEvaluationContext(isolate);
    //last_run 此时为true,use_interactive_shell()用于判断是否为交互shell
    bool use_existing_context = last_run && use_interactive_shell();
    //LZ运行的js文件,所以这里为false,跳过
    if (use_existing_context) {
      // Keep using the same context in the interactive shell.
      evaluation_context_.Reset(isolate, context);
    }
    {
      //创建Scope类型的作用域,用于管理context
      Context::Scope cscope(context);
      //创建InspectorClient,默认options.enable_inspector为false
      InspectorClient inspector_client(context, options.enable_inspector);
      //自定义了一个scope
      PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
      //开始运行第一个isolate孤岛,暂定这样翻译吧
      //LZ放了一个死循环,gdb的是否就会停在这里,等待中断
      if (!options.isolate_sources[0].Execute(isolate)) success = false;
      if (!CompleteMessageLoop(isolate)) success = false;
    }
    if (!use_existing_context) {
      DisposeModuleEmbedderData(context);
    }
    WriteLcovData(isolate, options.lcov_file);
  }
  //回收isolate
  CollectGarbage(isolate);
  //多线程的情况,需要启动或等待每个线程。不太懂last_run是啥意思
  // 可以看到索引从1开始,0代表第一个线程,已经执行过了,从1以后需要单独执行
  for (int i = 1; i < options.num_isolates; ++i) {
    if (last_run) {
      options.isolate_sources[i].JoinThread();
    } else {
      options.isolate_sources[i].WaitForThread();
    }
  }
  //等待所有worker结束
  WaitForRunningWorkers();
  // In order to finish successfully, success must be != expected_to_throw.
  return success == Shell::options.expected_to_throw ? 1 : 0;
}

0x03 CreateEvaluationContext函数分析

这个函数是d8.cc中用于创建一段内置js代码的自定义函数。这里创建shell中内置的arguments参数变量。

Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
  // This needs to be a critical section since this is not thread-safe
  base::MutexGuard lock_guard(context_mutex_.Pointer());
  // Initialize the global objects
  //创建全局模板
  Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
  //创建一个作用域handle
  EscapableHandleScope handle_scope(isolate);
  //创建一个context上下文
  Local<Context> context = Context::New(isolate, nullptr, global_template);
  DCHECK(!context.IsEmpty());
  if (i::FLAG_perf_prof_annotate_wasm || i::FLAG_vtune_prof_annotate_wasm) {
    isolate->SetWasmLoadSourceMapCallback(ReadFile);
  }
  //初始化嵌入器数据
  //在context中指定的索引index位置,预设EmbedderData,用于保存一些自定义数据
  InitializeModuleEmbedderData(context);
  //d8是否包含参数,就是d8 '--'后面跟随的参数列表
  if (options.include_arguments) {
  	//创建Scope作用域,用于管理context对象
    Context::Scope scope(context);
    //保存arguments的值
    const std::vector<const char*>& args = options.arguments;
    //arguments的个数
    int size = static_cast<int>(args.size());
    //在isolate中创建一个lLocal数组变量
    Local<Array> array = Array::New(isolate, size);
    //遍历arguments的值
    for (int i = 0; i < size; i++) {
      //创建一个string类型的Local变量,urf8编码,arguments的值用于初始化
      Local<String> arg =
          v8::String::NewFromUtf8(isolate, args[i], v8::NewStringType::kNormal)
              .ToLocalChecked();
      // 创建Number类型的Local变量,保存arguments的索引
      Local<Number> index = v8::Number::New(isolate, i);
      //给js语言中数据赋上js语言的index和字符串的值。
      array->Set(context, index, arg).FromJust();
    }
    //这个js数组变量还没有名字,此时创建一个Local<String> name,初始值为"arguments",即为我们
    //在d8中使用的arguments数组变量
    Local<String> name =
        String::NewFromUtf8(isolate, "arguments", NewStringType::kInternalized)
            .ToLocalChecked();
    //在context上下文中加入名为name的array数据
    context->Global()->Set(context, name, array).FromJust();
  }
  //返回带有此上下文的作用域handle_scope句柄
  //【q1】擦,为什么escape后就变成一个context了,为什么不直接返回一个context?
  return handle_scope.Escape(context);
}

0x04 参考文献

https://v8docs.nodesource.com/node-0.8/df/d69/classv8_1_1_context.html
https://zhuanlan.zhihu.com/p/35371048
https://www.yuque.com/killa/node/v8-api

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值