Skip to content

Commit

Permalink
Added inline caches for method lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
Hirevo committed Aug 21, 2020
1 parent 2247a14 commit 11af59a
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 24 deletions.
5 changes: 5 additions & 0 deletions som-interpreter-bc/src/block.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use std::rc::Rc;

use som_core::bytecode::Bytecode;

use crate::class::Class;
use crate::compiler::Literal;
use crate::frame::Frame;
use crate::method::Method;
use crate::universe::Universe;
use crate::value::Value;
use crate::SOMRef;
Expand All @@ -18,6 +22,7 @@ pub struct Block {
pub literals: Vec<Literal>,
pub body: Vec<Bytecode>,
pub nb_params: usize,
pub inline_cache: Rc<RefCell<HashMap<(*const Class, usize), Rc<Method>>>>,
}

impl Block {
Expand Down
3 changes: 3 additions & 0 deletions som-interpreter-bc/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! This is the bytecode compiler for the Simple Object Machine.
//!
use std::cell::RefCell;
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::rc::{Rc, Weak};

Expand Down Expand Up @@ -410,6 +411,7 @@ fn compile_method(outer: &mut dyn GenCtxt, defn: &ast::MethodDef) -> Option<Meth
locals: ctxt.inner.locals.iter().map(|_| Value::Nil).collect(),
literals: ctxt.inner.literals.into_iter().collect(),
body: ctxt.inner.body.unwrap_or_default(),
inline_cache: RefCell::new(HashMap::new()),
};
MethodKind::Defined(env)
}
Expand Down Expand Up @@ -450,6 +452,7 @@ fn compile_block(outer: &mut dyn GenCtxt, defn: &ast::Block) -> Option<Block> {
literals: ctxt.literals.into_iter().collect(),
body: ctxt.body.unwrap_or_default(),
nb_params: ctxt.args.len(),
inline_cache: Rc::new(RefCell::new(HashMap::new())),
};

// println!("(system) compiled block !");
Expand Down
103 changes: 79 additions & 24 deletions som-interpreter-bc/src/interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::rc::Rc;
use std::time::Instant;

Expand Down Expand Up @@ -43,11 +44,12 @@ impl Interpreter {

pub fn run(&mut self, universe: &mut Universe) -> Option<Value> {
loop {
let frame = match self.current_frame() {
let frame = match self.current_frame().map(Rc::clone) {
Some(frame) => frame,
None => return Some(Value::Nil),
};

let bytecode_idx = frame.borrow().bytecode_idx;
let opt_bytecode = frame.borrow().get_current_bytecode();
let bytecode = match opt_bytecode {
Some(bytecode) => bytecode,
Expand Down Expand Up @@ -113,12 +115,12 @@ impl Interpreter {
Literal::Block(blk) => Block::clone(&blk),
_ => return None,
};
block.frame.replace(Rc::clone(frame));
block.frame.replace(Rc::clone(&frame));
frame.borrow_mut().stack.push(Value::Block(Rc::new(block)));
}
Bytecode::PushConstant(idx) => {
let literal = frame.borrow().lookup_constant(idx as usize).unwrap();
let value = convert_literal(frame, literal).unwrap();
let value = convert_literal(&frame, literal).unwrap();
frame.borrow_mut().stack.push(value);
}
Bytecode::PushGlobal(idx) => {
Expand Down Expand Up @@ -192,13 +194,43 @@ impl Interpreter {
};
let signature = universe.lookup_symbol(symbol);
let nb_params = nb_params(signature);
let method = frame
.borrow()
.stack
.iter()
.nth_back(nb_params)
.unwrap()
.lookup_method(universe, symbol);
let method = {
let borrow = frame.borrow();
let receiver = borrow.stack.iter().nth_back(nb_params)?;
let receiver_class = receiver.class(universe);
let cache_key = (receiver_class.as_ptr() as *const _, bytecode_idx);
match frame.borrow().kind() {
FrameKind::Block { block } => {
match block.inline_cache.borrow_mut().entry(cache_key) {
Entry::Occupied(entry) => Some(Rc::clone(entry.get())),
Entry::Vacant(entry) => {
let method = receiver_class.borrow().lookup_method(symbol);
if let Some(method) = method.as_ref() {
entry.insert(Rc::clone(&method));
}
method
}
}
}
FrameKind::Method { method, .. } => {
if let MethodKind::Defined(env) = method.kind() {
match env.inline_cache.borrow_mut().entry(cache_key) {
Entry::Occupied(entry) => Some(Rc::clone(entry.get())),
Entry::Vacant(entry) => {
let method =
receiver_class.borrow().lookup_method(symbol);
if let Some(method) = method.as_ref() {
entry.insert(Rc::clone(&method));
}
method
}
}
} else {
receiver_class.borrow().lookup_method(symbol)
}
}
}
};

if let Some(method) = method {
match method.kind() {
Expand All @@ -215,13 +247,11 @@ impl Interpreter {
args.reverse();

let holder = method.holder.upgrade().unwrap();
self.push_frame(FrameKind::Method {
let frame = self.push_frame(FrameKind::Method {
self_value,
method,
holder,
});

let frame = self.current_frame().unwrap();
frame.borrow_mut().args = args;
}
MethodKind::Primitive(func) => {
Expand Down Expand Up @@ -258,15 +288,42 @@ impl Interpreter {
};
let signature = universe.lookup_symbol(symbol);
let nb_params = nb_params(signature);
let holder = frame.borrow().get_method_holder();
let method = {
let super_class = holder.borrow().super_class()?;
let cache_key = (super_class.as_ptr() as *const _, bytecode_idx);

let method = frame
.borrow()
.get_method_holder()
.borrow()
.super_class()
.unwrap()
.borrow()
.lookup_method(symbol);
match frame.borrow().kind() {
FrameKind::Block { block } => {
match block.inline_cache.borrow_mut().entry(cache_key) {
Entry::Occupied(entry) => Some(Rc::clone(entry.get())),
Entry::Vacant(entry) => {
let method = super_class.borrow().lookup_method(symbol);
if let Some(method) = method.as_ref() {
entry.insert(Rc::clone(&method));
}
method
}
}
}
FrameKind::Method { method, .. } => {
if let MethodKind::Defined(env) = method.kind() {
match env.inline_cache.borrow_mut().entry(cache_key) {
Entry::Occupied(entry) => Some(Rc::clone(entry.get())),
Entry::Vacant(entry) => {
let method = super_class.borrow().lookup_method(symbol);
if let Some(method) = method.as_ref() {
entry.insert(Rc::clone(&method));
}
method
}
}
} else {
super_class.borrow().lookup_method(symbol)
}
}
}
};

if let Some(method) = method {
match method.kind() {
Expand All @@ -283,13 +340,11 @@ impl Interpreter {
args.reverse();

let holder = method.holder.upgrade().unwrap();
self.push_frame(FrameKind::Method {
let frame = self.push_frame(FrameKind::Method {
self_value,
method,
holder,
});

let frame = self.current_frame().unwrap();
frame.borrow_mut().args = args;
}
MethodKind::Primitive(func) => {
Expand Down
3 changes: 3 additions & 0 deletions som-interpreter-bc/src/method.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use std::rc::Rc;

Expand All @@ -18,6 +20,7 @@ pub struct MethodEnv {
pub locals: Vec<Value>,
pub literals: Vec<Literal>,
pub body: Vec<Bytecode>,
pub inline_cache: RefCell<HashMap<(*const Class, usize), Rc<Method>>>,
}

/// The kind of a class method.
Expand Down

0 comments on commit 11af59a

Please sign in to comment.