V8引擎-枚举+位运算实现参数配置

更新日期: 2018-06-23阅读: 2k标签: 引擎

基本上从初始化引擎,到Isolate、handleScope、Context一直到编译其实都有记录,但是实在是无从下手。虽说我的博客也没有什么教学意义,但是至少也需要有一个中心和结论。很遗憾,上述的每一步都并互有关联,也就是单独拿出来写毫无意义。而从整体架构来阐述,然后细化到这每一步,我又还没有到那个境界。因此,综合考虑下,决定先暂时放弃逐步解析,优先产出一些有意义的东西。

这一篇的内容属于V8中(或许是C++独有)使用比较普遍的一个技巧,很多模块都有使用。

当初在入门学JS的时候,到了ajax那里,跟着视频学封装。老师讲,如果参数过多,就包装成封装一个对象,这样只需要一个参数就可以了。当时我想着,一个对象也好麻烦啊,还不如封装的时候自己定义一下,如果传1,就代表是"GET"请求,传2,就代表"POST"等等。没想到,当初天真的想法,竟然在C++里面实现了。

 

下面开始正文,首先需要简单介绍一下枚举,话说各位用过TS的大佬应该都懂,或者接触过protobuf这些数据格式化库也有。枚举在很多语言中都有,定义简单说就是一系列的常量集合,通常用来做简单配置。如果没有指定值,那么就是0、1、2...依次增加,举例如下。

enum fruit {
  apple,
  banana,
  pear,
  orange = 5,
};

int main(int argc, const char * argv[]) {
  cout << "enum apple is " << fruit::apple << endl;
  cout << "enum banana is " << fruit::banana << endl;
  cout << "enum pear is " << fruit::pear << endl;
  cout << "enum orange is " << fruit::orange << endl;
  return 0;
}


这里我们定义了一个枚举类型,依次打印每一个值,会得到0、1、2,而第四个由于手动指定了值,所以会得到5。如果不去手动指定值,从JS的角度来看枚举有点类似于一个颠倒形式的数组,比如说定义['apple', 'banana', 'pear'],通过下标0、1、2可以取到对应的值,而枚举恰恰相反,通过枚举值取到的是"下标"。大部分简单的配置情况下,是不用去关心枚举具体的值。这样,关于枚举就介绍完了,很简单。

接下来,来看看V8是如何利用这个数据类型来实现参数配置。在对JS源码字符串的编译过程中,有一个类十分重要,负责记录String => AST的过程,名为ParseInfo,这里不去探究转换过程,单纯看一下这个类的标记配置相关,类定义如下。

namespace v8 {
namespace interval {

// A container for the inputs, configuration options, and outputs of parsing.
/**
 * 有5个构造函数和大量私有属性
 */
class ParseInfo {
  public:
    explicit ParseInfo(AccountingAllocator* zone_allocator);
    explicit ParseInfo(Isolate*);
    ParseInfo(Isolate*, AccountingAllocator* zone_allocator);
    ParseInfo(Isolate* isolate, Handle<Script> script);
    ParseInfo(Isolate* isolate, Handle<SharedFunctionInfo> shared);
  private:
    // Various configuration flags for parsing.
    enum Flag {
      kToplevel = 1 << 0,
      kEager = 1 << 1,
      kEval = 1 << 2,
      kStrictMode = 1 << 3,
      kNative = 1 << 4,
      // ...more
    };
    unsigned flags_;
    void SetFlag(Flag f) { flags_ |= f; }
    void SetFlag(Flag f, bool v) { flags_ = v ? flags_ | f : flags_ & ~f; }
    bool GetFlag(Flag f) const { return (flags_ & f) != 0; }
};


省略了很多代码,这个类真的超级大,特别是构造函数,虽说内部走的Isolate那一个,但是变向的调用会走全套构造。目前只需要关心私有属性枚举Flag和其相关的三个方法,Flag负责标记编译的代码的一些特征,比如说[native code]、module、IIFE、'strict mode'等等。

枚举Flag的定义有点意思,除去了正常的语义化集合,每一项都给了具体的值,依次为1、2、4、8...,后面会解释原因。flags_就代表了整个Flag的配置,类型比较狗,只注明了一个无符号类型,大部门情况下编译器会认为是一个unsigned int。剩下的三个方法则是根据参数来调整flag_的值,具体实现非常简单,但是理解起来有点恶心,全是位运算。

如果要理解这个操作的原理,需要从二进制的角度来理解,枚举类型的每一个值,其实代表的是二进制的1、10、100、1000等等,所以flags_其实也需要从二进制来理解,默认情况是一个全0的数。这样再来看SetFlag方法,假设解析中发现字符串"strict mode",此时需要调用SetFlag(Flag::kStrictMode)来设置参数,或运算表示只要有一个是1即置1,所以flags_的第4位会被置位1,值就变成了1000。

那么GetFlag就很好理解了,传入一个Flag枚举值,由于与运算需要两个都是1才会为真,而传入的总为1,所以只要flag_对应的位为1(即被设置过)就会返回真。

而SetFlag的重载方法则是一个扩展,当第二个参数为true时,使用与单参数一致。当第二个参数为false时,会将该位置0,也就是取消这个配置。

这样,用一个数字就可以代表非常多的编译参数。在应用时,直接取出数字对应位数的值,如果为1,说明该配置为真,否则为假,即简单,又很高效。当然,这个方法的局限性也很明显,只能针对布尔值的配置,如果是复杂类型那还是需要一个xxxoptions的类来管理。


链接: https://fly63.com/article/detial/3893

V8引擎是如何工作?

V8是google开发的JavaScript引擎, 它是 开源的 ,而且是用C++编写的。它用于客户端(Google Chrome)和服务器端(node.js)JavaScript应用程序。V8最初旨在提高Web浏览器中JavaScript执行的性能。为了提升速度,V8将JavaScript代码转换为更高效的机器代码,而不是使用解释器。

Javascript模版引擎mustache.js简介

最近使用ELK的sentinl进行告警配置,sentinl的邮件通知支持mustache。mustache的核心是标签和logic-less.标签: 定义模板的时候,使用了{{name}}、{{#systems}}{{/systems}}标记. 这就是mustache的标签,只不过用{{}}替代了<>

JavaScript 引擎

编写Web代码有时会让开发人员编写一系列字符并像魔术那样神奇,这些字符会在浏览器中变成具体的图像,文字和动作。了解该技术可以帮助开发人员更好地调整他们作为程序员的技能

JavaScript物理引擎之Matter.js与Box2d性能对比

在挑选JavaScript 2D物理引擎的时候,不外乎两种主流的选择:第一种是老牌的Box2D,最开始的版本是C++实现的,后来有了很多种实现,比如flash版本和js版本,第二种是新潮的matter-js,matter-js比较轻量,API和文档都比较有友好。

JS 引擎 V8 发布 v7.4,性能又大幅提高了

JavaScript 引擎 V8 发布了 7.4 版本,目前处于 beta 阶段,正式版将于几个星期后与 Chrome 74 Stable 一起发布。此版本带来了一些新特性,并极大提升了性能。

精读《V8 引擎 Lazy Parsing》

本周精读的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎为了优化性能,做了怎样的尝试吧!这篇文章介绍的优化技术叫 preparser,是通过跳过不必要函数编译的方式优化性能。

JavaScript引擎是如何工作的?从调用栈到Promise你需要知道的一切

你有没有想过浏览器是如何读取和运行 JavaScript 代码的吗?这看起来很神奇,但你可以学到一些发生在幕后的事情。让我们通过介绍 JavaScript 引擎的精彩世界在这种语言中尽情畅游。

从Google V8引擎剖析Promise实现

本文阅读的源码为Google V8 Engine v3.29.45,此版本的promise实现为js版本,在后续版本Google继续对其实现进行了处理。引入了es6语法等,在7.X版本迭代后,逐渐迭代成了C版本实现。

Node js 视图引擎

Node js 视图引擎就像 Laravel 中的 Blade。其最基本的定义是,视图引擎是帮助我们用比通常更短、更简单的方式编写 HTML 代码并重用的工具。此外,它还可以从服务器端导入数据并渲染最终的 HTML

规则引擎解决方案浅析

用于页面,流程,扩展点实现的选择;输出结果:实现的位置;编排无数的条件积木和行为积木,达到业务逻辑计算,券库存消减的目的;输出结果:商品重计算后的价格;通过订单,售后单,会员等信息编排和判断

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!