Skip to content

Issues with TraceKind #1314

Open
Open
@qinsoon

Description

@qinsoon

We currently use TraceKind (a u8 value) to decouple plan, work packets, and the tracing function in the policy. Basically, a plan creates work packets that carry TraceKind const values. The policy trace objects according to the TraceKind value.

The benefits from this design

  1. It decouples plan, work packets and policies. Work packets are general and can be used for multiple plans. Policies are unaware of the plan, and only trace objects according to the TraceKind. In Java MMTk, a plan directly calls to the tracing function in the policies, which no longer works for MMTk core.
  2. TraceKind is a const generic parameter, and the Rust compiler can specialize code based on the const. Thus it introduces no overhead.

TraceKind values

Global

255 - DEFAULT_TRACE
254 - TRACE_KIND_TRANSITIVE_PIN

Plan specific

Mark Compact: 0 - TRACE_KIND_MARK, 1 - TRACE_KIND_FORWARD
Immix: 0 - TRACE_KIND_FAST, 1 - TRACE_KIND_DEFRAG

Issues

Conflict of plan specific values

If we use mark compact along with an Immix space, the same TraceKind value will be interpreted differently by each policy. E.g. 0 is marking trace for mark compact, and also the fast trace for Immix. This causes unintended behavior.

Cross product of TraceKind among policies

To solve the previous issue, we could use different values for plan specific TraceKind, such as 0 - TRACE_KIND_MC_MARK, 1 - TRACE_KIND_MC_FORWARD, 2 - TRACE_KIND_IX_FAST, 3 - TRACE_KIND_IX_DEFRAG. This leads to an unreasonable situation that Immix needs to know what to do in a mark compact marking trace.

TraceKind is skipped in some cases

For sticky immix's nursery GC (GenNurseryProcessEdges), we use DEFAULT_TRACE, but Immix does not have code in its tracing function to deal with DEFAULT_TRACE. Instead, GenNurseryProcessEdges calls functions in the plan which specifically calls tracing functions in the policies. This causes confusion.

TraceKind cannot not solely decide the tracing behavior.

The function may_move_objects<const KIND: TraceKind>() -> bool is implemented for each policy, and only uses TraceKind to determine whether the policy may move objects in a trace. When we have two Immix spaces, one for moving, and one for non moving, this function no longer works -- we need information from the space instance to know whether it will move objects or not. Though we can conservatively state that the policy may move objects even if the instance does not really move objects, this causes confusion as well.

Solution

We should remove plan-specific traces, and only have a few defined general TraceKind, and each policy needs to know what to do for such cases. E.g.

TraceKind Immix MarkCompact
default non moving marking
exhaustive defrag/moving if the instance allows moving fall back to default
nursery not reachable -- handled specifically not reachable
secondary fall back to default forwarding
transitive pinning non moving panic

may_move_objects needs to take a self paramter, or conservatively states that it may move objects if it is uncertain.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions