[SimpleJIT] When finalizing multiple functions, make them all executable at the end. (#474)
Add `publish()` function to cranelift-module's `Backend` trait, which allows `finalize_all()` to defer making memory executable until it has finished all of the patching it needs to do.
This commit is contained in:
@@ -281,6 +281,10 @@ impl Backend for FaerieBackend {
|
|||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn publish(&mut self) {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
fn finish(self) -> FaerieProduct {
|
fn finish(self) -> FaerieProduct {
|
||||||
FaerieProduct {
|
FaerieProduct {
|
||||||
artifact: self.artifact,
|
artifact: self.artifact,
|
||||||
|
|||||||
@@ -105,6 +105,9 @@ where
|
|||||||
namespace: &ModuleNamespace<Self>,
|
namespace: &ModuleNamespace<Self>,
|
||||||
) -> Self::FinalizedData;
|
) -> Self::FinalizedData;
|
||||||
|
|
||||||
|
/// "Publish" all finalized functions and data objects to their ultimate destinations.
|
||||||
|
fn publish(&mut self);
|
||||||
|
|
||||||
/// Consume this `Backend` and return a result. Some implementations may
|
/// Consume this `Backend` and return a result. Some implementations may
|
||||||
/// provide additional functionality through this result.
|
/// provide additional functionality through this result.
|
||||||
fn finish(self) -> Self::Product;
|
fn finish(self) -> Self::Product;
|
||||||
|
|||||||
@@ -600,6 +600,7 @@ where
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.contents.functions[func].finalized = true;
|
self.contents.functions[func].finalized = true;
|
||||||
|
self.backend.publish();
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,6 +628,7 @@ where
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.contents.data_objects[data].finalized = true;
|
self.contents.data_objects[data].finalized = true;
|
||||||
|
self.backend.publish();
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,6 +648,9 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for info in self.contents.functions.values_mut() {
|
||||||
|
info.finalized = true;
|
||||||
|
}
|
||||||
for info in self.contents.data_objects.values() {
|
for info in self.contents.data_objects.values() {
|
||||||
if info.decl.linkage.is_definable() && !info.finalized {
|
if info.decl.linkage.is_definable() && !info.finalized {
|
||||||
self.backend.finalize_data(
|
self.backend.finalize_data(
|
||||||
@@ -658,12 +663,16 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for info in self.contents.data_objects.values_mut() {
|
||||||
|
info.finalized = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume the module and return the resulting `Product`. Some `Backend`
|
/// Consume the module and return the resulting `Product`. Some `Backend`
|
||||||
/// implementations may provide additional functionality available after
|
/// implementations may provide additional functionality available after
|
||||||
/// a `Module` is complete.
|
/// a `Module` is complete.
|
||||||
pub fn finish(self) -> B::Product {
|
pub fn finish(mut self) -> B::Product {
|
||||||
|
self.backend.publish();
|
||||||
self.backend.finish()
|
self.backend.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -335,8 +335,6 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we're done patching, make the memory executable.
|
|
||||||
self.code_memory.set_executable();
|
|
||||||
func.code
|
func.code
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,10 +395,15 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.readonly_memory.set_readonly();
|
|
||||||
(data.storage, data.size)
|
(data.storage, data.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn publish(&mut self) {
|
||||||
|
// Now that we're done patching, prepare the memory for execution!
|
||||||
|
self.readonly_memory.set_readonly();
|
||||||
|
self.code_memory.set_executable();
|
||||||
|
}
|
||||||
|
|
||||||
/// SimpleJIT emits code and data into memory as it processes them, so it
|
/// SimpleJIT emits code and data into memory as it processes them, so it
|
||||||
/// doesn't need to provide anything after the `Module` is complete.
|
/// doesn't need to provide anything after the `Module` is complete.
|
||||||
fn finish(self) -> () {}
|
fn finish(self) -> () {}
|
||||||
|
|||||||
Reference in New Issue
Block a user