kobako 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +25 -0
- data/Cargo.lock +3 -1
- data/README.md +35 -14
- data/data/kobako.wasm +0 -0
- data/ext/kobako/Cargo.toml +11 -1
- data/ext/kobako/src/runtime/cache.rs +168 -4
- data/ext/kobako/src/runtime/dispatch.rs +2 -2
- data/ext/kobako/src/runtime/exports.rs +32 -21
- data/ext/kobako/src/runtime/instance_pre.rs +97 -0
- data/ext/kobako/src/runtime/invocation.rs +12 -69
- data/ext/kobako/src/runtime.rs +371 -384
- data/lib/kobako/catalog/handles.rb +9 -13
- data/lib/kobako/catalog/namespaces.rb +22 -3
- data/lib/kobako/catalog/snippets.rb +9 -1
- data/lib/kobako/codec/decoder.rb +5 -1
- data/lib/kobako/errors.rb +11 -1
- data/lib/kobako/namespace.rb +16 -2
- data/lib/kobako/pool.rb +182 -0
- data/lib/kobako/sandbox.rb +16 -14
- data/lib/kobako/version.rb +1 -1
- data/lib/kobako.rb +1 -0
- data/release-please-config.json +16 -1
- data/sig/kobako/catalog/handles.rbs +0 -2
- data/sig/kobako/errors.rbs +3 -0
- data/sig/kobako/namespace.rbs +2 -0
- data/sig/kobako/pool.rbs +44 -0
- data/sig/kobako/sandbox.rbs +2 -2
- metadata +4 -1
|
@@ -2,29 +2,28 @@
|
|
|
2
2
|
//! [SPEC.md Single-Invocation Slot] (one `Invocation` per OS thread
|
|
3
3
|
//! for the lifetime of one `Runtime::eval` / `Runtime::run` call).
|
|
4
4
|
//!
|
|
5
|
-
//! Owned
|
|
6
|
-
//! and threaded through every host import —
|
|
7
|
-
//! dispatcher reads the bound dispatch Proc,
|
|
8
|
-
//! on `crate::runtime::Runtime` install
|
|
9
|
-
//!
|
|
5
|
+
//! Owned as the data of each per-invocation `wasmtime::Store`
|
|
6
|
+
//! (docs/behavior.md B-49) and threaded through every host import —
|
|
7
|
+
//! the `__kobako_dispatch` dispatcher reads the bound dispatch Proc,
|
|
8
|
+
//! while the run-path methods on `crate::runtime::Runtime` install the
|
|
9
|
+
//! invocation's WASI context + pipes at Store creation
|
|
10
|
+
//! (docs/behavior.md B-03 / B-04).
|
|
10
11
|
//!
|
|
11
12
|
//! The slot also carries the per-invocation wall-clock deadline
|
|
12
13
|
//! (docs/behavior.md B-01, E-19) and the per-invocation linear-memory
|
|
13
14
|
//! delta cap `MemoryLimiter` (docs/behavior.md B-01, E-20). Both are
|
|
14
15
|
//! read from the wasmtime `epoch_deadline_callback` / `ResourceLimiter`
|
|
15
|
-
//! callbacks installed in `crate::runtime::Runtime::
|
|
16
|
+
//! callbacks installed in `crate::runtime::Runtime::new_store`. The
|
|
16
17
|
//! memory cap measures only the `memory.grow` delta past the linear-
|
|
17
|
-
//! memory size captured at invocation entry — the
|
|
18
|
-
//!
|
|
19
|
-
//! budget.
|
|
18
|
+
//! memory size captured at invocation entry — the image's initial
|
|
19
|
+
//! allocation is outside the budget.
|
|
20
20
|
//!
|
|
21
21
|
//! [SPEC.md Single-Invocation Slot]: ../../../../SPEC.md
|
|
22
22
|
|
|
23
|
-
use std::cell::{Ref, RefCell, RefMut};
|
|
24
23
|
use std::time::{Duration, Instant};
|
|
25
24
|
|
|
26
25
|
use magnus::{value::Opaque, Value};
|
|
27
|
-
use wasmtime::
|
|
26
|
+
use wasmtime::ResourceLimiter;
|
|
28
27
|
use wasmtime_wasi::p1::WasiP1Ctx;
|
|
29
28
|
use wasmtime_wasi::p2::pipe::MemoryOutputPipe;
|
|
30
29
|
|
|
@@ -134,14 +133,14 @@ impl Invocation {
|
|
|
134
133
|
}
|
|
135
134
|
|
|
136
135
|
/// Return the current per-run deadline. Read from the epoch-deadline
|
|
137
|
-
/// callback installed by `crate::runtime::Runtime::
|
|
136
|
+
/// callback installed by `crate::runtime::Runtime::new_store`.
|
|
138
137
|
pub(super) fn deadline(&self) -> Option<Instant> {
|
|
139
138
|
self.deadline
|
|
140
139
|
}
|
|
141
140
|
|
|
142
141
|
/// Mutable handle to the embedded `MemoryLimiter`. Required by
|
|
143
142
|
/// the wasmtime `ResourceLimiter` callback wiring in
|
|
144
|
-
/// `crate::runtime::Runtime::
|
|
143
|
+
/// `crate::runtime::Runtime::new_store`
|
|
145
144
|
/// (`store.limiter(|state| state.limiter_mut())`); kept private to
|
|
146
145
|
/// the wasm submodule so the only public surface for arming the
|
|
147
146
|
/// cap goes through `Invocation::arm_memory_cap` /
|
|
@@ -362,62 +361,6 @@ impl std::fmt::Display for TimeoutTrap {
|
|
|
362
361
|
|
|
363
362
|
impl std::error::Error for TimeoutTrap {}
|
|
364
363
|
|
|
365
|
-
/// Interior-mutability wrapper around `wasmtime::Store<Invocation>`.
|
|
366
|
-
///
|
|
367
|
-
/// Magnus requires `Send + Sync` for wrapped types. `wasmtime::Store` is not
|
|
368
|
-
/// `Sync`, so we wrap it in a `RefCell`. `RefCell` alone is sufficient
|
|
369
|
-
/// because magnus enforces single-threaded GVL access from Ruby; `Send` and
|
|
370
|
-
/// `Sync` are asserted via the unsafe impls below.
|
|
371
|
-
pub(super) struct StoreCell {
|
|
372
|
-
inner: RefCell<WtStore<Invocation>>,
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
impl StoreCell {
|
|
376
|
-
/// Wrap a freshly-built `wasmtime::Store<Invocation>` so it can be owned
|
|
377
|
-
/// by the magnus-wrapped `Runtime`.
|
|
378
|
-
pub(super) fn new(store: WtStore<Invocation>) -> Self {
|
|
379
|
-
Self {
|
|
380
|
-
inner: RefCell::new(store),
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/// Immutable borrow of the wrapped Store. Panics if a `borrow_mut()`
|
|
385
|
-
/// is currently live — matches `RefCell::borrow` semantics.
|
|
386
|
-
pub(super) fn borrow(&self) -> Ref<'_, WtStore<Invocation>> {
|
|
387
|
-
self.inner.borrow()
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/// Mutable borrow of the wrapped Store. Panics if any other borrow is
|
|
391
|
-
/// currently live — matches `RefCell::borrow_mut` semantics.
|
|
392
|
-
pub(super) fn borrow_mut(&self) -> RefMut<'_, WtStore<Invocation>> {
|
|
393
|
-
self.inner.borrow_mut()
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// SAFETY: magnus requires `Send + Sync` on `#[magnus::wrap]` types. Both
|
|
398
|
-
// claims hold under the GVL invariant:
|
|
399
|
-
//
|
|
400
|
-
// * Send — `wasmtime::Store<Invocation>` is itself `Send` (verified
|
|
401
|
-
// upstream by wasmtime; see `wasmtime::Store`'s trait impls).
|
|
402
|
-
// `RefCell<T>: Send` whenever `T: Send`. The remaining stored state
|
|
403
|
-
// (`Invocation`) holds `Opaque<Value>` for the Ruby Server handle —
|
|
404
|
-
// `Opaque<Value>` is documented as `Send` by magnus precisely so
|
|
405
|
-
// wrapped objects can satisfy this bound.
|
|
406
|
-
//
|
|
407
|
-
// * Sync — `RefCell` is *not* `Sync` in the general Rust sense
|
|
408
|
-
// (concurrent `borrow_mut` is UB). We assert `Sync` here because the
|
|
409
|
-
// GVL serialises every call into Ruby C and every entry into magnus-
|
|
410
|
-
// wrapped methods onto a single OS thread at a time: by the time the
|
|
411
|
-
// `Sync` bound matters, magnus has already established that only one
|
|
412
|
-
// thread can be inside the wrapper. Cross-thread mutation cannot
|
|
413
|
-
// occur. If a future magnus release adopts a thread model that
|
|
414
|
-
// permits concurrent access to wrapped objects, this assertion would
|
|
415
|
-
// have to revert and `StoreCell` would need to switch to
|
|
416
|
-
// `Mutex<wasmtime::Store<…>>` — but as of magnus 0.8 the contract
|
|
417
|
-
// holds.
|
|
418
|
-
unsafe impl Send for StoreCell {}
|
|
419
|
-
unsafe impl Sync for StoreCell {}
|
|
420
|
-
|
|
421
364
|
#[cfg(test)]
|
|
422
365
|
mod tests {
|
|
423
366
|
//! Unit tests for `MemoryLimiter` — the per-invocation memory
|