node解释执行js的过程分析

说明:node是单线程,非阻塞,事件驱动(类似内核中udev事件,可以参考监听-回调机制)
1. 入口
    node-v8.10.0/src/node_main.cc --> 90 int main(int argc, char *argv[])
    调用node::Start(argc, argv);
    node-v8.10.0/src/node.cc --> 4863 int Start(int argc, char** argv)
      a:  4864   atexit([] () { uv_tty_reset_mode(); });
          # 在执行完*.js后 执行匿名函数,实际上就是执行uv_tty_reset_mode()
      b:  4865   PlatformInit();
          # 执行内联函数PlatformInit(), 信号量处理函数注册
      c:  4866   node::performance::performance_node_start = PERFORMANCE_NOW();
          封装uv_hrtime函数:src/node_perf_common.h:13:#define PERFORMANCE_NOW() uv_hrtime()
          导出定义:deps/uv/include/uv.h:1457:UV_EXTERN uint64_t uv_hrtime(void);
          实现:deps/uv/src/unix/core.c:111:uint64_t uv_hrtime(void)
          uv_hrtime调用uv__hrtime
          定义:deps/uv/src/unix/internal.h:252:uint64_t uv__hrtime(uv_clocktype_t type);
          实现:deps/uv/src/unix/linux-core.c:442:uint64_t uv__hrtime(uv_clocktype_t type) {
          总之: 记录node执行*.js脚本的开始运行时间点,类似的,记录v8的开始运行时间点:
            4903   node::performance::performance_v8_start = PERFORMANCE_NOW();
      d:  4868   CHECK_GT(argc, 0);
          src/util.h:129:#define CHECK_GT(a, b) CHECK((a) > (b))
      e:  4871   argv = uv_setup_args(argc, argv);
          定义:deps/uv/include/uv.h:1051:UV_EXTERN char** uv_setup_args(int argc, char** argv);
          实现:
      f:  4877   Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
          4542 void Init(int* argc,
          4543           const char** argv,
          4544           int* exec_argc,
          4545           const char*** exec_argv) {
          4617   ProcessArgv(argc, argv, exec_argc, exec_argv);
          4502   ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv, is_env);
            4015 static void ParseArgs(int* argc,
            解析参数
      g:  openssl相关配置
      h:  4895   v8_platform.Initialize(v8_thread_pool_size, uv_default_loop());
      i:  4902   V8::Initialize();
          v8初始化
      j:  4905   const int exit_code =
          4906       Start(uv_default_loop(), argc, argv, exec_argc, exec_argv);
      k:  退出
          4908     v8_platform.StopTracingAgent();
          4910   v8_initialized = false;
          4911   V8::Dispose();
          4919   v8_platform.Dispose();
          4921   delete[] exec_argv;
          4922   exec_argv = nullptr;
          4924   return exit_code;
2. 分析1中的j部分
      a:  4814 inline int Start(uv_loop_t* event_loop,
          4815                  int argc, const char* const* argv,
          4816                  int exec_argc, const char* const* exec_argv) {
      b:  4824   Isolate* const isolate = Isolate::New(params);
          4828   isolate->AddMessageListener(OnMessage);
          4829   isolate->SetAbortOnUncaughtExceptionCallback(ShouldAbortOnUncaughtException);
          4830   isolate->SetAutorunMicrotasks(false);
          4831   isolate->SetFatalErrorHandler(OnFatalError);
            new Isolate对象,并设置相关参数。
      c:  4843   int exit_code;
          4844   {
          4845     Locker locker(isolate);
          4846     Isolate::Scope isolate_scope(isolate);
          4847     HandleScope handle_scope(isolate);
          4848     IsolateData isolate_data(isolate, event_loop, allocator.zero_fill_field());
          4849     exit_code = Start(isolate, &isolate_data, argc, argv, exec_argc, exec_argv);
          4850   }
            准备开始执行的参数,isolate对象。
      d:  4745 inline int Start(Isolate* isolate, IsolateData* isolate_data,
          4746                  int argc, const char* const* argv,
          4747                  int exec_argc, const char* const* exec_argv) {
      e:  环境准备,加载*.js文件内容
            4748   HandleScope handle_scope(isolate);
            4749   Local<Context> context = Context::New(isolate);
            4750   Context::Scope context_scope(context);
            4751   Environment env(isolate_data, context);
            4754   env.Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
            执行代码 src/env.cc:18:void Environment::Start(int argc,
            4771     LoadEnvironment(&env);//加载env
            3741   Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(),
            3742                                                     "bootstrap_node.js");// 加载bootstrap_node.js,而不是我们的*.js
      f:  ./lib/internal/bootstrap_node.js
            匿名函数的第一个步骤是给startup()函数挂载一堆函数,startup的相关函数都挂载完之后,匿名函数执行最后一步,调用startup(),执行这一堆挂载函数,匿名函数的参数process是C++模块传进来的对象(也就是f->Call()传进来的参数)
            609   startup();
      g:  3743   Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
          1931 // Executes a str within the current v8 context.
          1932 static Local<Value> ExecuteString(Environment* env,
          在LoadEnvironment()里面调用ExecuteString() 解析执行bootstrap_node.js文件,返回值是一个f_value。而这个f_value通过V8的接口 Local<Function>::Cast转换成一个Local<Function>类型的变量f ,而Local<Function>类型是V8中表示一个js 函数的C++类型。在LoadEnvironment()的最后一行通过 f->Call(),去执行bootstrap_node.js返回来的一个函数。而从bootstrap_node.js文件中也可以看出确实返回的是一个匿名函数。所以,*.js并不在ExecuteString()里面执行,而是在f->Call()的时候被执行。
          3791   auto ret = f->Call(env->context(), Null(env->isolate()), 1, &arg);
      h:  为何*.js代码里面有exports、require、module这几个变量可以用了
        580   NativeModule.wrapper = [
        581     '(function (exports, require, module, __filename, __dirname) { ',
        582     '\n});'
        583   ];
        Module.runMain()包装*.js文件,看到startup()函数在执行runMain()之前,对process.argv[1]里做了一下处理,这个argv就是node命令行启动的时候,main函数接收的参数。比如“node app.js”启动,argv[1]就保存着我们的js文件名了。那么runMain()通过process.argv[1]去读取app.js文件,读成字符串,调用NativeModule.wrap()函数,把我们的app.js代码封装在里面。这里就可以说明app.js代码里面为何生来就有require、exports、module这几个变量可以用了。其实是被放到一个js函数里面了。最后runMain()里面也是调用V8的Compile()、Run()等接口,去执行app.js代码。
      i:  在d中的函数里面进行eventloop,没有event的时候,就会退出node

3.  分析核心部分
        4777   {
        4778     SealHandleScope seal(isolate);
        4779     bool more;
        4780     PERFORMANCE_MARK(&env, LOOP_START);
        4781     do {
        4782       uv_run(env.event_loop(), UV_RUN_DEFAULT);
        4783
        4784       v8_platform.DrainVMTasks();
        4785
        4786       more = uv_loop_alive(env.event_loop());
        4787       if (more)
        4788         continue;
        4789
        4790       EmitBeforeExit(&env);
        4791
        4792       // Emit `beforeExit` if the loop became alive either after emitting
        4793       // event, or after running some callbacks.
        4794       more = uv_loop_alive(env.event_loop()); // 再次去判断是否有event没有处理,可能一些异步操作会有回调函数。
        4795     } while (more == true);
        4796     PERFORMANCE_MARK(&env, LOOP_EXIT); // 没有事件处理,就退出。
        4797   }
      a:  处理event的核心函数uv_run
        声明:deps/uv/include/uv.h:281:UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);
        实现:deps/uv/src/unix/core.c:348:int uv_run(uv_loop_t* loop, uv_run_mode mode) { // 循环体
      b:  判断loop是否时alive状态:是否有handle、request-signal且handle没有关闭。
         343 int uv_loop_alive(const uv_loop_t* loop) {
         344     return uv__loop_alive(loop);
         345 }
         336 static int uv__loop_alive(const uv_loop_t* loop) {
         337   return uv__has_active_handles(loop) ||
         338          uv__has_active_reqs(loop) ||
         339          loop->closing_handles != NULL;
         340 }
      c:  uv__has_active_handles(loop):
          deps/uv/src/uv-common.h:145:#define uv__has_active_handles(loop)                                          \
          145 #define uv__has_active_handles(loop)                                          \
          146   ((loop)->active_handles > 0)
      d:  uv__has_active_reqs(loop):
          129 #define uv__has_active_reqs(loop)                                             \
          130   (QUEUE_EMPTY(&(loop)->active_reqs) == 0)






















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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值