Skip to content

Pattern-matching on mutable field surprisingly allocates a closure #10641

Description

@copy

I suspect the OCaml developers might already be aware of this issue, however, as a user of the language, I found this behaviour quite surprising. The allocation showed up while optimising some code and was found using memtrace. Below is a reduced test case.

type t = {
    mutable buffer: Bytes.t;
    mutable line_to_byte: int array;
    mutable number_of_lines: int;
}

let get_line_start { line_to_byte; _ } i = Array.get line_to_byte i

Which compiles to (using 4.12.0 with flambda -O3):

0000000000015f40 <camlTest__get_line_start_177>:
   15f40:	48 83 ec 08          	sub    rsp,0x8
   15f44:	48 8b 58 08          	mov    rbx,QWORD PTR [rax+0x8]
   15f48:	49 83 ef 20          	sub    r15,0x20
   15f4c:	4d 3b 7e 08          	cmp    r15,QWORD PTR [r14+0x8]
   15f50:	72 2d                	jb     15f7f <camlTest__get_line_start_177+0x3f>
   15f52:	49 8d 47 08          	lea    rax,[r15+0x8]
   15f56:	48 c7 40 f8 f7 0c 00 	mov    QWORD PTR [rax-0x8],0xcf7
   15f5d:	00 
   15f5e:	48 8d 3d 2b 00 00 00 	lea    rdi,[rip+0x2b]        # 15f90 <camlTest__fun_242>
   15f65:	48 89 38             	mov    QWORD PTR [rax],rdi
   15f68:	48 bf 05 00 00 00 00 	movabs rdi,0x100000000000005
   15f6f:	00 00 01 
   15f72:	48 89 78 08          	mov    QWORD PTR [rax+0x8],rdi
   15f76:	48 89 58 10          	mov    QWORD PTR [rax+0x10],rbx
   15f7a:	48 83 c4 08          	add    rsp,0x8
   15f7e:	c3                   	ret    
   15f7f:	e8 8c c8 01 00       	call   32810 <caml_call_gc>
   15f84:	eb cc                	jmp    15f52 <camlTest__get_line_start_177+0x12>
   15f86:	66 2e 0f 1f 84 00 00 	cs nop WORD PTR [rax+rax*1+0x0]
   15f8d:	00 00 00 

0000000000015f90 <camlTest__fun_242>:
   15f90:	48 83 ec 08          	sub    rsp,0x8
   15f94:	48 8b 5b 10          	mov    rbx,QWORD PTR [rbx+0x10]
   15f98:	48 8b 7b f8          	mov    rdi,QWORD PTR [rbx-0x8]
   15f9c:	48 c1 ef 09          	shr    rdi,0x9
   15fa0:	48 39 c7             	cmp    rdi,rax
   15fa3:	76 0a                	jbe    15faf <camlTest__fun_242+0x1f>
   15fa5:	48 8b 44 83 fc       	mov    rax,QWORD PTR [rbx+rax*4-0x4]
   15faa:	48 83 c4 08          	add    rsp,0x8
   15fae:	c3                   	ret    
   15faf:	e8 94 cb 01 00       	call   32b48 <caml_ml_array_bound_error>
   15fb4:	66 66 2e 0f 1f 84 00 	data16 cs nop WORD PTR [rax+rax*1+0x0]
   15fbb:	00 00 00 00 
   15fbf:	90                   	nop

Changing the function to let get_line_start t i = Array.get t.line_to_byte i or making the field immutable fixes the issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions