美文网首页
JSCore运行时一些概念

JSCore运行时一些概念

作者: FingerStyle | 来源:发表于2020-03-28 18:31 被阅读0次

JS运行时

Share/Structure: JS对象所包含的属性集合的一个全局唯一标识,类似C语言里面的结构体。增加或减少属性会导致Shape的变化,Shape之间是有继承关系的(transition chains). Shape中保存了每个属性的offset, 使用Shape可以减少因为存储同样属性集合的变量所占用的内存,减少冗余数据,并且通过offset直接获取属性和方法,访问效率会更高。

内联缓存: 对一些经常查询的属性和方法对应的的Shape的offset进行缓存,在下次读取时跳过对shape的查找过程,直接定位属性。

对开发者的建议:
1.尽量以相同方式初始化对象,因为这样会生成较少的 Shapes。
2.不要混淆对象的 propertyKey 与数组的下标,虽然都是用类似的结构存储,但 JS 引擎对数组下标做了额外优化。
3.不要使用argument.callee.caller,这个会导致调用的参数类型和方法都不确定, JS引擎没办法做内联缓存优化
https://stackoverflow.com/questions/103598/why-was-the-arguments-callee-caller-property-deprecated-in-javascript

Shape如何获取:
LLInt 和 Baseline JIT 会从函数参数或者来自堆的读取来收集每个变量的值信息,根据这些信息来假设一个类型

关于数字类型的编码

参考:https://liveoverflow.com/the-butterfly-of-jsobject-browser-0x02/

Pointer { 0000:PPPP:PPPP:PPPP
/ 0001:****:****:****
Double { ...
\ FFFE:****:****:****
Integer { FFFF:0000:IIII:IIII

False: 0x06
True: 0x07
Undefined: 0x0a
Null: 0x02

JS 的 Number 在生成时,会把值编码到它的地址里,解析时也是靠解码地址来解值,可以自己实现这个过程避免 JSLock,除此之外 JS 里的 undefined,null 都是固定值。TypedArray 也有个好处,初始化后它底层的地址不会改变,可以靠地址偏移还高效去数据。 类似iOS 的tagged number 。每一种类型的number都有固定的地址区间,不会重叠(通过前面几位来标识),这也导致了只有53个bit可以用来表示数字,当js数字超过16位(2^53)时,就会丢失精度。

因为 JSNumber 不会被 GC,且传递相对高效,只需要编解码地址,所以 JSObject 我们可以设置一个 JSNumber 作为句柄,JS 和 Native 靠这个句柄从缓存中取对象,不用经过 JS 虚拟机。
RN里面js和native交互使用了number类型作为moduleID,而不是string类型,应该也是有这方面的考虑。

关于js的定时器和promise

定时器没找到源码,应该是通过把回调函数(microtask)添加到异步队列中(通过runloop的timer事件唤醒),在同步队列执行完成后执行的

promise:采用于timer类似的方式放到异步队列中,只是不定时

JavaScriptCore runtime类说明

VM : JS虚拟机,超级大的一个对象,解释并执行JS,被globalObject所引用,也引用了很多其他对象(如调用栈的栈顶、最近一次的异常、入口作用域、运行循环、字节码的缓存等)

methodTable 一个结构体,里面定义了很多函数指针, 可以获取和操作js对象里面的属性、方法

classInfo 一个结构体,里面有类名、父类的指针、方法表等

JSCell Structure和JSObject的基类,对methodTable和classInfo的一些封装

JSObject 表示一个js的对象,继承自JSCell,实现了很多js对象的基本操作方法

Structure 表示JS对象的结构,类似V8中的Shape,用来快速查找对象的属性,属性不一样,structure ID也不一样

Bufferfly JS对象的封装,其结构为各种属性(第一个是structureId)+ 长度+ 内部元素, 其指针指向的不是结构体开始的地址,而是中间的地址(内部元素开始的位置)

StringObject、NumberObject、JSFunction,JSArray 等等: 对JS里面相应类型变量的封装, 里面有一些操作Object的方法如: defineOwnProperty ,put ,create, getOwnPropertyDescriptor等

ArrayProtoType/StringProtoType等:对JS标准库函数的实现,比如array的reverse(),string 的split()

LiteralParser : 对JSON的解析

JSWarpperValue : JS包装对象,如StringObject、NumberObject、BooleanObject、BitIntObject,是对原始类型的封装

JSONObject: JSON对象,实现了stringify方法,里面会对JS包装对象解包,转成对应字符串,注意bigInt不能被转换

ObjcCallbackFunction: 通过runtime把OC的方法转成JS的方法

TypedArray: 把js Array中的 number类型的数据转成了float、int 、uint等类型,跟原生的数据类型对应

Inspector:用来调试用的,即safari的debug功能
eventLoop : 事件循环,对应于iOS的runloop

CodeBlock: 代码片段,是函数体经过词法、语法解析后生成的字节码集合

==================调用栈相关==================
ScriptCallStack: 普通的JS调用栈,用vector容器保存了最多200个栈帧(ScriptCallFrame)

ScriptCallStackFactory: 调用栈的工厂类,包含了4种调用栈:普通调用栈、console用的调用栈、异常调用栈、脚本参数。 异常调用栈的信息基本都从异常对象(JSC::Exception)中获取

ScriptCallFrame: JS栈帧,里面有行号、列号、函数名测、脚本名称等信息 ,可以转换为CallFrame类型

CallFrame: 原始的栈帧,继承于Register. 里面包含了作用域(scope)、调用者(callee)的引用。内部有一个结构体CallerFrameAndPC,包含了调用者的栈帧(callerFrame)和返回值的地址(returnPC),以及对应的寄存器数量

CallFrameShuffler: 不知道怎么翻译,看源码主要是用来生成栈帧的, 根据调用函数前保存调用者地址、变量等到虚拟寄存器,调用完成后再从虚拟寄存器恢复地址。虚拟寄存器分为两类:
1.FPR: 函数参数域(Function Parameter Register), 这个区域的大小是变化的,当调用者传递给被调用者的参数少于8个时,用GPR3-GPR10这8个寄存器就行,被调用者的栈帧中就可不要这个区域;但如果传递的参数多于8个时就需要这个区域。
2.GPR:通用寄存器(General Parameter Register),当需要保存GPR寄存器中的一个寄存器GPRx时,就需要把从GPRx-GPR31的值都保存到堆栈帧中。
可以看出,大部分情况使用的是GPR。
关于栈帧的结构,可以看这个 https://www.cnblogs.com/qinfengxiaoyue/p/3523166.html
生成栈帧有两个方法:尾调用(prepareForTailCall)和 常规调用( prepareForSlowPath)。
prepareForTailCall 就是正常的往栈顶扩展,不会覆盖调用者的栈帧。但是prepareForSlowPath 会恢复保存调用者的寄存器(callee save registers),当前帧的局部变量也会被覆盖。

相关文章

  • JSCore运行时一些概念

    JS运行时 Share/Structure: JS对象所包含的属性集合的一个全局唯一标识,类似C语言里面的结构体...

  • iOS-RunTime介绍及使用

    一、RunTime概念 RunTime简称运行时,我们总是听说OC是动态语言运行时机制,也就是系统在运行时候的一些...

  • Weex和React Native的异同

    JS引擎: weex使用安卓V8,iOS使用JSCore, React Native使用JSCore JS开发框架...

  • iOS JSCore的一些思考

    JSCore的头文件中 有一些面向C的类和函数 原生值转换JS

  • JSCore

    JSCore 简单描述 JSCore是专门用来解释和执行JS代码,可以直接使用OC代码执行一段JS代码 JSPat...

  • JSCore运行时(三)- async函数与Generator

    我们都知道ES7里面async函数内部是用generator实现的,而generator实现起来大概是这样,有一个...

  • 安卓基础知识

    在了解 Android 运行时之前,我们需要了解什么是运行时环境以及一些基本概念,即 Java 虚拟机(JVM)和...

  • 扒一扒 Android 运行时: DVM vs ART

    在了解 Android 运行时之前,我们需要了解什么是运行时环境以及一些基本概念,即 Java 虚拟机(JVM)和...

  • 【小程序】数据绑定

    【小程序】笔记内容声明及汇总 小程序的脚本逻辑运行在 JSCore 中,JSCore 是没有 DOM 的环境,它完...

  • 自动内存管理机制

    一些概念 方法区:与java堆一样。。。运行时常量池: 直接内存:

网友评论

      本文标题:JSCore运行时一些概念

      本文链接:https://www.haomeiwen.com/subject/rmusuhtx.html