大白话讲透 Chromium 源码(宏观篇)

发表于 2年以前  | 总阅读数:378 次

自从我 对C语言有过编译原理上的实践经验 && 对js和浏览器的表层(非chromium源码级我都统称表层) 有了更深的理解后,对于JS及其相关的很多事物愈发的产生了疑惑,比如"执行上下文"、"渲染流水线"、"浏览器多进程到底怎么玩的(ipc等)"等等,网上现有的理论(包括ES官方),已经不能解决我产生的各种疑惑了。我需要的是chromium源码级的解释!!

我想先解决"执行上下文"等疑惑,又奈何,截止2021.11.1(我得严谨一点嘛,世事难料,我们永远不知道下一刻会发生什么,更何况过去了一个月呢)我竟然没有搜到一篇关于"执行上下文"的源码级解释(我需要的不是八股文也不是ES官方规范呐)。准确说是关于Chromium源码解释的资源本身就太少太少太少了,

为什么要读源码呢?大家要先明白,ES规范的官方标准,它只是一个理论标准。它也是在某个技术实现后,才出的标准。所以最终实现上是怎样的婀娜多姿,只有相应开发者知道。其他人只能通过阅读源码窥得一二。而且源码中充斥着大量的最佳实践,以及为了极限性能而各种"骚操作"(导致难以阅读),可以瞻仰瞻仰。

没辙了,由于自身强烈的强迫症,我只好硬着头皮自己上了(虽然只有大一的C基础,也没学过C++,并且我也只是个仍在实习的小FEer。但是!这并不能阻挡我探索chromium的决心,Fighting!Fighting!)。 经过一个多月(每天完成公司任务后,自己加的2~3hour)对chromium的折腾(虽然本地都准备好了,但未能在本地调试。于是我在 chromium 【需要科学上网】,干巴巴的读。文末对chromium的阅读经验中会解释为何未能调试)。

打个不恰当的比方:如果其他矿工无暇分享来自chromium这座矿山的"资源",那我愿意学着如何去当一名矿工。戴上小钢帽儿,背上行囊,提起小铁铲儿,把挖到的、探索到的"资源"分享给大家。

Hi~ 我是本文向导

(: 后来想了想,不太推荐纯小白观看噢,纯小白慎入⚠️。最好是熟悉js&懂一点编译和c++。编译和C++不了解也没关系,了解js就行,其他的我来讲

首先关于 chromium 和 chrome 的关系大家可自行搜索哈。

“无忌,我教你的还记得多少?”“回太师傅,我只记得一大半” “ 那,现在呢?”“已经剩下一小半了” “那,现在呢?”“我已经把所有的全忘记了!” “好,你可以上了…”

先忘掉你之前学过的js上下文和作用域等知识,包括ES官方说的,也忘掉!我只能说,官方描述的"样子"源码里有对应的体现,但是具体称呼、约定、实现,官方无法强约束。再次强调,是chrome(或各大浏览器厂商)先有的实现,然后ES组织后来才出的官方标准。所以希望你最好和我一起,我们重新探索,重新学习。

本篇文章主要是从chromium源码中的v8(JavaScript引擎,主要内容都是由C++实现,还涉及Chrome自研的Torque语言.tq),去梳理js上下文&作用域、对象及数组等内容。还会涉及一些编译原理的知识。为了尽量同步最新源码&风格统一,所有截图均为 chromium 里最新实时截图,就不看我本地代码了。

行文至此,俺懵了,my mind goes completely blank.。因为这是写给大家看的,"你要我怎么做怎么说,你才能爱我~"

把所有本文涉及的东西都截图出来--不太可能,那样这篇文章体积就太大了。但我会尽量的截图源码。

为了帮助兄弟姐妹萌过渡,我会先宏观介绍一些知识,再结合微观探索细节,最好不要跳着看噢

v8源码宏观铺垫与分析

我会先为大家讲解一下各种铺垫知识,来慢慢揭开v8这神秘魔法石的一部分 -- js Context&Scope&others

注意下文中我画的图、翻译的话、我打的注释希望XDJMM可以一个字一个字的扫一遍,很重要的,我长时间的摸索才得来的经验。不读一下的话,我担心后文你们直接懵了‍‍

Handle--大智若愚的"憨豆"先生

首先:Handle用于管理v8对象的内存地址,它的本质就是一个指向指针的指针。

重要的前菜--指针介绍

C/C++之所以那么汹涌澎湃、大海无量,我个人认为指针(针哥)占了50%的功劳。

我们的程序、变量等,最终一定是存到物理硬件中的。运行程序一般都是在内存中,分配的空间也在内存中。你要找到某个东西,就一定需要地址,C/C++是偏底层的语言,因为它们能通过指针直接操作内存单元!

指针就是地址,地址就是指针。地址就是内存单元的编号。指针变量就是就是一个存放指针/地址的变量。申请内存空间后的返回的地址都是内存单元的起始地址,然后通过偏移量即可访问具体数据。

指针的几点好处:可以访问硬件、快速的传递数据(通过指针可以直接找到一个复杂的数据结构的起始地址)..

那么为何需要"憨豆"先生呢?

首先Handle应取其句柄含义,起源于Handle-C。我觉得你可以直接理解为柄,联想到什么了吗?手提袋的柄?打魂斗罗的游戏机手柄?书包上面的柄?无所谓,差不多就那个意思,啥意思?有点拿捏了&&四两拨千斤的韵味。

v8中重新实现了一个Handle类,然后我们先来看源码中的一段注释,看看为啥需要"憨豆"先生:

从 v8 返回的所有对象都必须由垃圾收集器跟踪,为了知道它们是否还活着。又因为垃圾收集器可能会移动对象,直接指向一个对象是不安全的。相反,所有对象都存储在垃圾收集器所知道的句柄中,并在对象移动时更新句柄。Handles应该总是按值传递(地址也是值,一般用16进制)(除了像out-parameters这样的情况--我并不知道这句个out-parameters是指什么,不过对本文应该没影响),并且它们不应该在堆上分配。

这有两种类型的句柄,local 和 persistent 类型的句柄。Local类型的句柄是轻量且瞬态的,通常用于local(我理解应翻译为:局部)操作。它们都由HandleScope管理。这意味着当Handles们被创建在有效的HandleScope内部时,一定是位于栈上。要将local句柄传递给外部 HandleScope,必须使用 EscapableHandleScope 及其 Escape() 方法。

本文涉及的源码涉及的代码里都是 Local 类型句柄,先不用管 Persistent。

当存储对象跨越多个独立操作时,可以使用持久句柄,并且在不再使用时必须明确释放。通过取消引用句柄来提取存储在句柄中的对象是安全的(例如,从Local中提取Object*),该值仍将由幕后的句柄控制,并且相同的规则适用于这些值的句柄。

Type* temp; 这代表的是一个叫temp的变量, 持有一个指向Type类型的指针;temp就是那个指针变量!通过 (*temp) 就可以拿到那个指针/地址所在的内存单元上存储的数据!但是这么做比较危险!因为GC可能移动对象从而导致产生新地址,原地址将会存着啥,谁都不知道。就是说,如果temp指向一个对象,GC换了地址存储这个对象,那开发者拿到的原地址上是啥,谁都不知道了。难道我们开发者不要面子的吗??!!所以得蹦出个Handle,来帮你管理这个对象的地址,你拿着Handle就行。你可以理解为Handle是一个指向指针的指针;一个智能的指针。

我没讲明白是吧?行,给宝宝我愁的啊,上图!

我讲清楚了吗,兄弟姐妹萌? 再不理解,俺也没辙啦,就先跳过吧

所以你Get到“憨豆”先生的大智若愚了吧

憨豆先生的几部作品中的片段我仍历历在目,始终觉得他是一位有大智慧的人。

回归正题。难道你没发现:你给js对象添加属性,js数组push元素之后,再去做恒等比较时,结果仍为true。

你没想过为啥吗?你总不会认为它不是分配新的内存空间,而是在原有内存后面加内存吧??????虽然对象和数组一开始都会分配固定默认容量的内存,但是你超过这个容量后,就得重新分配内存了。你不会想问为啥得重新分配而不是追加内存或者覆盖其后地址上的数据吧? 兄弟姐妹萌。。你们怎么比我还天真呢。稚嫩呐。。真好。

首先,追加是不可能的。因为物理内存一个挨着一个,你凭什么无中生有呢?你顶多是把x号单元后连着的单元,覆盖上你想要的数据。但是这也不行,为啥?你根本没权利这么干,就算有,你也绝对不能这么干!!

打个不恰当的比方:地铁上,这排5个座位,就剩中间一个了,你女朋友坐了上去。到了下一站,你也上来了,想坐在你女朋友身边。你总不能让它旁边某个人起开,然后给你腾座位吧?凭啥?人家先来的,人家凭啥让给你,而且这是公共场所。至少有一个人会"遭殃"。

但反映到内存上,它可不是这么简单的让开就行,你能知道这块“需要让座”的内存单元正在存储着什么吗?你能知道它是为了什么而存储吗?你有权利动人家吗?你一冲动,可能后面n个内存单元都错了,那就不是一个单元的事儿了!而且这些内存所服务的事情也都会出错,可怕吗?我就问你怕不怕!为了一点点内存,至于这么大动干戈吗。当然不至于!所以才要重新分配内存空间!!也就是你和你女朋友去找一个2连座,然后再享受欢乐时光。

拿数组举例:当你push后,达到扩容条件时,v8就得这么干:

  • 申请新容量的内存空间,如果失败,报错并直接return;
  • 申请成功,则把旧地址上的数据按序复制到新内存单元上,并把新内存单元的起始地址交给Handle,"憨豆"先生帮你管理;
  • 无论后续怎么变,新的内存的起始地址都是交给"憨豆"先生;
  • 你的变量拿着的始终是Handle先生的初始地址(从初始化之后都是)。所以你 === 的比较,结果肯定是true。

这次我讲明白了吧,小哥哥小姐姐?Handle哥帮你做了那么多事,任劳任怨,还得保证你不会出错,你说人聪不聪明?大智若愚~

本杰明·巴顿奇事--编译原理科普

实现一门编程语言,实际上就是在实现一个翻译程序--编译器,因为CPU只认识0和1,汇编可以认识指令。

这里以编译型语言为例,我简单描述下编译程序的流程:

不断的退化,回归原始至臻,是不是有点本杰明的韵味呢?

虽然JS是解释型语言,但也有"编译"的部分,采用了JIT技术。大家可自行在掘金搜索介绍v8对js如何解释执行的相关文章。

v8 部分类关系图概览

可以结合上文和下文内容后再读下图。兄弟姐妹萌!每个方块都是一个类。其实绿色的(我们这次不care)你们不理解也没事,其他颜色的没看懂,也没事;毕竟这个图只是为了大家有个宏观的认识而已,而且后面我会拉扯出非绿色的其中几个模块 -- 就是我们这次要聊的js上下文&作用域。

精美包装--js上下文Context概览

上述类图中对js Context我也写了一点描述,是js代码执行的小型沙箱,因此我美其名曰:精美包装。

请 XDJMM 先仔细阅读我的翻译,因为有些话不在原英文中(宝贝们也可读它个20遍,若不理解,没关系,后续我会慢慢"拉扯出来"),然后可以自己去翻译一下。大致是说:

JSFunction 是成对的(上下文、函数代码),有时也称为闭包(注意:这里不要狭隘了,JSFunction和这个closures不是单纯指大家理解的js函数和闭包,这个JSFunction还包含了很多字节码、优化代码的相关操作等)。Context 对象常常用于表示函数上下文和动态推送“with”上下文(或 ECMA-262 中的“scope”)。

在运行时,上下文们会构建一个与执行栈并行的栈!(注意注意:这就有提示了,上下文的栈最初不是诞生在执行栈里!!)栈顶的上下文是当前上下文。所有上下文有以下插槽(理解为字段/属性吧):

  • [ scope_info ] 这是描述当前上下文的作用域信息。它包含静态分配的上下文槽的名称(提前说一下,很多时候我们的变量会被直接放在 context 中),和栈分配的locals。名称需要用于存在“with”或“eval”时的动态查找,以及为了调试器。
  • [ previous ] 指向前一个上下文的指针。
  • [ extension ] 附加数据。此插槽仅在以下情况下可用 -
  • [ ScopeInfo::HasContextExtensionSlot ] 返回 true。

对于 native 上下文,它包含全局对象。(其实只是Browser把全局对象的指针暴露给了v8,v8又暴露给了native上下文;native上下文你们可以类似理解为你们以前所学的"全局执行上下文")对于 module 上下文,它包含模块对象。

对于 await 上下文,它包含生成器对象。对于 var block(varblock这东西太难找了,后面再说)上下文,它可能包含一个“extension object”。

对于 with 上下文,它包含一个“extension object”。“extension object”用于动态扩展一个带有附加变量的上下文,也就是在'with'结构和'eval'结构的实现中。例如, Context::Lookup 也搜索扩展对象的属性。存储扩展对象是这个上下文槽的原始目的,因此得名。此外,带有草率的 eval 的函数上下文可能会静态地分配上下文槽,来存储要从内部函数(通过静态上下文地址)或通过 'eval'(动态上下文查找)访问的局部变量/函数。

native上下文包含用于快速访问native属性的附加插槽。最后,在和谐的scope氛围下(我淦,我真不知道怎么翻译这个Harmony了),JSFunction 表示顶级脚本将具有 ScriptContext而不是 FunctionContext。所有来自顶级scripts的ScriptContext都被收集在脚本上下文表:ScriptContextTable 中。

所以说,每个Context一定至少有三个共同的槽位:scope_info, previous, extension

那么你猜,主要信息都在哪儿呢?Bingo!当然一定以及肯定的在scope_info中了啊!!!

所以Context本身是没有大家以前认为的所谓的那些什么 变量环境、词法环境、this、outer;都没有!!这些东西倒是在Scope中都有涉及!但是在Scope中分得非常细致,所以,请不要叫词法环境,你可以称呼为词法标识。也不要叫变量环境,这些概念都太大,源码中没有对应实现。因为在源码实现中拆分了各种细致的东西。如果你不拆分为各种标识,那么绝对无法应对千奇百怪的各种语法和语义!拥有足够多细腻的信息,你就可以"金刚不坏"了。

现在我们通过判断上下文类型的方法,反向看看都有哪些类型的Context:

但是!其实最终还是从native_context的扩展对象里的拿的global_object啊,如下:

出现了个全局代理,它和全局对象啥关系呢?global_proxy_object.prototype指向global_object,如下:

v8期望只有只有全局对象能作为全局代理的原型,所以v8不希望我们改变全局代理对象的原型的指向,否则可能发生意向不到的事,因为很可能破坏虚拟机!!

ps:global_object 就是 ES规定的全局对象,也是Browser暴露给v8的window

一人之下万人之上--NativeContext

上述类图中,我已经画了,NativeContext继承自Context,然后他重写了获取global_object方法,并为它又重载了一个方法。但其实还是调用的是Context里的gobal_object(); 自己拿自己的东西还得绕一圈,可还行?行,估计是为了某种安全,chrome这么注重性能的团队,不会做不必要的事情。

716~721在说,722行的方法忽略了是否加载完毕的tag。可以在并发(并发噢,没毛病)情况下安全的读取全局对象,因为在它初始化后就不可变了(指的是指针不可变,即地址不会变了)。722行的方法不能用于heap-refs.cc以外的地方。估计是其他地方如果你瞎调用,可能还没load完,你去操作全局对象就要出事。所以723行来了个重载函数,有标识的时候,就调723的的方法就行了。

并且NativeContext中还有微任务队列的指针:

你们想知道微任务具体是在什么情况下、什么时候运行的吗?欸,我就是不说,就是玩儿,就是皮。

为啥说 "一人之下万人之上",请继续往下看↓↓

跨脚本共享的关键--ScriptContext及其Table

首先ScriptContext和ScriptContextTable都可以通过NativeContext拿到。

再来看下面一段注释:

就是说ScriptContextTable存放着所有加载完毕的顶级脚本下的顶级词法声明变量(let/const)。在源码中,我看它首先是通过JSFunction(它不是单纯我们说的js的function,它承载着v8对我们整个js的掌控,包括优化信息、字节码等编译后端的底层知识,我目前没继续深入了解JSFunction),拿到native_context,然后native_context 访问ScriptContextTable,遍历上面说的顶级词法变量,表中没有的就存进去,有的就共享。但是注意!!其实script_context仍然会为这些变量开辟一个槽位占位,但是他们共享访问table中对应变量修改的也是table中对应的变量。这就是为什么你在html中引入了多个script标签后,可以跨script去使用顶级let/const的变量的原因。注意,这只是你可以跨脚本调用,本质上这些顶级词法变量是没有被安装到global_object中的!!比如你跨脚本使用顶级词法变量temp:直接用temp, 但你不能用window.temp!!因为它本质上就不在global_object中!!

那为什么没提到var声明的变量呢?首先在源码中,顶级脚本是需要被安装到native_context中的,然后JSFunction会拿到native上下文,继而拿到native上下文扩展对象里的 global_object,之后通过一系列函数,最后遍历脚本中的顶级var声明存储进global_object。所以你既可以跨脚本直接使用var变量,也可以利用window.xxx使用。

关于函数有些复杂,还得看你最初怎么定义的,然后就会有不同的体现,总之思路要点都是一致的:通过JSFunction拿到native_context进而拿到script_context_table或者global_object去操作或者不操作。

还是再贴一点点源码吧,在 NewScriptContext 方法里,框起来的都是经过一堆操作后的入口,每个入口后面又会调N个函数,我贴的其他源码图也是这样,毕竟v8这么大,chromium那么那么大。。:

现在是不是觉得native_context几乎权势滔天了?只有JSFunction比他官儿大。当然最大的是v8,v8上面还有Chrome Browser,

颤栗吧!不可思议的再次声明let/const!

但是你发现没有,你在控制台的话:

为什么第一和第三种模式居然可以通过,第二种和第四种就是错的?其实控制台算是一种调试模式!是Devtools照顾大家的。会在一定情况下触发repl模式作用域,然后你每敲一次回车之后,相当要新建立一个ScriptContext,然后在源码中:

就看我框起来的3个地方小方框,就是说,(let和let || const和const) && 此种特殊情况下,就可以重复声明,否则会报相应错误。

, 我为什么要举这么个破玩意儿例子呢?不是来刷存在感的,只是想证明,N多情况都不是我们未经源码考证时可以解释的。其实还有N多小细节,我只是随便举了一个例子而已。希望大家对一切都抱有敬畏之心!

其他 Context 就不讲了,主体和精髓都是各种 Scope,下篇 scopes 里面讲讲就行了。

本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/-kNsV_sEcHq6J_Exb-K1Og

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237229次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8063次阅读
 目录