Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add internal block type for use in the compiler. IncrementalBuilder only maintains two states #11750

Merged
merged 6 commits into from
Jul 2, 2021

Conversation

TIHan
Copy link
Contributor

@TIHan TIHan commented Jun 29, 2021

This is mostly a refactoring PR. It does add the block type for internal compiler use; it is basically ImmutableArray<'T> but with F# idiomatic collection functions.

Incremental Builder changes:

  • Added IncrementalBuilderInitialState to group the initial state when creating an IncrementalBuilder internally.
  • Lifted a lot of local functions in IncrementalBuilder to be top-level.
  • IncrementalBuilder now manages only two states: IncrementalBuilderInitialState and IncrementalBuilderState.

@TIHan TIHan changed the title Add internal block type for use in the compiler. IncrementalBuilder only maintains two states. Add internal block type for use in the compiler. IncrementalBuilder only maintains two states Jun 29, 2021
Copy link
Contributor

@NinoFloris NinoFloris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a review of the block api, I hope that's alright.

Also, sometimes there are reasons to get the underlying array cheaply. I'm using this, posted below, in our codebase here and there. Though going fully unsafe you could do Unsafe.As<Block<'T>, 'T[]> as it's the only field in the struct. I just prefer my code to die a little nicer than with a segfault in the very unlikely case ImmutableArray changes implementations 😅.

    let unsafeGetArray(value: ImmutableArray<'T>) =
        match MemoryMarshal.TryGetArray(value.AsMemory()) with
        | false, _ -> failwith "Expected ImmutableArray to wrap a managed array but it didn't."
        | true, seg -> seg.Array

src/fsharp/block.fs Outdated Show resolved Hide resolved
src/fsharp/block.fs Show resolved Hide resolved
src/fsharp/block.fs Outdated Show resolved Hide resolved
src/fsharp/block.fs Show resolved Hide resolved
src/fsharp/block.fs Outdated Show resolved Hide resolved
src/fsharp/block.fs Show resolved Hide resolved
src/fsharp/block.fs Show resolved Hide resolved
@TIHan
Copy link
Contributor Author

TIHan commented Jun 29, 2021

@NinoFloris of course! Thank you for reviewing :)

@TIHan
Copy link
Contributor Author

TIHan commented Jul 1, 2021

@NinoFloris This should be a lot better. :) I didn't realize how naïve my original impl was.

Copy link
Contributor

@NinoFloris NinoFloris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, I picked up a few things since I introduced ImmutableArray into our codebase a few years back. Besides, anything that helps compiler perf is welcome :)


let choose (chooser: 'T -> 'U option) (arr: block<'T>) : block<'U> =
let builder = ImmutableArray.CreateBuilder(arr.Length)
for i = 0 to arr.Length - 1 do
let result = chooser arr.[i]
if result.IsSome then
builder.Add(result.Value)
builder.ToImmutable()
builder.Capacity <- builder.Count
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't know the length it doesn't matter too much if you do ToImmutable. You'll do a copy by changing capacity anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the capacity will only copy if the count is different.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough :)

let builder = ImmutableArray.CreateBuilder(acc)
for i = 0 to arrs.Length - 1 do
builder.AddRange(arrs.[i])
builder.MoveToImmutable()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing capacity <- count or ToImmutable here, as capacity could be anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine. acc is the total length of the final array.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I completely missed the the length summing loop, yep it's fine!

ImmutableArray.Create(item)

let filter predicate (arr: block<'T>) : block<'T> =
let builder = ImmutableArray.CreateBuilder(arr.Length)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test for empty initially

@dsyme dsyme merged commit a85aac5 into dotnet:main Jul 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants