Skip to content

Commit

Permalink
Release registers upon return
Browse files Browse the repository at this point in the history
  • Loading branch information
voltrevo committed Jun 30, 2023
1 parent 52f4233 commit f985698
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 22 deletions.
8 changes: 6 additions & 2 deletions inputs/failing/copyCounting/externalMethod.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! test_output(1)
//! test_output(2)
// Should be: 0

/// <reference path="../../../concept-code/vs.d.ts" />
Expand All @@ -16,7 +16,7 @@ function measure(doPush: boolean) {
arr = push(arr, "y");
}

return x.count;
return len(arr) + x.count;
}

function push<T>(x: T[], value: T) {
Expand All @@ -27,3 +27,7 @@ function push<T>(x: T[], value: T) {
function echo<T>(x: T) {
return x;
}

function len<T>(arr: T[]) {
return arr.length;
}
17 changes: 17 additions & 0 deletions inputs/failing/exceptions/finallyWithoutThrow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! test_output(E: undefined)
// Should be: "Ok"

// FIXME: This is failing because the optimizer learned to move out of the exception variable. This
// is resulting in a void->undefined conversion (I think), which breaks because we rely on
// throw(void) to not actually throw.

export default function () {
let result: string;

try {
} finally {
result = "Ok";
}

return result;
}
11 changes: 11 additions & 0 deletions inputs/failing/exceptions/throwTypeError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! test_output(undefined)
// Should be: E: TypeError{"message":"Cannot subscript undefined"}

// FIXME: This is failing because the optimizer is removing the subscript instruction because the
// result is unused. We need to implement throw detection in the optimizer and only remove
// instructions that can throw when we know that they won't throw.

export default function () {
const arr = undefined;
const len = arr.length;
}
12 changes: 0 additions & 12 deletions inputs/passing/exceptions/finallyWithoutThrow.ts

This file was deleted.

6 changes: 0 additions & 6 deletions inputs/passing/exceptions/throwTypeError.ts

This file was deleted.

4 changes: 4 additions & 0 deletions valuescript_compiler/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@ impl Register {
return self.name == "ignore";
}

pub fn is_special(&self) -> bool {
return self.is_return() || self.is_this() || self.is_ignore();
}

pub fn value_type(&self) -> ValueType {
if self.take {
ValueType::TakeRegister
Expand Down
11 changes: 11 additions & 0 deletions valuescript_compiler/src/function_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@ impl FunctionCompiler {
self.current.body.push(FnLine::Release(reg.clone()));
}

pub fn insert_all_releases(&mut self) {
for reg in self.reg_allocator.all_used() {
if !reg.is_special() {
self.current.body.push(FnLine::Release(reg));
}
}
}

pub fn compile(
definition_pointer: Pointer,
fn_name: Option<String>,
Expand Down Expand Up @@ -341,6 +349,8 @@ impl FunctionCompiler {
}
};

self.insert_all_releases();

if let Some(end_label) = self.end_label.as_ref() {
self.current.body.push(FnLine::Label(end_label.clone()));

Expand Down Expand Up @@ -493,6 +503,7 @@ impl FunctionCompiler {
self.push(Instruction::Mov(Value::Bool(true), is_returning.clone()));
self.push(Instruction::Jmp(finally_label.ref_()));
} else {
self.insert_all_releases();
self.push(Instruction::End);
}
}
Expand Down
14 changes: 12 additions & 2 deletions valuescript_compiler/src/name_allocator.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::collections::HashSet;
use std::collections::BTreeSet;

use crate::asm::{Pointer, Register};

#[derive(Default, Clone)]
pub struct NameAllocator {
used_names: HashSet<String>,
used_names: BTreeSet<String>,
released_names: Vec<String>,
}

Expand Down Expand Up @@ -149,6 +149,16 @@ impl RegAllocator {
false => panic!("Can't release non-named register"),
}
}

pub fn all_used(&self) -> Vec<Register> {
let mut res = Vec::<Register>::new();

for name in &self.alloc.used_names {
res.push(Register::named(name.clone()));
}

res
}
}

impl Default for RegAllocator {
Expand Down

0 comments on commit f985698

Please sign in to comment.