摘要

  • Adele Goldberg 与 David Robson 在 1983 年出版的“蓝皮书”划出了 Smalltalk-80 虚拟镜像与各主机虚拟机之间的接口:对象内存、字节码、执行上下文、消息派发和原语。
  • Goldberg 没有让规范只接受内部审阅。Apple、DEC、Hewlett-Packard 与 Tektronix 真正实施移植,把差异反馈给 Xerox PARC,并用参考执行轨迹检验行为。
  • 这项工作证明的是特定边界上的可移植性,而不是主机之间的全面等效。吞吐、停顿、字体度量、窗口规则、输入设备、文件系统和交互手感仍由各自实现控制。

一份必须真正启动的规范

Smalltalk-80 不只是能由语法定义的编程语言。它是一个持续存在的工作环境:类、编译器、浏览器、调试器、图形和界面都以对象的形式生活在同一份镜像里。把它移到另一台计算机上,迁移的是整个对象世界,而不是让另一个编译器接受几段源代码。

Goldberg 与 Robson 在 Smalltalk-80: The Language and Its Implementation 中提出的办法,是把系统切成两层。虚拟镜像保存系统对象和高层工具;主机专用的虚拟机在下方提供解释器、对象内存,以及连接算术、存储、显示器、指点设备和文件的原语。源方法编译为紧凑的八位字节码,由栈式解释器执行;上下文对象记录正在进行的计算。

可移植性的交易因此十分明确:每一种硬件只需正确实现较小的底层内核,随后便可加载共享镜像。“蓝皮书”的价值不在于用文字替代软件,而在于把足够多的可观察行为说清楚,使外部团队能够重建缺失的底层,而不必依赖 PARC 内部的口耳相传。

Goldberg 又加上了一项更难的条件:规范够不够,不由原作者自己裁定,而要由别处的机器来回答。

外部移植团队就是测试装置

Goldberg 在 2010 年接受 Computer History Museum 口述史采访时回忆,她先取得了 Xerox 对全面发表的书面许可。随后在主管 Bert Sutherland 的支持下,她邀请 Tektronix、Hewlett-Packard、DEC 与 Apple 参与。规则要求公司内部的软件团队与硬件团队共同工作。要回答的问题不是“你是否喜欢这门语言”,而是“硬件的哪些特点会改变它的性能”。

后来收录在 Smalltalk-80: Bits of History, Words of Advice 中的发布记录给出了更细的过程。六家公司收到邀请,其中四家进入实际实现阶段。它们同意共享发现的规范错误与设计建议。Xerox 分批交付虚拟镜像、对象指针和对象空间说明、上下文、编译方法与类的资料;书面规范和运行结果发生冲突时,还可直接沟通。

于是,每一个移植版本都成了对文档的实验。在 Alto 或 Dorado 上不言自明的假设,一旦 DEC、HP、Tektronix 或 Apple 的工程师无法复现,就会暴露为没有写进契约的本地条件。不同硬件不是需要排除的噪声,恰恰是规范发现自身边界的工具。

四家企业也不是给成品盖章的见证人。实施期间,原语分配发生变化,镜像不断增长,首届 Smalltalk-80 实现者会议讨论了引用计数、垃圾回收与方法缓存。Goldberg 写道,早期书稿的大部分章节最终被丢弃重写;经多种实现调试过的虚拟机正式规范,才是值得保留的部分。

执行轨迹定义了“相符”到底指什么

屏幕看起来相似远远不够。Xerox 提供了几种精度不同的执行轨迹。最细的一种记录内存引用、分配、字节码、消息发送、返回与原语调用;较长的轨迹减少细节,覆盖更多执行。新虚拟机可以把自己的实际步骤与预期行为逐项比较。

这种检查与“蓝皮书”的分层接口相配。对象内存协议区分对象指针、字和字节访问;解释器必须按规则查找类与方法、创建上下文、维护栈、处理查找失败,并发送 doesNotUnderstand:。字节码分为压栈、存储、发送、返回与跳转;原语覆盖算术、数组和流、存储管理、控制、输入输出及系统功能。

图形最能显示接缝。一大部分 BitBlt、文本与画面组合逻辑存在于镜像对象中,但光标、键盘、位图显示器和文件最终要接触物理设备。原语在这里跨越边界。同一个镜像请求,可以由不同显示控制器、内存布局或机器指令完成。

成功标准因而是运行层面的,同时也是有限的:一台主机能够“读取并采用”虚拟镜像,并重现所要求的行为。到第四批镜像时,已经成功的实现可以不修改虚拟机便直接加载新镜像。这是接口趋于稳定的强证据,却不是所有机器已变成同一台机器的证据。

兼容止于体验等效之前

Goldberg 的发布记录把镜像采用与另一项更主观的指标分开:系统在各家公司硬件上的实际性能。共享镜像的确会产生惊人的连续性——同样的类存在,同样的方法能编译,同样的浏览器能打开。但体验仍受接口上下方与外围的一切影响。

方法查找可以采用不同缓存。内存回收可以依靠引用计数、追踪或混合方案。某个原语可以由微码实现,也可以是汇编或较慢的主机例程。调度和输入轮询会改变响应延迟。屏幕几何、位图布局、字体存储、光标设备与文件服务会改变显示和交互。两台正确的虚拟机可以保持对象语义一致,却出现完全不同的停顿和重绘速度。

字符集甚至留下了一个细小而清楚的妥协。Goldberg 回忆,因为参与方并不都能控制字体,项目被迫采用标准 ASCII。可移植性让更多机器加入,同时也把这个表达界面收窄到各主机能可靠共享的最低范围。

“蓝皮书”序言还坦率承认,当时以及近期计划中的硬件都不足以承载研究团队的全部交互目标。契约可以规定一次消息发送、一次返回或一次对象读取的意义,却不能让慢处理器拥有 Dorado 的感觉,不能扩大屏幕,也不能消除所有垃圾回收停顿。

这给今天留下了一条很实用的原则:兼容证据只能证明它实际观察的层。通过镜像加载与字节码轨迹,证明的是镜像/虚拟机接口相符;它不会自动证明时间特性、字体、窗口、外设或完整用户体验相同。

发布的是一组互相补充的成果

Smalltalk-80 的公开发布并不只有“蓝皮书”。1981 年 8 月的 BYTE 专刊先为公众提供了入口。Goldberg 与 Robson 的 1983 年著作把语言和虚拟机规范放在一起。1984 年的 Smalltalk-80: The Interactive Programming Environment 专门描述程序员如何在环境中工作。Glenn Krasner 主编的实现经验集,则让各移植团队讲述开放接口之下的具体选择。

Goldberg 与 Robson 共同组织语言与实现一书。Goldberg 回忆,她与 Dan Ingalls 会把有争议的系统问题带到团队讨论并做最终决定,Robson 则作为异议的倾听者。Ingalls 后来指出,参考解释器的大部分工作由 Robson 完成。文字、可执行模型与集体决策必须在发布前彼此吻合。

这条历史谱系不能被压缩为单人发明。Simula 的对象观和 Sketchpad 的交互图形影响了 Alan Kay;Kay 提出了以消息为中心的个人计算愿景;Dan Ingalls 构建并多次演化解释器与虚拟机。Diana Merry 对文本显示和混排编辑作出贡献,Ted Kaehler 参与早期位图绘制并在后来研究内存系统,Larry Tesler 参与 Notetaker 和编程环境,David Robson 把团队决策写成严谨规范与参考解释器。PARC 更大的团队和外部移植者共同让契约能够运行。

把 Goldberg 放回这个网络,并不会削弱她的成就。她争取公开许可,连接研究团队与外部实现社群,把硬件观察引回文档,参与系统决策、共同撰写规范,并推动复杂材料进入可公开复现的完成状态。她组织的不只是一本书,而是一种检验知识是否已从原团队中独立出来的方法。

契约之所以耐久,正因为机械可以改变

后来的历史说明了边界的价值。有些 Smalltalk 来自获许可的镜像,有些则从公开文档重新实现。Ingalls 在 Apple 调整了界面以适应不同鼠标与屏幕;更快处理器和更大显示面积显著改变使用感受,却没有切断系统谱系。

Squeak 是更彻底的例子。1990 年代,Ingalls 与同事用已发表的参考解释器和 APDA 镜像启动新实现,随后用直接指针替换对象表,引入分代垃圾回收,并从受限 Smalltalk 子集生成 C。Ted Kaehler 与 Ingalls 重做内存系统,John Maloney 编写转换器,Scott Wallace 改造文件访问。底层机制变化很大,仍然保持有意义的 Smalltalk 连续性。

这正是良好可移植契约的作用:保护一条有用的接缝,而不是冻结全部历史。它让新实现者有把握改变下层,也让他们在改变破坏上层时有办法发现。

Computer History Museum 的 Smalltalk Zoo 如今把这种多样性直接呈现出来。共同祖先并不意味着同一种机器。“蓝皮书”让 Smalltalk 得以远行,是因为它说明哪些行为必须越过边界,也说明哪些选择可以留在当地。

资料来源