get rid of duplicate BlockFrame

This commit is contained in:
Svyatoslav Nikolsky
2017-06-23 09:20:58 +03:00
parent a8852a9791
commit 673392cad4
2 changed files with 41 additions and 66 deletions

View File

@ -13,6 +13,7 @@ use interpreter::value::{
RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto, RuntimeValue, TryInto, WrapInto, TryTruncateInto, ExtendInto,
ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto, ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto,
}; };
use interpreter::validator::{BlockFrame, BlockFrameType};
use interpreter::variable::VariableInstance; use interpreter::variable::VariableInstance;
/// Index of default linear memory. /// Index of default linear memory.
@ -66,38 +67,6 @@ pub enum InstructionOutcome<'a> {
Return, Return,
} }
/// Control stack frame.
#[derive(Debug, Clone)]
pub struct BlockFrame {
/// Frame type.
frame_type: BlockFrameType,
/// A label for reference to block instruction.
begin_position: usize,
/// A label for reference from branch instructions.
branch_position: usize,
/// A label for reference from end instructions.
end_position: usize,
/// A limit integer value, which is an index into the value stack indicating where to reset it to on a branch to that label.
value_limit: usize,
/// A signature, which is a block signature type indicating the number and types of result values of the region.
signature: BlockType,
}
/// Type of block frame.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BlockFrameType {
/// Function frame.
Function,
/// Usual block frame.
Block,
/// Loop frame (branching to the beginning of block).
Loop,
/// True-subblock of if expression.
IfTrue,
/// False-subblock of if expression.
IfFalse,
}
/// Function run result. /// Function run result.
enum RunResult<'a> { enum RunResult<'a> {
/// Function has returned (optional) value. /// Function has returned (optional) value.
@ -1095,7 +1064,7 @@ impl<'a> FunctionContext<'a> {
&mut self.frame_stack &mut self.frame_stack
} }
pub fn push_frame(&mut self, frame_type: BlockFrameType, signature: BlockType) -> Result<(), Error> { pub fn push_frame(&mut self, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error> {
let begin_position = self.position; let begin_position = self.position;
let branch_position = match frame_type { let branch_position = match frame_type {
BlockFrameType::Function => usize::MAX, BlockFrameType::Function => usize::MAX,
@ -1115,11 +1084,11 @@ impl<'a> FunctionContext<'a> {
}; };
self.frame_stack.push(BlockFrame { self.frame_stack.push(BlockFrame {
frame_type: frame_type, frame_type: frame_type,
block_type: block_type,
begin_position: begin_position, begin_position: begin_position,
branch_position: branch_position, branch_position: branch_position,
end_position: end_position, end_position: end_position,
value_limit: self.value_stack.len(), value_stack_len: self.value_stack.len(),
signature: signature,
}) })
} }
@ -1130,15 +1099,15 @@ impl<'a> FunctionContext<'a> {
pub fn pop_frame(&mut self, is_branch: bool) -> Result<(), Error> { pub fn pop_frame(&mut self, is_branch: bool) -> Result<(), Error> {
let frame = self.frame_stack.pop()?; let frame = self.frame_stack.pop()?;
if frame.value_limit > self.value_stack.len() { if frame.value_stack_len > self.value_stack.len() {
return Err(Error::Stack("invalid stack len".into())); return Err(Error::Stack("invalid stack len".into()));
} }
let frame_value = match frame.signature { let frame_value = match frame.block_type {
BlockType::Value(_) if frame.frame_type != BlockFrameType::Loop || !is_branch => Some(self.value_stack.pop()?), BlockType::Value(_) if frame.frame_type != BlockFrameType::Loop || !is_branch => Some(self.value_stack.pop()?),
_ => None, _ => None,
}; };
self.value_stack.resize(frame.value_limit, RuntimeValue::I32(0)); self.value_stack.resize(frame.value_stack_len, RuntimeValue::I32(0));
self.position = if is_branch { frame.branch_position } else { frame.end_position }; self.position = if is_branch { frame.branch_position } else { frame.end_position };
if let Some(frame_value) = frame_value { if let Some(frame_value) = frame_value {
self.value_stack.push(frame_value)?; self.value_stack.push(frame_value)?;

View File

@ -8,8 +8,6 @@ use interpreter::module::ItemIndex;
use interpreter::stack::StackWithLimit; use interpreter::stack::StackWithLimit;
use interpreter::variable::VariableType; use interpreter::variable::VariableType;
use interpreter::runner::BlockFrameType;
/// Constant from wabt' validator.cc to skip alignment validation (not a part of spec). /// Constant from wabt' validator.cc to skip alignment validation (not a part of spec).
const NATURAL_ALIGNMENT: u32 = 0xFFFFFFFF; const NATURAL_ALIGNMENT: u32 = 0xFFFFFFFF;
@ -19,14 +17,14 @@ pub struct FunctionValidationContext<'a> {
module: &'a Module, module: &'a Module,
/// Module imports. /// Module imports.
imports: &'a ModuleImports, imports: &'a ModuleImports,
/// Position. /// Current instruction position.
position: usize, position: usize,
/// Local variables. /// Local variables.
locals: &'a [ValueType], locals: &'a [ValueType],
/// Value stack. /// Value stack.
value_stack: StackWithLimit<StackValueType>, value_stack: StackWithLimit<StackValueType>,
/// Frame stack. /// Frame stack.
frame_stack: StackWithLimit<ValidationFrame>, frame_stack: StackWithLimit<BlockFrame>,
/// Function return type. None if validating expression. /// Function return type. None if validating expression.
return_type: Option<BlockType>, return_type: Option<BlockType>,
/// Labels positions. /// Labels positions.
@ -44,17 +42,36 @@ pub enum StackValueType {
Specific(ValueType), Specific(ValueType),
} }
/// Function validation frame. /// Control stack frame.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ValidationFrame { pub struct BlockFrame {
/// Frame type /// Frame type.
pub frame_type: BlockFrameType, pub frame_type: BlockFrameType,
/// Return type. /// A signature, which is a block signature type indicating the number and types of result values of the region.
pub block_type: BlockType, pub block_type: BlockType,
/// Value stack len. /// A label for reference to block instruction.
pub begin_position: usize,
/// A label for reference from branch instructions.
pub branch_position: usize,
/// A label for reference from end instructions.
pub end_position: usize,
/// A limit integer value, which is an index into the value stack indicating where to reset it to on a branch to that label.
pub value_stack_len: usize, pub value_stack_len: usize,
/// Frame instruction position. }
pub position: usize,
/// Type of block frame.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BlockFrameType {
/// Function frame.
Function,
/// Usual block frame.
Block,
/// Loop frame (branching to the beginning of block).
Loop,
/// True-subblock of if expression.
IfTrue,
/// False-subblock of if expression.
IfFalse,
} }
/// Function validator. /// Function validator.
@ -103,19 +120,6 @@ impl Validator {
//body = new_body; //body = new_body;
//position = 0; //position = 0;
}, },
/*InstructionOutcome::ValidateBlock2(is_loop, block_type, new_body, new_body2) => {
let need_pop_value = match block_type {
BlockType::NoResult => false,
BlockType::Value(_) => true,
};
context.push_label(is_loop, block_type)?;
context.push_label(is_loop, block_type)?;
block_stack.push_back((body, position + 1, false));
block_stack.push_back((new_body2, 0, need_pop_value));
body = new_body;
position = 0;
},*/
} }
} }
} }
@ -643,11 +647,13 @@ impl<'a> FunctionValidationContext<'a> {
} }
pub fn push_label(&mut self, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error> { pub fn push_label(&mut self, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error> {
self.frame_stack.push(ValidationFrame { self.frame_stack.push(BlockFrame {
frame_type: frame_type, frame_type: frame_type,
block_type: block_type, block_type: block_type,
begin_position: self.position,
branch_position: self.position,
end_position: self.position,
value_stack_len: self.value_stack.len(), value_stack_len: self.value_stack.len(),
position: self.position,
}) })
} }
@ -672,7 +678,7 @@ impl<'a> FunctionValidationContext<'a> {
_ => return Err(Error::Validation(format!("Expected block to return {:?} while it has returned {:?}", frame.block_type, actual_value_type))), _ => return Err(Error::Validation(format!("Expected block to return {:?} while it has returned {:?}", frame.block_type, actual_value_type))),
} }
if !self.frame_stack.is_empty() { if !self.frame_stack.is_empty() {
self.labels.insert(frame.position, self.position); self.labels.insert(frame.begin_position, self.position);
} }
if is_else { if is_else {
self.push_label(BlockFrameType::IfFalse, frame.block_type)?; self.push_label(BlockFrameType::IfFalse, frame.block_type)?;
@ -683,7 +689,7 @@ impl<'a> FunctionValidationContext<'a> {
Ok(InstructionOutcome::ValidateNextInstruction) Ok(InstructionOutcome::ValidateNextInstruction)
} }
pub fn require_label(&self, idx: u32) -> Result<&ValidationFrame, Error> { pub fn require_label(&self, idx: u32) -> Result<&BlockFrame, Error> {
self.frame_stack.get(idx as usize) self.frame_stack.get(idx as usize)
} }