版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lusing/article/details/53035185
V8世界探险 (1) - v8 API概览
v8是Google开发的JavaScript引擎,自推出后就对js生态产生了巨大的影响。比如产生了运行在服务端的Node.js的巨大生态。
这么好玩的东西,我们当然要冲起去看看它的内部是如何实现的了。
Hello,v8 World!
首先好玩的一点是,v8可以作为一个库来嵌入到其它的应用中。
我们废话不多说,直接上代码.这是Google官方的调用在代码中嵌入一个v8引擎的例子,地址在:https://chromium.googlesource.com/v8/v8/+/branch-heads/4.8/samples/hello-world.cc
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "include/libplatform/libplatform.h"
#include "include/v8.h"
using namespace v8;
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
 public:
  virtual void* Allocate(size_t length) {
    void* data = AllocateUninitialized(length);
    return data == NULL ? data : memset(data, 0, length);
  }
  virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
  virtual void Free(void* data, size_t) { free(data); }
};
int main(int argc, char* argv[]) {
  // Initialize V8.
  V8::InitializeICU();
  V8::InitializeExternalStartupData(argv[0]);
  Platform* platform = platform::CreateDefaultPlatform();
  V8::InitializePlatform(platform);
  V8::Initialize();
  // Create a new Isolate and make it the current one.
  ArrayBufferAllocator allocator;
  Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = &allocator;
  Isolate* isolate = Isolate::New(create_params);
  {
    Isolate::Scope isolate_scope(isolate);
    // Create a stack-allocated handle scope.
    HandleScope handle_scope(isolate);
    // Create a new context.
    Local<Context> context = Context::New(isolate);
    // Enter the context for compiling and running the hello world script.
    Context::Scope context_scope(context);
    // Create a string containing the JavaScript source code.
    Local<String> source =
        String::NewFromUtf8(isolate, "'Hello' + ', World!'",
                            NewStringType::kNormal).ToLocalChecked();
    // Compile the source code.
    Local<Script> script = Script::Compile(context, source).ToLocalChecked();
    // Run the script to get the result.
    Local<Value> result = script->Run(context).ToLocalChecked();
    // Convert the result to an UTF8 string and print it.
    String::Utf8Value utf8(result);
    printf("%s\n", *utf8);
  }
  // Dispose the isolate and tear down V8.
  isolate->Dispose();
  V8::Dispose();
  V8::ShutdownPlatform();
  delete platform;
  return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
我们从中可以看到几个重要的类: 
* V8:这个是个大杂烩的工具类,从初始化到关闭平台都离不开它。 
* ArrayBuffer是v8的数据类型,下面我们会来一张v8的数据结构图。 
* Isolate是v8中最重要的功能类,代表了一个v8引擎的实例。它不是线程安全的,如果在线程不安全情况下运行需要加锁。 
* Local是v8中存储对象的结构,代表了被GC管理的对象引用。与其对应的就是持久性对象,如Global和Persistent。 
* Context代表了在沙箱中运行的上下文。与Java一样,JavaScript也运行在一个沙箱安全环境中。 
* Script代表了运行在v8中的脚本。
上面使用的都是v8的公开API。这些API代表了v8的主要功能和主要数据结构。 
我们先看一张v8的API的大图:
对象与句柄
与C/C++与Rust等存在栈式管理的语言不同,JavaScript并没有栈上分配这样的概念。但是在v8的实现中,是有通过栈式管理作用域的数据结构,就是例程中我们所看到的HandleScope。 
另外还有SealHandleScope类,将当前的HandleScope封装起来,强制需要创建新的HandleScope.
v8中的对象按生命周期可以分为两类,由GC管理的局部对象Local,还有持久性的对象。 
持久性的对象分为:一次性的永续对象Eternal,和全局性的PersistentBase。 
PersistentBase根据管理所有权方式的不同,采用赋值和复制方式的叫做Persistent,采用移动语义的叫做Global. 
还有个UniquePersistent的模块类,其实是Global的别名。C++11中定义模板别名的方式,之前我们有文章讲过了:
template <class T> using UniquePersistent = Global<T>;
1
从例子中我们可以看到,通常我们使用的变量都是Local为主。不管是Context,String,Script还是Value都是通过Local模板来进行管理的:
    // Create a new context.
    Local<Context> context = Context::New(isolate);
    Local<String> source =
        String::NewFromUtf8(isolate, "'Hello' + ', World!'",
                            NewStringType::kNormal).ToLocalChecked();
    // Compile the source code.
    Local<Script> script = Script::Compile(context, source).ToLocalChecked();
    // Run the script to get the result.
    Local<Value> result = script->Run(context).ToLocalChecked();
1
2
3
4
5
6
7
8
9
现在并没有一个共同的Handle基类,Local,Eternal和PersistentBase之间没有共基类的关系。
由于返回值也大部分是Local,为了强制代码判空,v8经常使用MaybeLocal的模块,它是Local的一个封装。
我们再画一个图来回顾下它们之间的关系:
脚本相关的API
脚本相关的API主要涉及到三个部分:源代码,编译后的脚本代码和编译器三部分。 
源代码表示的类是ScriptOrigin和ScriptOriginOptions. 
编译之后的脚本,按照是否跟上下文绑定,分为UnboundScript和Script两种。 
编译器是ScriptCompiler.
另外,脚本的运行时信息也是很重要的结构,v8提供了包装错误信息的Message类,提供跟踪栈信息的StackTrace和StackFrame。
v8的数据类型
我们先看个数据类型的图,如果对于ES6不太熟悉的同学,可能对于某些ES6新增的类型会有些疑惑。不过不用担心,后面如果有会用到ES6的知识的话,我会尽可能做一些快餐式的简介。
所有的v8数据类型都继承自Data类。 
这个类非常简单:
/**
 * The superclass of values and API object templates.
 */
class V8_EXPORT Data {
  private:
  Data();
};
1
2
3
4
5
6
7
首先继承自Data的是一个跟js无关的NativeWeakMap: 
同时让大家继续体验下几乎一切皆Local的感受,基本上每个类型都要加上Local<>模板管理一下:
/**
 * A map whose keys are referenced weakly. It is similar to JavaScript WeakMap
 * but can be created without entering a v8::Context and hence shouldn't
 * escape to JavaScript.
 */
class V8_EXPORT NativeWeakMap : public Data {
 public:
  static Local<NativeWeakMap> New(Isolate* isolate);
  void Set(Local<Value> key, Local<Value> value);
  Local<Value> Get(Local<Value> key);
  bool Has(Local<Value> key);
  bool Delete(Local<Value> key);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
Value类是所有的JavaScript类型的基类,它有两个巨大的子类,一个是代表原始类型的Primitive,一个就是所有js对象之根Object类。当然,还有个实现上用途的包装C++ void*指针的External类。
ES6新增了Symbol类型,它和String共同派生自Name类型。 
虽然JavaScript的数都是浮点数,但是在v8的实现里,整数仍然是大行其道的。
对象类型中,Promise, Proxy, ArrayBufferView这些都是ES6新增的。有些还需要–harmony选项的支持。 
剩下是对于原始类型的包装,如NumberObject, BooleanObject, StringObject, SymbolObject。 
还有的就是Date日期类和RegExp正则表达式类两个内置类的支持,也在API中。
最后,直接继承自Data的,还有4个类: 
* Private:私有的符号 
* Template:模板,分为函数模板和对象模板。这两个在后面我们分析v8的实现中有重要意义,因为它们是将JavaScript函数或者对象绑定到C++相应的对象上的重要工具。 
* 两个签名类,用于调用时检验用
小结
这一节新增的概念可能有点多。我们尝试小结一下: 
v8提供了可供外部调用的一系列的API: 
* Isolate:提供了一个v8虚拟机的实例 
* Context:提供了一个沙箱,也就是独立的上下文可以运行Isolate 
* v8通过HandleScope栈式管理内存 
* Local<>是最常用的变量分配方式 
* v8的数据类型基类是Data,所有js对象的基类是Value。Value下面分Primitive和Object
最后引用一个新概念,v8为了提升性能,引入了一个高效的编译器Crankshaft.
好了,这一讲就这么多。
--------------------- 
版权声明:本文为CSDN博主「Jtag特工」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lusing/article/details/53035185

V8世界探险 (1) - v8 API概览的更多相关文章

  1. Zookeeper C API 指南四(C API 概览)(转)

    上一节<Zookeeper C API 指南三(回调函数)>重点讲了 Zookeeper C API 中各种回调函数的原型,本节将切入正题,正式讲解 Zookeeper C API.相信大 ...

  2. node-webkit学习(3)Native UI API概览

    node-webkit学习(3)Native UI API概览 文/玄魂 目录 node-webkit学习(3)Native UI API概览 前言 3.1  Native UI api概览 Exte ...

  3. Android 设备管理API概览(Device Administration API)

    原文:http://android.eoe.cn/topic/android_sdk Android 2.2通过提供Android设备管理API的支持来引入企业应用支持.在系统级的设备管理API提供了 ...

  4. 《暗黑世界V1.4》API说明文档

    <暗黑世界V1.4>API说明文档 阵法位置示意图 上方:                        下方:      账号注册   100 请求信息 { username   str ...

  5. Chrome V8系列--浅析Chrome V8引擎中的垃圾回收机制和内存泄露优化策略

    V8 实现了准确式 GC,GC 算法采用了分代式垃圾回收机制.因此,V8 将内存(堆)分为新生代和老生代两部分. 一.前言 V8的垃圾回收机制:JavaScript使用垃圾回收机制来自动管理内存.垃圾 ...

  6. 20. API概览 Schemas

    能被机器所理解的概要, 描述了通过api可得到的资源, URL, 表示方式以及支持的操作. API概要在很多使用场景下都是有用的工具, 例如生成参考文档, 或者驱动可以与API交互的动态客户端库. r ...

  7. 2018世界气象日,API为气象助力

    "世界气象日"(World Meteorological Day)又称"国际气象日",是[世界气象组织]成立的纪念日. 国际气象组织的前身原为非官方性国际气象合 ...

  8. Java 8 Date-Time API概览

    更新时间:2018-04-19 根据网上资料整理 java 8增加了新的Date-Time API (JSR 310),增强对日期与时间的处理.它在很大程度上受到Joda-Time的影响.之前写过一篇 ...

  9. 架构探险笔记11-与Servlet API解耦

    Servlet API解耦 为什么需要与Servlet API解耦 目前在Controller中是无法调用Servlet API的,因为无法获取Request与Response这类对象,我们必须在Di ...

随机推荐

  1. Kotlin函数使用综述与显式返回类型分析

    位置参数与具名参数: 继续接着上一次https://www.cnblogs.com/webor2006/p/11498842.html的方法参数学习,再定义一个函数来说明具名参数的问题: 调用一下,先 ...

  2. 树莓派安装C#运行环境

    一. 安装mono ARMv6(一代 Raspberry Pi B+) : http://yunpan.cn/cw6NYzXkD9kHq 访问密码 63ae ARMv7(二代 Raspberry Pi ...

  3. P5024 保卫王国[倍增+dp]

    窝当然不会ddp啦,要写这题当然是考虑优化裸dp啦,但是这题非常麻烦,于是变成了黑题. 首先,这个是没有上司的舞会模型,求图的带权最大独立集. 不考虑国王的限制条件,有 \[ dp[x][0]+=dp ...

  4. 项目alpha冲刺-总结

    作业要求 这个作业属于哪个课程 软件工程1916-W(福州大学) 这个作业要求在哪里 项目Alpha冲刺 团队名称 基于云的胜利冲锋队 项目名称 云评:高校学生成绩综合评估及可视化分析平台 这个作业的 ...

  5. LG1378

    题目描述 在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界.必须等一个油滴扩展完毕才能放置下一个油滴. ...

  6. java 数组遍历(方法内部的代码)

    //数组遍历(依次输出数组中的每一个元素)二维数组: int[][] arr={{1,2},{3,4,5},{6,7}}; for(int i=0;i<arr.length;i++){ for( ...

  7. WinDbg常用命令系列---线程栈中局部上下文切换.frame

    .frame (Set Local Context) .frame命令指定使用哪个本地上下文(作用域)解释本地变量或显示当前本地上下文. .frame [/c] [/r] [FrameNumber] ...

  8. circus 做为批处理的守护进程

    circus 是集成了zeromq,使用python编写的一个进程以及socket 管理工具,使用circus 的进程管理,我们可以用来进行批任务的 处理,同时又能保证任务的准确 项目使用docker ...

  9. 洛谷 P1063 能量项链 题解

    P1063 能量项链 题目描述 在\(Mars\)星球上,每个\(Mars\)人都随身佩带着一串能量项链.在项链上有\(N\)颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并 ...

  10. 分类模型的性能评价指标(Classification Model Performance Evaluation Metric)

    二分类模型的预测结果分为四种情况(正类为1,反类为0): TP(True Positive):预测为正类,且预测正确(真实为1,预测也为1) FP(False Positive):预测为正类,但预测错 ...