Skip to content

Linear stack blowup with multiple Vec::push of big struct with destructor #40883

Closed
@arielb1

Description

@arielb1

Meta

Checked on rustc 1.12.0 with MIR on, 1.15.1, 1.16 and 1.18. Does not affect 1.12.0 with MIR off.

STR

#![crate_type="rlib"]

pub struct Big {
    drop_me: [Option<Box<u8>>; 64],
}

pub fn supersize_me(meal: fn() -> Big, out: &mut Vec<Big>) {
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal());
    out.push(meal()); // 16 calls to `push`
}

Expected Result

Function should use a small amount of stack space, definitely less than 2 kilobytes (Big is 512 bytes per copy); 1.12.0 with -Z orbit=off uses 1088 bytes of stack.

Actual Result

When compiled, the function uses more than 16384 = 8*64*16*2 bytes of stack space, as is evident from subq $16384, %rsp in the assembly - 2 copies of Big for every call to push.

Notes

This is the root cause for #40573. It is not new, however - it was probably always present in MIR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-codegenArea: Code generationI-slowIssue: Problems and improvements with respect to performance of generated code.P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions