成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

V8 Object 內(nèi)存結(jié)構(gòu)與屬性訪問詳解

loonggg / 2888人閱讀

摘要:內(nèi)存結(jié)構(gòu)與屬性訪問詳解從屬于筆者的前端入門與工程實(shí)踐,推薦閱讀我的前端之路工具化與工程化。內(nèi)存結(jié)構(gòu)與屬性訪問上世紀(jì)九十年代,隨著網(wǎng)景瀏覽器的發(fā)行,首次進(jìn)入人們的視線。

V8 Object 內(nèi)存結(jié)構(gòu)與屬性訪問詳解從屬于筆者的Web 前端入門與工程實(shí)踐,推薦閱讀2016-我的前端之路:工具化與工程化。更多關(guān)于 JavaScript 引擎文章參考這里。

V8 Object 內(nèi)存結(jié)構(gòu)與屬性訪問

上世紀(jì)九十年代,隨著網(wǎng)景瀏覽器的發(fā)行,JavaScript 首次進(jìn)入人們的視線。之后隨著 AJAX 的大規(guī)模應(yīng)用與富客戶端、單頁應(yīng)用時(shí)代的到來,JavaScript 在 Web 開發(fā)中占據(jù)了越來越重要的地位。在早期的 JavaScript 引擎中,性能越發(fā)成為了開發(fā)網(wǎng)頁應(yīng)用的瓶頸。而 V8 引擎設(shè)計(jì)的目標(biāo)就是為了保證大型 JavaScript 應(yīng)用的執(zhí)行效率,在很多測試中可以明顯發(fā)現(xiàn) V8 的性能優(yōu)于 JScript (Internet Explorer), SpiderMonkey (Firefox), 以及 JavaScriptCore(Safari). 根據(jù) V8 的官方文檔介紹,其主要是從屬性訪問、動(dòng)態(tài)機(jī)器碼生成以及高效的垃圾回收這三個(gè)方面著手性能優(yōu)化。Obejct 當(dāng)屬 JavaScript 最重要的數(shù)據(jù)類型之一,本文我們對(duì)其內(nèi)部結(jié)構(gòu)進(jìn)行詳細(xì)闡述。其繼承關(guān)系圖如下所示:

在 V8 中新分配的 JavaScript 對(duì)象結(jié)構(gòu)如下所示:

[ class / map ] -> ... ; 指向內(nèi)部類
[ properties  ] -> [empty array]
[ elements    ] -> [empty array] ; 數(shù)值類型名稱的屬性
[ reserved #1 ] -
[ reserved #2 ]  |
[ reserved #3 ]  }- in object properties,即預(yù)分配的內(nèi)存空間
...............  |
[ reserved #N ] -/

在創(chuàng)建新的對(duì)象時(shí),V8 會(huì)創(chuàng)建某個(gè)預(yù)分配的內(nèi)存區(qū)域來存放所謂的 in-object 屬性,預(yù)分配區(qū)域的大小由構(gòu)造函數(shù)中的參數(shù)數(shù)目決定(this.field = expr)。當(dāng)你打算向?qū)ο笾刑砑幽硞€(gè)新屬性時(shí),V8 首先會(huì)嘗試放入所謂的 in-order 槽位中,當(dāng) in-object 槽位過載之后,V8 會(huì)嘗試將新的屬性添加到 out-of-object 屬性列表。而屬性名與屬性下標(biāo)的映射關(guān)系即存放在所謂隱藏類中,譬如{ a: 1, b: 2, c: 3, d: 4}對(duì)象的存儲(chǔ)方式可能如下:

[ class       ] -> [a: in obj #1, b: in obj #2, c: out obj #1, d: out obj #2]
[ properties  ] -> [  3  ][  4  ] ; this is linear array
[ elements    ]    
[ 1           ]
[ 2           ]

隨著屬性數(shù)目的增加,V8 會(huì)轉(zhuǎn)回到傳統(tǒng)的字典模式/哈希表模式:

[ class       ] -> [ OBJECT IS IN DICTIONARY MODE ]
[ properties  ] -> [a: 1, b: 2, c: 3, d: 4, e: 5] ; this is classical hash table
[ elements    ]  
Reference

V8 Design Elements

A tour of V8: object representation

Demystifying v8 and JavaScript Performance

V8 Docs:Object Class Reference

How does V8 manage the memory of object instances?

Property Name:屬性名

作為動(dòng)態(tài)語言,JavaScript 允許我們以非常靈活的方式來定義對(duì)象,譬如:

obj.prop
obj["prop"]

參照 JavaScript 定義規(guī)范中的描述,屬性名恒為字符串,即使你使用了某個(gè)非字符串的名字,也會(huì)隱式地轉(zhuǎn)化為字符串類型。譬如你創(chuàng)建的是個(gè)數(shù)組,以數(shù)值下標(biāo)進(jìn)行訪問,然而 V8 還是將其轉(zhuǎn)化為了字符串再進(jìn)行索引,因此以下的方式就會(huì)獲得相同的效果:

obj[1];    //
obj["1"];  // names for the same property
obj[1.0];  //

var o = { toString: function () { return "-1.5"; } };

obj[-1.5];  // also equivalent
obj[o];     // since o is converted to string

而 JavaScript 中的 Array 只是包含了額外的length屬性的對(duì)象而已,length會(huì)返回當(dāng)前最大下標(biāo)加一的結(jié)果(此時(shí)字符串下標(biāo)會(huì)被轉(zhuǎn)化為數(shù)值類型計(jì)算):

var a = new Array();
a[100] = "foo";
a.length;  //101
a[undefined] = "a";
a.length; //0

Function本質(zhì)上也是對(duì)象,只不過length屬性會(huì)返回參數(shù)的長度而已:

> a = ()=>{}
[Function: a]
> a.length
0
> a = (b)=>{}
[Function: a]
> a.length
1
In-Object Properties & Fast Property Access:對(duì)象內(nèi)屬性與訪問優(yōu)化

作為動(dòng)態(tài)類型語言,JavaScript 中的對(duì)象屬性可以在運(yùn)行時(shí)動(dòng)態(tài)地增刪,意味著整個(gè)對(duì)象的結(jié)構(gòu)會(huì)頻繁地改變。大部分 JavaScript 引擎傾向于使用字典類型的數(shù)據(jù)結(jié)構(gòu)來存放對(duì)象屬性( Object Properties),每次進(jìn)行屬性訪問的時(shí)候引擎都需要在內(nèi)層中先動(dòng)態(tài)定位屬性對(duì)應(yīng)的下標(biāo)地址然后讀取值。這種方式實(shí)現(xiàn)上比較容易,但是會(huì)導(dǎo)致較差的性能表現(xiàn)。其他的類似于 Java 與 Smalltalk 這樣的靜態(tài)語言中,成員變量在編譯階段即確定了其在內(nèi)存中的固定偏移地址,進(jìn)行屬性訪問的時(shí)候只需要單指令從內(nèi)存中加載即可。而 V8 則利用動(dòng)態(tài)創(chuàng)建隱藏內(nèi)部類的方式動(dòng)態(tài)地將屬性的內(nèi)存地址記錄在對(duì)象內(nèi),從而提升整體的屬性訪問速度??偨Y(jié)而言,每當(dāng)為某個(gè)對(duì)象添加新的屬性時(shí),V8 會(huì)自動(dòng)修正其隱藏內(nèi)部類。我們先通過某個(gè)實(shí)驗(yàn)來感受下隱藏類的存在:

var PROPERTIES = 10000000;
var o = {};

var start = +new Date;

for (var i = 0; i < PROPERTIES; i++) {
  o[i] = i;
}

console.log(+new Date - start);

function O(size) {
  for (var i = 0; i < size; i++) {
    this[i] = null;
  }
}

var o = new O(PROPERTIES);

var start = +new Date;

for (var i = 0; i < PROPERTIES; i++) {
  o[i] = i;
}

console.log(+new Date - start);

class OClass {

    constructor(size){
        for (var i = 0; i < size; i++) {
            this[i] = null;
        }
    }

}

var o = new OClass(PROPERTIES);

var start = +new Date;

for (var i = 0; i < PROPERTIES; i++) {
  o[i] = i;
}

console.log(+new Date - start);

該程序的執(zhí)行結(jié)果如下:

// Babel 下結(jié)果
385
37
49
// Chrome 下結(jié)果
416
32
31

第一種實(shí)現(xiàn)中,每次為對(duì)象o設(shè)置新的屬性時(shí),V8 都會(huì)創(chuàng)建新的隱藏內(nèi)部類(內(nèi)部稱為 Map)來存儲(chǔ)新的內(nèi)存地址以優(yōu)化屬性查找速度。而第二種實(shí)現(xiàn)時(shí),我們?cè)趧?chuàng)建新的對(duì)象時(shí)即初始化了內(nèi)部類,這樣在賦值屬性時(shí) V8 以及能夠高性能地定位這些屬性。第三種實(shí)現(xiàn)則是用的 ES6 Class,在純正的 V8 下性能最好。接下來我們具體闡述下隱藏類的工作原理,假設(shè)我們定義了描述點(diǎn)的函數(shù):

function Point(x, y) {
  this.x = x;
  this.y = y;
}

當(dāng)我們執(zhí)行new Point(x,y)語句時(shí),V8 會(huì)創(chuàng)建某個(gè)新的Point對(duì)象。創(chuàng)建的過程中,V8 首先會(huì)創(chuàng)建某個(gè)所謂C0的隱藏內(nèi)部類,因?yàn)樯形礊閷?duì)象添加任何屬性,此時(shí)隱藏類還是空的:

接下來調(diào)用首個(gè)賦值語句this.x = x;為當(dāng)前Point對(duì)象創(chuàng)建了新的屬性x,此時(shí) V8 會(huì)基于C0創(chuàng)建另一個(gè)隱藏類C1來替換C0,然后在C1中存放對(duì)象屬性x的內(nèi)存位置信息:

這里從C0C1的變化稱為轉(zhuǎn)換(Transitions),當(dāng)我們?yōu)橥粋€(gè)類型的對(duì)象添加新的屬性時(shí),并不是每次都會(huì)創(chuàng)建新的隱藏類,而是多個(gè)對(duì)象會(huì)共用某個(gè)符合轉(zhuǎn)換條件的隱藏類。接下來繼續(xù)執(zhí)行this.y = y 這一條語句,會(huì)為Point對(duì)象創(chuàng)建新的屬性。此時(shí) V8 會(huì)進(jìn)行以下步驟:

基于C1創(chuàng)建另一個(gè)隱藏類C1,并且將關(guān)于屬性y的位置信息寫入到C2中。

更新C1為其添加轉(zhuǎn)換信息,即當(dāng)為Point對(duì)象添加屬性 y 時(shí),應(yīng)該轉(zhuǎn)換到隱藏類 C2


整個(gè)過程的偽代碼描述如下:



  Class C0
    "x": TRANSITION to C1 at offset 0

this.x = x;

  Class C1
    "x": FIELD at offset 0
    "y": TRANSITION to C2 at offset 1

this.y = y;

  Map C2
    "x": FIELD at offset 0
    "y": FIELD at offset 1
Reused Hidden Class:重復(fù)使用的隱藏類

我們?cè)谏衔闹刑峒?,如果每次添加新的屬性時(shí)都創(chuàng)建新的隱藏類無疑是極大的性能浪費(fèi),實(shí)際上當(dāng)我們?cè)俅蝿?chuàng)建新的Point對(duì)象時(shí),V8 并不會(huì)創(chuàng)建新的隱藏類而是使用已有的,過程描述如下:

初始化新的Point對(duì)象,并將隱藏類指向C0。

添加x屬性時(shí),遵循隱藏類的轉(zhuǎn)換原則指向到C1 , 并且根據(jù)C1指定的偏移地址寫入x。

添加y屬性時(shí),遵循隱藏類的轉(zhuǎn)換原則指向到C2,并且根據(jù)C2指定的偏移地址寫入y

另外我們?cè)谏衔囊枣湵淼姆绞矫枋鲛D(zhuǎn)換,實(shí)際上真實(shí)場景中 V8 會(huì)以樹的結(jié)構(gòu)來描述轉(zhuǎn)換及其之間的關(guān)系,這樣就能夠用于類似于下面的屬性一致而賦值順序顛倒的場景:

function Point(x, y, reverse) {
  if (reverse) {
    this.x = x;
    this.y = y;
  } else {
    this.y = x;
    this.x = y;
  }
}
Methods & Prototypes:方法與原型

JavaScript 中并沒有類的概念(語法糖除外),因此對(duì)于方法的調(diào)用處理會(huì)難于 C++ 或者 Java。下面這個(gè)例子中,distance方法可以被看做Point的普通屬性之一,不過其并非原始類型的數(shù)據(jù),而是指向了另一個(gè)函數(shù):

function Point(x, y) {
  this.x = x;
  this.y = y;
  this.distance = PointDistance;
}

function PointDistance(p) {
  var dx = this.x - p.x;
  var dy = this.y - p.y;
  return Math.sqrt(dx*dx + dy*dy);
}

如果我們像上文介紹的普通的 in-object 域一樣來處理distance屬性,那么無疑會(huì)帶來較大的內(nèi)存浪費(fèi),畢竟每個(gè)對(duì)象都要存放一段外部函數(shù)引用(Reference 的內(nèi)存占用往往大于原始類型)。C++ 中則是以指向多個(gè)虛函數(shù)的虛函數(shù)表(V-Tables)解決這個(gè)問題。每個(gè)包含虛函數(shù)的類的實(shí)例都會(huì)指向這個(gè)虛函數(shù)表,當(dāng)調(diào)用某個(gè)虛函數(shù)時(shí),程序會(huì)自動(dòng)從虛函數(shù)表中加載該函數(shù)的地址信息然后轉(zhuǎn)向到該地址調(diào)用。V8 中我們已經(jīng)使用了隱藏類這一共享數(shù)據(jù)結(jié)構(gòu),因此可以很方便地改造下就可以。我們引入了所謂 Constant Functions 的概念,某個(gè) Constant Function 即代表了對(duì)象中僅包含某個(gè)名字,而具體的屬性值存放在描述符本身的概念:



  Class C0
    "x": TRANSITION to C1 at offset 0

this.x = x;

  Class C1
    "x": FIELD at offset 0
    "y": TRANSITION to C2 at offset 1

this.y = y;

  Class C2
    "x": FIELD at offset 0
    "y": FIELD at offset 1
    "distance": TRANSITION to C3 

this.distance = PointDistance;

  Class C3
    "x": FIELD at offset 0
    "y": FIELD at offset 1
    "distance": CONSTANT_FUNCTION 

注意,在這里如果我們將PointDistance 重定義指向了其他函數(shù),那么這個(gè)轉(zhuǎn)換也會(huì)自動(dòng)失效,V8 會(huì)創(chuàng)建新的隱藏類。另一種解決這個(gè)問題的方法就是使用原型,每個(gè)構(gòu)造函數(shù)都會(huì)有所謂的Prototype屬性,該屬性會(huì)自動(dòng)成為對(duì)象的原型鏈上的一環(huán),上面的例子可以改寫為以下方式:

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.distance = function(p) {
  var dx = this.x - p.x;
  var dy = this.y - p.y;
  return Math.sqrt(dx*dx + dy*dy);
}

...
var u = new Point(1, 2);
var v = new Point(3, 4);
var d = u.distance(v);

V8 同樣會(huì)把原型鏈上的方法在隱藏類中映射為 Constant Function 描述符,而調(diào)用原型方法往往會(huì)比調(diào)用自身方法慢一點(diǎn),畢竟引擎不僅要去掃描自身的隱藏類,還要去掃描原型鏈上對(duì)象的隱藏類才能得知真正的函數(shù)調(diào)用地址。不過這個(gè)不會(huì)對(duì)于代碼的性能造成明顯的影響,因此寫代碼的時(shí)候也不必小心翼翼的避免這個(gè)。

Dictionary Mode

對(duì)于復(fù)雜屬性的對(duì)象,V8 會(huì)使用所謂的字典模式(Dictionary Mode)來存儲(chǔ)對(duì)象,也就是使用哈希表來存放鍵值信息,這種方式存儲(chǔ)開銷會(huì)小于上文提到的包含了隱藏類的方式,不過查詢速度會(huì)遠(yuǎn)小于前者。初始狀態(tài)下,哈希表中的所有的鍵與值都被設(shè)置為了undefined,當(dāng)插入新的數(shù)據(jù)時(shí),計(jì)算得出的鍵名的哈希值的低位會(huì)被當(dāng)做初始的存儲(chǔ)索引地址。如果此地址已經(jīng)被占用了,V8 會(huì)嘗試向下一個(gè)地址進(jìn)行插入,直到插入成功,偽代碼表述如下:

// 插入
insert(table, key, value):
  table = ensureCapacity(table, length(table) + 1)
  code = hash(key)
  n = capacity(table)
  index = code (mod n)
  while getKey(table, index) is not undefined:
    index += 1 (mod n)
  set(table, index, key, value)

//查找
lookup(table, key):
  code = hash(key)
  n = capacity(table)
  index = code (mod n)
  k = getKey(table, index)
  while k is not null or undefined
        and k != key: 
    index += 1 (mod n)
    k = getKey(table, index)
  if k == key:
    return getValue(table, index)
  else:
    return undefined

盡管計(jì)算鍵名哈希值與比較的速度會(huì)比較快,但是每次讀寫屬性的時(shí)候都進(jìn)行這么多步驟無疑會(huì)大大拉低速度,因此 V8 盡可能地會(huì)避免使用這種存儲(chǔ)方式。

Fast Elements:數(shù)值下標(biāo)的屬性

V8 中將屬性名為非負(fù)整數(shù)(0、1、2……)的屬性稱為Element,每個(gè)對(duì)象都有一個(gè)指向Element數(shù)組的指針,其存放和其他屬性是分開的。注意,隱藏類中并不包含 Element 的描述符,但可能包含其它有著不同 Element 類型的同一種隱藏類的轉(zhuǎn)換描述符。大多數(shù)情況下,對(duì)象都會(huì)有 Fast Element,也就是說這些 Element 以連續(xù)數(shù)組的形式存放。有三種不同的 Fast Element:

Fast small integers

Fast doubles

Fast values

根據(jù)標(biāo)準(zhǔn),JavaScript 中的所有數(shù)字都理應(yīng)以64位浮點(diǎn)數(shù)形式出現(xiàn)。因此 V8 盡可能以31位帶符號(hào)整數(shù)來表達(dá)數(shù)字(最低位總是0,這有助于垃圾回收器區(qū)分?jǐn)?shù)字和指針)。因此含有Fast small integers類型的對(duì)象,其 Element 類型只會(huì)包含這樣的數(shù)字。如果需要存儲(chǔ)小數(shù)、大整數(shù)或其他特殊值,如-0,則需要將數(shù)組提升為 Fast doubles。于是這引入了潛在的昂貴的復(fù)制-轉(zhuǎn)換操作,但通常不會(huì)頻繁發(fā)生。Fast doubles 仍然是很快的,因?yàn)樗械臄?shù)字都是無封箱存儲(chǔ)的。但如果我們要存儲(chǔ)的是其他類型,比如字符串或者對(duì)象,則必須將其提升為普通的 Fast Element 數(shù)組。

JavaScript 不提供任何確定存儲(chǔ)元素多少的辦法。你可能會(huì)說像這樣的辦法,new Array(100),但實(shí)際上這僅僅針對(duì)Array構(gòu)造函數(shù)有用。如果你將值存在一個(gè)不存在的下標(biāo)上,V8會(huì)重新開辟更大的內(nèi)存,將原有元素復(fù)制到新內(nèi)存。V8 可以處理帶空洞的數(shù)組,也就是只有某些下標(biāo)是存有元素,而期間的下標(biāo)都是空的。其內(nèi)部會(huì)安插特殊的哨兵值,因此試圖訪問未賦值的下標(biāo),會(huì)得到undefined。當(dāng)然,F(xiàn)ast Element 也有其限制。如果你在遠(yuǎn)遠(yuǎn)超過當(dāng)前數(shù)組大小的下標(biāo)賦值,V8 會(huì)將數(shù)組轉(zhuǎn)換為字典模式,將值以哈希表的形式存儲(chǔ)。這對(duì)于稀疏數(shù)組來說很有用,但性能上肯定打了折扣,無論是從轉(zhuǎn)換這一過程來說,還是從之后的訪問來說。如果你需要復(fù)制整個(gè)數(shù)組,不要逆向復(fù)制(索引從高到低),因?yàn)檫@幾乎必然觸發(fā)字典模式。

    // 這會(huì)大大降低大數(shù)組的性能
    function copy(a) {
        var b = new Array();
        for (var i = a.length - 1; i >= 0; i--)
            b[i] = a[i];
        return b;
    }

由于普通的屬性和數(shù)字式屬性分開存放,即使數(shù)組退化為字典模式,也不會(huì)影響到其他屬性的訪問速度(反之亦然)。

Object 代碼聲明
// https://v8docs.nodesource.com/node-7.2/d4/da0/v8_8h_source.html#l02660
class V8_EXPORT Object : public Value {
  public:
   V8_DEPRECATE_SOON("Use maybe version",
                     bool Set(Local key, Local value));
   V8_WARN_UNUSED_RESULT Maybe Set(Local context,
                                         Local key, Local value);
 
   V8_DEPRECATE_SOON("Use maybe version",
                     bool Set(uint32_t index, Local value));
   V8_WARN_UNUSED_RESULT Maybe Set(Local context, uint32_t index,
                                         Local value);
 
   // Implements CreateDataProperty (ECMA-262, 7.3.4).
   //
   // Defines a configurable, writable, enumerable property with the given value
   // on the object unless the property already exists and is not configurable
   // or the object is not extensible.
   //
   // Returns true on success.
   V8_WARN_UNUSED_RESULT Maybe CreateDataProperty(Local context,
                                                        Local key,
                                                        Local value);
   V8_WARN_UNUSED_RESULT Maybe CreateDataProperty(Local context,
                                                        uint32_t index,
                                                        Local value);
 
   // Implements DefineOwnProperty.
   //
   // In general, CreateDataProperty will be faster, however, does not allow
   // for specifying attributes.
   //
   // Returns true on success.
   V8_WARN_UNUSED_RESULT Maybe DefineOwnProperty(
       Local context, Local key, Local value,
       PropertyAttribute attributes = None);
 
   // Sets an own property on this object bypassing interceptors and
   // overriding accessors or read-only properties.
   //
   // Note that if the object has an interceptor the property will be set
   // locally, but since the interceptor takes precedence the local property
   // will only be returned if the interceptor doesn"t return a value.
   //
   // Note also that this only works for named properties.
   V8_DEPRECATED("Use CreateDataProperty / DefineOwnProperty",
                 bool ForceSet(Local key, Local value,
                               PropertyAttribute attribs = None));
   V8_DEPRECATE_SOON("Use CreateDataProperty / DefineOwnProperty",
                     Maybe ForceSet(Local context,
                                          Local key, Local value,
                                          PropertyAttribute attribs = None));
 
   V8_DEPRECATE_SOON("Use maybe version", Local Get(Local key));
   V8_WARN_UNUSED_RESULT MaybeLocal Get(Local context,
                                               Local key);
 
   V8_DEPRECATE_SOON("Use maybe version", Local Get(uint32_t index));
   V8_WARN_UNUSED_RESULT MaybeLocal Get(Local context,
                                               uint32_t index);
 
   V8_DEPRECATED("Use maybe version",
                 PropertyAttribute GetPropertyAttributes(Local key));
   V8_WARN_UNUSED_RESULT Maybe GetPropertyAttributes(
       Local context, Local key);
 
   V8_DEPRECATED("Use maybe version",
                 Local GetOwnPropertyDescriptor(Local key));
   V8_WARN_UNUSED_RESULT MaybeLocal GetOwnPropertyDescriptor(
       Local context, Local key);
 
   V8_DEPRECATE_SOON("Use maybe version", bool Has(Local key));
   V8_WARN_UNUSED_RESULT Maybe Has(Local context,
                                         Local key);
 
   V8_DEPRECATE_SOON("Use maybe version", bool Delete(Local key));
   // TODO(dcarney): mark V8_WARN_UNUSED_RESULT
   Maybe Delete(Local context, Local key);
 
   V8_DEPRECATED("Use maybe version", bool Has(uint32_t index));
   V8_WARN_UNUSED_RESULT Maybe Has(Local context, uint32_t index);
 
   V8_DEPRECATED("Use maybe version", bool Delete(uint32_t index));
   // TODO(dcarney): mark V8_WARN_UNUSED_RESULT
   Maybe Delete(Local context, uint32_t index);
 
   V8_DEPRECATED("Use maybe version",
                 bool SetAccessor(Local name,
                                  AccessorGetterCallback getter,
                                  AccessorSetterCallback setter = 0,
                                  Local data = Local(),
                                  AccessControl settings = DEFAULT,
                                  PropertyAttribute attribute = None));
   V8_DEPRECATED("Use maybe version",
                 bool SetAccessor(Local name,
                                  AccessorNameGetterCallback getter,
                                  AccessorNameSetterCallback setter = 0,
                                  Local data = Local(),
                                  AccessControl settings = DEFAULT,
                                  PropertyAttribute attribute = None));
   // TODO(dcarney): mark V8_WARN_UNUSED_RESULT
   Maybe SetAccessor(Local context, Local name,
                           AccessorNameGetterCallback getter,
                           AccessorNameSetterCallback setter = 0,
                           MaybeLocal data = MaybeLocal(),
                           AccessControl settings = DEFAULT,
                           PropertyAttribute attribute = None);
 
   void SetAccessorProperty(Local name, Local getter,
                            Local setter = Local(),
                            PropertyAttribute attribute = None,
                            AccessControl settings = DEFAULT);
 
   Maybe HasPrivate(Local context, Local key);
   Maybe SetPrivate(Local context, Local key,
                          Local value);
   Maybe DeletePrivate(Local context, Local key);
   MaybeLocal GetPrivate(Local context, Local key);
 
   V8_DEPRECATE_SOON("Use maybe version", Local GetPropertyNames());
   V8_WARN_UNUSED_RESULT MaybeLocal GetPropertyNames(
       Local context);
   V8_WARN_UNUSED_RESULT MaybeLocal GetPropertyNames(
       Local context, KeyCollectionMode mode,
       PropertyFilter property_filter, IndexFilter index_filter);
 
   V8_DEPRECATE_SOON("Use maybe version", Local GetOwnPropertyNames());
   V8_WARN_UNUSED_RESULT MaybeLocal GetOwnPropertyNames(
       Local context);
 
   V8_WARN_UNUSED_RESULT MaybeLocal GetOwnPropertyNames(
       Local context, PropertyFilter filter);
 
   Local GetPrototype();
 
   V8_DEPRECATED("Use maybe version", bool SetPrototype(Local prototype));
   V8_WARN_UNUSED_RESULT Maybe SetPrototype(Local context,
                                                  Local prototype);
 
   Local FindInstanceInPrototypeChain(Local tmpl);
 
   V8_DEPRECATED("Use maybe version", Local ObjectProtoToString());
   V8_WARN_UNUSED_RESULT MaybeLocal ObjectProtoToString(
       Local context);
 
   Local GetConstructorName();
 
   Maybe SetIntegrityLevel(Local context, IntegrityLevel level);
 
   int InternalFieldCount();
 
   V8_INLINE static int InternalFieldCount(
       const PersistentBase& object) {
     return object.val_->InternalFieldCount();
   }
 
   V8_INLINE Local GetInternalField(int index);
 
   void SetInternalField(int index, Local value);
 
   V8_INLINE void* GetAlignedPointerFromInternalField(int index);
 
   V8_INLINE static void* GetAlignedPointerFromInternalField(
       const PersistentBase& object, int index) {
     return object.val_->GetAlignedPointerFromInternalField(index);
   }
 
   void SetAlignedPointerInInternalField(int index, void* value);
   void SetAlignedPointerInInternalFields(int argc, int indices[],
                                          void* values[]);
 
   // Testers for local properties.
   V8_DEPRECATED("Use maybe version", bool HasOwnProperty(Local key));
   V8_WARN_UNUSED_RESULT Maybe HasOwnProperty(Local context,
                                                    Local key);
   V8_WARN_UNUSED_RESULT Maybe HasOwnProperty(Local context,
                                                    uint32_t index);
   V8_DEPRECATE_SOON("Use maybe version",
                     bool HasRealNamedProperty(Local key));
   V8_WARN_UNUSED_RESULT Maybe HasRealNamedProperty(Local context,
                                                          Local key);
   V8_DEPRECATE_SOON("Use maybe version",
                     bool HasRealIndexedProperty(uint32_t index));
   V8_WARN_UNUSED_RESULT Maybe HasRealIndexedProperty(
       Local context, uint32_t index);
   V8_DEPRECATE_SOON("Use maybe version",
                     bool HasRealNamedCallbackProperty(Local key));
   V8_WARN_UNUSED_RESULT Maybe HasRealNamedCallbackProperty(
       Local context, Local key);
 
   V8_DEPRECATED(
       "Use maybe version",
       Local GetRealNamedPropertyInPrototypeChain(Local key));
   V8_WARN_UNUSED_RESULT MaybeLocal GetRealNamedPropertyInPrototypeChain(
       Local context, Local key);
 
   V8_DEPRECATED(
       "Use maybe version",
       Maybe GetRealNamedPropertyAttributesInPrototypeChain(
           Local key));
   V8_WARN_UNUSED_RESULT Maybe
   GetRealNamedPropertyAttributesInPrototypeChain(Local context,
                                                  Local key);
 
   V8_DEPRECATED("Use maybe version",
                 Local GetRealNamedProperty(Local key));
   V8_WARN_UNUSED_RESULT MaybeLocal GetRealNamedProperty(
       Local context, Local key);
 
   V8_DEPRECATED("Use maybe version",
                 Maybe GetRealNamedPropertyAttributes(
                     Local key));
   V8_WARN_UNUSED_RESULT Maybe GetRealNamedPropertyAttributes(
       Local context, Local key);
 
   bool HasNamedLookupInterceptor();
 
   bool HasIndexedLookupInterceptor();
 
   int GetIdentityHash();
 
   // TODO(dcarney): take an isolate and optionally bail out?
   Local Clone();
 
   Local CreationContext();
 
   bool IsCallable();
 
   bool IsConstructor();
 
   V8_DEPRECATED("Use maybe version",
                 Local CallAsFunction(Local recv, int argc,
                                             Local argv[]));
   V8_WARN_UNUSED_RESULT MaybeLocal CallAsFunction(Local context,
                                                          Local recv,
                                                          int argc,
                                                          Local argv[]);
 
   V8_DEPRECATED("Use maybe version",
                 Local CallAsConstructor(int argc, Local argv[]));
   V8_WARN_UNUSED_RESULT MaybeLocal CallAsConstructor(
       Local context, int argc, Local argv[]);
 
   V8_DEPRECATE_SOON("Keep track of isolate correctly", Isolate* GetIsolate());
 
   static Local New(Isolate* isolate);
 
   V8_INLINE static Object* Cast(Value* obj);
 
  private:
   Object();
   static void CheckCast(Value* obj);
   Local SlowGetInternalField(int index);
   void* SlowGetAlignedPointerFromInternalField(int index);
 };           
               
                                           
                       
                 
            
                     
             
               

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81320.html

相關(guān)文章

  • V8 中的 Fast 屬性

    摘要:這些是中可用的最快屬性。通常來說我們將線性屬性存儲(chǔ)中存儲(chǔ)的屬性稱為。因此也支持所謂的屬性。整數(shù)索引屬性的處理和命名屬性的復(fù)雜性相同。 本文為譯文,原文地址:http://v8project.blogspot.com...,作者,@Camillo Bruni ,V8 JavaScript Engine Team Blog 在這篇博客中,我們想解釋 V8 如何在內(nèi)部處理 JavaScrip...

    Andrman 評(píng)論0 收藏0
  • 【前端進(jìn)階之路】內(nèi)存基本知識(shí)

    摘要:在運(yùn)行腳本時(shí),需要顯示的指定對(duì)象。大對(duì)象區(qū)每一個(gè)區(qū)域都是由一組內(nèi)存頁構(gòu)成的。這里是唯一擁有執(zhí)行權(quán)限的內(nèi)存區(qū)。換句話說,是該對(duì)象被之后所能回收到內(nèi)存的總和。一旦活躍對(duì)象已被移出,則在舊的半空間中剩下的任何死亡對(duì)象被丟棄。 內(nèi)存管理 本文以V8為背景 對(duì)之前的文章進(jìn)行重新編輯,內(nèi)容做了很多的調(diào)整,使其具有邏輯更加緊湊,內(nèi)容更加全面。 1. 基礎(chǔ)概念 1.1 生命周期 不管什么程序語言,內(nèi)存...

    Simon_Zhou 評(píng)論0 收藏0
  • Node - 內(nèi)存管理和垃圾回收

    摘要:的內(nèi)存限制和垃圾回收機(jī)制內(nèi)存限制內(nèi)存限制一般的后端語言開發(fā)中,在基本的內(nèi)存使用是沒有限制的。的內(nèi)存分代目前沒有一種垃圾自動(dòng)回收算法適用于所有場景,所以的內(nèi)部采用的其實(shí)是兩種垃圾回收算法。 前言 從前端思維轉(zhuǎn)變到后端, 有一個(gè)很重要的點(diǎn)就是內(nèi)存管理。以前寫前端因?yàn)橹皇窃跒g覽器上運(yùn)行, 所以對(duì)于內(nèi)存管理一般不怎么需要上心, 但是在服務(wù)器端, 則需要斤斤計(jì)較內(nèi)存。 V8的內(nèi)存限制和垃圾回收機(jī)...

    joyqi 評(píng)論0 收藏0
  • JavaScript 堆內(nèi)存分析新工具 OneHeap

    摘要:關(guān)注于運(yùn)行中的內(nèi)存信息的展示,用可視化的方式還原了,有助于理解內(nèi)存管理。背景運(yùn)行過程中的大部分?jǐn)?shù)據(jù)都保存在堆中,所以性能分析另一個(gè)比較重要的方面是內(nèi)存,也就是堆的分析。上周發(fā)布了工具,可以用來動(dòng)態(tài)地展示的結(jié)果,分析各種函數(shù)的調(diào)用關(guān)系。 OneHeap 關(guān)注于運(yùn)行中的 JavaScript 內(nèi)存信息的展示,用可視化的方式還原了 HeapGraph,有助于理解 v8 內(nèi)存管理。 ...

    zilu 評(píng)論0 收藏0
  • 2017文章總結(jié)

    摘要:歡迎來我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動(dòng)及頁面渲染優(yōu)化理論寫法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁瞬開緩存網(wǎng)頁性能管理詳解寫給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁面渲染優(yōu)化 理論 | HTML寫法...

    dailybird 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<