get rid of function labels clone

This commit is contained in:
Svyatoslav Nikolsky 2017-06-26 12:28:21 +03:00
parent 4b3f67e3cc
commit 6aec26e0ff
2 changed files with 46 additions and 50 deletions

View File

@ -584,11 +584,10 @@ impl ModuleInstanceInterface for ModuleInstance {
}
fn call_internal_function(&self, mut outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
let function_labels = self.functions_labels.get(&index).ok_or(Error::Function(format!("trying to call non-validated internal function {}", index)))?;
let function_type = self.function_type(ItemIndex::Internal(index))?;
let args = prepare_function_args(&function_type, outer.value_stack)?;
let function_ref = InternalFunctionReference { module: self.self_ref(Some(outer.externals))?, internal_index: index };
let inner = FunctionContext::new(function_ref, outer.externals, function_labels.clone(), outer.value_stack_limit, outer.frame_stack_limit, &function_type, args);
let inner = FunctionContext::new(function_ref, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &function_type, args);
Interpreter::run_function(inner)
}
}

View File

@ -32,8 +32,6 @@ pub struct FunctionContext<'a> {
pub function: InternalFunctionReference<'a>,
/// Execution-local external modules.
pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>,
/// Function labels.
pub function_labels: HashMap<usize, usize>,
/// Function return type.
pub return_type: BlockType,
/// Local variables.
@ -77,28 +75,30 @@ impl Interpreter {
loop {
let mut function_context = function_stack.pop_back().expect("on loop entry - not empty; on loop continue - checking for emptiness; qed");
let function_ref = function_context.function.clone();
let function_body = function_ref.module.function_body(function_ref.internal_index)?;
let function_return = {
let function_body = function_ref.module.function_body(function_ref.internal_index)?;
let function_return = match function_body {
Some(function_body) => {
if !function_context.is_initialized() {
let return_type = function_context.return_type;
function_context.initialize(function_body.locals, function_body.labels.clone())?;
function_context.push_frame(BlockFrameType::Function, return_type)?;
}
match function_body {
Some(function_body) => {
if !function_context.is_initialized() {
let return_type = function_context.return_type;
function_context.initialize(function_body.locals)?;
function_context.push_frame(function_body.labels, BlockFrameType::Function, return_type)?;
}
Interpreter::do_run_function(&mut function_context, function_body.body)?
},
None => {
// move locals back to the stack
let locals_to_move: Vec<_> = function_context.locals.drain(..).rev().collect();
for local in locals_to_move {
function_context.value_stack_mut().push(local.get())?;
}
Interpreter::do_run_function(&mut function_context, function_body.body, function_body.labels)?
},
None => {
// move locals back to the stack
let locals_to_move: Vec<_> = function_context.locals.drain(..).rev().collect();
for local in locals_to_move {
function_context.value_stack_mut().push(local.get())?;
}
let nested_context = CallerContext::nested(&mut function_context);
RunResult::Return(function_ref.module.call_internal_function(nested_context, function_ref.internal_index)?)
},
let nested_context = CallerContext::nested(&mut function_context);
RunResult::Return(function_ref.module.call_internal_function(nested_context, function_ref.internal_index)?)
},
}
};
match function_return {
@ -118,12 +118,12 @@ impl Interpreter {
}
}
fn do_run_function<'a>(function_context: &mut FunctionContext<'a>, function_body: &[Opcode]) -> Result<RunResult<'a>, Error> {
fn do_run_function<'a>(function_context: &mut FunctionContext<'a>, function_body: &[Opcode], function_labels: &HashMap<usize, usize>) -> Result<RunResult<'a>, Error> {
loop {
let instruction = &function_body[function_context.position];
debug!(target: "interpreter", "running {:?}", instruction);
match Interpreter::run_instruction(function_context, instruction)? {
match Interpreter::run_instruction(function_context, function_labels, instruction)? {
InstructionOutcome::RunNextInstruction => function_context.position += 1,
InstructionOutcome::Branch(mut index) => {
// discard index - 1 blocks
@ -156,14 +156,14 @@ impl Interpreter {
}))
}
fn run_instruction<'a>(context: &mut FunctionContext<'a>, opcode: &Opcode) -> Result<InstructionOutcome<'a>, Error> {
fn run_instruction<'a>(context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, opcode: &Opcode) -> Result<InstructionOutcome<'a>, Error> {
match opcode {
&Opcode::Unreachable => Interpreter::run_unreachable(context),
&Opcode::Nop => Interpreter::run_nop(context),
&Opcode::Block(block_type) => Interpreter::run_block(context, block_type),
&Opcode::Loop(block_type) => Interpreter::run_loop(context, block_type),
&Opcode::If(block_type) => Interpreter::run_if(context, block_type),
&Opcode::Else => Interpreter::run_else(context),
&Opcode::Block(block_type) => Interpreter::run_block(context, labels, block_type),
&Opcode::Loop(block_type) => Interpreter::run_loop(context, labels, block_type),
&Opcode::If(block_type) => Interpreter::run_if(context, labels, block_type),
&Opcode::Else => Interpreter::run_else(context, labels),
&Opcode::End => Interpreter::run_end(context),
&Opcode::Br(idx) => Interpreter::run_br(context, idx),
&Opcode::BrIf(idx) => Interpreter::run_br_if(context, idx),
@ -358,21 +358,21 @@ impl Interpreter {
Ok(InstructionOutcome::RunNextInstruction)
}
fn run_block<'a>(context: &mut FunctionContext<'a>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
context.push_frame(BlockFrameType::Block, block_type)?;
fn run_block<'a>(context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
context.push_frame(labels, BlockFrameType::Block, block_type)?;
Ok(InstructionOutcome::RunNextInstruction)
}
fn run_loop<'a>(context: &mut FunctionContext<'a>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
context.push_frame(BlockFrameType::Loop, block_type)?;
fn run_loop<'a>(context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
context.push_frame(labels, BlockFrameType::Loop, block_type)?;
Ok(InstructionOutcome::RunNextInstruction)
}
fn run_if<'a>(context: &mut FunctionContext<'a>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
fn run_if<'a>(context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
let branch = context.value_stack_mut().pop_as()?;
let block_frame_type = if branch { BlockFrameType::IfTrue } else {
let else_pos = context.function_labels[&context.position];
if !context.function_labels.contains_key(&else_pos) {
let else_pos = labels[&context.position];
if !labels.contains_key(&else_pos) {
context.position = else_pos;
return Ok(InstructionOutcome::RunNextInstruction);
}
@ -380,11 +380,11 @@ impl Interpreter {
context.position = else_pos;
BlockFrameType::IfFalse
};
context.push_frame(block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction)
context.push_frame(labels, block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_else<'a>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> {
let end_pos = context.function_labels[&context.position];
fn run_else<'a>(context: &mut FunctionContext, labels: &HashMap<usize, usize>) -> Result<InstructionOutcome<'a>, Error> {
let end_pos = labels[&context.position];
context.pop_frame(false)?;
context.position = end_pos;
Ok(InstructionOutcome::RunNextInstruction)
@ -933,12 +933,11 @@ impl Interpreter {
}
impl<'a> FunctionContext<'a> {
pub fn new(function: InternalFunctionReference<'a>, externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>, function_labels: HashMap<usize, usize>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionSignature, args: Vec<VariableInstance>) -> Self {
pub fn new(function: InternalFunctionReference<'a>, externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionSignature, args: Vec<VariableInstance>) -> Self {
FunctionContext {
is_initialized: false,
function: function,
externals: externals,
function_labels: function_labels,
return_type: function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult),
value_stack: StackWithLimit::with_limit(value_stack_limit),
frame_stack: StackWithLimit::with_limit(frame_stack_limit),
@ -959,7 +958,6 @@ impl<'a> FunctionContext<'a> {
is_initialized: false,
function: function,
externals: self.externals,
function_labels: HashMap::new(),
return_type: function_return_type,
value_stack: StackWithLimit::with_limit(self.value_stack.limit() - self.value_stack.len()),
frame_stack: StackWithLimit::with_limit(self.frame_stack.limit() - self.frame_stack.len()),
@ -972,7 +970,7 @@ impl<'a> FunctionContext<'a> {
self.is_initialized
}
pub fn initialize(&mut self, locals: &[Local], labels: HashMap<usize, usize>) -> Result<(), Error> {
pub fn initialize(&mut self, locals: &[Local]) -> Result<(), Error> {
debug_assert!(!self.is_initialized);
self.is_initialized = true;
@ -981,7 +979,6 @@ impl<'a> FunctionContext<'a> {
.map(|vt| VariableInstance::new(true, vt, RuntimeValue::default(vt)))
.collect::<Result<Vec<_>, _>>()?;
self.locals.extend(locals);
self.function_labels = labels;
Ok(())
}
@ -1022,23 +1019,23 @@ impl<'a> FunctionContext<'a> {
&mut self.frame_stack
}
pub fn push_frame(&mut self, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error> {
pub fn push_frame(&mut self, labels: &HashMap<usize, usize>, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error> {
let begin_position = self.position;
let branch_position = match frame_type {
BlockFrameType::Function => usize::MAX,
BlockFrameType::Loop => begin_position,
BlockFrameType::IfTrue => {
let else_pos = self.function_labels[&begin_position];
1usize + match self.function_labels.get(&else_pos) {
let else_pos = labels[&begin_position];
1usize + match labels.get(&else_pos) {
Some(end_pos) => *end_pos,
None => else_pos,
}
},
_ => self.function_labels[&begin_position] + 1,
_ => labels[&begin_position] + 1,
};
let end_position = match frame_type {
BlockFrameType::Function => usize::MAX,
_ => self.function_labels[&begin_position] + 1,
_ => labels[&begin_position] + 1,
};
self.frame_stack.push(BlockFrame {
frame_type: frame_type,