Fix a lot of things and implement gc

This commit is contained in:
2019-05-29 21:06:42 +02:00
parent c3876da74f
commit 84bdcf4b20
16 changed files with 146 additions and 55 deletions

2
.gitignore vendored
View File

@@ -2,5 +2,5 @@ target
/*.jas
/*.ijvm
*.conf
goJASM
gojasm
rustijvm

17
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,17 @@
stages:
- build
rust-latest:
stage: build
image: rust:latest
script:
- cargo build --verbose
- cargo test --verbose
allow_failure: true
rust-nightly:
stage: build
image: rustlang/rust:nightly
script:
- cargo build --verbose
- cargo test --verbose

View File

@@ -18,6 +18,7 @@ bonus = ["bonus:network", "bonus:heap"]
extra = ["extra:sleep"]
"extra:sleep" = []
debug = ["debug:instr", "debug:frame"]
debug = ["debug:instr", "debug:frame", "debug:gc"]
"debug:instr" = []
"debug:frame" = []
"debug:gc" = []

37
ijvm.config Normal file
View File

@@ -0,0 +1,37 @@
0x10 BIPUSH byte
0x59 DUP
0xA7 GOTO label
0x60 IADD
0x7E IAND
0x99 IFEQ label
0x9B IFLT label
0x9F IF_ICMPEQ label
0x84 IINC var byte
0x15 ILOAD var
0xB6 INVOKEVIRTUAL method
0xB0 IOR
0xAC IRETURN
0x36 ISTORE var
0x64 ISUB
0x13 LDC_W constant
0x00 NOP
0x57 POP
0x5F SWAP
0xC4 WIDE
0xFF HALT
0xFE ERR
0xFD OUT
0xFC IN
0xD1 NEWARRAY
0xD2 IALOAD
0xD3 IASTORE
0xD4 GC
0xE1 NETBIND
0xE2 NETCONNECT
0xE3 NETIN
0xE4 NETOUT
0xE5 NETCLOSE
0xF0 SLP byte

View File

@@ -2,7 +2,6 @@ use block::Block;
use ops::{num_to_op, Operation};
use Result;
#[allow(unknown_lints, len_without_is_empty)]
pub trait BinReadable {
fn get(&mut self) -> Result<u8>;
fn cur(&self) -> usize;

View File

@@ -1,11 +1,17 @@
use value::Value;
use std::rc::Rc;
use std::cell::RefCell;
pub type Heap = Rc<RefCell<Vec<Value>>>;
#[derive(Debug,Default)]
pub struct Heap {
pub heaps: Vec<Vec<i32>>
pub struct Heaps {
pub heaps: Vec<Heap>
}
impl Heap {
pub fn new() -> Heap {
Heap {
impl Heaps {
pub fn new() -> Heaps {
Heaps {
heaps: Vec::new()
}
}
@@ -14,16 +20,38 @@ impl Heap {
self.heaps.len()
}
pub fn get(&mut self, i: usize) -> &mut Vec<i32> {
&mut self.heaps[i]
pub fn get(&mut self, i: usize) -> Heap {
self.heaps[i].clone()
}
pub fn alloc(&mut self, size: usize) -> usize {
self.heaps.push(vec![0; size]);
self.len() - 1
pub fn alloc(&mut self, size: usize) -> Heap {
let heap = Rc::new(RefCell::new(vec![Value::Int(0); size]));
self.heaps.push(heap.clone());
heap
}
pub fn is_empty(&self) -> bool {
self.heaps.is_empty()
}
pub fn gc(&mut self) {
let pre_size = self.len();
if cfg!(feature = "debug:gc") {
for (i, heap) in self.heaps.iter().enumerate() {
eprintln!("GC heap {} ref = {}", i, Rc::strong_count(heap));
}
}
self.heaps = self.heaps.iter()
.filter(|e| Rc::strong_count(e) > 1)
.map(|e| Rc::clone(e))
.collect();
let post_size = self.len();
if cfg!(feature = "debug:gc") {
eprintln!("GC reaped {} heaps", pre_size - post_size);
}
}
}

View File

@@ -2,6 +2,7 @@
extern crate serde_derive;
#[macro_use]
extern crate lazy_static;
extern crate core;
pub mod ijvmreader;
pub mod binread;

View File

@@ -11,7 +11,7 @@ use stack::Stack;
use Result;
#[cfg(feature = "bonus:heap")]
use heap::Heap;
use heap::Heaps;
#[cfg(feature = "bonus:network")]
use netstack::NetStack;
use std::convert::TryInto;
@@ -28,7 +28,7 @@ pub struct Machine {
#[cfg(feature = "bonus:network")]
pub net: NetStack,
#[cfg(feature = "bonus:heap")]
pub heap: Heap,
pub heap: Heaps,
pub stream_in: Box<Read + Send + Sync>,
pub stream_out: Arc<Mutex<Write + Send + Sync>>,
@@ -49,7 +49,7 @@ impl Machine {
net: NetStack::new(),
#[cfg(feature = "bonus:heap")]
heap: Heap::new(),
heap: Heaps::new(),
}
}

View File

@@ -74,6 +74,7 @@ lazy_static! {
m[0xD1] = Operation::Op("NEWARRAY", newarray, vec![]);
m[0xD2] = Operation::Op("IALOAD", iaload, vec![]);
m[0xD3] = Operation::Op("IASTORE", iastore, vec![]);
m[0xD4] = Operation::Op("GC", gc, vec![]);
}
m
@@ -110,7 +111,7 @@ fn out(machine: &mut Machine) -> Result<()> {
let mut out = machine.stream_out.lock().unwrap();
out.write_all(&buffer).unwrap();
out.flush().unwrap();
return Ok(());
Ok(())
}
fn pop(machine: &mut Machine) -> Result<()> {
@@ -266,6 +267,8 @@ fn invokevirtual(machine: &mut Machine) -> Result<()> {
}
fn ireturn(machine: &mut Machine) -> Result<()> {
// Lifetime for prev frame, allows gc to reap into the frame
{
let mut prev_frame: Frame = match machine.frame.pop() {
Some(a) => a,
None => return Err("Got no frame... somehow..."),
@@ -273,7 +276,11 @@ fn ireturn(machine: &mut Machine) -> Result<()> {
let result = prev_frame.stack.pop()?;
let return_addr: i32 = prev_frame.get(0)?.try_into()?;
machine.cur_stack().push(result);
machine.block.seek(return_addr as usize)
machine.block.seek(return_addr as usize)?;
}
machine.heap.gc();
Ok(())
}
#[cfg(feature = "extra:sleep")]
@@ -323,40 +330,46 @@ fn netclose(machine: &mut Machine) -> Result<()> {
#[cfg(feature = "bonus:heap")]
fn newarray(machine: &mut Machine) -> Result<()> {
let size: i32 = machine.cur_stack().pop()?.try_into()?;
let heapref = machine.heap.alloc(size as usize);
machine.cur_stack().push(Value::HeapRef(heapref));
let heap = machine.heap.alloc(size as usize);
machine.cur_stack().push(Value::HeapRef(heap));
Ok(())
}
#[cfg(feature = "bonus:heap")]
fn iastore(machine: &mut Machine) -> Result<()> {
let heapref = match machine.cur_stack().pop()? {
use std::cell::RefCell;
let heap = match machine.cur_stack().pop()? {
Value::HeapRef(a) => a,
_ => return Err("Cannot use int as heapref"),
};
let index: i32 = machine.cur_stack().pop()?.try_into()?;
let value: i32 = machine.cur_stack().pop()?.try_into()?;
let value = machine.cur_stack().pop()?.clone();
let heap = machine.heap.get(heapref);
heap[index as usize] = value;
RefCell::borrow_mut(&heap)[index as usize] = value;
Ok(())
}
#[cfg(feature = "bonus:heap")]
fn iaload(machine: &mut Machine) -> Result<()> {
let heapref = match machine.cur_stack().pop()? {
let heap = match machine.cur_stack().pop()? {
Value::HeapRef(a) => a,
_ => return Err("Cannot use int as heapref"),
};
let index: i32 = machine.cur_stack().pop()?.try_into()?;
let value: i32;
let value: Value;
{
let heap = machine.heap.get(heapref);
value = heap[index as usize];
value = heap.borrow()[index as usize].clone();
}
machine.cur_stack().push(Value::Int(value));
machine.cur_stack().push(value);
Ok(())
}
#[cfg(feature = "bonus:heap")]
fn gc(machine: &mut Machine) -> Result<()> {
machine.heap.gc();
Ok(())
}

View File

@@ -1,10 +1,11 @@
use Result;
use std::convert::TryInto;
use heap::Heap;
#[derive(Debug, Copy, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Int(i32),
HeapRef(usize),
HeapRef(Heap),
}
impl TryInto<i32> for Value {
@@ -22,9 +23,9 @@ impl TryInto<i32> for &Value {
type Error = &'static str;
fn try_into(self) -> Result<i32> {
match self {
&Value::Int(a) => Ok(a),
&Value::HeapRef(_) => Err("Cannot use HeapRef as i32"),
match *self {
Value::Int(a) => Ok(a),
Value::HeapRef(_) => Err("Cannot use HeapRef as i32"),
}
}
}

View File

@@ -1,7 +1,6 @@
extern crate rustijvm;
use std::sync::{Arc, Mutex};
use std::io::{Cursor, Seek, SeekFrom, Read};
use std::io::{Seek, SeekFrom, Read};
fn steps(machine: &mut rustijvm::Machine, num: usize) {
for _ in 0..num {

View File

@@ -1,7 +1,6 @@
extern crate rustijvm;
use std::sync::{Arc, Mutex};
use std::io::{Cursor, Seek, SeekFrom, Read};
use std::io::{Seek, SeekFrom, Read};
#[test]
fn advanced4_tanenbaum() {

View File

@@ -1,7 +1,6 @@
extern crate rustijvm;
use std::sync::{Arc, Mutex};
use std::io::{Cursor, Seek, SeekFrom, Read};
use std::io::{Seek, SeekFrom, Read};
fn run_calc(input: &'static str, expected: &str) {
let rc = rustijvm::stubs::output_stub();

View File

@@ -1,7 +1,6 @@
extern crate rustijvm;
use std::sync::{Arc, Mutex};
use std::io::{Cursor, Seek, SeekFrom, Read};
use std::io::{Seek, SeekFrom, Read};
fn run_calc(input: &'static str, expected: &str) {
let rc = rustijvm::stubs::output_stub();

View File

@@ -1,8 +1,7 @@
extern crate rustijvm;
use std::fs::File;
use std::sync::{Arc, Mutex};
use std::io::{Cursor, Seek, SeekFrom, Read};
use std::io::{Seek, SeekFrom, Read};
fn run_bfi(file: &str) -> String {
let file = File::open(file).expect("Missing bf file");

View File

@@ -1,7 +1,6 @@
extern crate rustijvm;
use std::io::{Cursor, Read, Seek, SeekFrom};
use std::sync::{Arc, Mutex};
use std::io::{Read, Seek, SeekFrom};
fn steps(machine: &mut rustijvm::Machine, num: usize) {
for _ in 0..num {