Skip to content

[vm] Add NoGC scopes to flow graph builder #48527

Open
@dcharkes

Description

@dcharkes

We have at least two places (soon to be three) where we rely in IL that the GC doesn't run between certain IL instructions.

// No GC from here til LoadIndexed.
body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += LoadLocal(arg_offset_not_null);
body += UnboxTruncate(kUnboxedFfiIntPtr);
body += LoadIndexed(typed_data_cid, /*index_scale=*/1,
/*index_unboxed=*/true, alignment);

// No GC from here til StoreIndexed.
body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += LoadLocal(arg_offset_not_null);
body += UnboxTruncate(kUnboxedFfiIntPtr);
body += LoadLocal(arg_value_not_null);
if (kind == MethodRecognizer::kFfiStorePointer) {
// This can only be Pointer, so it is always safe to LoadUntagged.
body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
} else {
// Avoid any unnecessary (and potentially deoptimizing) int
// conversions by using the representation consumed by StoreIndexed.
body += UnboxTruncate(
StoreIndexedInstr::RepresentationOfArrayElement(typed_data_cid));
if (kind == MethodRecognizer::kFfiStoreFloat ||
kind == MethodRecognizer::kFfiStoreFloatUnaligned) {
body += DoubleToFloat();
}
}
body += StoreIndexedTypedData(typed_data_cid, /*index_scale=*/1,
/*index_unboxed=*/true, alignment);

Currently, we:

  1. force optimize them
  2. prevent them from being inlined (by being force optimized)

Preventing inlining gives us enough confidence that code motion doesn't move any GCing instructions in between currently.

If we start inlining these, we need to take special care that code motion doesn't move an instruction that can trigger GC in between those instructions:

We should consider adding a NoGC-scope construct that:

  • Checks that only IL instructions with kNoGC are added to that scope
  • Prevents code motion of any kNoGC instructions out of that scope and prevents code motion of any non-kNoGC into that scope.

cc @mkustermann @mraleph (I don't believe we had a tracking issue yet.)

Edit: For the two existing cases running GC is fine, they happen to be idempotent, for the new case it is not. Having this NoGC-scope clarifies the difference.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-vmUse area-vm for VM related issues, including code coverage, and the AOT and JIT backends.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions