Skip to content

Commit 543f3cf

Browse files
committed
refactor(vm): unify host runtime lifecycle
1 parent dccf2fd commit 543f3cf

48 files changed

Lines changed: 10230 additions & 1729 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 295 additions & 107 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ name = "vm"
2727
[features]
2828
default = ["runtime", "cli", "cranelift-jit"]
2929
runtime = []
30+
sqlite = ["runtime", "dep:rusqlite"]
3031
edge-abi = [
3132
"dep:edge_abi",
3233
"edge_abi/console",
@@ -60,6 +61,7 @@ cranelift-jit = { version = "0.129.1", optional = true }
6061
cranelift-module = { version = "0.129.1", optional = true }
6162
cranelift-native = { version = "0.129.1", optional = true }
6263
pd-host-function = { path = "./pd-host-function", version = "0.1.0" }
64+
rusqlite = { version = "0.32", default-features = false, features = ["bundled", "hooks", "limits"], optional = true }
6365
edge_abi = { package = "pd-edge-abi", version = "0.1.1", default-features = false, optional = true }
6466
futures-channel = "0.3"
6567
paste = "1"
@@ -77,6 +79,7 @@ windows-sys = { version = "0.59", features = ["Win32_System_Diagnostics_Debug",
7779
libc = "0.2"
7880

7981
[dev-dependencies]
82+
futures-util = "0.3"
8083
syn = { version = "2", features = ["full"] }
8184
tokio = { version = "1", features = ["macros", "rt", "time", "sync"] }
8285

@@ -85,5 +88,10 @@ name = "host_binding_generation_tests"
8588
path = "tests/host_binding_generation_tests.rs"
8689
required-features = ["cranelift-jit"]
8790

91+
[[test]]
92+
name = "sqlite_host_tests"
93+
path = "tests/vm/sqlite_host_tests.rs"
94+
required-features = ["sqlite"]
95+
8896
[build-dependencies]
8997
syn = { version = "2", features = ["full"] }

build.rs

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,25 @@ fn main() {
149149
println!("cargo:rerun-if-changed={}", catalog_path.display());
150150
let catalog = parse_catalog(&catalog_path);
151151

152-
let host_sources = [SourceSpec {
153-
path: "src/builtins/runtime/host.rs".to_string(),
154-
module: "host".to_string(),
155-
category: SourceCategory::DefaultHost,
156-
}];
152+
let mut host_sources = vec![
153+
SourceSpec {
154+
path: "src/builtins/runtime/host.rs".to_string(),
155+
module: "host".to_string(),
156+
category: SourceCategory::DefaultHost,
157+
},
158+
SourceSpec {
159+
path: "src/builtins/runtime/context_host.rs".to_string(),
160+
module: "context_host".to_string(),
161+
category: SourceCategory::DefaultHost,
162+
},
163+
];
164+
if env::var_os("CARGO_FEATURE_SQLITE").is_some() {
165+
host_sources.push(SourceSpec {
166+
path: "src/builtins/runtime/sqlite.rs".to_string(),
167+
module: "sqlite".to_string(),
168+
category: SourceCategory::DefaultHost,
169+
});
170+
}
157171
let builtin_sources = builtin_source_specs(&namespaces);
158172
let core_sources = [SourceSpec {
159173
path: "src/builtins/runtime/core.rs".to_string(),
@@ -934,6 +948,7 @@ fn render_builtin_catalog(
934948

935949
writeln!(&mut out, "impl BuiltinFunction {{").unwrap();
936950
render_builtin_name_method(&mut out, &builtin_variant_order, &actual_builtin_by_variant);
951+
render_builtin_capability_method(&mut out, builtin_callables);
937952
render_builtin_arity_method(&mut out, &builtin_variant_order, &actual_builtin_by_variant);
938953
render_builtin_accepts_arity_method(
939954
&mut out,
@@ -1075,6 +1090,12 @@ fn render_builtin_runtime_dispatch(
10751090
)
10761091
.unwrap();
10771092
}
1093+
writeln!(
1094+
&mut out,
1095+
" registry.mark_runtime_owned_pending({:?});",
1096+
callable.name
1097+
)
1098+
.unwrap();
10781099
}
10791100
writeln!(&mut out, "}}").unwrap();
10801101
writeln!(&mut out).unwrap();
@@ -1091,6 +1112,12 @@ fn render_builtin_runtime_dispatch(
10911112
.render_bind_static_call(&callable.name, &host_wrapper_adapter_name(callable));
10921113
writeln!(&mut out, " {:?} => {{", callable.name).unwrap();
10931114
writeln!(&mut out, " {bind_call}").unwrap();
1115+
writeln!(
1116+
&mut out,
1117+
" vm.mark_runtime_owned_pending_binding({:?});",
1118+
callable.name
1119+
)
1120+
.unwrap();
10941121
writeln!(&mut out, " true").unwrap();
10951122
writeln!(&mut out, " }}").unwrap();
10961123
}
@@ -1408,6 +1435,35 @@ fn render_builtin_name_method(
14081435
writeln!(out).unwrap();
14091436
}
14101437

1438+
fn render_builtin_capability_method(out: &mut String, builtin_callables: &[CallableDecl]) {
1439+
let mut capability_variants = Vec::new();
1440+
for callable in builtin_callables {
1441+
let variant = builtin_variant_name(&callable.name);
1442+
if !capability_variants.contains(&variant) {
1443+
capability_variants.push(variant);
1444+
}
1445+
}
1446+
capability_variants.sort();
1447+
writeln!(out, " #[cfg(feature = \"runtime\")]").unwrap();
1448+
writeln!(
1449+
out,
1450+
" pub(crate) const fn requires_explicit_host_capability(self) -> bool {{"
1451+
)
1452+
.unwrap();
1453+
if capability_variants.is_empty() {
1454+
writeln!(out, " false").unwrap();
1455+
} else {
1456+
let patterns = capability_variants
1457+
.iter()
1458+
.map(|variant| format!("BuiltinFunction::{variant}"))
1459+
.collect::<Vec<_>>()
1460+
.join(" | ");
1461+
writeln!(out, " matches!(self, {patterns})").unwrap();
1462+
}
1463+
writeln!(out, " }}").unwrap();
1464+
writeln!(out).unwrap();
1465+
}
1466+
14111467
fn render_builtin_arity_method(
14121468
out: &mut String,
14131469
builtin_variant_order: &[String],

crates/rustscript/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ runtime = ["pd_vm_crate/runtime"]
1616
edge-abi = ["pd_vm_crate/edge-abi"]
1717
cli = ["pd_vm_crate/cli"]
1818
cranelift-jit = ["pd_vm_crate/cranelift-jit"]
19+
sqlite = ["pd_vm_crate/sqlite"]
1920

2021
[dependencies]
21-
pd_vm_crate = { package = "pd-vm", path = "../..", version = ">=0.1.0, <1.0.0" }
22+
pd_vm_crate = { package = "pd-vm", path = "../..", version = "=0.1.0", default-features = false }

crates/rustscript/tests/alias_smoke.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,30 @@ fn alias_exports_op_code() {
2121
let _ = rustscript::OpCode::Nop;
2222
let _ = rustscript::OpCode::Add;
2323
}
24+
25+
#[cfg(feature = "runtime")]
26+
#[test]
27+
fn alias_exports_public_runtime_event_contract() {
28+
fn accept_sink<S: rustscript::EventSink>(_sink: S) {}
29+
30+
struct Sink;
31+
impl rustscript::EventSink for Sink {
32+
fn emit(&mut self, _payload: rustscript::EventPayload) -> rustscript::RuntimeResult<()> {
33+
Ok(())
34+
}
35+
}
36+
37+
accept_sink(Sink);
38+
}
39+
40+
#[cfg(feature = "sqlite")]
41+
#[test]
42+
fn alias_exports_public_sqlite_configuration() {
43+
let program = rustscript::compile_source("0;")
44+
.expect("minimal alias SQLite program should compile")
45+
.program;
46+
let mut vm = rustscript::Vm::new(program);
47+
vm.configure_sqlite(rustscript::SqlitePolicy::default());
48+
let _limits = rustscript::SqliteLimits::default();
49+
vm.clear_sqlite_configuration();
50+
}

docs/callable-runtime.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ RustScript bytecode format version 11 (VMBC v11) introduces runtime script call
99
- callable environments are bound through the internal builtin call path; callable creation adds no bytecode opcode.
1010
- `ret` completes the active script frame. A nested frame leaves exactly one result at the caller segment base, using `null` when the body produced no value. Root `ret` keeps the historical program-result stack behavior.
1111

12-
VMBC v11 is a hard format boundary. Decoders reject all earlier versions (v10 and below) with a deterministic unsupported-version error; there is no compatibility decoder and no old-ID alias. The stream includes script-function entry ranges, callable prototypes, function regions, root callable bindings, and call indices drawn from the static builtin catalog. PDRC v6 recordings and AOT artifacts (format 7, ABI 6) use their corresponding bumped versions and include callable metadata in cache identity.
12+
VMBC v11 is a hard format boundary. Decoders reject all earlier versions (v10 and below) with a deterministic unsupported-version error; there is no compatibility decoder and no old-ID alias. The stream includes script-function entry ranges, callable prototypes, function regions, root callable bindings, and call indices drawn from the static builtin catalog. PDRC v6 recordings and AOT artifacts (format 7, ABI 7) use their corresponding bumped versions and include callable metadata in cache identity.
1313

1414
## Static builtin IDs
1515

0 commit comments

Comments
 (0)