国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

V8 Object 內存結構與屬性訪問詳解

loonggg / 2885人閱讀

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

V8 Object 內存結構與屬性訪問詳解從屬于筆者的Web 前端入門與工程實踐,推薦閱讀2016-我的前端之路:工具化與工程化。更多關于 JavaScript 引擎文章參考這里。

V8 Object 內存結構與屬性訪問

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

在 V8 中新分配的 JavaScript 對象結構如下所示:

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

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

[ 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 會轉回到傳統(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:屬性名

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

obj.prop
obj["prop"]

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

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屬性的對象而已,length會返回當前最大下標加一的結果(此時字符串下標會被轉化為數(shù)值類型計算):

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

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

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

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

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í)行結果如下:

// Babel 下結果
385
37
49
// Chrome 下結果
416
32
31

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

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

當我們執(zhí)行new Point(x,y)語句時,V8 會創(chuàng)建某個新的Point對象。創(chuàng)建的過程中,V8 首先會創(chuàng)建某個所謂C0的隱藏內部類,因為尚未為對象添加任何屬性,此時隱藏類還是空的:

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

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

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

更新C1為其添加轉換信息,即當為Point對象添加屬性 y 時,應該轉換到隱藏類 C2


整個過程的偽代碼描述如下:



  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:重復使用的隱藏類

我們在上文中提及,如果每次添加新的屬性時都創(chuàng)建新的隱藏類無疑是極大的性能浪費,實際上當我們再次創(chuàng)建新的Point對象時,V8 并不會創(chuàng)建新的隱藏類而是使用已有的,過程描述如下:

初始化新的Point對象,并將隱藏類指向C0

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

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

另外我們在上文以鏈表的方式描述轉換,實際上真實場景中 V8 會以樹的結構來描述轉換及其之間的關系,這樣就能夠用于類似于下面的屬性一致而賦值順序顛倒的場景:

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

JavaScript 中并沒有類的概念(語法糖除外),因此對于方法的調用處理會難于 C++ 或者 Java。下面這個例子中,distance方法可以被看做Point的普通屬性之一,不過其并非原始類型的數(shù)據(jù),而是指向了另一個函數(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屬性,那么無疑會帶來較大的內存浪費,畢竟每個對象都要存放一段外部函數(shù)引用(Reference 的內存占用往往大于原始類型)。C++ 中則是以指向多個虛函數(shù)的虛函數(shù)表(V-Tables)解決這個問題。每個包含虛函數(shù)的類的實例都會指向這個虛函數(shù)表,當調用某個虛函數(shù)時,程序會自動從虛函數(shù)表中加載該函數(shù)的地址信息然后轉向到該地址調用。V8 中我們已經使用了隱藏類這一共享數(shù)據(jù)結構,因此可以很方便地改造下就可以。我們引入了所謂 Constant Functions 的概念,某個 Constant Function 即代表了對象中僅包含某個名字,而具體的屬性值存放在描述符本身的概念:



  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ù),那么這個轉換也會自動失效,V8 會創(chuàng)建新的隱藏類。另一種解決這個問題的方法就是使用原型,每個構造函數(shù)都會有所謂的Prototype屬性,該屬性會自動成為對象的原型鏈上的一環(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 同樣會把原型鏈上的方法在隱藏類中映射為 Constant Function 描述符,而調用原型方法往往會比調用自身方法慢一點,畢竟引擎不僅要去掃描自身的隱藏類,還要去掃描原型鏈上對象的隱藏類才能得知真正的函數(shù)調用地址。不過這個不會對于代碼的性能造成明顯的影響,因此寫代碼的時候也不必小心翼翼的避免這個。

Dictionary Mode

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

// 插入
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

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

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

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

Fast small integers

Fast doubles

Fast values

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

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

    // 這會大大降低大數(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ù)組退化為字典模式,也不會影響到其他屬性的訪問速度(反之亦然)。

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);
 };           
               
                                           
                       
                 
            
                     
             
               

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

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81320.html

相關文章

  • V8 中的 Fast 屬性

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

    Andrman 評論0 收藏0
  • 【前端進階之路】內存基本知識

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

    Simon_Zhou 評論0 收藏0
  • Node - 內存管理和垃圾回收

    摘要:的內存限制和垃圾回收機制內存限制內存限制一般的后端語言開發(fā)中,在基本的內存使用是沒有限制的。的內存分代目前沒有一種垃圾自動回收算法適用于所有場景,所以的內部采用的其實是兩種垃圾回收算法。 前言 從前端思維轉變到后端, 有一個很重要的點就是內存管理。以前寫前端因為只是在瀏覽器上運行, 所以對于內存管理一般不怎么需要上心, 但是在服務器端, 則需要斤斤計較內存。 V8的內存限制和垃圾回收機...

    joyqi 評論0 收藏0
  • JavaScript 堆內存分析新工具 OneHeap

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

    zilu 評論0 收藏0
  • 2017文章總結

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

    dailybird 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<