-
Notifications
You must be signed in to change notification settings - Fork 825
Closed as duplicate of#18756
Copy link
Labels
Milestone
Description
let [<TailCall>] inline Y ([<InlineIfLambda>] f) x =
let rec y x = f y x
y x
type Vertex = (struct(int * int))
type [<Struct>] Graph =
{
Grid: byte[,]
Rows: int
Cols: int
Shift: struct(int * int)
ObstacleID: byte
PlatformID: byte
}
type [<Struct>] Agent =
{
MaxJumpHeight: uint
AABBLeft: uint
AABBTop: uint
AABBRight: uint
}
let inline isGrounding
({Grid = grid; Rows = rows; Cols = cols; Shift = shift; ObstacleID = obstacleID; PlatformID = platformID} as graph: Graph)
({MaxJumpHeight = maxJumpHeight; AABBLeft = absL; AABBTop = absT; AABBRight = absR} as agent: Agent)
((x, y): Vertex) =
if y + 1 >= rows then false
else
let left = - int absL
// let top = - int absT
let right = int absR
// let mutable i = left
// let mutable found = false
// while i <= right && x + i < cols && not found do
// if x + i < 0 then
// i <- -x
// elif grid[y + 1, x + i] = obstacleID || grid[y + 1, x + i] = platformID then
// found <- true
// else
// i <- i + 1
// found
let rec loop i =
if x + i < 0 then loop -x
elif i > right || x + i >= cols then false
elif grid[y + 1, x + i] = obstacleID || grid[y + 1, x + i] = platformID then true
else loop (i + 1)
loop left // or use Y-combinators
let foo() =
let graph: Graph =
{
Grid = array2D [|
[|0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy|]
[|255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy|]
[|255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy|]
[|255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy|]
[|255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy|]
[|255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy|]
[|255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy|]
[|255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy; 255uy|]
[|0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy; 0uy|]
|]
Rows = 9
Cols = 16
Shift = struct(0, 0)
ObstacleID = 0uy
PlatformID = 1uy
}
let agent: Agent =
{
MaxJumpHeight = 3u
AABBLeft = 1u
AABBTop = 1u
AABBRight = 1u
}
isGrounding graph agent (0, 0)
dotnet 8/9
Then we could check compiled code:
- (Caller) For the
isGrounding
's implementation in functionfoo()
, everything is ok.
public static bool foo() {
// xxx
return loop@46-1(platformID@, obstacleID@, grid@, cols@, item, item2, num, i);
}
Static func so it is ok
- (Self) For the
isGrounding
, heap allocations is created.
public static bool isGrounding(Graph graph, Agent agent, ValueTuple<int, int> _arg1)
{
int rows@ = graph.Rows@;
byte platformID@ = graph.PlatformID@;
byte obstacleID@ = graph.ObstacleID@;
byte[,] grid@ = graph.Grid@;
int cols@ = graph.Cols@;
uint aABBRight@ = agent.AABBRight@;
uint aABBLeft@ = agent.AABBLeft@;
int item = _arg1.Item2;
int item2 = _arg1.Item1;
if (item + 1 >= rows@)
{
return false;
}
int func = (int)(0 - aABBLeft@);
int right = (int)aABBRight@;
FSharpFunc<int, bool> fSharpFunc = new loop@47(platformID@, obstacleID@, grid@, cols@, item, item2, right);
return fSharpFunc.Invoke(func);
}
There are some heap allocations here since closure captured a lot of variables.
Expected behavior
Produce similar msil code. No allocations is needed.
Actual behavior
Create closures and heap allocations.
Known workarounds
Use while
or no-inlining.
Related information
Provide any related information (optional):
- Windows 11
- .Net 8 / .Net 9
- MSBuild, SharpLab, ILSPY
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Done