范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Chrome系列深入理解V8V8如何实现Object?

  JavaScript 对象是一组属性(properties)和元素(elements)。 出于性能和内存的原因,V8 设计了几种不同的属性表示形式,例如对象内(in-object)、慢速属性(slow property)和自字典(self-dict)。 在本章中,让我们更深入地研究 JavaScript 对象。 1.JavaScript 对象布局
  下面的图 1 显示了一个基本的 JavaScript 对象在内存中的样子。
  元素和属性存储在两个独立的数据结构中,这使得添加和访问属性(property)或元素(elements)对于不同的使用模式更加高效。
  元素主要用于各种 Array.prototype 方法,例如 pop 或 slice。 鉴于这些函数访问连续范围内的属性,V8 内部大多数情况下也将它们表示为简单数组。
  命名属性以类似的方式存储在单独的数组中。 然而,与元素不同的是,我们不能简单地使用键来推断它们在属性数组中的位置; 我们需要一些额外的元数据。  在 V8 中,每个 JavaScript 对象都有一个关联的 HiddenClass。 HiddenClass 存储关于对象详情的信息,以及从属性名称到属性值的映射 。
  在图 2 中,有元素(elements)、属性(propertis)和对象内(in-object)属性。 与元素或属性不同,对象内属性存储在对象本身中,这意味着您可以直接访问它们而无需映射。 in-object 的数量是在创建 JavaScript 对象时分配的(不同 V8 版本数量可能不一样)。
  在图 3 中,存在三种不同的命名属性类型:in-object、fast/slow dictionary。 对象内属性直接存储在对象本身并提供最快的访问方式 Fast 属性存在于属性存储中,所有元信息都存储在 HiddenClass 的描述符数组中 慢速属性存在于一个独立的属性字典中,元信息不再通过 HiddenClass 共享
  图 4 显示了 JavaScript 对象内存布局,所有 V8 托管堆对象都必须有一个存储在首地址的映射指针。 当然,也有元素和属性。 描述符是 map 中的一个重要成员,它负责描述一个对象的属性,这个我们以后会讲到。
  在下面的例子中,sayname 是一个等同于 console.log 的函数。这里可以想一个问题:一个对象的函数存储在哪里? 即,sayname 在哪里? 1.  function person(name) { 2.      this.name=name; 3.  	this.sayname=function(){console.log(this.name);} 4.  } 5.  worker = new person("Nicholas"); 6.  worker.sayname(); 7.  //separation........................................ 8.  //separation........................................ 9.  Bytecode Age: 0 10.           000001DAA2FA1E96 @    0 : 13 00             LdaConstant [0] 11.           000001DAA2FA1E98 @    2 : c2                Star1 12.           000001DAA2FA1E99 @    3 : 19 fe f8          Mov , r2 13.      0 E> 000001DAA2FA1E9C @    6 : 64 51 01 f9 02    CallRuntime [DeclareGlobals], r1-r2 14.    100 S> 000001DAA2FA1EA1 @   11 : 21 01 00          LdaGlobal [1], [0] 15.           000001DAA2FA1EA4 @   14 : c2                Star1 16.           000001DAA2FA1EA5 @   15 : 13 02             LdaConstant [2] 17.           000001DAA2FA1EA7 @   17 : c1                Star2 18.           000001DAA2FA1EA8 @   18 : 0b f9             Ldar r1 19.    109 E> 000001DAA2FA1EAA @   20 : 68 f9 f8 01 02    Construct r1, r2-r2, [2] 20.    107 E> 000001DAA2FA1EAF @   25 : 23 03 04          StaGlobal [3], [4] 21.    134 S> 000001DAA2FA1EB2 @   28 : 21 03 06          LdaGlobal [3], [6] 22.           000001DAA2FA1EB5 @   31 : c1                Star2 23.    141 E> 000001DAA2FA1EB6 @   32 : 2d f8 04 08       LdaNamedProperty r2, [4], [8] 24.           000001DAA2FA1EBA @   36 : c2                Star1 25.    141 E> 000001DAA2FA1EBB @   37 : 5c f9 f8 0a       CallProperty0 r1, r2, [10] 26.           000001DAA2FA1EBF @   41 : c3                Star0 27.    151 S> 000001DAA2FA1EC0 @   42 : a8                Return 28.  Constant pool (size = 5) 29.  000001DAA2FA1E29: [FixedArray] in OldSpace 30.   - map: 0x024008ac12c1  31.   - length: 5 32.             0: 0x01daa2fa1d11  33.             1: 0x01daa2fa1c09  34.             2: 0x01daa2fa1c39  35.             3: 0x01daa2fa1c21  36.             4: 0x01daa2fa1c51 
  第一部分是 JavaScript 代码,最后是相应的字节码。第 19-21 行使用 person 对象构造一个名为 worker 的实例,第 23 行加载名称为 sayname 的属性。
  你了解 line23 吗? 它告诉我们 sayname 只是一个属性,与其类型无关。 如果再深入一点,您会发现 console 和 log 也是属性。
  因此, 在 JavaScript 对象中,所有函数都被视为属性(property) 。 2.实例化 一个 JavaScript 对象
  为了调试上述代码,我们将单步执行以下代码: 1.  RUNTIME_FUNCTION(Runtime_NewObject) { 2.    HandleScope scope(isolate); 3.    DCHECK_EQ(2, args.length()); 4.    CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0); 5.    CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1); 6.    RETURN_RESULT_OR_FAILURE( 7.        isolate, 8.        JSObject::New(target, new_target, Handle::null())); 9.  } 10.  //separation..................................... 11.  MaybeHandle JSObject::New(Handle constructor, 12.                                      Handle new_target, 13.                                      Handle site) { 14.    Isolate* const isolate = constructor->GetIsolate(); 15.    DCHECK(constructor->IsConstructor()); 16.    DCHECK(new_target->IsConstructor()); 17.    DCHECK(!constructor->has_initial_map() || 18.           !InstanceTypeChecker::IsJSFunction( 19.               constructor->initial_map().instance_type())); 20.    Handle initial_map; 21.    ASSIGN_RETURN_ON_EXCEPTION( 22.        isolate, initial_map, 23.        JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject); 24.    int initial_capacity = V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL 25.                               ? SwissNameDictionary::kInitialCapacity 26.                               : NameDictionary::kInitialCapacity; 27.    Handle result = isolate->factory()->NewFastOrSlowJSObjectFromMap( 28.        initial_map, initial_capacity, AllocationType::kYoung, site); 29.    isolate->counters()->constructed_objects()->Increment(); 30.    isolate->counters()->constructed_objects_runtime()->Increment(); 31.    return result; 32.  }
  RUNTIME_FUNCTION(Runtime_NewObject) 是我们在上一章中提到的一个 MACRO。它调用 JSObject::New() 来创建一个新对象, JSObject::New() 调用 JSFunction::GetDerivedMap() 来分配 map,在 JSFunction::GetDerivedMap() 中,将调用以下函数。 1.  void JSFunction::EnsureHasInitialMap(Handle function) { 2.    DCHECK(function->has_prototype_slot()); 3.    DCHECK(function->IsConstructor() || 4.           IsResumableFunction(function->shared().kind())); 5.    if (function->has_initial_map()) return; 6.    Isolate* isolate = function->GetIsolate(); 7.    int expected_nof_properties = 8.        CalculateExpectedNofProperties(isolate, function); 9.    if (function->has_initial_map()) return; 10.    InstanceType instance_type; 11.    if (IsResumableFunction(function->shared().kind())) { 12.      instance_type = IsAsyncGeneratorFunction(function->shared().kind()) 13.                          ? JS_ASYNC_GENERATOR_OBJECT_TYPE 14.                          : JS_GENERATOR_OBJECT_TYPE; 15.    } else { 16.      instance_type = JS_OBJECT_TYPE; 17.    } 18.    int instance_size; 19.    int inobject_properties; 20.    CalculateInstanceSizeHelper(instance_type, false, 0, expected_nof_properties, 21.                                &instance_size, &inobject_properties); 22.    Handle map = isolate->factory()->NewMap(instance_type, instance_size, 23.                                                 TERMINAL_FAST_ELEMENTS_KIND, 24.                                                 inobject_properties); 25.    Handle prototype; 26.    if (function->has_instance_prototype()) { 27.      prototype = handle(function->instance_prototype(), isolate); 28.    } else { 29.      prototype = isolate->factory()->NewFunctionPrototype(function); 30.    } 31.    DCHECK(map->has_fast_object_elements()); 32.    DCHECK(prototype->IsJSReceiver()); 33.    JSFunction::SetInitialMap(isolate, function, map, prototype); 34.    map->StartInobjectSlackTracking(); 35.  }
  第 7 行,返回构造函数期望的属性数,第 26 到 30 行生成原型,关键字 function 是一个构造函数。 在我们的例子中,函数是 person,原型为 null,因为 person 是第一次执行,所以第 29 行被执行。
  生成的原型与构造函数绑定,并为所有实例共享,这就是 V8 实现的原型原则。下面是在第 7 行中调用的 CalculateExpectedNofProperties。  int JSFunction::CalculateExpectedNofProperties(Isolate* isolate, 2.                                                 Handle function) { 3.    int expected_nof_properties = 0; 4.    for (PrototypeIterator iter(isolate, function, kStartAtReceiver); 5.         !iter.IsAtEnd(); iter.Advance()) { 6.      Handle current = 7.          PrototypeIterator::GetCurrent(iter); 8.      if (!current->IsJSFunction()) break; 9.      Handle func = Handle::cast(current); 10.      Handle shared(func->shared(), isolate); 11.      IsCompiledScope is_compiled_scope(shared->is_compiled_scope(isolate)); 12.      if (is_compiled_scope.is_compiled() || 13.          Compiler::Compile(isolate, func, Compiler::CLEAR_EXCEPTION, 14.                            &is_compiled_scope)) { 15.        DCHECK(shared->is_compiled()); 16.        int count = shared->expected_nof_properties(); 17.        if (expected_nof_properties <= JSObject::kMaxInObjectProperties - count) { 18.          expected_nof_properties += count; 19.        } else { 20.          return JSObject::kMaxInObjectProperties; 21.        } 22.      } else { 23.        continue; 24.      } 25.    } 26.    if (expected_nof_properties > 0) { 27.      expected_nof_properties += 8; 28.      if (expected_nof_properties > JSObject::kMaxInObjectProperties) { 29.        expected_nof_properties = JSObject::kMaxInObjectProperties; 30.      } 31.    } 32.    return expected_nof_properties; 33.  }
  第 28 行, MaxInObject 是 in-object 的最大数量,超过的属性存入 properties 列表 。下面图 5 显示了调用堆栈。
  参考资料
  https://javascript.plainenglish.io/lets-understand-chrome-v8-how-does-v8-implement-a-javascript-object-ddde32120bb5
  https://v8.dev/blog/fast-properties

男士网购服装,尺寸避坑指南网购已经不是什么稀奇的事情了,现在每一天中国的快递包裹已经超过了3亿件。但当网购涉及到服装时,仍然是一些男士的痛点。原因很简单,因为网上购买衣服时并不知道衣服实际上是否合身,或材质爱上美女街拍第110卷,动感身材太美了艺术来源于生活!美丽来源于生活!只有运动的女人才会有动感身材!每个女人都渴望自己有动感身材!每个男人都盼望自己的女人有动感身材。动感身材那么美,受欢迎是必然的。如果你对动感身材不太路易威登引领鞋履潮流风尚众所周知,LV是一家箱包起家的百年蓝血品牌,但是在百年的时间里LV也在不断开发探索成衣鞋履饰品等领域,用其高端和品质和卓越的品牌匠心不断地探索着时尚与艺术的边界,展现了当代的摩登潮穿来穿去,还是脚踝靴最显高显瘦,配裤子裙子都特好看每年的秋冬季节当中,真的会有一批又一批的经典鞋型被不少的时尚博主和女一人带上热门,这其中不乏有非常经典的短靴和长筒靴的搭配,而在今年最具热度的绝对是脚裸靴。靴子一类的鞋型穿来穿去其开衫总是那么受欢迎,长袖羊毛开衫教程,休闲舒适易穿搭春天很适合穿开衫,而且喜欢休闲风穿搭的,开衫是必不可缺的款式。今天我们来学习一款长袖羊毛开衫的钩法,示范用线为混色亮丝羊毛线(使用别的线如羊绒线或混纺线等都可以),7。0mm的钩针决战荷兰,阿根廷队需要做出的三点改变北京时间12月10日凌晨300,卡塔尔世界杯将迎来夺冠热门阿根廷队与欧洲劲旅荷兰队的一场四分之一决赛。回顾比赛历程,阿根廷队晋级世界杯八强之路并不平坦。首战12负于沙特自不必说,次辽篮逆转深圳,赵继伟化身隆多,桑普森大赞!二哥送上暖心祝福CBA第二阶段比赛继续火热进行,深圳男篮在一度领先辽宁男篮11分的情况下,被辽篮完成逆转,最终辽篮以10490战胜深圳,拿到三连胜!赢下深圳后,辽篮目前战绩为9胜2负,排名积分榜第再见,黄金一代死亡之组的故事相当精彩,但我今天想写写比利时黄金一代。是的,德布劳内领衔的欧洲红魔,在不断错失机会后战平了克罗地亚,小组赛就惨遭淘汰了。出局之时,他们排名世界第二。世界排名有时候当医圣治咽第一方半夏厚朴汤,行气化痰降逆,咽喉疾病一扫光你身边有这样的人吗?没事儿总是吭吭吭地清嗓子,时不时的总想找个地方吐痰,嗓子总有异物感不停的吞咽口水,张嘴说话嘴巴里总有很大的气味这些症状,是由于肝气郁结肺胃失于宣降,导致体内津液全市四类药品储备量可满足我市家庭用药需求大型连锁药店药品价格基本平稳全市四类药品储备量可满足我市家庭用药需求大型连锁药店药品价格基本平稳哈市市场监管部门采取四方面措施加大药品稳价力度目前,哈市退热止咳治感冒抗病毒四类相关药品供应储备情况如何?市场监膝盖肿痛就用六穴五针治疗,效果突出足阳明经内属于胃,外行于承泣至厉兑的缝隙中,通过足阳明经别加强了对脾胃的联系。素问灵兰秘典论曰脾胃者,仓禀之官,五味出焉。素问六节藏象论曰脾胃大肠小肠三焦膀胱者,仓禀之本。说明足阳
继社交软件之后,手游也将逐步开放IP属地展示功能?据雷霆游戏官网公告,为维护网络空间的健康秩序,防范网络诈骗恶意炒作散布谣言等违规行为,雷霆游戏平台将依据相关法律法规要求,在旗下部分游戏开放试行展示账号IP属地功能。日前,雷霆旗下终于用上超声波指纹!小米13相关配置曝光,光学指纹彻底说再见自三星在S10系列上用上超声波指纹之后,截止到目前为止跟进的厂商其实并不算太多,也就只有iQOO和魅族有几款产品在使用。而其他绝大多数的国产手机,依旧在使用传统的光学屏下指纹解锁。黑盘SSD新旗舰开售首次带来4TB西部数据今年5月份发布的SN850X黑盘SSD已经正式开卖,提供1TB2TB和4TB容量,价格分别是160美元310美元和700美元,1TB2TB额外需要散热装甲的话,还需多加20那些你绝对不知道的电视选购指南(一)电视不是易耗品,买回家起码要用个七八年,所以购买前一定要慎重。今天就跟大家聊聊电视选购要注意些什么。1。尺寸的选择坚持一个原则,买大不买小!选择电视时,大家要记得先测量一下观影距离努比亚红魔7s和红魔7区别是什么,哪个好努比亚红魔7s和红魔7区别包括在外观配色处理器散热三方面,至于红魔7s和红魔7哪个好,在性能配置上肯定是红魔7s要好一些,但是一般大型游戏它们都能很好运行,如果你追求更流畅的游戏体iOS16重大调整,史上首次众所周知,苹果一般会在每年9月举行秋季新品发布会,推出包括新旗舰iPhone在内的一系列新品。同时,在推出新iPhone后,此前在WWDC开发者大会上预览的iOSiPadOS新版本IP68防水5000mAh大电池2K曲面屏,比小米官方商城便宜1240元在世界500强排名中,小米已经上升到266位,是一家非常有实力的互联网科技公司,获得了很多用户的青睐,小米手机电视笔记本电脑和手环等都非常热销,以互联网方式做产品,用感动人心价格厚外媒腾讯欲购买更多育碧股份,成为育碧最大股东据路透社最新报道,中国游戏巨头腾讯欲购买更多育碧股份,成为育碧最大股东。路透社在报道中援引独立消息人士的话称,作为一家中国大型游戏制造商,腾讯希望放眼全球游戏市场,并有意增持法国游WBG迎来新一轮比赛,大安状态成关键,粉丝期待ON再次搞活LPL夏季赛的常规赛已经来到了末尾阶段,部分队伍早已锁定了季后赛席位,目前要做的事情还是要尽量保持状态,尽可能获得连胜,这样在季后赛的对决中获得更有利的排名,如果能够获得复活甲的话刘诗雯获新任命!重返广东后即刻上岗,手链曝光如今恋情状态近日,有球迷在机场看到了刘诗雯的身影,这位优秀的女乒球员,如今已经远离赛场,对此,球迷们非常的遗憾和无奈。刘诗雯实力强大,获得了五次世界杯单打比赛冠军,但是她始终没有获得奥运会单打LPL夏季赛首支水鬼战队出现,RA击溃LNG,线下赛网就是不卡前言S12赛季的比赛已经正式开始了,相信绝大多数的玩家都关注了最近一段时间的夏季赛,lpl赛区的对抗是非常激烈的,尤其是排名靠前的几支战队,都在争夺季后赛的复活甲。Lng战队作为大