You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: multi-threading support and parallel compiler pipeline (v0.4.0)
perry/thread module with three primitives:
- parallelMap(array, fn): data-parallel array processing across CPU cores
- parallelFilter(array, fn): data-parallel array filtering across CPU cores
- spawn(fn): background OS thread returning Promise
Threading infrastructure:
- SerializedValue deep-copy for safe cross-thread value transfer
- Thread-local arenas with Drop cleanup for worker threads
- Promise integration via PENDING_THREAD_RESULTS queue
- Compile-time mutable capture rejection for thread safety
Parallel compiler pipeline (rayon):
- Module codegen runs across all CPU cores
- Transform passes (JS imports, native instances, monomorphization) parallelized
- nm symbol scanning parallelized
Runtime improvements:
- Array.sort() upgraded from O(n²) insertion sort to O(n log n) TimSort hybrid
Documentation:
- New "Multi-Threading" section (4 pages) in docs
- Updated introduction, hello-world, and limitations pages
Copy file name to clipboardExpand all lines: CLAUDE.md
+30-55Lines changed: 30 additions & 55 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
8
8
9
9
Perry is a native TypeScript compiler written in Rust that compiles TypeScript source code directly to native executables. It uses SWC for TypeScript parsing and Cranelift for code generation.
Mark-sweep GC in `crates/perry-runtime/src/gc.rs` with conservative stack scanning. Arena objects (arrays, objects) discovered by linear block walking (zero per-alloc tracking). Malloc objects (strings, closures, promises, bigints, errors) tracked in thread-local Vec. Triggers on new arena block allocation (~8MB) or explicit `gc()` call. 8-byte GcHeader per allocation.
68
68
69
+
## Threading (`perry/thread`)
70
+
71
+
User code is single-threaded by default. `perry/thread` module provides three primitives with compile-time safety (no mutable captures allowed):
72
+
73
+
-**`parallelMap(array, fn)`** — data-parallel array processing across all CPU cores
74
+
-**`parallelFilter(array, fn)`** — data-parallel array filtering across all CPU cores
75
+
-**`spawn(fn)`** — background OS thread, returns Promise
76
+
77
+
Values cross threads via `SerializedValue` deep-copy (zero-cost for numbers, O(n) for strings/arrays/objects). Each thread has independent arena + GC. Arena `Drop` frees blocks when worker threads exit. Results from `spawn` flow back via `PENDING_THREAD_RESULTS` queue, drained during `js_promise_run_microtasks()`.
78
+
79
+
**Compiler pipeline** also parallelized via rayon: module codegen, transform passes, and nm symbol scanning.
80
+
69
81
## Native UI (`perry/ui`)
70
82
71
83
Declarative TypeScript compiles to AppKit/UIKit calls. 47 `perry_ui_*` FFI functions. Handle-based widget system (1-based i64 handles, NaN-boxed with POINTER_TAG). 5 reactive binding types dispatched from `state_set()`. `--target ios-simulator`/`--target ios` for cross-compilation.
@@ -84,39 +96,25 @@ Projects can list npm packages to compile natively instead of routing to V8. Con
**Dedup logic**: When `@noble/hashes` appears in both `@noble/curves/node_modules/` and `@solana/web3.js/node_modules/`, the first-resolved directory is cached in `compile_package_dirs`. Subsequent imports redirect to the same copy, preventing duplicate linker symbols.
99
+
**Dedup logic**: When `@noble/hashes` appears in multiple `node_modules/`, the first-resolved directory is cached in `compile_package_dirs`. Subsequent imports redirect to the same copy, preventing duplicate linker symbols.
96
100
97
101
## Known Limitations
98
102
99
103
-**No runtime type checking**: Types erased at compile time. `typeof` via NaN-boxing tags. `instanceof` via class ID chain.
100
-
-**Single-threaded**: User code on one thread. Async I/O on tokio worker pool. Use `spawn_for_promise_deferred()` for safe cross-thread data transfer.
104
+
-**No shared mutable state across threads**: Thread primitives enforce immutable captures at compile time. No `SharedArrayBuffer` or `Atomics`.
101
105
102
106
## Common Pitfalls & Patterns
103
107
104
108
### NaN-Boxing Mistakes
105
109
-**Double NaN-boxing**: If value is already F64, don't NaN-box again. Check `builder.func.dfg.value_type(val)`.
-`try_compile_index_as_i32` keeps i32 ops contained to array indexing only
140
-
141
133
### Handle-Based Dispatch
142
134
- TWO systems: `HANDLE_METHOD_DISPATCH` (methods) and `HANDLE_PROPERTY_DISPATCH` (properties)
143
135
- Both must be registered. Small pointer detection: value < 0x100000 = handle.
144
136
145
-
### UI Codegen
146
-
- NativeMethodCall has TWO arg paths: has-object and no-object — don't mix them up
147
-
-`js_object_get_field_by_name_f64` (NOT `js_object_get_field_by_name`) for runtime field extraction
148
-
149
137
### objc2 v0.6 API
150
138
-`define_class!` with `#[unsafe(super(NSObject))]`, `msg_send!` returns `Retained` directly
151
139
- All AppKit constructors require `MainThreadMarker`
152
-
-`CGPoint`/`CGSize`/`CGRect` in `objc2_core_foundation`
153
140
154
141
## Recent Changes
155
142
156
-
### v0.3.2
157
-
- watchOS native app support (`--target watchos`/`--target watchos-simulator`): data-driven SwiftUI renderer, `perry-ui-watchos` crate with full `perry_ui_*` FFI surface, fixed PerryWatchApp.swift runtime, `perry setup watchos`, `perry run watchos`, `[watchos]` config in perry.toml
158
-
159
-
### v0.3.0
160
-
- Compile-time i18n system (`perry/i18n` module): zero-ceremony localization for UI strings, `[i18n]` config in perry.toml, embedded 2D string table, native locale detection (all 6 platforms via OS APIs), `{param}` interpolation, CLDR plural rules (30+ locales), format wrappers (`Currency`, `Percent`, `ShortDate`, `LongDate`, `FormatNumber`, `FormatTime`, `Raw`), `perry i18n extract` CLI, iOS `.lproj` + Android `values-xx/` generation, compile-time validation
161
-
162
-
### v0.2.203
163
-
-`perry setup` summary: show what's stored in global config vs project perry.toml for all platforms
143
+
### v0.4.0
144
+
-`perry/thread` module: `parallelMap`, `parallelFilter`, and `spawn` — real OS threads with compile-time safety. `SerializedValue` deep-copy, thread-local arenas with `Drop`, promise integration via `PENDING_THREAD_RESULTS`.
145
+
- Parallel compiler pipeline via rayon: module codegen, transform passes, nm symbol scanning all across CPU cores.
146
+
- Array.sort() upgraded from O(n²) insertion sort to O(n log n) TimSort-style hybrid.
147
+
- Comprehensive threading docs in `docs/src/threading/` (4 pages).
164
148
165
-
### v0.2.202
166
-
-Fix `perry setup ios` not saving bundle_id to perry.toml
149
+
### v0.3.3
150
+
-`perry publish`: `.env` loading, `[publish] exclude` in perry.toml
0 commit comments