日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

深入V8引擎-AST(2)

發布時間:2024/4/17 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入V8引擎-AST(2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  先聲明一下,這種長系列的大塊頭博客只能保證盡可能的深入到每一行源碼,有些代碼我不樂意深究就寫個注釋說明一下作用。另外,由于本地整理的比較好,博客就隨心寫了。

  整個Compile過程目前只看到asmjs之前,簡單的過了幾遍,大部分方法沒有點進去看,實在是太復雜了。上一篇的結尾指出了AST的入口,也就是命名空間parsing的一個公共方法,如下。

bool ParseProgram(ParseInfo* info, Isolate* isolate) {// .../*** 生成一個Parser實例* 調用內部方法啟動轉換*/Parser parser(info);FunctionLiteral* result = nullptr;/*** 轉換AST后將結果賦值給ParseInfo的literal_*/result = parser.ParseProgram(isolate, info);info->set_literal(result);// ...return (result != nullptr); }

  所需要關心的核心代碼就是這些,非常簡單,Parser對象的初始化屬性非常多,這里就不列出來了。

  接下來進入第二個核心方法,即ParseProgram。

FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {// .../*** scanner_為Parser類的一個私有屬性* 這里僅僅進行初始化*/scanner_.Initialize();FunctionLiteral* result = DoParseProgram(isolate, info);// ...return result; }

  同樣,所需要關心代碼只有兩行,其中第一步則是啟動了scanner的初始化,第二步則是開始全面解析。

  Scanner包含scanner、scanner-character-strams兩個部分,其中stream則是經過初步處理的源String,必須轉換后才能進行解析。處理的過程在之前省略的代碼中,這里稍微給出大概的轉換流程。

bool ParseProgram(ParseInfo* info, Isolate* isolate) {// .../*** 1、info->script()返回的是字符串的描述信息 source是Local<String>類型的源字符串* 2、ScannerStream是scanner-character-streams頭文件的類 內部方法均為靜態類型 可以直接調用* 3、返回的具體類型根據String類型不同而不同 但是由于均繼承于Utf16CharacterStream 所以直接用父類接*/Handle<String> source(String::cast(info->script()->source()), isolate);std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(isolate, source));info->set_character_stream(std::move(stream));// ... }/*** 有四種特殊的String類型 分別new不同的子類* ScannerStream::For(isolate, data, 0, data->length());*/ Utf16CharacterStream* ScannerStream::For(Isolate* isolate, Handle<String> data, int start_pos, int end_pos) {size_t start_offset = 0;// ...if (data->IsSeqOneByteString()) {return new BufferedCharacterStream<OnHeapStream>(static_cast<size_t>(start_pos), Handle<SeqOneByteString>::cast(data),start_offset, static_cast<size_t>(end_pos));} }

  常規的字符串一般都是OneByteString,這里就不細講了。最后返回一個特殊Stream類,其屬性記錄字符串的長度、當前的解析進度、解析的開始與結束標記等等。

  將字符串轉換后,就可以利用Scanner來進行逐步解析,在此之前,需要對Scanner類有一個簡單的了解,如下。

/*** Scanner類* 跟Utf16CharacterStream一個文件*/ class V8_EXPORT_PRIVATE Scanner {public:// 返回next_的token類型Token::Value peek() const { return next().token; }// 返回current_的位置信息const Location& location() const { return current().location; }private:// 當前字符的Unicode編碼 -1表示結尾(typedef int32_t uc32) uc32 c0_;TokenDesc* current_; // desc for current token (as returned by Next())TokenDesc* next_; // desc for next token (one token look-ahead)TokenDesc* next_next_; // desc for the token after next (after PeakAhead())// 從Handle<String>轉換后的類型 負責執行解析的實際類Utf16CharacterStream* const source_; }

  選取了一些比較簡單的屬性和方法,Scanner內部有三個游標屬性負責遍歷字符串,分別是current_、next_、next_next_,字面意思理解就行了。source_則是之前說的轉換Stream類,所有的解析實際上都是調用這個屬性的方法。而兩個結構體TokenDesc、Location也非常重要,一個負責詞法描述,一個負責記錄詞法位置信息,如下。

/*** 詞法結構體* 每一個TokenDesc代表單獨一段詞法*/ struct TokenDesc {/*** 詞法所在位置* 該結構體比較簡單 就不展開了 兩個值代表起始、結束位置* 例如sample中 "'Hello' + ' World'" 'Hello'會被解析為TOKEN::STRING location為{0, 7}*/Location location = {0, 0};/*** 字符串詞法相關*/LiteralBuffer literal_chars;LiteralBuffer raw_literal_chars;/*** 詞法的枚舉類型* 例如 '(' 是 TOKEN::LPAREN '===' 是 TOKEN::EQ_STRICT* 所有類型可見token.h*/Token::Value token = Token::UNINITIALIZED;MessageTemplate invalid_template_escape_message = MessageTemplate::kNone;Location invalid_template_escape_location;// 小整數uint32_t smi_value_ = 0;bool after_line_terminator = false; }

  通過這個結構體和一些方法,就能完整的將源字符串逐步轉換為抽象語法樹。但是實際轉換過程非常復雜,分支極多,后面再繼續探究。

轉載于:https://www.cnblogs.com/QH-Jimmy/p/11115324.html

總結

以上是生活随笔為你收集整理的深入V8引擎-AST(2)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。