This repository has been archived by the owner on Mar 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 165
/
region.rs
148 lines (126 loc) · 5.62 KB
/
region.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
pub mod mmap;
#[cfg(all(target_os = "linux", feature = "uffd"))]
pub mod uffd;
use crate::alloc::{Alloc, AllocStrategy, Limits, Slot};
use crate::embed_ctx::CtxMap;
use crate::error::Error;
use crate::instance::InstanceHandle;
use crate::module::Module;
use std::any::Any;
use std::sync::Arc;
/// A memory region in which Lucet instances are created and run.
///
/// These methods return an [`InstanceHandle`](struct.InstanceHandle.html) smart pointer rather than
/// the `Instance` itself. This allows the region implementation complete control of where the
/// instance metadata is stored.
pub trait Region: RegionInternal {
/// Create a new instance within the region.
///
/// Calling `region.new_instance(module)` is shorthand for
/// `region.new_instance_builder(module).build()` for use when further customization is
/// unnecessary.
fn new_instance(&self, module: Arc<dyn Module>) -> Result<InstanceHandle, Error> {
self.new_instance_builder(module).build()
}
/// Return an [`InstanceBuilder`](struct.InstanceBuilder.html) for the given module.
fn new_instance_builder<'a>(&'a self, module: Arc<dyn Module>) -> InstanceBuilder<'a> {
InstanceBuilder::new(self.as_dyn_internal(), module)
}
/// Return the number of instance slots that are currently free in the region.
///
/// A value greater than zero does not guarantee that a subsequent call to
/// `Region::new_instance()` will succeed, as other threads may instantiate from the region in
/// the meantime.
fn free_slots(&self) -> usize;
/// Return the number of instance slots that are currently in use in the region.
///
/// A value less than `self.capacity()` does not guarantee that a subsequent call to
/// `Region::new_instance()` will succeed, as other threads may instantiate from the region in
/// the meantime.
fn used_slots(&self) -> usize;
/// Return the total instance slot capacity of the region.
fn capacity(&self) -> usize;
}
/// A `RegionInternal` is a collection of `Slot`s which are managed as a whole.
pub trait RegionInternal: Send + Sync {
fn new_instance_with(&self, args: NewInstanceArgs) -> Result<InstanceHandle, Error>;
/// Unmaps the heap, stack, and globals of an `Alloc`, while retaining the virtual address
/// ranges in its `Slot`.
fn drop_alloc(&self, alloc: &mut Alloc);
/// Expand the heap for the given slot to include the given range.
fn expand_heap(&self, slot: &Slot, start: u32, len: u32) -> Result<(), Error>;
fn reset_heap(&self, alloc: &mut Alloc, module: &dyn Module) -> Result<(), Error>;
/// Get the runtime memory size limits
fn get_limits(&self) -> &Limits;
fn as_dyn_internal(&self) -> &dyn RegionInternal;
}
/// A trait for regions that are created with a fixed capacity and limits.
///
/// This is not part of [`Region`](trait.Region.html) so that `Region` types can be made into trait
/// objects.
pub trait RegionCreate: Region {
/// The type name of the region; useful for testing.
const TYPE_NAME: &'static str;
/// Create a new `Region` that can support a given number instances, each subject to the same
/// runtime limits.
fn create(instance_capacity: usize, limits: &Limits) -> Result<Arc<Self>, Error>;
}
/// A builder for instances; created by
/// [`Region::new_instance_builder()`](trait.Region.html#method.new_instance_builder).
pub struct InstanceBuilder<'a> {
region: &'a dyn RegionInternal,
args: NewInstanceArgs,
}
/// Arguments that a region needs to create a new `Instance`.
///
/// This type is primarily created by `InstanceBuilder`, but its definition is public to support
/// out-of-crate implementations of `RegionInternal`.
pub struct NewInstanceArgs {
pub module: Arc<dyn Module>,
pub embed_ctx: CtxMap,
pub heap_memory_size_limit: usize,
pub alloc_strategy: AllocStrategy,
}
impl<'a> InstanceBuilder<'a> {
fn new(region: &'a dyn RegionInternal, module: Arc<dyn Module>) -> Self {
InstanceBuilder {
region,
args: NewInstanceArgs {
module,
embed_ctx: CtxMap::default(),
heap_memory_size_limit: region.get_limits().heap_memory_size,
alloc_strategy: AllocStrategy::Linear,
},
}
}
/// Allocate the instance using the supplied `AllocStrategy`.
///
/// This call is optional. The default allocation strategy for
/// Regions is Linear, which allocates the instance using next available
/// alloc. If a different strategy is desired, choose from those
/// available in `AllocStrategy`.
pub fn with_alloc_strategy(mut self, alloc_strategy: AllocStrategy) -> Self {
self.args.alloc_strategy = alloc_strategy;
self
}
/// Add a smaller, custom limit for the heap memory size to the built instance.
///
/// This call is optional. Attempts to build a new instance fail if the
/// limit supplied by with_heap_size_limit() exceeds that of the region.
pub fn with_heap_size_limit(mut self, heap_memory_size_limit: usize) -> Self {
self.args.heap_memory_size_limit = heap_memory_size_limit;
self
}
/// Add an embedder context to the built instance.
///
/// Up to one context value of any particular type may exist in the instance. If a context value
/// of the same type already exists, it is replaced by the new value.
pub fn with_embed_ctx<T: Any>(mut self, ctx: T) -> Self {
self.args.embed_ctx.insert(ctx);
self
}
/// Build the instance.
pub fn build(self) -> Result<InstanceHandle, Error> {
self.region.new_instance_with(self.args)
}
}