鸚鵡虛擬機器/PMC 系統
我們已經討論過 PMCs——在鸚鵡虛擬機器/多型容器 (PMCs)章節中——包括如何使用 PMC 編譯器定義新的 PMC 型別,以及如何在 PIR 程式中使用它們。本章將更詳細地介紹 PMCs 在 Parrot 中的實際使用方式,包括 PMCs 的記憶體管理、變形 PMCs 以及與 PMCs 的互動。
PMC 資料結構看似簡單,並且被設計成足夠可擴充套件,以供通用資料和功能使用。以下是 PMC 結構和相關的 PMC_EXT 結構的定義
struct PMC {
Parrot_UInt flags;
VTABLE *vtable;
DPOINTER *data;
struct PMC_EXT *pmc_ext;
};
typedef struct PMC_EXT {
DPOINTER *data;
PMC *_metadata;
struct _Sync *_synchronize;
PMC *_next_for_GC;
} PMC_EXT;
從這些定義中我們可以看到,PMC 實際上非常小。關於 PMC 的大部分資訊,包括它所有不同的方法和 VTABLE 介面都儲存在 ->vtable 指標中。VTABLE 結構是一個非常大的結構,包含所有不同 VTABLE 介面的函式指標。
每個 PMC 型別還包含一個指向特定於該 PMC 的資料結構的指標。這些資料結構是根據 PMC 的繼承層次結構及其定義的所有屬性來定義的。例如,這個 PMC 定義
pmclass MyPmc {
ATTR INTVAL a;
ATTR FLOATVAL b;
ATTR STRING *c;
ATTR PMC *d;
...
}
將轉換為這個 C 資料結構定義
typedef struct Parrot_MyPmc_attributes {
INTVAL a;
FLOATVAL b;
STRING *c;
PMC *d;
} Parrot_MyPmc_attributes;
這個結構應該包含在 ->data 指標中,應該始終使用 PMC_data 宏訪問它。這樣,如果 PMC 結構定義最終發生了變化,所有正確使用宏的程式碼都將自動更新,因為宏也會更新。以下是一個使用這些屬性的初始化 VTABLE 的示例
VTABLE void init () {
Parrot_MyPmc_attributes *p = mem_allocate_typed(Parrot_MyPmc_attributes);
p->a = 0;
p->b = 0.0
p->c = NULL;
p->d = PMCNULL;
PMC_data(SELF) = p;
}
還有一個宏使用單詞 PARROT 和 PMC 的全大寫字母名稱來檢索資料結構,並正確地進行型別轉換(因此你的編譯器不會對使用未型別轉換的指標發出警告)
Parrot_MyPmc_attributes *attr = PARROT_MYPMC(SELF);
C 不是一種基於類的(或“面向物件”的)語言,但 OO 程式設計方法的許多教訓已被改編用於 Parrot 的程式碼庫。PMCs、STRINGs 和一些其他資料型別是基於“PObj”的定義,也稱為“Buffer”
typedef struct Buffer {
Parrot_UInt flags;
} Buffer;
請注意,Buffer 中的前兩個條目與 PMC 中的是一樣的?所有以這兩個資料項開始的物件都被稱為“PObject 同構”。簡而言之,我們說所有 pobject 同構都只是“PObjects”,並且有許多型別的 PObjects。例如,記憶體管理系統可以測試所有 pobjects 的標誌以確定記憶體物件是什麼型別的 PObject。
PMC 可以選擇包含一個 PMC_EXT 結構,它添加了額外的功能。PMC_EXT 允許一個 PMC 在多個執行緒之間或多個 Parrot 直譯器之間共享,而不會引入資料競爭。PMC_EXT 還允許一個 PMC 包含一個元資料雜湊(屬性值對),這些元資料通常作為屬性新增到 PIR 中。
PMCs 從兩個特殊的池中分配,一個 PMC 池和一個常量 PMC 池。常量 PMCs 被認為是不可變且永久存在的,因此它們從不被修改,也不被垃圾收集器收集。STRINGS 在字串池或常量字串池中分配。相同的關係適用,常量字串從不被修改,也不被收集。PMC_EXT 結構目前不受記憶體管理子系統的管理。但是,由於 PMC_EXT 與 PMCs 之間是一對一的關係,我們總是知道當它的 PMC 被釋放時可以釋放它。
就垃圾收集而言,PMCs 是 Parrot 中唯一的一種聚合資料型別。STRINGS 不包含指向垃圾收集器感興趣的其他資料項的指標。堆疊塊,在某些結構中內部使用,是 PObjs 也是聚合,但由收集器單獨標記,並且不直接作為聚合處理。
VTables 代表對所有型別 PMCs 的標準介面。對於每個 PMC,有一系列可以執行(或嘗試)的標準操作。並非所有 PMCs 都支援所有 Vtable 操作
VTables 是複雜的資料項,除了包含大量的函式指標之外,還包含一些資料項來支援 PMCs。其中一個數據項是一個類 PMC,一個代表特定 PMC 類的 PMC。另一個數據項是一個列舉,它區分所有 PMC 類。