Skip to content

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

@copy

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions