Skip to content

Instantly share code, notes, and snippets.

@amosr
Created September 5, 2016 05:12
Show Gist options
  • Save amosr/718e86bcd71b7780752fdf0bf53ca826 to your computer and use it in GitHub Desktop.
Save amosr/718e86bcd71b7780752fdf0bf53ca826 to your computer and use it in GitHub Desktop.
// Tree implementation using Box of Option of Node.
// Would hope Box<Option<Node>> should be just *Node where null = None
// But it appears to use ***Node as argument type in lookup
pub struct Node {
val: i64,
l: Tree,
r: Tree,
}
pub type Tree = Box<Option<Node>>;
// The assembly shows that this requires *two* memory lookups just to check if the input tree is empty/None.
// (It 'should' be zero)
#[no_mangle]
pub fn lookup(t : &Tree, needle: i64) -> &Tree {
match **t {
Some(ref node) => {
if node.val == needle {
return t
} else if needle < node.val {
return lookup(&node.l, needle)
} else {
return lookup(&node.r, needle)
}
}
None => {
return t
}
}
}
// This insert function has to deallocate/drop the empty trees.
// It also calls drop on some temporary trees it creates on the stack
#[no_mangle]
pub fn insert_tree(t : &mut Tree, new_val: i64) {
match **t {
Some(ref mut node) => {
if node.val == new_val {
return
} else if new_val < node.val {
insert_tree(&mut node.l, new_val);
} else {
insert_tree(&mut node.r, new_val)
}
}
None => {
// It creates three trees on the stack, then copies them over to the heap and drops the stack ones.
// It also drops the empty tree that was already on *t
// I would expect None to be stored as a null pointer..
*t = Box::new(Some( Node { val: new_val, l: Box::new(None), r: Box::new(None) }));
}
}
}
.section __TEXT,__text,regular,pure_instructions
.globl _lookup
.align 4, 0x90
_lookup:
.cfi_startproc
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
movq (%rdi), %rax
cmpq $0, 8(%rax)
je LBB0_4
leaq 8(%rax), %rcx
.align 4, 0x90
LBB0_2:
movq (%rax), %rdx
cmpq %rsi, %rdx
je LBB0_4
addq $16, %rax
cmpq %rsi, %rdx
movq %rax, %rdi
cmovgq %rcx, %rdi
movq (%rdi), %rax
leaq 8(%rax), %rcx
cmpq $0, 8(%rax)
jne LBB0_2
LBB0_4:
movq %rdi, %rax
popq %rbp
retq
.cfi_endproc
.section __TEXT,__literal16,16byte_literals
.align 4
LCPI1_0:
.space 16
.section __TEXT,__text,regular,pure_instructions
.globl _insert_tree
.align 4, 0x90
_insert_tree:
Lfunc_begin0:
.cfi_startproc
.cfi_personality 155, _rust_eh_personality
.cfi_lsda 16, Lexception0
pushq %rbp
Ltmp12:
.cfi_def_cfa_offset 16
Ltmp13:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp14:
.cfi_def_cfa_register %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $48, %rsp
Ltmp15:
.cfi_offset %rbx, -48
Ltmp16:
.cfi_offset %r12, -40
Ltmp17:
.cfi_offset %r14, -32
Ltmp18:
.cfi_offset %r15, -24
movq %rdi, %r14
movq (%r14), %rdi
cmpq $0, 8(%rdi)
je LBB1_3
leaq 8(%rdi), %rax
cmpq %rsi, (%rdi)
jne LBB1_7
jmp LBB1_2
LBB1_3:
movq %rsi, -56(%rbp)
xorps %xmm0, %xmm0
movaps %xmm0, -80(%rbp)
movq $0, -64(%rbp)
movl $24, %edi
movl $8, %esi
callq ___rust_allocate
movq %rax, %r15
testq %r15, %r15
je LBB1_4
LBB1_5:
movabsq $2097865012304223517, %r12
movq -64(%rbp), %rax
movq %rax, 16(%r15)
movq -80(%rbp), %rax
movq -72(%rbp), %rcx
movq %rcx, 8(%r15)
movq %rax, (%r15)
movq %r12, -64(%rbp)
movq %r12, -72(%rbp)
movq %r12, -80(%rbp)
leaq -80(%rbp), %rdi
callq __ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E
movq %r15, -48(%rbp)
xorps %xmm0, %xmm0
movaps %xmm0, -80(%rbp)
movq $0, -64(%rbp)
movl $24, %edi
movl $8, %esi
callq ___rust_allocate
movq %rax, %rbx
testq %rbx, %rbx
je LBB1_6
movq -64(%rbp), %rax
movq %rax, 16(%rbx)
movq -80(%rbp), %rax
movq -72(%rbp), %rcx
movq %rcx, 8(%rbx)
movq %rax, (%rbx)
movq %r12, -64(%rbp)
movq %r12, -72(%rbp)
movq %r12, -80(%rbp)
leaq -80(%rbp), %rdi
callq __ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E
movq %rbx, -40(%rbp)
movl $24, %edi
movl $8, %esi
callq ___rust_allocate
movq %rax, %rbx
testq %rbx, %rbx
je LBB1_12
movq -40(%rbp), %rax
movq %rax, 16(%rbx)
movq -56(%rbp), %rax
movq -48(%rbp), %rcx
movq %rcx, 8(%rbx)
movq %rax, (%rbx)
movq %r12, -40(%rbp)
movq %r12, -48(%rbp)
movq %r12, -56(%rbp)
leaq -56(%rbp), %rdi
callq __ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E
movq (%r14), %r15
cmpq %r12, %r15
je LBB1_17
movq %r15, %rdi
callq __ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E
movl $24, %esi
movl $8, %edx
movq %r15, %rdi
callq ___rust_deallocate
LBB1_17:
movq %rbx, (%r14)
LBB1_2:
addq $48, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
LBB1_4:
Ltmp9:
callq __ZN5alloc3oom3oom17h8fced2f5f33bcdebE
Ltmp10:
jmp LBB1_5
LBB1_20:
Ltmp11:
movq %rax, %r14
leaq -80(%rbp), %rdi
jmp LBB1_21
LBB1_6:
Ltmp6:
callq __ZN5alloc3oom3oom17h8fced2f5f33bcdebE
Ltmp7:
LBB1_7:
jle LBB1_10
movq %rax, %rdi
jmp LBB1_9
LBB1_10:
addq $16, %rdi
LBB1_9:
addq $48, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp _insert_tree
LBB1_12:
Ltmp3:
callq __ZN5alloc3oom3oom17h8fced2f5f33bcdebE
Ltmp4:
LBB1_18:
Ltmp8:
movq %rax, %r14
leaq -80(%rbp), %rdi
callq __ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E
cmpq %r12, %r15
je LBB1_22
movq %r15, %rdi
callq __ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E
movl $24, %esi
movl $8, %edx
movq %r15, %rdi
callq ___rust_deallocate
movq %r14, %rdi
callq __Unwind_Resume
LBB1_14:
Ltmp5:
movq %rax, %r14
leaq -56(%rbp), %rdi
LBB1_21:
callq __ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E
LBB1_22:
movq %r14, %rdi
callq __Unwind_Resume
Lfunc_end0:
.cfi_endproc
.section __TEXT,__gcc_except_tab
.align 2
GCC_except_table1:
Lexception0:
.byte 255
.byte 155
.asciz "\303\200"
.byte 3
.byte 65
Lset0 = Ltmp9-Lfunc_begin0
.long Lset0
Lset1 = Ltmp10-Ltmp9
.long Lset1
Lset2 = Ltmp11-Lfunc_begin0
.long Lset2
.byte 0
Lset3 = Ltmp6-Lfunc_begin0
.long Lset3
Lset4 = Ltmp7-Ltmp6
.long Lset4
Lset5 = Ltmp8-Lfunc_begin0
.long Lset5
.byte 0
Lset6 = Ltmp7-Lfunc_begin0
.long Lset6
Lset7 = Ltmp3-Ltmp7
.long Lset7
.long 0
.byte 0
Lset8 = Ltmp3-Lfunc_begin0
.long Lset8
Lset9 = Ltmp4-Ltmp3
.long Lset9
Lset10 = Ltmp5-Lfunc_begin0
.long Lset10
.byte 0
Lset11 = Ltmp4-Lfunc_begin0
.long Lset11
Lset12 = Lfunc_end0-Ltmp4
.long Lset12
.long 0
.byte 0
.align 2
.section __TEXT,__text,regular,pure_instructions
.align 4, 0x90
__ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %r14
movq 8(%r14), %rbx
movabsq $2097865012304223517, %r15
cmpq %r15, %rbx
je LBB2_3
testq %rbx, %rbx
je LBB2_4
movq %rbx, %rdi
callq __ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E
movl $24, %esi
movl $8, %edx
movq %rbx, %rdi
callq ___rust_deallocate
LBB2_3:
movq 16(%r14), %rbx
cmpq %r15, %rbx
je LBB2_4
movq %rbx, %rdi
callq __ZN31std..option..Option$LT$Node$GT$9drop.776717h3ebf62a6a38e1f69E
movl $24, %esi
movl $8, %edx
movq %rbx, %rdi
addq $8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp ___rust_deallocate
LBB2_4:
addq $8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
.subsections_via_symbols
// Tree implementation using Option of Box of Node.
// Would hope Option<Box<Node>> should be just *Node where null = None
// But it appears to use **Node in lookup. I don't know why this is better than Box<Option<Node>>
pub struct Node {
val: i64,
l: Tree,
r: Tree,
}
pub type Tree = Option<Box<Node>>;
pub const empty : Tree = None;
// This one only requires one dereference, so it's better than Box<Option>
#[no_mangle]
pub fn lookup(t : &Tree, needle: i64) -> &Tree {
match t {
&Some(ref node) => {
if node.val == needle {
return t
} else if needle < node.val {
return lookup(&node.l, needle)
} else {
return lookup(&node.r, needle)
}
}
&None => {
return t
}
}
}
// The insert function has the same deallocate/drop problem as Box<Option.
#[no_mangle]
pub fn insert_tree(t : &mut Tree, new_val: i64) {
match t {
&mut Some(ref mut node) => {
if node.val == new_val {
return
} else if new_val < node.val {
insert_tree(&mut node.l, new_val);
} else {
insert_tree(&mut node.r, new_val)
}
}
&mut None => {
let new_node = Node { val: new_val, l: empty, r: empty };
let bbox = Box::new(new_node);
let boxed_node = Some(bbox);
*t = boxed_node;
}
}
}
.section __TEXT,__text,regular,pure_instructions
.globl _lookup
.align 4, 0x90
_lookup:
.cfi_startproc
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
cmpq $0, (%rdi)
je LBB0_3
.align 4, 0x90
LBB0_1:
movq (%rdi), %rax
movq (%rax), %rcx
cmpq %rsi, %rcx
je LBB0_3
leaq 8(%rax), %rdx
addq $16, %rax
cmpq %rsi, %rcx
cmovgq %rdx, %rax
cmpq $0, (%rax)
movq %rax, %rdi
jne LBB0_1
LBB0_3:
movq %rdi, %rax
popq %rbp
retq
.cfi_endproc
.globl _insert_tree
.align 4, 0x90
_insert_tree:
Lfunc_begin0:
.cfi_startproc
.cfi_personality 155, _rust_eh_personality
.cfi_lsda 16, Lexception0
pushq %rbp
Ltmp6:
.cfi_def_cfa_offset 16
Ltmp7:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp8:
.cfi_def_cfa_register %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $48, %rsp
Ltmp9:
.cfi_offset %rbx, -48
Ltmp10:
.cfi_offset %r12, -40
Ltmp11:
.cfi_offset %r14, -32
Ltmp12:
.cfi_offset %r15, -24
movq %rdi, %r14
movq (%r14), %rdi
testq %rdi, %rdi
je LBB1_2
cmpq %rsi, (%rdi)
jne LBB1_4
jmp LBB1_12
LBB1_2:
movq %rsi, -56(%rbp)
movq $0, -40(%rbp)
movq $0, -48(%rbp)
movq -40(%rbp), %rax
movq %rax, -64(%rbp)
movq -56(%rbp), %rax
movq -48(%rbp), %rcx
movq %rcx, -72(%rbp)
movq %rax, -80(%rbp)
movabsq $2097865012304223517, %r12
movq %r12, -40(%rbp)
movq %r12, -48(%rbp)
movq %r12, -56(%rbp)
movl $24, %edi
movl $8, %esi
callq ___rust_allocate
movq %rax, %rbx
testq %rbx, %rbx
je LBB1_3
movq -64(%rbp), %rax
movq %rax, 16(%rbx)
movq -80(%rbp), %rax
movq -72(%rbp), %rcx
movq %rcx, 8(%rbx)
movq %rax, (%rbx)
movq %r12, -64(%rbp)
movq %r12, -72(%rbp)
movq %r12, -80(%rbp)
leaq -80(%rbp), %rdi
callq __ZN4Node9drop.777217hdd4541c543bb3b02E
movq (%r14), %r15
testq %r15, %r15
je LBB1_11
cmpq %r12, %r15
je LBB1_11
movq %r15, %rdi
callq __ZN4Node9drop.777217hdd4541c543bb3b02E
movl $24, %esi
movl $8, %edx
movq %r15, %rdi
callq ___rust_deallocate
LBB1_11:
movq %rbx, (%r14)
leaq -56(%rbp), %rdi
callq __ZN4Node9drop.777217hdd4541c543bb3b02E
LBB1_12:
addq $48, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
LBB1_3:
Ltmp3:
callq __ZN5alloc3oom3oom17h8fced2f5f33bcdebE
Ltmp4:
LBB1_4:
jle LBB1_7
addq $8, %rdi
jmp LBB1_6
LBB1_7:
addq $16, %rdi
LBB1_6:
addq $48, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp _insert_tree
LBB1_13:
Ltmp5:
movq %rax, %rbx
leaq -80(%rbp), %rdi
callq __ZN4Node9drop.777217hdd4541c543bb3b02E
leaq -56(%rbp), %rdi
callq __ZN4Node9drop.777217hdd4541c543bb3b02E
movq %rbx, %rdi
callq __Unwind_Resume
Lfunc_end0:
.cfi_endproc
.section __TEXT,__gcc_except_tab
.align 2
GCC_except_table1:
Lexception0:
.byte 255
.byte 155
.asciz "\234"
.byte 3
.byte 26
Lset0 = Ltmp3-Lfunc_begin0
.long Lset0
Lset1 = Ltmp4-Ltmp3
.long Lset1
Lset2 = Ltmp5-Lfunc_begin0
.long Lset2
.byte 0
Lset3 = Ltmp4-Lfunc_begin0
.long Lset3
Lset4 = Lfunc_end0-Ltmp4
.long Lset4
.long 0
.byte 0
.align 2
.section __TEXT,__text,regular,pure_instructions
.align 4, 0x90
__ZN4Node9drop.777217hdd4541c543bb3b02E:
pushq %rbp
movq %rsp, %rbp
pushq %r14
pushq %rbx
movq %rdi, %r14
movq 8(%r14), %rbx
testq %rbx, %rbx
je LBB2_3
movabsq $2097865012304223517, %rax
cmpq %rax, %rbx
je LBB2_3
movq %rbx, %rdi
callq __ZN4Node9drop.777217hdd4541c543bb3b02E
movl $24, %esi
movl $8, %edx
movq %rbx, %rdi
callq ___rust_deallocate
LBB2_3:
movq 16(%r14), %rbx
testq %rbx, %rbx
je LBB2_5
movabsq $2097865012304223517, %rax
cmpq %rax, %rbx
jne LBB2_6
LBB2_5:
popq %rbx
popq %r14
popq %rbp
retq
LBB2_6:
movq %rbx, %rdi
callq __ZN4Node9drop.777217hdd4541c543bb3b02E
movl $24, %esi
movl $8, %edx
movq %rbx, %rdi
popq %rbx
popq %r14
popq %rbp
jmp ___rust_deallocate
.subsections_via_symbols
// Polymorphic in the region (or something)
// This one is really good, and has perfect assembly for lookup.
// However, I don't know how to write an insert for it.
// The problem is, insert cannot allocate to a polymorphic region, so it can't create a new node.
pub struct Node<'a> {
val: i64,
l: Tree<'a>,
r: Tree<'a>,
}
pub type Tree<'a> = Option<&'a Node<'a>>;
#[no_mangle]
pub fn lookup<'a>(t : Tree<'a>, needle: i64) -> Tree<'a> {
match t {
Some(ref node)
if needle == node.val
=> { return t; }
Some(ref node)
if needle < node.val
=> { return lookup(node.l, needle); }
Some(ref node)
=> { return lookup(node.r, needle); }
None
=> { return t; }
}
}
.section __TEXT,__text,regular,pure_instructions
.globl _lookup
.align 4, 0x90
_lookup:
.cfi_startproc
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
xorl %eax, %eax
testq %rdi, %rdi
je LBB0_5
xorl %eax, %eax
.align 4, 0x90
LBB0_2:
movq (%rdi), %rcx
cmpq %rsi, %rcx
je LBB0_3
leaq 8(%rdi), %rdx
addq $16, %rdi
cmpq %rsi, %rcx
cmovgq %rdx, %rdi
movq (%rdi), %rdi
testq %rdi, %rdi
jne LBB0_2
LBB0_5:
popq %rbp
retq
LBB0_3:
movq %rdi, %rax
popq %rbp
retq
.cfi_endproc
.subsections_via_symbols
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment