content: [package]
  name = "mmtk"
  version = "0.31.0"
  authors = ["The MMTk Developers <>"]
  edition = "2021"
  license = "MIT OR Apache-2.0"
  description = "MMTk is a framework for the design and implementation of high-performance and portable memory managers."
  homepage = "https://www.mmtk.io"
  repository = "https://github.com/mmtk/mmtk-core"
  readme = "README.md"
  categories = ["memory-management"]
  keywords = ["gc", "garbage", "collection", "garbage-collection", "allocation"]
  rust-version = "1.74.1"
  build = "build.rs"
  
  [lib]
  name = "mmtk"
  crate-type = ["rlib"]
  doctest = false
  
  [dependencies]
  atomic = "0.6.0"
  atomic_refcell = "0.1.7"
  atomic-traits = "0.4.0"
  bytemuck = { version = "1.14.0", features = ["derive", "zeroable_maybe_uninit"] }
  bytemuck_derive = "=1.8.1" # We can remove this dependency when we use MSRV 1.84+
  cfg-if = "1.0"
  crossbeam = "0.8.1"
  delegate = "0.13.2"
  downcast-rs = "2.0.1"
  enum-map = "2.7.3"
  env_logger = { version = "0.11.3", optional = true }
  is-terminal = "0.4.7"
  itertools = "0.14.0"
  jemalloc-sys = { version = "0.5.3", features = ["disable_initial_exec_tls"], optional = true }
  lazy_static = "1.1"
  libc = "0.2"
  log = { version = "0.4", features = ["max_level_trace", "release_max_level_off"] }
  memoffset = "0.9"
  mimalloc-sys = { version = "0.1.6", optional = true }
  # MMTk macros - we have to specify a version here in order to publish the crate, even though we use the dependency from a local path.
  mmtk-macros = { version="0.31.0", path = "macros/" }
  num_cpus = "1.8"
  num-traits = "0.2"
  pfm = { version = "0.1.1", optional = true }
  portable-atomic = "1.4.3"
  probe = "0.5"
  regex = "1.7.0"
  rustversion = "1.0"
  rayon-core = "=1.12.1" # We can remove this dependency when we use MSRV 1.80+
  spin = "0.9.5"
  static_assertions = "1.1.0"
  strum = "0.27.1"
  strum_macros = "0.27.1"
  sysinfo = "0.33.1"
  
  [dev-dependencies]
  paste = "1.0.8"
  rand = "0.9.0"
  rand_chacha = "0.9.0"
  criterion = "0.5"
  # Note: `half` v2.5.0 started to require Rust 1.81.
  # `criterion` transitively depends on `half` via the dependency chain:
  #     criterion -> ciborium -> ciborium_ll -> half
  # The MSRV of `ciborium` v0.2.2 is declared as 1.58, and is declared to depend on `half` v2.2.
  # Ciborium should either bump its MSRV or select a version of `half` that satisfies its current MSRV.
  # We lock the version of `half` to 2.4.1 to workaround this.
  # TODO: When we bump MSRV to 1.84 or above, we can rely on Cargo's MSRV-aware dependency resolver and remove such workarounds.
  half = "=2.4.1"
  
  [build-dependencies]
  built = { version = "0.7.7", features = ["git2"] }
  # Note: Some components in ICU4X started to require Rust 1.81 since some versions, such as `litemap` v0.7.5.
  # The `built` crate depends on ICU4X via the dependency chain:
  #     built -> git2 -> url -> idna -> idna_adapter --(default)--------> crates from the ICU4X projects
  #                                                  --(alternatively)--> `unicode-rs`
  # But we don't need ICU4X (or even `url`) because we only use `git2` to get the Git commit hash.
  # We move away from ICU4X completely following the instruction in https://docs.rs/crate/idna_adapter/1.2.0
  idna_adapter = "=1.1.0"
  
  [lints.clippy]
  # Allow this. Clippy suggests we should use Sft, Mmtk, rather than SFT and MMTK.
  # According to its documentation (https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms),
  # with upper-case-acronyms-aggressive turned on, it should also warn us about SFTMap, VMBinding, GCWorker.
  # However, it seems clippy does not catch all these patterns at the moment. So it would be hard for us to
  # find all the patterns and consistently change all of them. I think it would be a better idea to just allow this.
  # We may reconsider this in the future. Plus, using upper case letters for acronyms does not sound a big issue
  # to me - considering it will break our API and all the efforts for all the developers to make the change, it may
  # not worth it.
  upper_case_acronyms = "allow"
  # Temporarily allow this -- 9 July 2025. Clippy suggests that we should always inline format args if possible.
  # We see pushbacks on this lint in Rust 1.67, and the lint was downgraded to pedantic in 1.67.1. It was upgraded
  # again in Rust 1.88. We temporarily disable this lint and see the reaction from the community.
  # If there is no pushback for this lint in a few momnths' time, we should remove the following line and migrate the codebase.
  # See https://github.com/mmtk/mmtk-core/issues/1334.
  uninlined_format_args = "allow"
  
  [[bench]]
  name = "main"
  harness = false
  
  [features]
  default = ["builtin_env_logger"]
  
  # Built-in env_logger.  This feature is enabled by default.
  # The user can disable this default feature to remove `env_logger` from the dependencies.
  # See `crate::util::logger` for more details.
  builtin_env_logger = ["dep:env_logger"]
  
  # Enable this feature if you want to use nightly features and compiler
  nightly = []
  
  # This feature is only supported on x86-64 for now
  # It's manually added to CI scripts
  perf_counter = ["dep:pfm"]
  
  # This feature is only used for tests with MockVM.
  # CI scripts run those tests with this feature.
  mock_test = ["test_private"]
  
  # This feature will expose some private functions for testings or benchmarking.
  test_private = []
  
  # .github/scripts/ci-common.sh extracts features from the following part (including from comments).
  # So be careful when editing or adding stuff to the section below.
  
  
  # Do not modify the following line - ci-common.sh matches it
  # -- Non mutually exclusive features --
  
  # spaces with different semantics
  
  # A VM-allocated/managed space. A binding could use this for their boot image, metadata space, etc.
  # FIXME: This is not properly implemented yet (it is only working for JikesRVM): https://github.com/mmtk/mmtk-core/issues/415
  # If a binding would need to trace/scan objects that is allocated and managed by the VM, `ActivePlan::vm_trace_object()` is an alternative.
  vm_space = []
  
  # Bulk set unlog bits for all objects inside the VM space. A binding can use
  # this in case they do not have a way to iterate through objects in the
  # bootimage to set the unlog bit. Note that this will set the unlog bit for
  # addresses that may not correspond to valid objects.
  set_unlog_bits_vm_space = []
  
  # A readonly 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.
  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`
  #
  # eager_sweeping: VO bits for dead objects must have been cleared by the end of each GC.
  # Native MarkSweep only ensures this in eager sweeping mode.
  vo_bit = ["eager_sweeping"]
  
  # conservative garbage collection support
  is_mmtk_object = ["vo_bit"]
  
  # Enable object pinning, in particular, enable pinning/unpinning, and its metadata
  object_pinning = []
  
  # The following two features are useful for using Immix for VMs that do not support moving GC.
  
  # Disable any object copying in Immix. This makes Immix a non-moving policy.
  immix_non_moving = []
  
  # Disable any object copying in nursery GC for Sticky Immix while allowing other kinds of copying.
  # `immix_non_moving` disables all kinds of copying in Immix, so this feature is not needed
  # if `immix_non_moving` is in use.
  sticky_immix_non_moving_nursery = []
  
  # Reduce block size for ImmixSpace.  This mitigates fragmentation when defrag is disabled.
  immix_smaller_block = []
  # Zero the unmarked lines after a GC cycle in immix. This helps debug untraced objects.
  immix_zero_on_release = []
  
  # Run sanity GC
  sanity = []
  # Run analysis
  analysis = []
  # Use lock free variant of NoGC
  nogc_lock_free = []
  # Use lock free with no zeroing NoGC
  nogc_no_zeroing = ["nogc_lock_free"]
  # For using a single GC thread
  # Q: Why do we need this as a compile time flat? We can always set the number of GC threads through options.
  single_worker = []
  
  # To run expensive comprehensive runtime checks, such as checking duplicate edges
  extreme_assertions = []
  
  # Enable multiple spaces for NoGC, each allocator maps to an individual ImmortalSpace.
  nogc_multi_space = []
  
  # Disable multiple spaces for Compressor.
  # Enabling this feature will cause the Compressor to move all objects, which will be
  # slower for large objects and will be outright incorrect for bindings which allocate
  # non-moving objects; but compacting all objects will be more space-efficient.
  compressor_single_space = []
  
  # To collect statistics for each GC work packet. Enabling this may introduce a small overhead (several percentage slowdown on benchmark time).
  work_packet_stats = []
  
  # Count the malloc'd memory into the heap size
  malloc_counted_size = []
  
  # Workaround a problem where bpftrace scripts (see tools/tracing/timeline/capture.bt) cannot
  # capture the type names of work packets.
  bpftrace_workaround = []
  
  # Disable mmap annotations.
  # All invocations of `mmap` in mmtk-core are accompanied by calls of `prctl` with
  # `PR_SET_VMA_ANON_NAME` to annotate the mmap ranges with human-readable names.  It is enabled by
  # default and should work fine even with large heap sizes.  However, if this is causing problems,
  # users can disable such annotations by enabling this Cargo feature.
  no_mmap_annotation = []
  
  # Allow the binding to access Valid Object (VO) bit.
  # MMTk uses VO bit to identify a valid object. Thus VO bit is carefully managed by MMTk in cooperation with the binding.
  # So normally this feature is not needed, and its use should be discouraged.
  # However, in rare cases, a binding may want to directly access and manipulate VO bit. For example, a binding cannot cooperate
  # with MMTk to identify each object for setting the VO bit. This is usually due to the limitation of the VM.
  # In such cases, a binding may use this feature and manipulate the VO bit to their needs. The binding's manipulation on VO bit
  # may violate MMTk's semantics, and may result in undefined behaviors for VO bit related APIs. This feature should
  # only be used if you understand how VO bit works internally. Use at your own risk.
  vo_bit_access = []
  
  # Do not modify the following line - ci-common.sh matches it
  # -- Mutally exclusive features --
  # Only one feature from each group can be provided. Otherwise build will fail.
  
  # Name of the mutualy exclusive feature group. ci-common.sh matches lines like this one.
  # Group:malloc
  # only one of the following features should be enabled, or none to use the default malloc from libc
  # this does not replace the global Rust allocator, but provides these libraries for GC implementation
  malloc_mimalloc = ["dep:mimalloc-sys"]
  malloc_jemalloc = ["dep:jemalloc-sys"]
  
  # Use the native mimalloc allocator for malloc. This is not tested by me (Yi) yet, and it is only used to make sure that some code
  # is not compiled in default builds.
  malloc_native_mimalloc = []
  
  # Group:marksweepallocation
  # default is native allocator with lazy sweeping
  eager_sweeping = []
  # Use library malloc as the freelist allocator for mark sweep. This will makes mark sweep slower. As malloc may return addresses outside our
  # normal heap range, we will have to use chunk-based SFT table. Turning on this feature will use a different SFT map implementation on 64bits,
  # and will affect all the plans in the build. Please be aware of the consequence, and this is only meant to be experimental use.
  malloc_mark_sweep = []
  
  # Group:nonmovingspace
  immortal_as_nonmoving = []
  marksweep_as_nonmoving = []
  
  # If there are more groups, they should be inserted above this line
  # Group:end
  