Skip to content

Commit 67911cd

Browse files
committed
Remove DupConst, move consts to vars at start of run
1 parent 973e306 commit 67911cd

File tree

4 files changed

+71
-86
lines changed

4 files changed

+71
-86
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ members = [
77
[profile.release]
88
lto = true
99
codegen-units = 1
10+
#debug = true

script/examples/vec2.bs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
fn main()
2-
for _ in 10_000_000
2+
#for _ in 10_000_000
33
#empty()
4-
args(0.5, 0.7)
4+
#args(1, 2)
55
#length(0.5, 0.7)
6-
#print(length(0.5, 0.7))
6+
print(length(0.5, 0.7))
77
pass
88

99

script/src/bytecode.rs

+66-82
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,38 @@ pub(crate) enum Instruction {
2020
CallSelf(Box<CallArgs>),
2121
CallGlobal(Box<CallArgs>),
2222
//Iter(Box<dyn Iterator<Item = Rc<dyn ScriptType>>>),
23-
Jmp(u32),
24-
JmpIf(u16, u32),
23+
//Jmp(u32),
24+
//JmpIf(u16, u32),
2525

2626
RetSome,
2727
RetNone,
2828

29-
// TODO avoid box
3029
IterConst(Box<(u16, u32, Box<dyn ScriptIter>)>),
3130
IterJmp(u16, u32),
3231

32+
/*
3333
AndJmp(u16, u16, u32),
3434
OrJmp(u16, u16, u32),
3535
Xor(u16, u16, u32),
3636
Eq,
3737
Neq,
38+
*/
3839

3940
Add(u16, u16, u16),
40-
Sub(u16, u16, u16),
41+
//Sub(u16, u16, u16),
4142
Mul(u16, u16, u16),
42-
Div(u16, u16, u16),
43-
Rem(u16, u16, u16),
43+
//Div(u16, u16, u16),
44+
//Rem(u16, u16, u16),
4445

4546
Move(u16, u16),
46-
DupConst(u16, Rc<dyn ScriptType>),
4747

48+
/*
4849
AddConst,
4950
SubConst,
5051
MulConst,
5152
DivConst,
5253
RemConst,
54+
*/
5355
}
5456

5557
#[derive(Debug)]
@@ -64,6 +66,7 @@ pub(crate) struct ByteCode {
6466
code: Vec<Instruction>,
6567
param_count: u16,
6668
var_count: u16,
69+
consts: Vec<Rc<dyn ScriptType>>,
6770
}
6871

6972
#[derive(Debug)]
@@ -81,7 +84,7 @@ pub struct Environment {
8184
functions: FxHashMap<Box<str>, EnvironmentFunction>,
8285
}
8386

84-
pub type EnvironmentFunction = Box<dyn Fn(&[&dyn ScriptType]) -> CallResult<RunError>>;
87+
pub type EnvironmentFunction = Box<dyn Fn(&[Rc<dyn ScriptType>]) -> CallResult<RunError>>;
8588
pub type CallResult<E> = Result<Rc<dyn ScriptType>, E>;
8689

8790
#[derive(Debug)]
@@ -99,6 +102,7 @@ impl ByteCode {
99102
) -> Result<Self, ByteCodeError> {
100103
let mut instr = Vec::new();
101104
let mut vars = FxHashMap::with_hasher(Default::default());
105+
let mut consts = Vec::new();
102106
let param_count = function.parameters.len() as u16;
103107
for p in function.parameters {
104108
if vars.insert(p, vars.len() as u16).is_some() {
@@ -112,17 +116,42 @@ impl ByteCode {
112116
locals,
113117
&mut instr,
114118
&mut vars,
119+
&mut consts,
115120
&mut var_count,
116121
0,
117122
)?;
118123
match instr.last() {
119124
Some(Instruction::RetSome) | Some(Instruction::RetNone) => (),
120125
_ => instr.push(Instruction::RetNone),
121126
}
127+
128+
if consts.len() > 0 {
129+
// All consts are using the upper-most registers, move them downwards
130+
let offset = (u16::MAX - consts.len() as u16).wrapping_add(1);
131+
for i in instr.iter_mut() {
132+
use Instruction::*;
133+
let conv = |c: &mut u16| if *c >= offset { *c = u16::MAX - *c + vars };
134+
match i {
135+
Call(box (_, ca)) | CallSelf(box ca) | CallGlobal(box ca) => {
136+
for a in ca.args.iter_mut() {
137+
conv(a);
138+
}
139+
}
140+
Move(_, a) => conv(a),
141+
Add(_, a, b) | Mul(_, a, b) => {
142+
conv(a);
143+
conv(b);
144+
}
145+
IterConst(_) | IterJmp(_, _) | RetSome | RetNone => (),
146+
}
147+
}
148+
}
149+
122150
Ok(Self {
123151
code: instr,
124152
var_count: vars,
125153
param_count,
154+
consts,
126155
})
127156
}
128157

@@ -132,6 +161,7 @@ impl ByteCode {
132161
locals: &FxHashMap<Box<str>, u16>,
133162
instr: &mut Vec<Instruction>,
134163
vars: &mut FxHashMap<&'a str, u16>,
164+
consts: &mut Vec<Rc<dyn ScriptType>>,
135165
curr_var_count: &mut u16,
136166
mut min_var_count: u16,
137167
) -> Result<u16, ByteCodeError> {
@@ -146,29 +176,15 @@ impl ByteCode {
146176
let mut args = Vec::with_capacity(arguments.len());
147177
// TODO move this to `parse_expression`
148178
for a in arguments {
179+
let mut add_const = |v| {
180+
consts.push(v);
181+
u16::MAX - consts.len() as u16 + 1
182+
};
149183
args.push(match a {
150184
Expression::Atom(a) => match a {
151-
Atom::String(a) => {
152-
let v = Rc::new(a.to_string().into_boxed_str());
153-
let v = Instruction::DupConst(*curr_var_count, v);
154-
instr.push(v);
155-
*curr_var_count += 1;
156-
*curr_var_count - 1
157-
}
158-
Atom::Integer(a) => {
159-
let v = Rc::new(*a);
160-
let v = Instruction::DupConst(*curr_var_count, v);
161-
instr.push(v);
162-
*curr_var_count += 1;
163-
*curr_var_count - 1
164-
}
165-
Atom::Real(a) => {
166-
let v = Rc::new(*a);
167-
let v = Instruction::DupConst(*curr_var_count, v);
168-
instr.push(v);
169-
*curr_var_count += 1;
170-
*curr_var_count - 1
171-
}
185+
Atom::String(a) => add_const(Rc::new(a.to_string().into_boxed_str())),
186+
Atom::Integer(a) => add_const(Rc::new(*a)),
187+
Atom::Real(a) => add_const(Rc::new(*a)),
172188
Atom::Name(a) => todo!("call {:?}", a),
173189
},
174190
Expression::Function {
@@ -184,31 +200,9 @@ impl ByteCode {
184200
match a {
185201
Expression::Atom(a) => {
186202
args.push(match a {
187-
Atom::String(a) => {
188-
let v =
189-
Rc::new(a.to_string().into_boxed_str());
190-
let v =
191-
Instruction::DupConst(*curr_var_count, v);
192-
instr.push(v);
193-
*curr_var_count += 1;
194-
*curr_var_count - 1
195-
}
196-
Atom::Integer(a) => {
197-
let v = Rc::new(*a);
198-
let v =
199-
Instruction::DupConst(*curr_var_count, v);
200-
instr.push(v);
201-
*curr_var_count += 1;
202-
*curr_var_count - 1
203-
}
204-
Atom::Real(a) => {
205-
let v = Rc::new(*a);
206-
let v =
207-
Instruction::DupConst(*curr_var_count, v);
208-
instr.push(v);
209-
*curr_var_count += 1;
210-
*curr_var_count - 1
211-
}
203+
Atom::String(a) => add_const(Rc::new(a.to_string().into_boxed_str())),
204+
Atom::Integer(a) => add_const(Rc::new(*a)),
205+
Atom::Real(a) => add_const(Rc::new(*a)),
212206
Atom::Name(a) => todo!("call {:?}", a),
213207
});
214208
}
@@ -271,6 +265,7 @@ impl ByteCode {
271265
locals,
272266
instr,
273267
vars,
268+
consts,
274269
curr_var_count,
275270
min_var_count,
276271
)?;
@@ -438,13 +433,14 @@ impl ByteCode {
438433
if args.len() != self.param_count as usize {
439434
return Err(RunError::IncorrectArgumentCount);
440435
}
441-
let mut vars = Vec::with_capacity(self.var_count as usize);
436+
let mut vars = Vec::with_capacity(self.var_count as usize + self.consts.len());
442437
for a in args.iter() {
443438
vars.push(a.clone());
444439
}
445440
vars.resize_with(self.var_count as usize, || {
446441
Rc::new(()) as Rc<dyn ScriptType>
447442
});
443+
vars.extend(self.consts.iter().cloned());
448444
let mut ip = 0;
449445
let mut iterators = Vec::new();
450446
let mut call_args = Vec::new();
@@ -457,7 +453,6 @@ impl ByteCode {
457453
ip += 1;
458454
use Instruction::*;
459455
match instr {
460-
/*
461456
Call(box (
462457
reg,
463458
CallArgs {
@@ -466,20 +461,12 @@ impl ByteCode {
466461
args,
467462
},
468463
)) => {
469-
let r = {
470-
let mut ca = Vec::with_capacity(args.len());
471-
for &a in args.iter() {
472-
ca.push(vars.get(a as usize).ok_or(err_roob())?.as_ref());
473-
}
474-
let obj = vars.get(*reg as usize).ok_or(err_roob())?.as_ref();
475-
obj.call(func, &ca[..]).map_err(err_call)?
476-
};
477-
// SAFETY: call_args has been cleared and thus does no longer actually
478-
// borrow any of the value in vars. However, Rust doesn't realize this, so
479-
// transmuting the lifetime is the only solution.
480-
// **NOTE**: an alternative solution would be to reallocate a new Vec.
481-
// This has far too much overhead however, so it's not an option.
482-
call_args = unsafe { mem::transmute(call_args) };
464+
for &a in args.iter() {
465+
call_args.push(vars.get(a as usize).ok_or(err_roob())?.clone());
466+
}
467+
let obj = vars.get(*reg as usize).ok_or(err_roob())?.as_ref();
468+
let r = obj.call(func, &call_args[..]).map_err(err_call)?;
469+
call_args.clear();
483470
if let Some(reg) = store_in {
484471
*vars.get_mut(*reg as usize).ok_or(err_roob())? = r;
485472
}
@@ -489,20 +476,15 @@ impl ByteCode {
489476
func,
490477
args,
491478
}) => {
492-
let r = {
493-
let mut ca = Vec::with_capacity(args.len());
494-
for &a in args.iter() {
495-
ca.push(vars.get(a as usize).ok_or(err_roob())?.as_ref());
496-
}
497-
env.call(func, &ca[..]).map_err(err_env)?
498-
};
499-
// SAFETY: ditto
500-
call_args = unsafe { mem::transmute(call_args) };
479+
for &a in args.iter() {
480+
call_args.push(vars.get(a as usize).ok_or(err_roob())?.clone());
481+
}
482+
let r = env.call(func, &call_args[..]).map_err(err_env)?;
483+
call_args.clear();
501484
if let Some(reg) = store_in {
502485
*vars.get_mut(*reg as usize).ok_or(err_roob())? = r;
503486
}
504487
}
505-
*/
506488
CallSelf(box CallArgs {
507489
store_in,
508490
func,
@@ -555,14 +537,16 @@ impl ByteCode {
555537
Add(r, a, b) => {
556538
let a = vars.get(*a as usize).ok_or(RunError::RegisterOutOfBounds)?;
557539
let b = vars.get(*b as usize).ok_or(RunError::RegisterOutOfBounds)?;
558-
let e = a.mul(b).map_err(|e| RunError::CallError(Box::new(e)))?;
540+
let e = a.add(b).map_err(|e| RunError::CallError(Box::new(e)))?;
559541
*vars
560542
.get_mut(*r as usize)
561543
.ok_or(RunError::RegisterOutOfBounds)? = e;
562544
}
545+
/*
563546
DupConst(r, c) => {
564547
*vars.get_mut(*r as usize).ok_or(err_roob())? = c.clone();
565548
}
549+
*/
566550
_ => todo!("{:?}", instr),
567551
}
568552
} else {
@@ -593,7 +577,7 @@ impl Environment {
593577
}
594578
}
595579

596-
pub fn call(&self, func: &str, args: &[&dyn ScriptType]) -> CallResult<EnvironmentError> {
580+
pub fn call(&self, func: &str, args: &[Rc<dyn ScriptType>]) -> CallResult<EnvironmentError> {
597581
Ok(self
598582
.functions
599583
.get(func)

script/src/script.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ impl Script {
126126
let mut env = Environment::new();
127127
env.add_function(
128128
"print".into(),
129-
Box::new(|a: &[&_]| {
129+
Box::new(|a: &[_]| {
130130
a.iter().for_each(|a| println!("{:?}", a));
131131
Ok(Rc::new(()))
132132
}),

0 commit comments

Comments
 (0)