Avoid calling Vec::split_off, avoiding more heap allocations.

This commit is contained in:
Dan Gohman
2017-09-05 09:15:29 -07:00
parent 9ea40ad44a
commit ef3ea72422
2 changed files with 54 additions and 35 deletions

View File

@@ -6,6 +6,7 @@ use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
use std::cmp::max; use std::cmp::max;
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use std::mem;
use MatchRange; use MatchRange;
use explain::{Recorder, Explainer}; use explain::{Recorder, Explainer};
@@ -131,7 +132,9 @@ impl CheckerBuilder {
pub fn finish(&mut self) -> Checker { pub fn finish(&mut self) -> Checker {
// Move directives into the new checker, leaving `self.directives` empty and ready for // Move directives into the new checker, leaving `self.directives` empty and ready for
// building a new checker. // building a new checker.
Checker::new(self.directives.split_off(0)) let mut new_directives = Vec::new();
mem::swap(&mut new_directives, &mut self.directives);
Checker::new(new_directives)
} }
} }

View File

@@ -153,8 +153,8 @@ pub fn translate_function_body(
// explicitely in Cretonne IL. // explicitely in Cretonne IL.
if !builder.is_filled() && (!builder.is_unreachable() || !builder.is_pristine()) { if !builder.is_filled() && (!builder.is_unreachable() || !builder.is_pristine()) {
let cut_index = state.stack.len() - sig.return_types.len(); let cut_index = state.stack.len() - sig.return_types.len();
let return_vals = state.stack.split_off(cut_index); builder.ins().return_(&state.stack[cut_index..]);
builder.ins().return_(&return_vals); state.stack.truncate(cut_index);
} }
// Because the function has an implicit block as body, we need to explicitely close it. // Because the function has an implicit block as body, we need to explicitely close it.
let frame = state.control_stack.pop().unwrap(); let frame = state.control_stack.pop().unwrap();
@@ -167,8 +167,8 @@ pub fn translate_function_body(
builder.ebb_args(frame.following_code()), builder.ebb_args(frame.following_code()),
); );
let cut_index = state.stack.len() - sig.return_types.len(); let cut_index = state.stack.len() - sig.return_types.len();
let return_vals = state.stack.split_off(cut_index); builder.ins().return_(&state.stack[cut_index..]);
builder.ins().return_(&return_vals); state.stack.truncate(cut_index);
} }
} }
Ok((func, func_imports)) Ok((func, func_imports))
@@ -288,8 +288,8 @@ fn translate_operator(
_ => panic!("should not happen"), _ => panic!("should not happen"),
}; };
let cut_index = state.stack.len() - return_values.len(); let cut_index = state.stack.len() - return_values.len();
let jump_args = state.stack.split_off(cut_index); builder.ins().jump(destination, &state.stack[cut_index..]);
builder.ins().jump(destination, &jump_args); state.stack.truncate(cut_index);
// We change the target of the branch instruction // We change the target of the branch instruction
let else_ebb = builder.create_ebb(); let else_ebb = builder.create_ebb();
builder.change_jump_destination(branch_inst, else_ebb); builder.change_jump_destination(branch_inst, else_ebb);
@@ -300,8 +300,11 @@ fn translate_operator(
let frame = state.control_stack.pop().unwrap(); let frame = state.control_stack.pop().unwrap();
if !builder.is_unreachable() || !builder.is_pristine() { if !builder.is_unreachable() || !builder.is_pristine() {
let cut_index = state.stack.len() - frame.return_values().len(); let cut_index = state.stack.len() - frame.return_values().len();
let jump_args = state.stack.split_off(cut_index); builder.ins().jump(
builder.ins().jump(frame.following_code(), &jump_args); frame.following_code(),
&state.stack[cut_index..],
);
state.stack.truncate(cut_index);
} }
builder.switch_to_block(frame.following_code(), frame.return_values()); builder.switch_to_block(frame.following_code(), frame.return_values());
builder.seal_block(frame.following_code()); builder.seal_block(frame.following_code());
@@ -339,13 +342,17 @@ fn translate_operator(
Operator::Br { relative_depth } => { Operator::Br { relative_depth } => {
let i = state.control_stack.len() - 1 - (relative_depth as usize); let i = state.control_stack.len() - 1 - (relative_depth as usize);
let frame = &mut state.control_stack[i]; let frame = &mut state.control_stack[i];
let jump_args = if frame.is_loop() { let cut_index = state.stack.len() -
Vec::new() if frame.is_loop() {
} else { 0
let cut_index = state.stack.len() - frame.return_values().len(); } else {
state.stack.split_off(cut_index) frame.return_values().len()
}; };
builder.ins().jump(frame.br_destination(), &jump_args); builder.ins().jump(
frame.br_destination(),
&state.stack[cut_index..],
);
state.stack.truncate(cut_index);
// We signal that all the code that follows until the next End is unreachable // We signal that all the code that follows until the next End is unreachable
frame.set_reachable(); frame.set_reachable();
state.real_unreachable_stack_depth = 1 + relative_depth as usize; state.real_unreachable_stack_depth = 1 + relative_depth as usize;
@@ -354,17 +361,20 @@ fn translate_operator(
let val = state.pop1(); let val = state.pop1();
let i = state.control_stack.len() - 1 - (relative_depth as usize); let i = state.control_stack.len() - 1 - (relative_depth as usize);
let frame = &mut state.control_stack[i]; let frame = &mut state.control_stack[i];
let jump_args = if frame.is_loop() { let cut_index = state.stack.len() -
Vec::new() if frame.is_loop() {
} else { 0
let cut_index = state.stack.len() - frame.return_values().len(); } else {
state.stack.split_off(cut_index) frame.return_values().len()
}; };
builder.ins().brnz(val, frame.br_destination(), &jump_args); builder.ins().brnz(
val,
frame.br_destination(),
&state.stack[cut_index..],
);
// The values returned by the branch are still available for the reachable // The values returned by the branch are still available for the reachable
// code that comes after it // code that comes after it
frame.set_reachable(); frame.set_reachable();
state.stack.extend(jump_args);
} }
Operator::BrTable { ref table } => { Operator::BrTable { ref table } => {
let (depths, default) = table.read_table(); let (depths, default) = table.read_table();
@@ -406,7 +416,6 @@ fn translate_operator(
// We then proceed to split the edges going out of the br_table // We then proceed to split the edges going out of the br_table
let val = state.pop1(); let val = state.pop1();
let cut_index = state.stack.len() - jump_args_count; let cut_index = state.stack.len() - jump_args_count;
let jump_args = state.stack.split_off(cut_index);
let jt = builder.create_jump_table(); let jt = builder.create_jump_table();
let dest_ebbs: HashMap<usize, Ebb> = let dest_ebbs: HashMap<usize, Ebb> =
depths.iter().enumerate().fold(HashMap::new(), |mut acc, depths.iter().enumerate().fold(HashMap::new(), |mut acc,
@@ -425,25 +434,25 @@ fn translate_operator(
let default_ebb = state.control_stack[state.control_stack.len() - 1 - let default_ebb = state.control_stack[state.control_stack.len() - 1 -
(default as usize)] (default as usize)]
.br_destination(); .br_destination();
builder.ins().jump(default_ebb, &jump_args); builder.ins().jump(default_ebb, &state.stack[cut_index..]);
state.stack.extend_from_slice(&jump_args);
for (depth, dest_ebb) in dest_ebbs { for (depth, dest_ebb) in dest_ebbs {
builder.switch_to_block(dest_ebb, &[]); builder.switch_to_block(dest_ebb, &[]);
builder.seal_block(dest_ebb); builder.seal_block(dest_ebb);
let i = state.control_stack.len() - 1 - depth; let i = state.control_stack.len() - 1 - depth;
let frame = &mut state.control_stack[i]; let frame = &mut state.control_stack[i];
let real_dest_ebb = frame.br_destination(); let real_dest_ebb = frame.br_destination();
builder.ins().jump(real_dest_ebb, &jump_args); builder.ins().jump(real_dest_ebb, &state.stack[cut_index..]);
frame.set_reachable(); frame.set_reachable();
} }
state.stack.truncate(cut_index);
state.real_unreachable_stack_depth = 1 + min_depth as usize; state.real_unreachable_stack_depth = 1 + min_depth as usize;
} }
} }
Operator::Return => { Operator::Return => {
let return_count = sig.return_types.len(); let return_count = sig.return_types.len();
let cut_index = state.stack.len() - return_count; let cut_index = state.stack.len() - return_count;
let return_args = state.stack.split_off(cut_index); builder.ins().return_(&state.stack[cut_index..]);
builder.ins().return_(&return_args); state.stack.truncate(cut_index);
state.real_unreachable_stack_depth = 1; state.real_unreachable_stack_depth = 1;
} }
/************************************ Calls **************************************** /************************************ Calls ****************************************
@@ -454,7 +463,6 @@ fn translate_operator(
Operator::Call { function_index } => { Operator::Call { function_index } => {
let args_num = args_count(function_index as usize, functions, signatures); let args_num = args_count(function_index as usize, functions, signatures);
let cut_index = state.stack.len() - args_num; let cut_index = state.stack.len() - args_num;
let call_args = state.stack.split_off(cut_index);
let internal_function_index = find_function_import( let internal_function_index = find_function_import(
function_index as usize, function_index as usize,
builder, builder,
@@ -463,7 +471,11 @@ fn translate_operator(
exports, exports,
signatures, signatures,
); );
let call_inst = builder.ins().call(internal_function_index, &call_args); let call_inst = builder.ins().call(
internal_function_index,
&state.stack[cut_index..],
);
state.stack.truncate(cut_index);
let ret_values = builder.inst_results(call_inst); let ret_values = builder.inst_results(call_inst);
for val in ret_values { for val in ret_values {
state.push1(*val); state.push1(*val);
@@ -480,9 +492,13 @@ fn translate_operator(
let args_num = builder.signature(sigref).unwrap().argument_types.len(); let args_num = builder.signature(sigref).unwrap().argument_types.len();
let index_val = state.pop1(); let index_val = state.pop1();
let cut_index = state.stack.len() - args_num; let cut_index = state.stack.len() - args_num;
let call_args = state.stack.split_off(cut_index); let ret_values = runtime.translate_call_indirect(
let ret_values = builder,
runtime.translate_call_indirect(builder, sigref, index_val, &call_args); sigref,
index_val,
&state.stack[cut_index..],
);
state.stack.truncate(cut_index);
for val in ret_values { for val in ret_values {
state.push1(*val); state.push1(*val);
} }