From c80ac23fd74fe07e7e02514486fd0ecfbc8da779 Mon Sep 17 00:00:00 2001 From: eunhhu Date: Mon, 19 Oct 2026 04:52:42 +0100 Subject: 140: small block fns inlined in aup, made and measured, not merged (the patch kept): a block fn whose only return is its last line, with no loop or called where the stack is empty, written out where it is called, its parameters slots of its own (one set a fn and kinds of arguments in a handler); the three specs' checks passed, but inflate 191.2 instructions a byte as before and HTTP 61.4 to 62.1 (+1.1%, 277.7 to 274.9 ns): the hot fns (inflate's decode, HTTP's crlf) return early inside a loop, a fn with a loop cannot be written out where values are on the stack (Pure opens no loop above values), and storing a short body's parameters costs what CALL and PICK did; inflate's 23% was the expression fn bit's (a loop, a let and conversions gone with the call); what would make it pay is Pure's (loops above values, or a cheaper frame), one spec behind it; the decision point's list of what was made after it --- docs/research/140-spec-suite.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'docs/research') diff --git a/docs/research/140-spec-suite.md b/docs/research/140-spec-suite.md index 28883a0..187e0cf 100644 --- a/docs/research/140-spec-suite.md +++ b/docs/research/140-spec-suite.md @@ -676,6 +676,22 @@ - 앞의 둘은 이제 핵에 들일 자격이 있다. 바이트 하나인 상태(저장, 교체, 보기, HTTP의 GET이 그것을 어떻게 다루는가)와 바이트의 비교 (TEXT_COMPARE의 인자로 할지, 새 명령으로 할지)는 설계 문서에서 정한다. 아직 시작하지 않았다. - aup의 셋은 컴파일러의 일이다. Pure의 함수 서명은 이미 리스트를 받는다. + +**결정점 뒤에 만든 것(2026-10-19).** +- 바이트의 `==`: TEXT_COMPARE의 인자 비트 `PURE_COMPARE_BYTES`(008). aup는 바이트끼리 견주고, 바이트를 만나는 문자열은 바이트다. +- 바이트 하나인 상태: [028](../design/028-bytes-state.md). 상태 타입 6, text와 한 draft, `values`의 표시로 손상과 옮김을 가른다. +- fn의 맨 리스트(aup): let의 리스트와 메시지의 행이 값이 되어 fn에 넘어가고 돌아온다. +- 블록 안의 let 리스트와 `xs = [...]`(aup): let을 지날 때마다 빈 리스트로 시작한다. +- **작은 블록 fn의 인라인(aup): 만들어 쟀고 넣지 않았다.** 반환이 끝에만 있고 고리가 없는(또는 스택이 빈 자리에서 부르는) 블록 + fn을 부른 쪽에 풀어 넣었다. 매개변수는 제 지역 칸이고, 칸은 핸들러마다 fn과 인자 종류의 한 벌이다. 세 명세의 검사는 모두 + 지났다. 하지만 inflate는 바이트당 명령 191.2 → 191.2(시간도 같다), HTTP는 61.4 → 62.1(+1.1%, 시간 277.7 → 274.9 ns)이었다. + - 효과가 없는 까닭은 셋이다. 첫째, 뜨거운 fn(inflate의 `decode`, HTTP의 `crlf`)은 고리 안에서 일찍 돌아오므로 조건에 들지 + 않는다. 둘째, 고리를 가진 fn은 식 안(스택에 값이 있는 자리)에서는 풀 수 없다. Pure가 값 위에 고리를 열지 않기 때문이다 + ("loop above values", 2c의 구멍을 막은 규칙). 셋째, 짧은 몸에서는 매개변수를 칸에 담는 값이 CALL과 PICK의 값만큼 든다. + - inflate의 23%는 부름을 없앤 것이 아니었다. `take(d, at, 1)`을 식 fn `bit`로 바꾸며 고리, let, i64 변환이 함께 사라진 값이었다. + - 그래서 인라인이 값을 하려면 Pure 쪽이 바뀌어야 한다. 값 위의 고리(블록의 스택이 그 자리의 높이에서 시작한다: 검증과 실행기), + 또는 더 싼 프레임이다. 명세 하나(inflate)가 닿은 핵의 질문이라 적어 두고 시작하지 않는다. + - 패치: `research/experiments/044-specs/2026-10-19-inline-block.patch`(aup의 `compiler/compile.c`, 142줄을 더한다). - 시간은 명령당 3.8–6.0 ns가 든다. 바이트 일을 C에 가깝게 하려면 명령의 수(바이트 찾기 같은 일을 명령 하나로 할지)와 명령당 비용(기계어 계층이 맡지 못하는 명령들) 둘 다를 봐야 한다. 이것도 따로 정한다. -- cgit v1.2.3