Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't actually create a full MIR stack frame when not needed #57351

Merged
merged 6 commits into from
Jan 13, 2019
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,36 @@ pub fn mk_eval_cx<'a, 'tcx>(
debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
let span = tcx.def_span(instance.def_id());
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
let mir = ecx.load_mir(instance.def)?;
let mir = mir::Mir::new(
::std::iter::once(
mir::BasicBlockData {
statements: Vec::new(),
is_cleanup: false,
terminator: Some(mir::Terminator {
source_info: mir::SourceInfo {
scope: mir::OUTERMOST_SOURCE_SCOPE,
span: DUMMY_SP,
},
kind: mir::TerminatorKind::Return,
}),
}
).collect(), // basic blocks
IndexVec::new(), // source_scopes
mir::ClearCrossCrate::Clear, // source_scope_local_data
IndexVec::new(), // promoted
None, // yield ty
::std::iter::once(mir::LocalDecl::new_return_place(tcx.types.unit, DUMMY_SP)).collect(),
IndexVec::new(), //user_type_annotations
0, // arg_count
Vec::new(), // upvar_decls
DUMMY_SP, // span
Vec::new(), // control_flow_destroyed
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this function is only ever called when we don't even want to execute any code? But then why even bother pushing a stack frame at all...? Basically I don't understand why this even works.

That entire mir variable is "fake" and takes no input, right? This could be made clearer by having a separate function to construct it.

How does this relate to mk_borrowck_eval_cx, which creates a "less fake" frame but also for some reason cannot use push_stack_frame. Could this function also just directly push to the stack instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this function is only ever called when we don't even want to execute any code? But then why even bother pushing a stack frame at all...? Basically I don't understand why this even works.

We do call all kinds of methods on the ecx that check the current stack frame for e.g. substs and other info. These methods would fail without a stack frame. I remember talking about this before (not sure with whom), and we decided not to hack some sort of global substitutions into the ecx.

How does this relate to mk_borrowck_eval_cx, which creates a "less fake" frame but also for some reason cannot use push_stack_frame. Could this function also just directly push to the stack instead?

Jup, I unified it, good idea. This works much better.

Copy link
Member

@RalfJung RalfJung Jan 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do call all kinds of methods on the ecx that check the current stack frame for e.g. substs and other info. These methods would fail without a stack frame.

I know.

But somewhere we also run some actual code, and then we need a real stack frame. I guess neither of these two mk*_eval_cx functions is called then?

Could you please add doc comments to all of these mk*_eval_cx functions explaining when they should be called, what the difference between them is, and what can and cannot be done with the context they return (e.g., you can project to fields of a constant etc., but you cannot actually run any code)?

// insert a stack frame so any queries have the correct substs
ecx.push_stack_frame(
instance,
mir.span,
mir,
span,
tcx.alloc_mir(mir),
None,
StackPopCleanup::Goto(None), // never pop
)?;
Expand Down