From c2ce219850aa3c880587e585b88718a3a25630a5 Mon Sep 17 00:00:00 2001 From: muqiuhan Date: Tue, 23 Jan 2024 12:34:19 +0000 Subject: deploy: 850faf4c6934ac6a7bd99a26948c2e3f7bed6c9a --- .../index.html" | 6 + .../28/A-Brief-History-of-Just-In-Time/index.html | 2 +- .../index.html" | 2 +- .../index.html" | 253 ++++++++++++++++++ .../index.html" | 2 +- 2024/01/08/OCaml-News-2024-1/index.html | 283 ++++++++++++++++++++ 2024/01/18/OCaml-News-2024-2/index.html | 293 +++++++++++++++++++++ 2024/01/22/Rescript-React-Native/index.html | 255 ++++++++++++++++++ 2024/01/23/G-Machine/index.html | 240 +++++++++++++++++ .../index.html" | 2 +- .../index.html" | 5 + archives/2023/10/index.html | 18 ++ archives/2023/page/2/index.html | 30 +-- archives/2023/page/3/index.html | 36 +-- archives/2023/page/4/index.html | 36 +-- archives/2023/page/5/index.html | 18 ++ archives/2024/01/index.html | 72 +++++ archives/2024/index.html | 72 +++++ archives/index.html | 60 ++--- archives/page/2/index.html | 60 ++--- archives/page/3/index.html | 60 ++--- archives/page/4/index.html | 60 ++--- archives/page/5/index.html | 60 ++--- archives/page/6/index.html | 66 ++--- archives/page/7/index.html | 92 +++++++ tag/index.html | 6 + tags/Life/index.html | 18 ++ tags/OCaml/index.html | 38 +++ tags/Rescript/index.html | 191 ++++++++++++++ tags/Technique/index.html | 83 ++++-- tags/Technique/page/2/index.html | 252 ++++++++++++++++++ 31 files changed, 2405 insertions(+), 266 deletions(-) create mode 100644 "2023/10/05/v8\344\270\255\347\232\204Number-toString/index.html" create mode 100644 2024/01/08/OCaml-News-2024-1/index.html create mode 100644 2024/01/18/OCaml-News-2024-2/index.html create mode 100644 2024/01/22/Rescript-React-Native/index.html create mode 100644 2024/01/23/G-Machine/index.html create mode 100644 tags/Rescript/index.html create mode 100644 tags/Technique/page/2/index.html diff --git "a/2023/06/17/\345\217\221\347\203\255\345\217\212\350\266\205\351\253\230\347\203\255\345\215\261\350\261\241/index.html" "b/2023/06/17/\345\217\221\347\203\255\345\217\212\350\266\205\351\253\230\347\203\255\345\215\261\350\261\241/index.html" index 3e05493c..e96f8521 100644 --- "a/2023/06/17/\345\217\221\347\203\255\345\217\212\350\266\205\351\253\230\347\203\255\345\215\261\350\261\241/index.html" +++ "b/2023/06/17/\345\217\221\347\203\255\345\217\212\350\266\205\351\253\230\347\203\255\345\215\261\350\261\241/index.html" @@ -139,6 +139,12 @@ Medicine + + + + Life + + diff --git a/2023/09/28/A-Brief-History-of-Just-In-Time/index.html b/2023/09/28/A-Brief-History-of-Just-In-Time/index.html index f6e4792b..1a6f5e11 100644 --- a/2023/09/28/A-Brief-History-of-Just-In-Time/index.html +++ b/2023/09/28/A-Brief-History-of-Just-In-Time/index.html @@ -203,7 +203,7 @@
- Prev + Prev
diff --git "a/2023/10/05/v8\344\270\255Number-toString-\347\232\204\345\256\236\347\216\260/index.html" "b/2023/10/05/v8\344\270\255Number-toString-\347\232\204\345\256\236\347\216\260/index.html" index ab166679..15ededb5 100644 --- "a/2023/10/05/v8\344\270\255Number-toString-\347\232\204\345\256\236\347\216\260/index.html" +++ "b/2023/10/05/v8\344\270\255Number-toString-\347\232\204\345\256\236\347\216\260/index.html" @@ -213,7 +213,7 @@
- Next + Next
diff --git "a/2023/10/05/v8\344\270\255\347\232\204Number-toString/index.html" "b/2023/10/05/v8\344\270\255\347\232\204Number-toString/index.html" new file mode 100644 index 00000000..b13f98eb --- /dev/null +++ "b/2023/10/05/v8\344\270\255\347\232\204Number-toString/index.html" @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + +v8中的Number.toString() | 暮秋小屋 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+
+ + + +
+
+
+ + +
+
+
+ + +
+ +
+ +
+ +
+
+
+

这里讲一下JavaScript中Number.toString()的实现, 以V8为例。

+ +

在很多地方都能看到:

+
1
*isolate->factory()->NumberToString(value);
+

例如 /src/builtins/builtins-number.cc 中。

+

下面看看NumberToString的定义, 应该是在 src/heap/factory-base.cc 中:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <typename Impl>
Handle<String> FactoryBase<Impl>::NumberToString(Handle<Object> number,
NumberCacheMode mode) {
SLOW_DCHECK(IsNumber(*number));
if (IsSmi(*number)) return SmiToString(Smi::cast(*number), mode);

double double_value = Handle<HeapNumber>::cast(number)->value();
// Try to canonicalize doubles.
int smi_value;
if (DoubleToSmiInteger(double_value, &smi_value)) {
return SmiToString(Smi::FromInt(smi_value), mode);
}
return HeapNumberToString(Handle<HeapNumber>::cast(number), double_value,
mode);
}
+ +

可以看到这里调用了 SmiToString, 这里不往下翻这个函数的定义, 只需要知道Smi是什么即可。 Smi 是一种特殊的整数类型,它被用于表示较小的整数值,通常在 32 位系统中是 31 位有符号整数。Smi 类型的值存储在指针的低位,而指针的高位用于标记该值是一个 Smi 类型。IsSmi 函数会检查给定的值是否为 Smi 类型,如果是,则返回 true,否则返回 false。这个函数通常用于 V8 引擎内部的优化和性能优化。

+

所以NumberToString会判断number是否是一个smi, 如果是的话就调用SmiToString, 否则会尝试将其转换为double再去调用DoubleToSmiInteger, 将DoubleToSmiInteger的调用结果存在smi_value里面, 再通过调用SmiToString将smi_value转换为字符串。

+

如果这两条路都行不通的话,就直接调用HeapNumberToString了。

+

HeapNumberToString的定义如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
template <typename Impl>
Handle<String> FactoryBase<Impl>::HeapNumberToString(Handle<HeapNumber> number,
double value,
NumberCacheMode mode) {
int hash = mode == NumberCacheMode::kIgnore
? 0
: impl()->NumberToStringCacheHash(value);

if (mode == NumberCacheMode::kBoth) {
Handle<Object> cached = impl()->NumberToStringCacheGet(*number, hash);
if (!IsUndefined(*cached, isolate())) return Handle<String>::cast(cached);
}

Handle<String> result;
if (value == 0) {
result = zero_string();
} else if (std::isnan(value)) {
result = NaN_string();
} else {
char arr[kNumberToStringBufferSize];
base::Vector<char> buffer(arr, arraysize(arr));
const char* string = DoubleToCString(value, buffer);
result = CharToString(this, string, mode);
}
if (mode != NumberCacheMode::kIgnore) {
impl()->NumberToStringCacheSet(number, hash, result);
}
return result;
}
+ +

就是熟知的NaN, Undefined处理,重点在:

+
1
2
3
4
char arr[kNumberToStringBufferSize];
base::Vector<char> buffer(arr, arraysize(arr));
const char* string = DoubleToCString(value, buffer);
result = CharToString(this, string, mode);
+ +

这里调用了DoubleToCString, 其定义在 /src/numbers/conversions.cc 中:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
const char* DoubleToCString(double v, base::Vector<char> buffer) {
switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) {
case FP_NAN:
return "NaN";
case FP_INFINITE:
return (v < 0.0 ? "-Infinity" : "Infinity");
case FP_ZERO:
return "0";
default: {
if (IsInt32Double(v)) {
// This will trigger if v is -0 and -0.0 is stringified to "0".
// (see ES section 7.1.12.1 #sec-tostring-applied-to-the-number-type)
return IntToCString(FastD2I(v), buffer);
}
SimpleStringBuilder builder(buffer.begin(), buffer.length());
int decimal_point;
int sign;
const int kV8DtoaBufferCapacity = base::kBase10MaximalLength + 1;
char decimal_rep[kV8DtoaBufferCapacity];
int length;

base::DoubleToAscii(
v, base::DTOA_SHORTEST, 0,
base::Vector<char>(decimal_rep, kV8DtoaBufferCapacity), &sign,
&length, &decimal_point);

if (sign) builder.AddCharacter('-');

if (length <= decimal_point && decimal_point <= 21) {
// ECMA-262 section 9.8.1 step 6.
builder.AddString(decimal_rep);
builder.AddPadding('0', decimal_point - length);

} else if (0 < decimal_point && decimal_point <= 21) {
// ECMA-262 section 9.8.1 step 7.
builder.AddSubstring(decimal_rep, decimal_point);
builder.AddCharacter('.');
builder.AddString(decimal_rep + decimal_point);

} else if (decimal_point <= 0 && decimal_point > -6) {
// ECMA-262 section 9.8.1 step 8.
builder.AddString("0.");
builder.AddPadding('0', -decimal_point);
builder.AddString(decimal_rep);

} else {
// ECMA-262 section 9.8.1 step 9 and 10 combined.
builder.AddCharacter(decimal_rep[0]);
if (length != 1) {
builder.AddCharacter('.');
builder.AddString(decimal_rep + 1);
}
builder.AddCharacter('e');
builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
int exponent = decimal_point - 1;
if (exponent < 0) exponent = -exponent;
builder.AddDecimalInteger(exponent);
}
return builder.Finalize();
}
}
}
+ +

不用过多解释, 已经很清晰了, FastD2I 就是 Fast Double to Integer的意思, 定义如下, 注释也很详尽:

+
1
2
3
4
5
6
7
8
9
// The fast double-to-(unsigned-)int conversion routine does not guarantee
// rounding towards zero.
// The result is undefined if x is infinite or NaN, or if the rounded
// integer value is outside the range of type int.
inline int FastD2I(double x) {
DCHECK(x <= INT_MAX);
DCHECK(x >= INT_MIN);
return static_cast<int32_t>(x);
}
+ +

以上

+ +
+ + + + + +
+ + + + + + + +
+ + +
+
+
+ + + +
+ + + + + + diff --git "a/2023/12/02/\344\272\214\343\200\207\344\272\214\344\270\211\345\271\264\345\215\201\344\272\214\346\234\210\344\272\214\346\227\245/index.html" "b/2023/12/02/\344\272\214\343\200\207\344\272\214\344\270\211\345\271\264\345\215\201\344\272\214\346\234\210\344\272\214\346\227\245/index.html" index c10f5b97..b508bdbf 100644 --- "a/2023/12/02/\344\272\214\343\200\207\344\272\214\344\270\211\345\271\264\345\215\201\344\272\214\346\234\210\344\272\214\346\227\245/index.html" +++ "b/2023/12/02/\344\272\214\343\200\207\344\272\214\344\270\211\345\271\264\345\215\201\344\272\214\346\234\210\344\272\214\346\227\245/index.html" @@ -187,7 +187,7 @@
- Prev + Prev
diff --git a/2024/01/08/OCaml-News-2024-1/index.html b/2024/01/08/OCaml-News-2024-1/index.html new file mode 100644 index 00000000..13a70b6c --- /dev/null +++ b/2024/01/08/OCaml-News-2024-1/index.html @@ -0,0 +1,283 @@ + + + + + + + + + + + + + + + + + + + + + +OCaml News 2024-1 | 暮秋小屋 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+
+ + + +
+
+
+ + +
+
+
+ + +
+ +
+ +
+ +
+
+
+

News

+

Videos

+

Blogs

+

Highlighted Projects

+

New Releases

+ +
+ + + + + +
+ + + + + + + +
+ + +
+
+
+ + + +
+ + + + + + diff --git a/2024/01/18/OCaml-News-2024-2/index.html b/2024/01/18/OCaml-News-2024-2/index.html new file mode 100644 index 00000000..a97be6e9 --- /dev/null +++ b/2024/01/18/OCaml-News-2024-2/index.html @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + + + + +OCaml News 2024-2 | 暮秋小屋 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+
+ + + +
+
+
+ + +
+
+
+ + +
+ +
+ +
+ +
+
+
+

News

+

Discussion

+

Videos

+

Blogs

+

Highlighted Projects

+

New Releases

+ +
+ + + + + +
+ + + + + + + +
+ + +
+
+
+ + + +
+ + + + + + diff --git a/2024/01/22/Rescript-React-Native/index.html b/2024/01/22/Rescript-React-Native/index.html new file mode 100644 index 00000000..47775070 --- /dev/null +++ b/2024/01/22/Rescript-React-Native/index.html @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + +Rescript React Native | 暮秋小屋 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+
+ + + +
+
+
+ + +
+
+
+ + +
+ +
+ +
+ +
+
+
+

Rescript 对 React Native 的支持还算可以,但如今的 RN 已经是 Expo 的 RN 了,所以仍然有些落后,在这个 template 中,我测试了 rescript + rescript-react-native + expo + nativewind 的组合,可以跑起来:

+ +

其中有两个问题,一是 rescript-expo 对 rescript v11 的兼容性,我通过简单的注释让其通过编译:

+ +

二是对于 nativewind 的支持,编写的 binding 非常丑陋:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type default_style = {
className?: string,
children?: React.element,
}

@module("nativewind")
external styled: React.component<'a> => React.component<default_style> = "styled"

module StyledText = {
let make = styled(ReactNative.Text.make)
}

module StyledView = {
let make = styled(ReactNative.View.make)
}

module StyledImage = {
type props = {
source?: string,
...default_style,
}

@module("nativewind")
external styled: React.component<'a> => React.component<props> = "styled"

let make: React.component<props> = styled(ReactNative.Image.make)
}
+ +

而这似乎并没有好的解决方案,理想中的实现应该是:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
module Styled = (Component: {
type params // or type params = 'a
let make: React.component<props>
}) => {
type props = {
...Component.props, // This can't work as it is not defined as record
className?: string
}
@module("nativewind")
external styled: React.component<Component.props> => React.component<props> = "styled"

let make: React.component<props> = styled(Component.make)
}
+ +

或者退一步:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type styledProps = {
className?: string,
// ...
}

@module("nativewind")
external styled: React.component<'a> => React.component<'b> = "styled"

module StyledText = {
type props = {
...ReactNative.Text.props,
...styledProps
}

let make: React.component<props> = styled(ReactNative.Text.make)
}
+ +

但这在当前的 rescript 中,根本无法实现。

+

详细的讨论看这个帖子:

+ + +
+ + + + + +
+ + + + + + + +
+ + +
+
+
+ + + +
+ + + + + + diff --git a/2024/01/23/G-Machine/index.html b/2024/01/23/G-Machine/index.html new file mode 100644 index 00000000..ff1d742e --- /dev/null +++ b/2024/01/23/G-Machine/index.html @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + +G-Machine | 暮秋小屋 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+
+ + + +
+
+
+ + +
+
+
+ + +
+ +
+ +
+ +
+
+
+ +

G-Machine 是一种通过图规约来对函数式语言程序求值的抽象架构。
与组合子规约不同,组合子规约的control是从表达式图本身动态导出的,而G-Machine是由通过编译Application表达式导出的指令序列指定的。

+
+

FP的程序基本上都可以用一个表达式的图表示,图计算机就是对这个图求值的机器,总的说来对图的求值是一个不停合并图上的节点生产新节点的过程。

+

例如:

+
1
2
let x = 2 + 3 in 
x * x
+ +

先计算出5,然后创建一个新的节点 5 * 5,然后再对这个节点求值,于是求值过程中就产生了很多临时的节点,这些中间节点也被叫做是 spine,求值过程是沿着 spine 进行的。

+

但是这样就产生了很多额外的开销,lambda lifting 里提到:可以把程序里,很多捕捉了外围绑定的闭包函数中的这些绑定,转换成函数的参数,从而消除闭包,得到的这个函数就可以自由脱离作用域,被静态的编译到机器码里。这些被 float out 的函数也叫 supercombinator.

+

在上面的代码中,如果不创建新的节点,顺序计算完了第一个 x,第二个 x 还会再被算一遍。

+

Spineless reduction 的概念:只有当面临需要重复计算的情况时,才去创建节点,不然就一路顺序算下去

+ + +
+ + + + + +
+ + + + + + + +
+ + +
+
+
+ + + +
+ + + + + + diff --git "a/2024/01/23/\344\272\214\343\200\207\344\272\214\345\233\233\345\271\264\344\270\200\346\234\210\344\272\214\345\215\201\344\270\211\346\227\245/index.html" "b/2024/01/23/\344\272\214\343\200\207\344\272\214\345\233\233\345\271\264\344\270\200\346\234\210\344\272\214\345\215\201\344\270\211\346\227\245/index.html" index b41da268..62bf3ade 100644 --- "a/2024/01/23/\344\272\214\343\200\207\344\272\214\345\233\233\345\271\264\344\270\200\346\234\210\344\272\214\345\215\201\344\270\211\346\227\245/index.html" +++ "b/2024/01/23/\344\272\214\343\200\207\344\272\214\345\233\233\345\271\264\344\270\200\346\234\210\344\272\214\345\215\201\344\270\211\346\227\245/index.html" @@ -195,7 +195,7 @@
- Next + Next
diff --git "a/2024/01/23/\346\205\242\346\200\247\350\202\272\346\272\220\346\200\247\345\277\203\350\204\217\347\227\205/index.html" "b/2024/01/23/\346\205\242\346\200\247\350\202\272\346\272\220\346\200\247\345\277\203\350\204\217\347\227\205/index.html" index 93def6d0..91a5abba 100644 --- "a/2024/01/23/\346\205\242\346\200\247\350\202\272\346\272\220\346\200\247\345\277\203\350\204\217\347\227\205/index.html" +++ "b/2024/01/23/\346\205\242\346\200\247\350\202\272\346\272\220\346\200\247\345\277\203\350\204\217\347\227\205/index.html" @@ -237,6 +237,11 @@