Methods and Initializers

1 Method Declarations

这回不从comipler开始,从runtime开始。

GC也需要follow

接下来难点在于如何填充这些表

2 Compiling method declarations

难点:

一个类可以声明任意数量的方法。运行时需要查找并绑定所有这些方法。如果将这些方法都打包到一条 OP_CLASS 指令中,工作量会非常大。

解决方案

编译器会发出一条 OP_CLASS 指令,创建一个新的空 ObjClass 对象。然后,编译器会发出指令,将该类存储到一个带有其名称的变量中。

这里有点像Closure。 emit OP_CLOSURE后,把upvalue 的内容放到这个指令之后。

Method也是。和OP_METHOD是分开的指令。

3 定义Method

现在,对于每个方法声明,我们都会发出一条新的 OP_METHOD 指令,为该类添加一个方法。当所有 OP_METHOD 指令都执行完毕后,我们就得到了一个完整的类。在用户看来,类的声明是一个单一的atomic操作,而虚拟机则将其作为一系列mutation来实现。

3.1 具体实现

identifier 放到 constant里。把constant的index当做OP_METHOD的operand

function函数会 compile 函数parameters 还有body

然后emit ObjClosure

3.2 去哪找class?然后bind method?

Class的定义可能在stack上,可能在global。

因此

编译时记录下class的名字

当编译method以前,先将这个class 调出来放到栈上,namedVariable可以来做这件事情

----

defineVariable也会做这件事(global),但是下一章这两个call之间有东西,所以不这么干

----

所以编译完method后要pop出来那个class

3.3 给一个例子

回头看下为什么OP_CLOSURE之后会pop出来

-----

这OP_CLOSURE 会把function 放到stack。

OP_METHOD会把Closure pop出来?

右侧是执行完左侧后 stack的样子。

-----

3.4 运行时,OP_METHOD

之后会把closure pop出来。

4 Method References

两种情况都要支持

4.1 第一步

需要用“.”来得到method

但要记住,这里需要bind instance的state

举例,这里应该打出来 jane

jlox中,用的是heap allcoated Environment class。

但是clox,有临时变量在stack,还有在global的table中的,还有在closure的upvalue。

所以需要一个新的class

5 Bound Method(来自 CPython)

receiver 其实只能是ObjInstance。但是这里为了兼容更多函数,所以用了这个

配套代码

这样可以确保method句柄在内存中保留receiver,以便以后调用句柄时仍能找到对象。我们还会跟踪method closure。

隐藏实现,所以类似打印function

这是最后一个runtime Obj tyep 牛逼

6 Accessing Methods

改下OP_GET_PROPERTY 

---

原来的

----

具体,先找method,如果不在就报错。

如果有,就bind method

然后把instance pop 出去,把method放到栈上。

7 bind 的例子

把instance 和 ObjClosure 结合

8 Calling Method 

---

---

目前可以run这样的函数了

但是目前没有用instance 的状态

8 使用This

把这个this 当作局部变量,这样可以复用很多处理。closure也可以用

false的意思是 是不是canAssign 。这里永远是false。

variable函数不在乎this 有自己的token 或者不是identifier

要考虑instance 什么时候要进入到memory

至少要在capture closure 以前,clox把所有local variable 在stack上。

每个参数会给自己在stack上有个占位。empty string

那个位置是为method留着的。那里会存this ,也就是instance

这个例子

应该打印 Nested instance

8.1 为此添加

runtime的时候, receiver不在slot zero。要这样修一下,那里原来是什么?

如果是call 的话, 那里原来是 fn function。现在换成了instance

8.2 this 的错误使用

全局放个currentClass

这个类用于 放完nearest enclosing function 又来看继承

我们创建一个链表,用来串起来所有nest class

编译class时,会隐式的把当前的放到linked stack上

这个classCompiler或者C的stack上。

结束时,pop他,c 会自动回收他

这里就可以检查是否在class 里面了。

9 Instance Initializers

对initializer的要求

大概这个逻辑

9.1 invoke initializer

例子

init() 方法的新 CallFrame 共享该堆栈窗口,因此这些参数会隐式地转发给初始化器。

init()后面时"egg" 还有“coffee”

如果没有定义init函数,但是传进了参数,就报错

因为每次创建instance 都要找init ,所有就提前创建这个string,就可以用intern string了

这里有个潜在的bug就是copyString 可能调用GC,这时访问他就挂了。

所以要给个初值。

9.2 initializer return values

确保initializer 会返回新的instance,而不是nil或者其他东西。

只要初始化方法返回,用户调用类创建实例的过程就会结束,并在堆栈中留下初始化方法的任何值。这意味着,除非用户在初始化方法的末尾加上 return this;,否则不会有实例产生。这并不是很有用。

为了解决这个,单独为initializer设置一个类型。单独处理。

9.3 Incorrect returns ini initializers

防止他提前返回

10 Optimized Invocations

method invocation= accessing the method + calling the result

现状支持

 但是效果不好

但是,总是将这些操作作为单独的操作执行会带来很大的代价。每次 Lox 程序访问和调用一个方法时,运行时堆都会分配一个新的 ObjBoundMethod,初始化其字段,然后再将其拉出。之后,GC 必须花费时间释放所有这些短暂的绑定方法。ObjBoundMethod 不用每次都new 吧

实际上,Compiler可以看到访问method 然后立即call it

所以可以有个单独的指令 来完成这两个操作

---

如果看下bytecode的运行情况,发现有很多OP_XXX都是成组重复出现。

可以把这些instruction组合起来,叫superinstruction 

影响表现表现最大的overhead之一,就是decoding and dispatching each instruction

还不能加太多instruction,否则可能decoding变慢。

----

10.1 代码这样改

OP_INVOKE  有两个operand

  1. The index of the property name in the constant table.

  2. The number of arguments passed to the method.

假设invoke成功,最后更新frame

invoke()函数,先得到instance。要检查下。

但是好像并没有bind?

这里都不用bind。因为receiver and method都在正确的位置,之后举个例子

快了好多,10s能够call的次数

10.2 如果是field 有点问题

这里和invoke处理的稍微不同。这里的. 是access field。这个filed 被赋值为一个函数。这个field本身不是method。

---

有时有些错误,但是算的很快也可以接受。这是Monte Carlo algorithms.

---

这样修改

在找method之前,先找field。

如果找到了,就把他放到receiver的位置。因为他不是medthod,所以不要instance。

invoke的总结

11 language design

 I believe this is one of the fundamental balancing acts of language design: similarity to other languages lowers learning cost, while divergence raises the compelling advantages.

novelty budget, idiosyncrasy credit,

作者牛逼

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/62332.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

飞飞5.4游戏源码(客户端+服务端+工具完整源代码+5.3fix+5.4patch+数据库可编译进游戏)

飞飞5.4游戏源码(客户端服务端工具完整源代码5.3fix5.4patch数据库可编译进游戏) 下载地址: 通过网盘分享的文件:【源码】飞飞5.4游戏源码(客户端服务端工具完整源代码5.3fix5.4patch数据库可编译进游戏) 链…

开源C代码之路:一、Gitee

开源c代码之路:一,Gitee 前言1、开源项目2、从哪里找?3、举个例子4、总结: 本系列回顾清单开源代码示例 前言 从开源开发的角度,由浅入深,一步步初探C语言编程的入门之路。 本篇讲解:Gitee 1…

基于协同过滤算法的宠物用品商城的设计与实现(计算机毕业设计)Java Spring 衍生为任何商城系统 毕业论文

系统合集跳转 源码获取链接 一、系统环境 运行环境: 最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 IDE环境: Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以 tomcat环境: Tomcat 7.x,8.x,9.x版本均可 操作系统…

算法-字符串-165.比较版本号

一、题目 二、思路解析 1.思路: 比较的是两个版本号它们以“.”作为分割的部分的有效值(即数值)是否一致 2.常用方法: 1.s.split("\\规则"),将字符串按参数规则进行分割并存储在字符串数组中 String[] str …

MySQL(四)--索引

MySQL的服务器,本质是在内存中的,那么所有对数据的CURD操作,全都是在对内存进行操作。 而,提高数据的CURD操作的效率,有两种方式:1、组织数据的格式(数据结构);2、算法。 而,数据结构,就是索引,即组织数据的格式。 1、没有索引的问题 索引:提高数据库的性能,索…

C# (WinForms) 使用 iTextSharp 库将图片转换为 PDF

iTextSharp简介 iTextSharp 是一个开源的 .NET 库,主要用于创建和操作 PDF 文档。它是 iText 的 .NET 版本,iText 是一个广泛使用的 Java 库。iTextSharp 继承了 iText 的核心功能并进行了适应 .NET 平台的调整。 iTextSharp 的主要功能包括&#xff1a…

【中间件开发】Redis基础命令详解及概念介绍

文章目录 前言一、Redis相关命令详解及原理1.1 string、set、zset、list、hash1.1.1 string1.1.2 list1.1.3 hash1.1.4 set1.1.5 zset 1.2 分布式锁的实现1.3 lua脚本解决ACID原子性1.4 Redis事务的ACID性质分析 二、Redis协议与异步方式2.1 Redis协议解析2.1.1 redis pipeline…

学习记录,正则表达式, 隐式转换

正则表达式 \\:表示正则表达式 W: 表示一个非字(不是一个字,例如:空格,逗号,句号) W: 多个非字 基本组成部分 1.字符字面量: 普通字符:在正则表达式中,大…

Selenium是广泛使用的模拟浏览器运行的库

简介 Selenium是广泛使用的模拟浏览器运行的库,它是一个用于Web应用程序测试的工具。 Selenium测试直接运行在浏览器中,就像真正的用户在操作一样,并且支持大多数现代 Web 浏览器。 环境 安装 pip install selenium下载Chrome驱动 系统环境…

网络练级宝典-> UDP传输层协议

目录 传输层 端口号 端口号和进程的关系 UDP协议 UDP协议格式 UDP数据封装: UDP数据分用: 面向数据报 UDP的缓冲区 UDP的缺点 基于UDP的应用层协议 传输层 端口号 我们知道端口号对应的其实就是一个进程的pid,在操作系统中二者的…

Redis原理—1.Redis数据结构

大纲 1.Redis的数据结构 2.Redis的SDS 3.Redis的链表 4.Redis的字典 5.Redis的跳跃表 6.Redis的整数集合 7.Redis的压缩列表 8.Redis的对象 9.Redis对象的几个关键属性 10.Redis的单线程为什么这么快 11.Redis的典型应用场景和说明 12.Redis的相关命令说明 1.Redis…

【Vue3中Router使用】

Vue3中Router使用 1. 安装vue-router组件2. 建两个测试页面2.1 测试页面Home.vue2.2 测试页面Category.vue 3. 创建路由对象4. 在入口main.js中引入router把App.vue改成路由页面5. 测试5.1 关闭检查解决ESlint报错5.2 改文件名解决ESlint检查报错测试WebHashHistory 和WebHisto…

python拆分Excel文件

按Sheet拆分Excel 或 按照某一列的不同值拆分Excel。文档样式如下: 结果:红色是按照Sheet名拆出的,蓝色和橙色是某个Sheet按照某列的不同值拆分的。 代码: # -*- coding: utf-8 -*- """ 拆分excel文件——按照…

交易所 Level-2 历史行情数据自动化导入攻略

用户部署完 DolphinDB 后,需要将历史股票数据批量导入数据库,再进行数据查询、计算和分析等操作。DolphinDB 开发了 ExchData 模块,主要用于沪深交易所 Level-2 行情原始数据的自动化导入,目前已支持的数据源包括: 沪…

开源ISP介绍(2)————嵌入式Vitis搭建

Vivado搭建参考前一节Vivado基于IP核的视频处理框架搭建: 开源ISP介绍(1)——开源ISP的Vivado框架搭建-CSDN博客 导出Hardware 在vivado中导出Hardware文件,成功综合—实现—生成比特流后导出硬件.xsa文件。(注意导…

109.【C语言】数据结构之二叉树层序遍历

目录 1.知识回顾 2.代码实现 准备工作 LevelOrder函数 代码框架 关键代码 3.执行结果 1.知识回顾 层序遍历参见106.【C语言】数据结构之二叉树的三种递归遍历方式文章 截取的部分内容 定义:按层的方式遍历(,设n为树的深度,h1-->h2-->h3-->...-->hn) 以下面…

安装部署PowerDNS--实现内网DNS解析

PDNS是PowerDNS的缩写,是一个开源的DNS服务器软件。PowerDNS具有高性能、灵活性和可扩展性,可用于搭建各种规模的DNS解析服务。它支持多种后端数据库(如MySQL、PostgreSQL等),提供高度定制化的配置选项,并具…

13.在 Vue 3 中使用OpenLayers加载鹰眼控件示例教程

在 WebGIS 开发中,鹰眼控件 是一个常用的功能,它可以为用户提供当前地图位置的概览,帮助更好地定位和导航。在本文中,我们将基于 Vue 3 的 Composition API 和 OpenLayers,创建一个简单的鹰眼控件示例。 效果预览 在最…

Elasticsearch 单节点安全配置与用户认证

Elasticsearch 单节点安全配置与用户认证 安全扫描时发现了一个高危漏洞:Elasticsearch 未授权访问 。在使用 Elasticsearch 构建搜索引擎或处理大规模数据时,需要启用基本的安全功能来防止未经授权的访问。本文将通过简单的配置步骤,为单节…

使用C#基于ADO.NET编写MySQL的程序

MySQL 是一个领先的开源数据库管理系统。它是一个多用户、多线程的数据库管理系统。MySQL 在网络上特别流行。MySQL 数据库可在大多数重要的操作系统平台上使用。它可在 BSD Unix、Linux、Windows 或 Mac OS 上运行。MySQL 有两个版本:MySQL 服务器系统和 MySQL 嵌入…