原创 標記-清除

標記-清除是主流的追蹤式收集算法的一種,和引用計數相比,追蹤式收集是一種間接方法,與程序耦合性很低,簡單地說,就是程序在需要的時候只管申請內存,使用時也不用像引用計數機制要做實時地維護,直到一定條件(一般是已申請內存空間達到一定閾值),進

原创 版本號標記

這是一個處理需要反覆標記的問題的一個小技巧,以一個ACM形式的題目爲例: 輸入:第一行是一個數字N,表示N個case,之後每個case第一行是一個數字M,表示這個case有M個數字輸入,接下來是M個數字,每個數字範圍是0<=n<K 輸出:

原创 GIL併發控制

如果一個語言要實現支持併發執行的接口,則一般來說需要在併發控制上下功夫,原因就是前面說的,由於虛擬機實現的細節問題,直接依賴宿主環境的併發容易出問題。簡單地,以使用宿主的線程爲例。假如源語言的線程對應宿主環境的真線程,那麼同步操作就需要用

原创 用戶態併發:事件驅動

上篇末尾有個地方說錯了,分時調度的yield過程應該是: env.running_queue.add(this); this.stat = STAT_YIELD; return; 需要將this加入到running_queue,否則這

原创 字節碼解釋執行

字節碼的解釋執行和AST的解釋執行有類似之處,而且更簡單,因爲樹形結構已經展開成順序了,以棧虛擬機爲例,爲方便起見,假設所有的指令都在一個指令數組裏,每個元素是一個指令對象,有code和arg兩個屬性,解釋器入口: Object exec

原创 寄存器虛擬機

前面說到,虛擬機是真機的一種模擬,而棧虛擬機模擬的是基於棧計算的機器,和現在常見的基於寄存器的硬件機器不同,於是相應的也有基於寄存器的虛擬機,不過這個虛擬機可能跟真機差別比較大 首先可以看看真機用寄存器的原因,計算機的存儲有一個規律,訪問

原创 垃圾收集簡述

在計算機領域,垃圾收集這個詞確切說是堆內存自動回收,因爲廣義上講,所謂垃圾也包括內存之外的一些東西,比如不再使用的文件句柄,但這些東西一般不算在這個概念裏,這個名字大概是一開始取了個形象的名字 從歷史看,垃圾回收技術既古老又年輕,現代的高

原创 協程

就一個簡單實現的語言來說,如果有併發需求,像之前說的直接使用宿主環境的線程,加上必要的調度控制即可實現需求,但如果要求比較高,觸發到上篇講的線程和單線程異步的相關缺陷,一個較普遍的解決辦法是採用用戶態併發,即對於os內核來說,進程只有一個

原创 運行時環境

AST或字節碼的解釋過程只是在代碼過程層面,不足以成爲一個完整的運行,因爲程序計算是需要數據和存儲空間的,光有代碼跑不起來,需要運行時環境,至少要有數據,實際情況中還需要一些其他信息。爲討論方便,在解釋器中將運行時環境抽象爲前述的env對

原创 語法和語義分析

顧名思義,一個命令式語言是由一個個“命令”爲單元組成,不過一般很少用命令這個詞,而是細分一下,比較低級的語言用指令(instruction),高低的語言一般認爲是一個語句(statement,以後簡稱stmt),詞法分析只將一段高級語言代

原创 引用計數

引用計數是垃圾收集中一種直接方式,其基本策略是每個對象維護一個引用計數,用於表示外界有多少地方引用自己,當有新的引用到這個對象的時候,計數+1,反之一個到這個對象的引用被拆除的時候,計數-1,當計數爲0的時候,說明沒有人引用這個對象了,這

原创 棧虛擬機字節碼

雖然AST可以直接解釋執行,實現也不復雜,但大部分語言,比如java,python,ruby(1.9版本之後)使用虛擬機解釋字節碼執行。字節碼和AST的執行有很強的一致性,但字節碼執行機制可以實現一些更細粒度的控制 這裏的虛擬機是指執行一

原创 用戶態併發:基本框架

前述關於線程的棧大小問題,其實棧是可以動態增長的,只不過爲了效率問題,一般都是固定的,這是一個實現相關,並非線程的原罪;不過說的第二點,線程調度需要陷入內核,這個的確非常影響效率。而協程沒有這兩個問題,首先所有協程本質是可以在一個線程裏面

原创 AST解釋執行

語法和語義分析的結果是抽象語法樹AST,再往後編譯原理還有代碼生成及優化的很大一部分,但如果只是做一個執行器,到AST爲止就可以解釋執行了,當然就算不生成AST,解析執行也可以,只是基於之前說過的原因,極少採用解析執行的方式 目前的大多數

原创 無鎖環形隊列,volatile和亂序執行

這裏說的環形隊列是一種內存通訊機制,本身這個機制和語言沒有什麼關係,不過上篇提到了volatile語法和acquire/release語義,就以這個機制做一個例子,C語言實現。這方面的內容涉及到一些現有的語言實現的東西 環形隊列的數據結構