1use std::any::Any;
2use std::cell::RefCell;
3use object::Object;
4use object_pool::ObjectPool;
5use basic_block::BasicBlock;
6use executor::ExecutorImpl;
7use errors;
8use function_optimizer::FunctionOptimizer;
9use value::Value;
10
11pub enum Function {
12 Virtual(RefCell<VirtualFunction>),
13 Native(NativeFunction)
14}
15
16pub struct VirtualFunction {
17 basic_blocks: Vec<BasicBlock>,
18 rt_handles: Vec<usize>,
19 should_optimize: bool,
20 this: Option<Value>
21}
22
23#[derive(Serialize, Deserialize, Clone, Debug)]
24pub struct VirtualFunctionInfo {
25 pub basic_blocks: Vec<BasicBlock>
26}
27
28pub type NativeFunction = Box<Fn(&mut ExecutorImpl) -> Value + Send>;
29
30impl Object for Function {
31 fn initialize(&mut self, pool: &mut ObjectPool) {
32 self.static_optimize(pool);
33 }
34
35 fn get_children(&self) -> Vec<usize> {
36 match *self {
37 Function::Virtual(ref f) => f.borrow().rt_handles.clone(),
38 Function::Native(_) => Vec::new()
39 }
40 }
41
42 fn as_any(&self) -> &Any {
43 self as &Any
44 }
45
46 fn as_any_mut(&mut self) -> &mut Any {
47 self as &mut Any
48 }
49
50 fn call(&self, executor: &mut ExecutorImpl) -> Value {
51 match *self {
52 Function::Virtual(ref vf) => {
53 let vf = vf.borrow();
54 if let Some(this) = vf.this {
55 executor.get_current_frame().set_this(this);
56 }
57 executor.eval_basic_blocks(vf.basic_blocks.as_slice(), 0)
58 },
59 Function::Native(ref nf) => {
60 nf(executor)
61 }
62 }
63 }
64}
65
66impl Function {
67 pub fn from_basic_blocks(blocks: Vec<BasicBlock>) -> Function {
68 let vf = VirtualFunction {
69 basic_blocks: blocks,
70 rt_handles: Vec::new(),
71 should_optimize: false,
72 this: None
73 };
74 println!("{:?}",vf.basic_blocks);
75 vf.validate().unwrap_or_else(|e| {
76 panic!(errors::VMError::from(e))
77 });
78
79 Function::Virtual(RefCell::new(vf))
80 }
81
82 pub fn bind_this(&self, this: Value) {
83 if let Function::Virtual(ref f) = *self {
84 if let Ok(mut f) = f.try_borrow_mut() {
85 if f.this.is_some() {
86 panic!(errors::VMError::from("Cannot rebind this"));
87 }
88 f.this = Some(this);
89 if let Value::Object(id) = this {
90 f.rt_handles.push(id);
91 }
92 } else {
93 panic!(errors::VMError::from("Cannot bind from inside the function"));
94 }
95 } else {
96 panic!(errors::VMError::from("Binding this is only supported on virtual functions"));
97 }
98 }
99
100 pub fn enable_optimization(&mut self) {
101 if let Function::Virtual(ref mut f) = *self {
102 f.borrow_mut().should_optimize = true;
103 }
104 }
105
106 pub fn from_native(nf: NativeFunction) -> Function {
107 Function::Native(nf)
108 }
109
110 pub fn to_virtual_info(&self) -> Option<VirtualFunctionInfo> {
111 match *self {
112 Function::Virtual(ref vf) => Some(VirtualFunctionInfo {
113 basic_blocks: vf.borrow().basic_blocks.clone()
114 }),
115 Function::Native(_) => None
116 }
117 }
118
119 pub fn from_virtual_info(vinfo: VirtualFunctionInfo) -> Self {
120 Function::from_basic_blocks(vinfo.basic_blocks)
121 }
122
123 pub fn static_optimize(&self, pool: &mut ObjectPool) {
124 if let Function::Virtual(ref f) = *self {
125 if let Ok(mut f) = f.try_borrow_mut() {
126 if f.should_optimize {
127 f.static_optimize(pool);
128 }
129 } else {
130 panic!(errors::VMError::from("Cannot optimize virtual functions within itself"));
131 }
132 }
133 }
134
135 pub fn dynamic_optimize(&self, pool: &mut ObjectPool) {
136 if let Function::Virtual(ref f) = *self {
137 if let Ok(mut f) = f.try_borrow_mut() {
138 if f.should_optimize {
139 f.dynamic_optimize(pool);
140 }
141 } else {
142 panic!(errors::VMError::from("Cannot optimize virtual functions within itself"));
143 }
144 }
145 }
146}
147
148impl VirtualFunction {
149 fn static_optimize(&mut self, pool: &mut ObjectPool) {
150 let mut optimizer = FunctionOptimizer::new(&mut self.basic_blocks, &mut self.rt_handles, pool);
151 optimizer.set_binded_this(self.this);
152 optimizer.static_optimize();
153 }
154
155 fn dynamic_optimize(&mut self, pool: &mut ObjectPool) {
156 let mut optimizer = FunctionOptimizer::new(&mut self.basic_blocks, &mut self.rt_handles, pool);
157 optimizer.set_binded_this(self.this);
158 optimizer.dynamic_optimize();
159 }
160
161 pub fn validate(&self) -> Result<(), errors::ValidateError> {
162 self.validate_basic_blocks()?;
163 self.validate_branch_targets()?;
164 Ok(())
165 }
166
167 pub fn validate_basic_blocks(&self) -> Result<(), errors::ValidateError> {
168 for bb in &self.basic_blocks {
169 bb.validate(false)?;
170 }
171
172 Ok(())
173 }
174
175 pub fn validate_branch_targets(&self) -> Result<(), errors::ValidateError> {
176 let blocks = &self.basic_blocks;
177
178 for bb in blocks {
179 let mut found_error: bool = false;
180
181 let (fst, snd) = bb.branch_targets();
182 if let Some(fst) = fst {
183 if fst >= blocks.len() {
184 found_error = true;
185 }
186 }
187 if let Some(snd) = snd {
188 if snd >= blocks.len() {
189 found_error = true;
190 }
191 }
192
193 if found_error {
194 return Err(errors::ValidateError::new("Invalid branch target(s)"));
195 }
196 }
197
198 Ok(())
199 }
200}