[gc_fuzz]: Add non-null types - #14276
Conversation
| type_ids_to_index: &BTreeMap<TypeId, u32>, | ||
| ) { | ||
| /// Returns `true` if this field type can be default-constructed. | ||
| pub fn is_defaultable(self) -> bool { |
There was a problem hiding this comment.
reports whether a field type has a default value. Only non-nullable references do not.
| } | ||
|
|
||
| /// Whether `field` can be given a value using only the types in `ok`. | ||
| fn field_satisfiable(&self, field: FieldType, ok: &BTreeMap<TypeId, u32>) -> bool { |
There was a problem hiding this comment.
tells whether a field can be given a value using only a given set of buildable types. A non-nullable concrete reference needs its target in that set. A non-nullable need any non-array in that set.
| } | ||
|
|
||
| /// Return the least-ranked inhabitable struct type, if any. | ||
| pub(crate) fn least_rank_inhabitable_struct( |
There was a problem hiding this comment.
this picks the buildable struct with the lowest round number. This is the struct built to fill a non-nullable (ref struct) field.
|
|
||
| /// Compute the set of types that should be encoded as prototypes, i.e. those | ||
| /// that are referenced by other types. | ||
| pub(crate) fn prototype_types( |
There was a problem hiding this comment.
This decides which types get shared prototype. It costs each type as one instruction per field plus one using each referent's own cost and hoists anything over the budget that something actually points at. So when a nonnull struct needed a new one is created till total # is < 8 after that they were reused. This also may be considered "the first step" to places paradigm.
Subscribe to Label Actioncc @fitzgen DetailsThis issue or pull request has been labeled: "fuzzing"Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
The gc_ops fuzzer never generated non-nullable reference fields. Fixup forced every reference field to nullable, so the generator only ever emitted
(ref null $t)andstructref. This change lets non-nullable fields survive, so the fuzzer now exercises(ref $t)and(ref struct)as well.Two design choices:
Briefly,
inhabitableproves types buildable by fixpoint, so anything it never admits is uninhabitable.fix_uninhabitabletakes one such type per pass and relaxes only the fields that cannot be satisfied to nullable, then re-runs the analysis until every type is admitted. A nullable field can always be filled withref.null, so relaxing one gives the cycle a base case, which usually unblocks several other types at once and leaves well founded non-nullable references untouched.emit_newbuilds a real object for non-null, pushing a value per field and ending withstruct.new.emit_ref_todecides build versus reuse. Types costing 8 instructions or less are built fresh at every use, and anything more expensive gets one shared object per loop iteration held in a local and read back withlocal.get+ref.as_non_null. Building cheap types fresh keeps many distinct objects on the heap instead of every reference aliasing one while the prototype stop a deep graph from expanding exponentially.P.S. I realized certain functions are very big (like
fixupnow). The next PR will be clean-up about these.+cc @fitzgen