From c53fbb4a5cece66c2a41bf4647bbe75ce191f9b5 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Tue, 30 Nov 2021 14:27:35 -0800 Subject: [PATCH] Fix fuzzbug related to bundle priority ordering. Changes in computation of bundle priorities during review of the initial PR introduced a possible mis-ordering of priorities: inner-loop bundle use weights could exceed the weights of 1_000_000 and 2_000_000 used for minimal bundles without and with fixed uses (respectively). These two kinds of minimal bundle are meant to be the highest-priority bundles, evicting any other bundle they need to, because they can't be split further. This PR introduces two special bundle weights for these two kinds of bundles, and clamps all other bundle weights to just below them. Thanks to @Amanieu for reporting the issue! Fixes #19. --- src/checker.rs | 2 +- src/ion/data_structures.rs | 7 ++++++- src/ion/process.rs | 16 ++++++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/checker.rs b/src/checker.rs index 55f4860..bf5c098 100644 --- a/src/checker.rs +++ b/src/checker.rs @@ -78,7 +78,7 @@ use crate::{ Allocation, AllocationKind, Block, Edit, Function, Inst, InstPosition, Operand, - OperandConstraint, OperandKind, OperandPos, Output, PReg, ProgPoint, RegClass, VReg, + OperandConstraint, OperandKind, OperandPos, Output, PReg, ProgPoint, VReg, }; use std::collections::{HashMap, HashSet, VecDeque}; diff --git a/src/ion/data_structures.rs b/src/ion/data_structures.rs index d1caa7f..711755e 100644 --- a/src/ion/data_structures.rs +++ b/src/ion/data_structures.rs @@ -185,6 +185,11 @@ pub struct LiveBundle { pub spill_weight_and_props: u32, } +pub const BUNDLE_MAX_SPILL_WEIGHT: u32 = (1 << 29) - 1; +pub const MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT; +pub const MINIMAL_BUNDLE_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT - 1; +pub const BUNDLE_MAX_NORMAL_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT - 2; + impl LiveBundle { #[inline(always)] pub fn set_cached_spill_weight_and_props( @@ -194,7 +199,7 @@ impl LiveBundle { fixed: bool, stack: bool, ) { - debug_assert!(spill_weight < ((1 << 29) - 1)); + debug_assert!(spill_weight <= BUNDLE_MAX_SPILL_WEIGHT); self.spill_weight_and_props = spill_weight | (if minimal { 1 << 31 } else { 0 }) | (if fixed { 1 << 30 } else { 0 }) diff --git a/src/ion/process.rs b/src/ion/process.rs index 7ee9e1c..123ae30 100644 --- a/src/ion/process.rs +++ b/src/ion/process.rs @@ -13,11 +13,15 @@ //! Main allocation loop that processes bundles. use super::{ - spill_weight_from_constraint, CodeRange, Env, LiveBundleIndex, LiveBundleVec, LiveRangeFlag, + spill_weight_from_constraint, Env, LiveBundleIndex, LiveBundleVec, LiveRangeFlag, LiveRangeIndex, LiveRangeKey, LiveRangeList, LiveRangeListEntry, PRegIndex, RegTraversalIter, Requirement, SpillWeight, UseList, }; use crate::{ + ion::data_structures::{ + CodeRange, BUNDLE_MAX_NORMAL_SPILL_WEIGHT, MINIMAL_BUNDLE_SPILL_WEIGHT, + MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT, + }, Allocation, Function, Inst, InstPosition, OperandConstraint, OperandKind, PReg, ProgPoint, RegAllocError, }; @@ -302,11 +306,11 @@ impl<'a, F: Function> Env<'a, F> { let spill_weight = if minimal { if fixed { - log::trace!(" -> fixed and minimal: spill weight 2000000"); - 2_000_000 + log::trace!(" -> fixed and minimal"); + MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT } else { - log::trace!(" -> non-fixed and minimal: spill weight 1000000"); - 1_000_000 + log::trace!(" -> non-fixed and minimal"); + MINIMAL_BUNDLE_SPILL_WEIGHT } } else { let mut total = SpillWeight::zero(); @@ -326,7 +330,7 @@ impl<'a, F: Function> Env<'a, F> { self.bundles[bundle.index()].prio, final_weight ); - final_weight + std::cmp::min(BUNDLE_MAX_NORMAL_SPILL_WEIGHT, final_weight) } else { 0 }