Skip to content

Commit

Permalink
implemented memory pool, precomputed literal hash, GC and more OPs fo…
Browse files Browse the repository at this point in the history
…r the new VM2
  • Loading branch information
marcj committed Jun 30, 2022
1 parent ef08bdb commit 1d82863
Show file tree
Hide file tree
Showing 10 changed files with 1,337 additions and 497 deletions.
18 changes: 17 additions & 1 deletion src/checker/MemoryPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class MemoryPool {

~MemoryPool() noexcept;

unsigned int active = 0;

MemoryPool &operator=(const MemoryPool &memoryPool) = delete;
MemoryPool &operator=(MemoryPool &&memoryPool) noexcept;

Expand All @@ -44,6 +46,9 @@ class MemoryPool {
pointer allocate(size_type n = 1, const_pointer hint = 0);
void deallocate(pointer p, size_type n = 1);

// Schedules for garbage collection
void gc(pointer p);

size_type max_size() const noexcept;

template<class U, class... Args>
Expand Down Expand Up @@ -172,22 +177,33 @@ MemoryPool<T, BlockSize>::allocateBlock() {
template<typename T, size_t BlockSize>
inline typename MemoryPool<T, BlockSize>::pointer
MemoryPool<T, BlockSize>::allocate(size_type n, const_pointer hint) {
active++;
if (freeSlots_ != nullptr) {
pointer result = reinterpret_cast<pointer>(freeSlots_);
freeSlots_ = freeSlots_->next;
return result;
} else {
if (currentSlot_ >= lastSlot_) {
allocateBlock();
// printf("allocate new block\n");
}
return reinterpret_cast<pointer>(currentSlot_++);
}
}

template<typename T, size_t BlockSize>
inline void
MemoryPool<T, BlockSize>::gc(pointer p) {
deallocate(p);
// if (p != nullptr) {
// reinterpret_cast<slot_pointer_>(p)->next = freeSlots_;
// freeSlots_ = reinterpret_cast<slot_pointer_>(p);
// }
}

template<typename T, size_t BlockSize>
inline void
MemoryPool<T, BlockSize>::deallocate(pointer p, size_type n) {
active--;
if (p != nullptr) {
reinterpret_cast<slot_pointer_>(p)->next = freeSlots_;
freeSlots_ = reinterpret_cast<slot_pointer_>(p);
Expand Down
50 changes: 43 additions & 7 deletions src/checker/check2.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,70 @@
#include "./types2.h"

namespace ts::vm2 {

namespace check {
struct Check {
Type *left;
Type *right;
};

inline std::array<Check, 4096> checks;
inline unsigned int depth;
}

/**
* `left extends right ? true : false`
*/
bool extends(Type *left, Type *right) {
switch (right->kind) {
case TypeKind::Union: {
auto current = (TypeRef *) right->type;
while (current) {
if (extends(left, current->type)) return true;
current = current->next;
}
return false;
}
case TypeKind::Literal: {
switch (left->kind) {
case TypeKind::Literal:
//todo: literal type
return left->hash == right->hash;
if ((left->flag & TypeFlag::StringLiteral && right->flag & TypeFlag::StringLiteral) || (left->flag & TypeFlag::NumberLiteral && right->flag & TypeFlag::NumberLiteral))
return left->hash == right->hash;
return (left->flag & TypeFlag::True && right->flag & TypeFlag::True) || left->flag & TypeFlag::False && right->flag & TypeFlag::False;
}
break;
return false;
}
case TypeKind::String: {
switch (left->kind) {
case TypeKind::String: return true;
case TypeKind::Literal: return left->flag | TypeFlag::StringLiteral;
case TypeKind::String:
return true;
case TypeKind::Literal:
return left->flag & TypeFlag::StringLiteral;
}
break;
return false;
}
case TypeKind::Number: {
switch (left->kind) {
case TypeKind::Number: return true;
case TypeKind::Literal: return left->flag | TypeFlag::NumberLiteral;
case TypeKind::Number:
return true;
case TypeKind::Literal:
return left->flag & TypeFlag::NumberLiteral;
}
break;
}
case TypeKind::Boolean: {
switch (left->kind) {
case TypeKind::Boolean:
return true;
case TypeKind::Literal:
return left->flag & TypeFlag::True || left->flag & TypeFlag::False;
}
break;
}
}
return false;
}


}
48 changes: 30 additions & 18 deletions src/checker/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ namespace ts::checker {
SourceMap sourceMap; //SourceMap of "main"

vector<string_view> storage; //all kind of literals, as strings
unordered_map<string_view, reference_wrapper<StorageItem>> storageMap; //used to deduplicated storage entries
unordered_map<uint64_t, reference_wrapper<StorageItem>> storageMap; //used to deduplicated storage entries

unsigned int storageIndex{};
shared<Frame> frame = make_shared<Frame>();

Expand Down Expand Up @@ -209,7 +210,7 @@ namespace ts::checker {
//errors need to be part of main
sourceMap.push(0, node->pos, node->end);
ops.push_back(OP::Error);
vm::writeUint16(ops, ops.size(), (unsigned int)code);
vm::writeUint16(ops, ops.size(), (unsigned int) code);
}

void pushSymbolAddress(Symbol &symbol) {
Expand Down Expand Up @@ -314,11 +315,11 @@ namespace ts::checker {

//note: make sure the same name is not added twice. needs hashmap
unsigned int registerStorage(const string_view &s) {
if (!storageIndex) storageIndex = 5; //jump+address
if (!storageIndex) storageIndex = 1 + 4; //jump+address

const auto address = storageIndex;
storage.push_back(s);
storageIndex += 2 + s.size();
storageIndex += 8 + 2 + s.size(); //hash + size + data
return address;
}

Expand All @@ -344,13 +345,14 @@ namespace ts::checker {
vm::writeUint32(bin, bin.size(), 0); //set after storage handling

for (auto &&item: storage) {
address += 2 + item.size();
address += 8 + 2 + item.size(); //hash+size+data
}

//set initial jump position to right after the storage data
vm::writeUint32(bin, 1, address);
//push all storage data to the binary
for (auto &&item: storage) {
vm::writeUint64(bin, bin.size(), hash::runtime_hash(item));
vm::writeUint16(bin, bin.size(), item.size());
bin.insert(bin.end(), item.begin(), item.end());
}
Expand Down Expand Up @@ -432,26 +434,35 @@ namespace ts::checker {
}
break;
}
case types::SyntaxKind::NeverKeyword: program.pushOp(OP::Never, node);
case types::SyntaxKind::NeverKeyword:
program.pushOp(OP::Never, node);
break;
case types::SyntaxKind::BooleanKeyword: program.pushOp(OP::Boolean, node);
case types::SyntaxKind::BooleanKeyword:
program.pushOp(OP::Boolean, node);
break;
case types::SyntaxKind::StringKeyword: program.pushOp(OP::String, node);
case types::SyntaxKind::StringKeyword:
program.pushOp(OP::String, node);
break;
case types::SyntaxKind::NumberKeyword: program.pushOp(OP::Number, node);
case types::SyntaxKind::NumberKeyword:
program.pushOp(OP::Number, node);
break;
case types::SyntaxKind::BigIntLiteral: program.pushOp(OP::BigIntLiteral, node);
case types::SyntaxKind::BigIntLiteral:
program.pushOp(OP::BigIntLiteral, node);
program.pushStorage(to<BigIntLiteral>(node)->text);
break;
case types::SyntaxKind::NumericLiteral: program.pushOp(OP::NumberLiteral, node);
case types::SyntaxKind::NumericLiteral:
program.pushOp(OP::NumberLiteral, node);
program.pushStorage(to<NumericLiteral>(node)->text);
break;
case types::SyntaxKind::StringLiteral: program.pushOp(OP::StringLiteral, node);
case types::SyntaxKind::StringLiteral:
program.pushOp(OP::StringLiteral, node);
program.pushStorage(to<StringLiteral>(node)->text);
break;
case types::SyntaxKind::TrueKeyword: program.pushOp(OP::True, node);
case types::SyntaxKind::TrueKeyword:
program.pushOp(OP::True, node);
break;
case types::SyntaxKind::FalseKeyword: program.pushOp(OP::False, node);
case types::SyntaxKind::FalseKeyword:
program.pushOp(OP::False, node);
break;
case types::SyntaxKind::IndexedAccessType: {
const auto n = to<IndexedAccessTypeNode>(node);
Expand Down Expand Up @@ -547,7 +558,7 @@ namespace ts::checker {
const auto n = to<TypeAliasDeclaration>(node);

auto &symbol = program.pushSymbolForRoutine(n->name->escapedText, SymbolType::Type, n); //move this to earlier symbol-scan round
if (symbol.declarations > 1) {
if (symbol.declarations>1) {
//todo: for functions/variable embed an error that symbol was declared twice in the same scope
} else {
//populate routine
Expand Down Expand Up @@ -602,7 +613,7 @@ namespace ts::checker {
const auto n = to<FunctionDeclaration>(node);
if (const auto id = to<Identifier>(n->name)) {
auto &symbol = program.pushSymbolForRoutine(id->escapedText, SymbolType::Function, id); //move this to earlier symbol-scan round
if (symbol.declarations > 1) {
if (symbol.declarations>1) {
//todo: embed error since function is declared twice
} else {
if (n->typeParameters) {
Expand Down Expand Up @@ -974,7 +985,8 @@ namespace ts::checker {

break;
}
default: throw runtime_error(fmt::format("BinaryExpression Operator token {} not handled", n->operatorToken->kind));
default:
throw runtime_error(fmt::format("BinaryExpression Operator token {} not handled", n->operatorToken->kind));
}
break;
}
Expand All @@ -988,7 +1000,7 @@ namespace ts::checker {
const auto n = to<VariableDeclaration>(node);
if (const auto id = to<Identifier>(n->name)) {
auto &symbol = program.pushSymbolForRoutine(id->escapedText, SymbolType::Variable, id); //move this to earlier symbol-scan round
if (symbol.declarations > 1) {
if (symbol.declarations>1) {
//todo: embed error since variable is declared twice
} else {
if (n->type) {
Expand Down
10 changes: 5 additions & 5 deletions src/checker/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ namespace ts::checker {
for (unsigned int i = 0; i < end; i++) {
if (storageEnd) {
while (i < storageEnd) {
auto size = vm::readUint16(bin, i);
auto data = bin.substr(i + 2, size);
auto size = vm::readUint16(bin, i + 8);
auto data = bin.substr(i + 8 + 2, size);
if (print) fmt::print("(Storage ({})\"{}\") ", size, data);
result.storages.push_back(string(data));
i += 2 + size;
i += 8 + 2 + size;
}
debug("");
storageEnd = 0;
Expand Down Expand Up @@ -103,7 +103,7 @@ namespace ts::checker {
case OP::Subroutine: {
auto nameAddress = vm::readUint32(bin, i + 1);
auto address = vm::readUint32(bin, i + 5);
string name = nameAddress ? string(vm::readStorage(bin, nameAddress)) : "";
string name = nameAddress ? string(vm::readStorage(bin, nameAddress + 8)) : "";
params += fmt::format(" {}[{}]", name, address);
i += 8;
result.subroutines.push_back({.name = name, .address = address});
Expand Down Expand Up @@ -168,7 +168,7 @@ namespace ts::checker {
case OP::BigIntLiteral:
case OP::StringLiteral: {
auto address = vm::readUint32(bin, i + 1);
params += fmt::format(" \"{}\"", vm::readStorage(bin, address));
params += fmt::format(" \"{}\"", vm::readStorage(bin, address + 8));
i += 4;
break;
}
Expand Down
Loading

0 comments on commit 1d82863

Please sign in to comment.