Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only map with executable permissions when using code space #1176

Merged
merged 9 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,12 @@ set_unlog_bits_vm_space = []
# TODO: This is not properly implemented yet. We currently use an immortal space instead, and do not guarantee read-only semantics.
ro_space = []
# A code space with execution permission.
# TODO: This is not properly implemented yet. We currently use an immortal space instead, and all our spaces have execution permission at the moment.
code_space = []

# By default, we only allow execution permission for code spaces. With this feature, all the spaces have execution permission.
# Use with care.
exec_permission_on_all_spaces = []

# Global valid object (VO) bit metadata.
# The VO bit is set when an object is allocated, and cleared when the GC determines it is dead.
# See `src/util/metadata/vo_bit/mod.rs`
Expand Down
4 changes: 2 additions & 2 deletions docs/userguide/src/tutorial/code/mygc_semispace/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ impl<VM: VMBinding> MyGC<VM> {
let res = MyGC {
hi: AtomicBool::new(false),
// ANCHOR: copyspace_new
copyspace0: CopySpace::new(plan_args.get_space_args("copyspace0", true, VMRequest::discontiguous()), false),
copyspace0: CopySpace::new(plan_args.get_space_args("copyspace0", true, false, VMRequest::discontiguous()), false),
// ANCHOR_END: copyspace_new
copyspace1: CopySpace::new(plan_args.get_space_args("copyspace1", true, VMRequest::discontiguous()), true),
copyspace1: CopySpace::new(plan_args.get_space_args("copyspace1", true, false, VMRequest::discontiguous()), true),
common: CommonPlan::new(plan_args),
};

Expand Down
4 changes: 0 additions & 4 deletions src/mmtk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,6 @@ impl<VM: VMBinding> MMTK<VM> {
},
);

if *options.transparent_hugepages {
MMAPPER.set_mmap_strategy(crate::util::memory::MmapStrategy::TransparentHugePages);
}

MMTK {
options,
state,
Expand Down
4 changes: 2 additions & 2 deletions src/plan/generational/copying/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,11 @@ impl<VM: VMBinding> GenCopy<VM> {
};

let copyspace0 = CopySpace::new(
plan_args.get_space_args("copyspace0", true, VMRequest::discontiguous()),
plan_args.get_space_args("copyspace0", true, false, VMRequest::discontiguous()),
false,
);
let copyspace1 = CopySpace::new(
plan_args.get_space_args("copyspace1", true, VMRequest::discontiguous()),
plan_args.get_space_args("copyspace1", true, false, VMRequest::discontiguous()),
true,
);

Expand Down
2 changes: 1 addition & 1 deletion src/plan/generational/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub struct CommonGenPlan<VM: VMBinding> {
impl<VM: VMBinding> CommonGenPlan<VM> {
pub fn new(mut args: CreateSpecificPlanArgs<VM>) -> Self {
let nursery = CopySpace::new(
args.get_space_args("nursery", true, VMRequest::discontiguous()),
args.get_space_args("nursery", true, false, VMRequest::discontiguous()),
true,
);
let full_heap_gc_count = args
Expand Down
2 changes: 1 addition & 1 deletion src/plan/generational/immix/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl<VM: VMBinding> GenImmix<VM> {
crate::plan::generational::new_generational_global_metadata_specs::<VM>(),
};
let immix_space = ImmixSpace::new(
plan_args.get_space_args("immix_mature", true, VMRequest::discontiguous()),
plan_args.get_space_args("immix_mature", true, false, VMRequest::discontiguous()),
ImmixSpaceArgs {
reset_log_bit_in_major_gc: false,
// We don't need to unlog objects at tracing. Instead, we unlog objects at copying.
Expand Down
12 changes: 10 additions & 2 deletions src/plan/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,11 +396,13 @@ impl<'a, VM: VMBinding> CreateSpecificPlanArgs<'a, VM> {
&mut self,
name: &'static str,
zeroed: bool,
permission_exec: bool,
vmrequest: VMRequest,
) -> PlanCreateSpaceArgs<VM> {
PlanCreateSpaceArgs {
name,
zeroed,
permission_exec,
vmrequest,
global_side_metadata_specs: self.global_side_metadata_specs.clone(),
vm_map: self.global_args.vm_map,
Expand All @@ -409,7 +411,7 @@ impl<'a, VM: VMBinding> CreateSpecificPlanArgs<'a, VM> {
constraints: self.constraints,
gc_trigger: self.global_args.gc_trigger.clone(),
scheduler: self.global_args.scheduler.clone(),
options: &self.global_args.options,
options: self.global_args.options.clone(),
global_state: self.global_args.state.clone(),
}
}
Expand All @@ -423,24 +425,28 @@ impl<VM: VMBinding> BasePlan<VM> {
code_space: ImmortalSpace::new(args.get_space_args(
"code_space",
true,
true,
VMRequest::discontiguous(),
)),
#[cfg(feature = "code_space")]
code_lo_space: ImmortalSpace::new(args.get_space_args(
"code_lo_space",
true,
true,
VMRequest::discontiguous(),
)),
#[cfg(feature = "ro_space")]
ro_space: ImmortalSpace::new(args.get_space_args(
"ro_space",
true,
false,
VMRequest::discontiguous(),
)),
#[cfg(feature = "vm_space")]
vm_space: VMSpace::new(args.get_space_args(
"vm_space",
false,
false, // it doesn't matter -- we are not mmapping for VM space.
VMRequest::discontiguous(),
)),

Expand Down Expand Up @@ -585,15 +591,17 @@ impl<VM: VMBinding> CommonPlan<VM> {
immortal: ImmortalSpace::new(args.get_space_args(
"immortal",
true,
false,
VMRequest::discontiguous(),
)),
los: LargeObjectSpace::new(
args.get_space_args("los", true, VMRequest::discontiguous()),
args.get_space_args("los", true, false, VMRequest::discontiguous()),
false,
),
nonmoving: ImmortalSpace::new(args.get_space_args(
"nonmoving",
true,
false,
VMRequest::discontiguous(),
)),
base: BasePlan::new(args),
Expand Down
2 changes: 1 addition & 1 deletion src/plan/immix/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl<VM: VMBinding> Immix<VM> {
) -> Self {
let immix = Immix {
immix_space: ImmixSpace::new(
plan_args.get_space_args("immix", true, VMRequest::discontiguous()),
plan_args.get_space_args("immix", true, false, VMRequest::discontiguous()),
space_args,
),
common: CommonPlan::new(plan_args),
Expand Down
8 changes: 6 additions & 2 deletions src/plan/markcompact/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,12 @@ impl<VM: VMBinding> MarkCompact<VM> {
global_side_metadata_specs,
};

let mc_space =
MarkCompactSpace::new(plan_args.get_space_args("mc", true, VMRequest::discontiguous()));
let mc_space = MarkCompactSpace::new(plan_args.get_space_args(
"mc",
true,
false,
VMRequest::discontiguous(),
));

let res = MarkCompact {
mc_space,
Expand Down
1 change: 1 addition & 0 deletions src/plan/marksweep/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ impl<VM: VMBinding> MarkSweep<VM> {
ms: MarkSweepSpace::new(plan_args.get_space_args(
"ms",
true,
false,
VMRequest::discontiguous(),
)),
common: CommonPlan::new(plan_args),
Expand Down
3 changes: 3 additions & 0 deletions src/plan/nogc/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,19 @@ impl<VM: VMBinding> NoGC<VM> {
nogc_space: NoGCImmortalSpace::new(plan_args.get_space_args(
"nogc_space",
cfg!(not(feature = "nogc_no_zeroing")),
false,
VMRequest::discontiguous(),
)),
immortal: ImmortalSpace::new(plan_args.get_space_args(
"immortal",
true,
false,
VMRequest::discontiguous(),
)),
los: ImmortalSpace::new(plan_args.get_space_args(
"los",
true,
false,
VMRequest::discontiguous(),
)),
base: BasePlan::new(plan_args),
Expand Down
2 changes: 1 addition & 1 deletion src/plan/pageprotect/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl<VM: VMBinding> PageProtect<VM> {

let ret = PageProtect {
space: LargeObjectSpace::new(
plan_args.get_space_args("pageprotect", true, VMRequest::discontiguous()),
plan_args.get_space_args("pageprotect", true, false, VMRequest::discontiguous()),
true,
),
common: CommonPlan::new(plan_args),
Expand Down
4 changes: 2 additions & 2 deletions src/plan/semispace/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,11 @@ impl<VM: VMBinding> SemiSpace<VM> {
let res = SemiSpace {
hi: AtomicBool::new(false),
copyspace0: CopySpace::new(
plan_args.get_space_args("copyspace0", true, VMRequest::discontiguous()),
plan_args.get_space_args("copyspace0", true, false, VMRequest::discontiguous()),
false,
),
copyspace1: CopySpace::new(
plan_args.get_space_args("copyspace1", true, VMRequest::discontiguous()),
plan_args.get_space_args("copyspace1", true, false, VMRequest::discontiguous()),
true,
),
common: CommonPlan::new(plan_args),
Expand Down
6 changes: 5 additions & 1 deletion src/policy/largeobjectspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,11 @@ impl<VM: VMBinding> LargeObjectSpace<VM> {
} else {
FreeListPageResource::new_contiguous(common.start, common.extent, vm_map)
};
pr.protect_memory_on_release = protect_memory_on_release;
pr.protect_memory_on_release = if protect_memory_on_release {
Some(common.mmap_strategy().prot)
} else {
None
};
LargeObjectSpace {
pr,
common,
Expand Down
9 changes: 4 additions & 5 deletions src/policy/lockfreeimmortalspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,10 @@ impl<VM: VMBinding> LockFreeImmortalSpace<VM> {
};

// Eagerly memory map the entire heap (also zero all the memory)
let strategy = if *args.options.transparent_hugepages {
MmapStrategy::TransparentHugePages
} else {
MmapStrategy::Normal
};
let strategy = MmapStrategy::new(
*args.options.transparent_hugepages,
crate::util::memory::MmapProtection::ReadWrite,
);
crate::util::memory::dzmmap_noreplace(start, aligned_total_bytes, strategy).unwrap();
if space
.metadata
Expand Down
37 changes: 29 additions & 8 deletions src/policy/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::util::heap::layout::Mmapper;
use crate::util::heap::layout::VMMap;
use crate::util::heap::space_descriptor::SpaceDescriptor;
use crate::util::heap::HeapMeta;
use crate::util::memory;
use crate::util::memory::{self, HugePageSupport, MmapProtection, MmapStrategy};
use crate::vm::VMBinding;

use std::marker::PhantomData;
Expand Down Expand Up @@ -137,13 +137,13 @@ pub trait Space<VM: VMBinding>: 'static + SFT + Sync + Downcast {
);
let bytes = conversions::pages_to_bytes(res.pages);

let map_sidemetadata = || {
let mmap = || {
// Mmap the pages and the side metadata, and handle error. In case of any error,
// we will either call back to the VM for OOM, or simply panic.
if let Err(mmap_error) = self
.common()
.mmapper
.ensure_mapped(res.start, res.pages)
.ensure_mapped(res.start, res.pages, self.common().mmap_strategy())
.and(
self.common()
.metadata
Expand All @@ -160,7 +160,7 @@ pub trait Space<VM: VMBinding>: 'static + SFT + Sync + Downcast {
// The scope of the lock is important in terms of performance when we have many allocator threads.
if SFT_MAP.get_side_metadata().is_some() {
// If the SFT map uses side metadata, so we have to initialize side metadata first.
map_sidemetadata();
mmap();
// then grow space, which will use the side metadata we mapped above
grow_space();
// then we can drop the lock after grow_space()
Expand All @@ -170,7 +170,7 @@ pub trait Space<VM: VMBinding>: 'static + SFT + Sync + Downcast {
grow_space();
drop(lock);
// and map side metadata without holding the lock
map_sidemetadata();
mmap();
}

// TODO: Concurrent zeroing
Expand Down Expand Up @@ -421,11 +421,13 @@ pub struct CommonSpace<VM: VMBinding> {
// the copy semantics for the space.
pub copy: Option<CopySemantics>,

immortal: bool,
movable: bool,
pub immortal: bool,
pub movable: bool,
pub contiguous: bool,
pub zeroed: bool,

pub permission_exec: bool,

pub start: Address,
pub extent: usize,

Expand All @@ -443,6 +445,7 @@ pub struct CommonSpace<VM: VMBinding> {

pub gc_trigger: Arc<GCTrigger<VM>>,
pub global_state: Arc<GlobalState>,
pub options: Arc<Options>,

p: PhantomData<VM>,
}
Expand All @@ -459,6 +462,7 @@ pub struct PolicyCreateSpaceArgs<'a, VM: VMBinding> {
pub struct PlanCreateSpaceArgs<'a, VM: VMBinding> {
pub name: &'static str,
pub zeroed: bool,
pub permission_exec: bool,
pub vmrequest: VMRequest,
pub global_side_metadata_specs: Vec<SideMetadataSpec>,
pub vm_map: &'static dyn VMMap,
Expand All @@ -467,7 +471,7 @@ pub struct PlanCreateSpaceArgs<'a, VM: VMBinding> {
pub constraints: &'a PlanConstraints,
pub gc_trigger: Arc<GCTrigger<VM>>,
pub scheduler: Arc<GCWorkScheduler<VM>>,
pub options: &'a Options,
pub options: Arc<Options>,
pub global_state: Arc<GlobalState>,
}

Expand Down Expand Up @@ -498,6 +502,7 @@ impl<VM: VMBinding> CommonSpace<VM> {
immortal: args.immortal,
movable: args.movable,
contiguous: true,
permission_exec: args.plan_args.permission_exec,
zeroed: args.plan_args.zeroed,
start: unsafe { Address::zero() },
extent: 0,
Expand All @@ -511,6 +516,7 @@ impl<VM: VMBinding> CommonSpace<VM> {
},
acquire_lock: Mutex::new(()),
global_state: args.plan_args.global_state,
options: args.plan_args.options.clone(),
p: PhantomData,
};

Expand Down Expand Up @@ -619,6 +625,21 @@ impl<VM: VMBinding> CommonSpace<VM> {
pub fn vm_map(&self) -> &'static dyn VMMap {
self.vm_map
}

pub fn mmap_strategy(&self) -> MmapStrategy {
MmapStrategy {
huge_page: if *self.options.transparent_hugepages {
HugePageSupport::TransparentHugePages
} else {
HugePageSupport::No
},
prot: if self.permission_exec || cfg!(feature = "exec_permission_on_all_spaces") {
MmapProtection::ReadWriteExec
} else {
MmapProtection::ReadWrite
},
}
}
}

fn get_frac_available(frac: f32) -> usize {
Expand Down
Loading
Loading