c++对象回收string类型成员时coredump_本体技术视点 | 虚拟机中引用性动态语言对象模型思考...
1
引言
Ontology 的 NeoVM 虛擬機新增加了 DCALL、HAS_KEY、KEYS 以及 VALUES 等幾條新的指令。因此,基于 NeoVM 的引用性動態語言對象的設計理論上可行,這可使得當前語言的支持能更接近原生語義。對象模型設計的必要性Ontology NeoVM 對用戶暴露的對象語義有4種,分別是 bytearray、array、struct 和 map。當前 Python、Go、C#編譯器的實現都是直接復用這4種對象語義,這樣一來就產生了幾個問題:首先,高級語言的基本對象往往不止這幾種對象語義,就會出現對象語義多對一的情況。
不同對象的運算有不同的行為,導致的后果是必須要犧牲其中一種對象的語義。
其次, 高級語言對象對應的底層對象,語義不一定是完全對等的。
2
對象模型
理論上,底層指令的語義模型需要足夠簡單抽象,才能滿足不同類型語言語義的實現。而且很難有一套指令架構,能滿足所有語言語義的運行要求。所以絕大多數高級語言都是重新定義特定的語義模型,構建在特定虛擬機之上運行。而相對底層的語言如 Rust,C 和 C++等則直接編譯后運行在 CPU 上。內存對象模型最佳的方式是不直接使用 Ontology NeoVM 的內置語義對象,而是重新根據語言特性設計其對象模型,更精準的語義對開發者更友好。但是重寫設計對象語義的代價在于,相同的邏輯實現,會產生數倍于當前實現編譯生成的字節碼,且編譯器的實現會更復雜。當前按照 Python 一切皆對象的語義設計,所有對象使用 map 或者 array 實現。為簡化表達,這里假設使用 map 實現對象。map 的第一個 key 為內置的__type__或用編碼表示,編譯器會檢查屬性 key 字段不屬于系統預留字段。在 Python 中,基本對象類型為:Number、string、List、Tuple、Set、Dict;基本運算符為[](subscript), +/-/*/%///以及 le 等。而這些運算符號是相應對象的成員屬性。在運行時,可通過 type 字段,對運算符做不同的語義區分。同樣的, 函數也是對象。各對象可用如下結構表示:{"__type__":"function",?"offset":xxx}{"__type__":"int", "__value__":value}{"__type__":"string", "__value__":value}{"__type__":"list", "__value__":lsitvalue}{"__type__":"map",?"__value__":mapvalue}在具體的實現中, 由于字符串會占用較大的字節碼空間或影響性能,對于全局結構,可以靜態映射為整數表示。3
符號表及重定位
為實現動態類型, 符號表需要保存在運行時環境,即全局運行時對象環境。對于加減乘除等運算,使用對象類型結合運算符名的修飾方式可確定函數對象;而對于對象的其他成員函數,使用對象名結合成員函數名修飾方式。而重定位的時機是編譯完成時,所有的函數偏移已確定。在系統構建好全局對象后,立即跳轉到重定位函數去處理需要重定位的符號信息。當需要訪問對象時,可以正確獲取對象的偏移,如函數調用為偽代碼:function args # 可支持動態參數的參數棧結構global object # 獲取全局運行時對象push function object index # 將函數對象編碼壓棧pickitem # 獲取函數對象。pick function object offset # 獲取函數偏移DCALL?#?跳轉4
全局對象的靜態映射
由于直接使用符號索引,會導致字節碼增大,且 ARRAY 字節碼的處理性能相對 map 更高,所以編譯時盡量減少符號的壓棧,而使用靜態符號表的方式,將全局或局部變量,映射為 index,減少字節碼的生成,提高性能。同時,在編譯時檢查出更多的語法錯誤,如未定義,重復定義等。全局對象可保存在 array 結構中:[funcobj, classobj, intobj, stringobj....]5
成員對象訪問及對象繼承處理
如上所述,全局對象保存在全局運行時環境中,而局部對象保存在函數的局部運行時環境中,某個對象的成員變量在訪問之前,該對象已從運行時環境中取出。所以,在當訪問成員變量時,根據索引成員變量的 key 即可獲取。由于是動態類型,無法在編譯時根據信息映射為 index 整數,只能直接使用變量名。偽碼如下:push class objectpush member object # 編譯器根據成員對象名,生成指令dup # 復制一份作為臨時變量has_Key object # 判斷是否存在jmpifnot label0 # 如果不存在跳轉到label0 get inherit object # 獲取繼承對象,如果不存在繼承繼承,則運行時報錯swaplebal0:Pickitem????????????#?如果是函數訪問,則需要生成DCALL指令6
運算符實現及重載
由于對象模型的變換,所有的運算符邏輯不能直接使用 NeoVM 的指令邏輯,需要用對應對象的邏輯實現。每個運算符的語義和特定的對象綁定。編譯時通過ast獲取運算符。對于不同的對象,編譯時生成不同的對象運算符函數;運行時根據對象類型的不同跳轉到相應的對象處理函數。比如 string 對象的加法和int對象加法,是兩個不同的函數實現。所以根據以上方法,任何對象,都可以重載 add 函數,實現對象的新的加法語義定義。其他運算類似。對于系統內建類型,如 Int、string、list、map。都需要在編譯時生成內建的運算符處理函數。7
控制邏輯
控制邏輯與對象語義關系不大,但是控制指令在判斷時需要將對象轉換成 Ontology NeoVM 的 Boolean 或 big.int。8
NeoVM Service 處理
NeoVM service 返回的數據都是 Ontology NeoVM 語義上的, 所以需要根據返回類型的不同,構造為當前設計的對象類型。對 Syscall 的翻譯,不能直接使用 Syscall + servicename 的方式。后面還需要加上對應的對象類型構造。而對于 syscall 傳入參數是,也需要復原成 Ontology NeoVM 底層語義的對象。9
結論
由于語言語義的多樣性,僅僅直接復用 Ontology NeoVM 原生語義,是不能很好的實現支持語言原生語義的。對象模型的設計,可以使得智能合約支持的語言語義更加精確,擴展能力更強,通過優化不斷地接近原生語義,對現有的內建對象 int、 string、list、map 支持更豐富精確的原生語義,對開發者更友好。但是,這同時會產生數倍于當前編譯器生成的字節碼,而且編譯器的實現更加復雜。上期回顧
下列選項表述正確的是??
A. Ontology Wasm 只支持使用 Rust 語言開發?
B. Ontology-wasm-cdt-rust 已經封裝了鏈上數據增刪改查的操作方法
C. 在使用 Rust 進行 Ontology Wasm 合約開發時,開發者需要自己實現與本體區塊鏈交互的接口?
D. ontio_std 庫不提供鏈上數據的模擬
恭喜@康有為【深耕區塊鏈】@強子 @星鉆1??率先答對,請私信后臺收件地址本期互動
下列哪個說法不正確?
A. Ontology NeoVM 對用戶暴露的對象語義有4種,分別是 bytearray、array、struct 和 map
B. 當前 Ontology 的 Neptune 編譯器已基本實現 Python 的運算邏輯及控制邏輯
C. 內存對象模型最佳的方式是不直接使用 Ontology NeoVM 的內置語義對象,而是重新根據語言特性設計其對象模型
D. 對象模型的設計不會使得相關編譯器的實現更加復雜
請將答案私信后臺,前三位搶答對的小伙伴可以收到本體記事本一個噢~
步驟1:關注「本體研究院」官方賬號;
點擊文章最上方藍色字
或在微信搜索框內查找“本體研究院”
或 ontologyresearch
點擊關注
步驟2:將答案填寫至對話框并發送
總結
以上是生活随笔為你收集整理的c++对象回收string类型成员时coredump_本体技术视点 | 虚拟机中引用性动态语言对象模型思考...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 完全相同的4个小矩形如图所示放置_吸睛!
- 下一篇: ajax和rxjs,javascript