Skip to content

rm: remove specialized string opcode - #5

Merged
lollipopkit merged 2 commits into
mainfrom
rm-string-starts-with-opcode
Jun 8, 2026
Merged

rm: remove specialized string opcode#5
lollipopkit merged 2 commits into
mainfrom
rm-string-starts-with-opcode

Conversation

@lollipopkit

@lollipopkit lollipopkit commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • remove the specialized StringStartsWith opcode and its VM/LLVM lowering paths
  • keep string instance method behavior through the runtime method helper
  • bump module artifact version after opcode renumbering
  • remove stale plan/status handoff docs from this branch

Validation

  • cargo fmt
  • git diff --check
  • cargo test -p lk-core
  • cargo test --workspace --all-features
  • rg "StringStartsWith|emit_dynamic_string_starts_with|emit_string_starts_with_block|native_static_string_starts_with" core cli stdlib website

Summary by CodeRabbit

  • Refactor
    • 移除 StringStartsWith 操作码及其编译/运行时专用处理,相关编译期内联与优化路径被去除,starts_with 调用改为运行时通用处理;操作码表顺序相应调整。
  • Chores
    • 模块制品版本号从 2 更新为 3,旧版本制品将被拒绝。
  • Tests
    • 删除或改为运行时验证的与 starts_with 相关单元测试。
  • Documentation
    • 删除多份关于性能、规划与交接的文档内容。

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 8, 2026

Copy link
Copy Markdown

Deploying lk-lang with  Cloudflare Pages  Cloudflare Pages

Latest commit: a752812
Status: ✅  Deploy successful!
Preview URL: https://301fb021.lk-d8q.pages.dev
Branch Preview URL: https://rm-string-starts-with-opcode.lk-d8q.pages.dev

View logs

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e6e5f54-6503-4138-9883-a6560ee8a767

📥 Commits

Reviewing files that changed from the base of the PR and between ac99cc1 and a752812.

📒 Files selected for processing (3)
  • core/src/vm/artifact.rs
  • core/src/vm/compiler/inline.rs
  • core/src/vm/compiler/tests/call_intrinsics.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/src/vm/artifact.rs
  • core/src/vm/compiler/tests/call_intrinsics.rs
📜 Recent review details
🔇 Additional comments (1)
core/src/vm/compiler/inline.rs (1)

345-347: LGTM!

Also applies to: 361-369


📝 Walkthrough

Walkthrough

此PR完整移除了LK VM中的StringStartsWith opcode及其全栈支持。变更涉及opcode枚举定义、编译器编译期降级、LLVM后端代码生成、执行器运行时分发,同步更新artifact版本号并清理相关测试和文档。

Changes

StringStartsWith Opcode全栈移除

Layer / File(s) Summary
Opcode枚举与版本更新
core/src/vm/ir.rs, core/src/vm/artifact.rs
删除Opcode::StringStartsWith = 99变体,将后续opcode编码下移;MODULE_ARTIFACT_VERSION从2更新至3并增加拒绝旧版本的测试。
编译器编译期降级移除
core/src/vm/compiler/call.rs
lower_builtin_method_call删除"starts_with"分支,并移除lower_starts_with_method_callstarts_with调用将走动态方法分发。
内联判定调整
core/src/vm/compiler/inline.rs
inline_expr_is_supported新增检查以禁止将调用字段为字符串字面量"starts_with"的访问内联(引入inline_call_expr_uses_runtime_method_helper)。
LLVM后端代码生成移除
core/src/llvm/... (多个文件)
删除LLVM标量编译与直线求值中针对StringStartsWith的静态折叠与动态生成路径;移除emit_dynamic_string_starts_withnative_static_string_starts_withstring_methods子模块及对应分发分支。
执行器运行时支持移除
core/src/vm/exec.rs, core/src/vm/exec/dispatch.rs, core/src/vm/exec/value_ops.rs
删除dispatch_string_starts_with方法和string_starts_with / 辅助实现,opcode分发中不再处理StringStartsWith
测试与文档清理
core/src/llvm/tests/strings.rs, core/src/vm/compiler/tests/call_intrinsics.rs, core/src/vm/exec/exec_tests/container.rs, OPCODE.md, STATUS.md, handoff.md, plan.md, plan-progress.md
移除或替换与starts_with相关的单元测试(若干测试改为通过VmContext运行时断言),并删除多份规划/状态/手册类文档内容。

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
core/src/vm/compiler/tests/call_intrinsics.rs (1)

311-329: ⚡ Quick win

保留对外层 direct call 仍被内联的断言。

这个新用例现在只验最终结果,覆盖不到“移除 StringStartsWith 后,外层直接函数调用没有退化成 Call/CallDirect”这个编译层契约。这里继续检查编译后的入口指令形状,会更容易抓到优化回退。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/vm/compiler/tests/call_intrinsics.rs` around lines 311 - 329, The
test compiler_runs_direct_function_with_string_method only asserts the final
result but must also assert that the outer direct call remains inlined (i.e.,
the compiled entry uses CallDirect and not Call) after the StringStartsWith
intrinsic is removed; update the test to compile the program (or obtain its
compiled entry) and add an assertion that the entry instruction/opcode for the
price call is CallDirect (or the equivalent direct-call opcode used by the
compiler), referencing the test function name
compiler_runs_direct_function_with_string_method and the StringStartsWith
intrinsic so the check fails if the compiler falls back to Call/CallDirect
degradation.
core/src/vm/artifact.rs (1)

16-16: ⚡ Quick win

补一条旧版本 artifact 的拒绝测试。

这次版本号升级是在防止旧指令流按新的 opcode 表被静默误解码;当前只有 round-trip 正例,没有覆盖 version=2 必须失败的回归场景。

可直接补一条很小的回归测试
 #[test]
 fn module_artifact_round_trips_compiled_module() {
     let source = "fn f(x) { return x + 1; }\nreturn f(3);\n";
     let tokens = crate::token::Tokenizer::tokenize(source).expect("tokenize");
     let program = crate::stmt::StmtParser::new(&tokens).parse_program().expect("parse");
     let module = Compiler::compile_module(&program).expect("compile");
     let imports = vec![ImportStmt::Items {
         items: vec![crate::stmt::import::ImportItem {
             name: "abs".to_string(),
             alias: None,
         }],
         source: ImportSource::Module("math".to_string()),
     }];

     let artifact = ModuleArtifact::new(imports.clone(), &module).expect("artifact");
     let json = artifact.to_json_string().expect("json");
     let decoded = ModuleArtifact::from_json_str(&json).expect("decode");
     assert_eq!(decoded.imports, imports);
     let decoded_module = decoded.into_module().expect("module");

     assert_eq!(decoded_module.entry, module.entry);
     assert_eq!(decoded_module.globals, module.globals);
     assert_eq!(decoded_module.functions.len(), module.functions.len());
     assert_eq!(decoded_module.functions[0].code, module.functions[0].code);
 }
+
+#[test]
+fn module_artifact_rejects_previous_version() {
+    let module = Module::single(Function::default());
+    let json = ModuleArtifact::new(Vec::new(), &module)
+        .expect("artifact")
+        .to_json_string()
+        .expect("json")
+        .replace(r#""version": 3"#, r#""version": 2"#);
+
+    assert!(ModuleArtifact::from_json_str(&json).is_err());
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/vm/artifact.rs` at line 16, Add a regression test that ensures old
artifact version 2 is rejected: create a minimal serialized artifact blob whose
header version field is 2 (instead of MODULE_ARTIFACT_VERSION) and assert that
the artifact decoder (e.g., ModuleArtifact::deserialize or the crate's public
artifact deserialization function) returns an Err or panics as appropriate;
place the test alongside existing round-trip tests so it fails if older versions
are silently accepted. Make sure the test references MODULE_ARTIFACT_VERSION to
show intent and to construct a contrasting invalid version value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@core/src/vm/artifact.rs`:
- Line 16: Add a regression test that ensures old artifact version 2 is
rejected: create a minimal serialized artifact blob whose header version field
is 2 (instead of MODULE_ARTIFACT_VERSION) and assert that the artifact decoder
(e.g., ModuleArtifact::deserialize or the crate's public artifact
deserialization function) returns an Err or panics as appropriate; place the
test alongside existing round-trip tests so it fails if older versions are
silently accepted. Make sure the test references MODULE_ARTIFACT_VERSION to show
intent and to construct a contrasting invalid version value.

In `@core/src/vm/compiler/tests/call_intrinsics.rs`:
- Around line 311-329: The test compiler_runs_direct_function_with_string_method
only asserts the final result but must also assert that the outer direct call
remains inlined (i.e., the compiled entry uses CallDirect and not Call) after
the StringStartsWith intrinsic is removed; update the test to compile the
program (or obtain its compiled entry) and add an assertion that the entry
instruction/opcode for the price call is CallDirect (or the equivalent
direct-call opcode used by the compiler), referencing the test function name
compiler_runs_direct_function_with_string_method and the StringStartsWith
intrinsic so the check fails if the compiler falls back to Call/CallDirect
degradation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 036cb4e4-ee48-4684-b037-be61c8c63fc2

📥 Commits

Reviewing files that changed from the base of the PR and between 2c92a84 and ac99cc1.

📒 Files selected for processing (22)
  • OPCODE.md
  • STATUS.md
  • core/src/llvm/callee_eval.rs
  • core/src/llvm/scalar/block_helpers.rs
  • core/src/llvm/scalar/blocks.rs
  • core/src/llvm/scalar/blocks/string_methods.rs
  • core/src/llvm/scalar/facts.rs
  • core/src/llvm/scalar/inline.rs
  • core/src/llvm/straightline_main.rs
  • core/src/llvm/straightline_value.rs
  • core/src/llvm/tests/strings.rs
  • core/src/vm/artifact.rs
  • core/src/vm/compiler/call.rs
  • core/src/vm/compiler/tests/call_intrinsics.rs
  • core/src/vm/exec.rs
  • core/src/vm/exec/dispatch.rs
  • core/src/vm/exec/exec_tests/container.rs
  • core/src/vm/exec/value_ops.rs
  • core/src/vm/ir.rs
  • handoff.md
  • plan-progress.md
  • plan.md
💤 Files with no reviewable changes (16)
  • handoff.md
  • plan.md
  • core/src/llvm/straightline_value.rs
  • core/src/llvm/scalar/blocks/string_methods.rs
  • OPCODE.md
  • plan-progress.md
  • STATUS.md
  • core/src/vm/exec.rs
  • core/src/llvm/scalar/blocks.rs
  • core/src/vm/exec/value_ops.rs
  • core/src/vm/exec/exec_tests/container.rs
  • core/src/vm/exec/dispatch.rs
  • core/src/llvm/scalar/block_helpers.rs
  • core/src/vm/compiler/call.rs
  • core/src/llvm/scalar/facts.rs
  • core/src/llvm/tests/strings.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
core/src/vm/ir.rs (1)

227-232: LGTM!

Also applies to: 341-346

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 8, 2026
@lollipopkit
lollipopkit merged commit 63b12a2 into main Jun 8, 2026
2 checks passed
@lollipopkit
lollipopkit deleted the rm-string-starts-with-opcode branch June 8, 2026 14:12
lollipopkit added a commit that referenced this pull request Jul 7, 2026
…trait prescan 契约锁

review PR #17 发现的三项修复:

1. **chan.rs 持锁 raise → 永久死锁**(最重):raise 走 longjmp 跳过
   Rust drop,存活的 MutexGuard 永不解锁。两处:
   - channel() 的 "Channel not found" raise 时 registry 全局锁 guard
     还在 match 临时值里活着(**当前可达**:try{recv(999)}catch 后
     一切 channel 操作死锁)→ 先 cloned() 出 Option 再 raise;
   - select send 臂在持 ChanInner state 锁时调用可 raise 的 own()
     (当前 tag 集下 latent)→ armed send 载荷进循环前预深拷,
     kind 预验证,循环内 fallback 改 unreachable。
   blocking send/recv 本就遵守 drop-before-raise 纪律——正是这纪律
   证明这两处是疏漏。纪律成文进 CLAUDE.md lkrt 段。

2. **trait prescan 形状契约锁**(J1 计划欠账):examples 差分对
   unsupported 静默 skip,compiler 改 impl 注册序列发射形状会静默
   丢 trait 覆盖。新 differential_trait_dispatch_contract 走
   run_differential(硬性要求 lower 成功)——形状漂移即红。

3. **CLAUDE.md**:lkrt 边界规则补 dev-dep lk-core(仅 order-
   conformance 测试)例外条款 + 锁跨 raise 硬规则。

新差分 ×3:trait 契约、chan 未知 id catch 后可用、select 闭 send
catch 后可用(2/3 是死锁回归测试,修前会挂死)。
留档不做(review findings #3/#5/#6):硬编码名单收拢进单表、
fixpoint 快照 clone 优化、select spin-poll 换 Condvar 多路等待。
门禁:50/51 · 差分 12/12 · workspace 0 · fuzz 150 · -D warnings
all-features 0 · clippy/fmt 0 · bench 见下
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant