Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are literal values copied from read-only memory to the stack before being placed in the heap?

When I experimented with Rust, I had noticed that if a boxed array is created from a literal with Box::new, there is extra copying to the stack from read only memory. Why can't the Rust compiler copy directly from read only memory to space allocated on the heap?

The fragment of Rust code:

fn main() {
    let v: Box<[u32]> = Box::new([1u32,2,3456,4,5,6]);
    println!("vector {}", v.len());
}

The appropriate fragment of assembly:

00000000000049d4         mov        rax, qword [ds:0x39ad0]
00000000000049db         mov        qword [ss:rsp+arg_F8], rax
00000000000049e3         movaps     xmm0, xmmword [ds:const1050]
00000000000049ea         movaps     xmmword [ss:rsp+arg_E8], xmm0
00000000000049f2         mov        ecx, 0x18
00000000000049f7         mov        edi, ecx                                    ; argument #1 for method _ZN4heap15exchange_malloc20h356508549306a536JeaE
00000000000049f9         mov        ecx, 0x4
00000000000049fe         mov        esi, ecx                                    ; argument #2 for method _ZN4heap15exchange_malloc20h356508549306a536JeaE
0000000000004a00         call       _ZN4heap15exchange_malloc20h356508549306a536JeaE ; heap::exchange_malloc::h356508549306a536Jea
0000000000004a05         mov        rsi, qword [ss:rsp+arg_F8]
0000000000004a0d         mov        qword [ds:rax+0x10], rsi
0000000000004a11         movaps     xmm0, xmmword [ss:rsp+arg_E8]
0000000000004a19         movups     xmmword [ds:rax], xmm0

The array resides at 0x39ad0 and const1050 in the binary:

0000000000039ac8         db  0x80 ; '.'
0000000000039ac9         db  0x0d ; '.'
0000000000039aca         db  0x00 ; '.'
0000000000039acb         db  0x00 ; '.'
0000000000039acc         db  0x04 ; '.'
0000000000039acd         db  0x00 ; '.'
0000000000039ace         db  0x00 ; '.'
0000000000039acf         db  0x00 ; '.'
0000000000039ad0         dq  0x0000000600000005                          ; XREF=_ZN4main20h90e2c514439f0097eaaE+52
like image 535
A. Mikhaylov Avatar asked Nov 05 '25 14:11

A. Mikhaylov


1 Answers

Your findings are correct; this is a consequence that Box::new() is a regular function.

The proper way to put a value directly on the heap is to use placement operator; however, no such thing is currently available in Rust, but there are two RFCs, this (accepted) and this (pending, but seems likely to be accepted). Also if you're using Rust nightly, you can use an unstable box syntax:

let v: Box<[u32]> = box [1u32,2,3456,4,5,6];
like image 141
Vladimir Matveev Avatar answered Nov 07 '25 12:11

Vladimir Matveev