[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:
Dan Gohman
2018-08-28 15:27:52 -07:00
committed by GitHub
parent 8e2d01a675
commit 9ada394d11
4 changed files with 23 additions and 4 deletions

View File

@@ -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,

View File

@@ -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;

View File

@@ -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()
} }
} }

View File

@@ -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) -> () {}