This commit is contained in:
blueloveTH 2023-04-07 21:36:45 +08:00
parent 6a27bc8bda
commit 7efb440388
8 changed files with 201 additions and 104 deletions

View File

@ -55,6 +55,7 @@ class Compiler {
}
static void init_pratt_rules(){
if(rules[TK(".")].precedence != PREC_NONE) return;
// http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
#define METHOD(name) &Compiler::name
#define NO_INFIX nullptr, PREC_NONE

View File

@ -7,7 +7,7 @@ namespace pkpy{
static THREAD_LOCAL uint64_t kFrameGlobalId = 0;
using ValueStack = small_vector<PyObject*, 6>;
using ValueStack = pod_vector<PyObject*>;
struct Frame {
ValueStack _data;

View File

@ -100,7 +100,7 @@ struct Lexer {
const char* curr_char;
int current_line = 1;
std::vector<Token> nexts;
small_stack<int, 4> indents;
stack<int> indents;
int brackets_level = 0;
bool used = false;

View File

@ -1,7 +1,6 @@
#pragma once
#include "common.h"
#include "vector.h"
namespace pkpy{
@ -69,48 +68,12 @@ shared_ptr<T> make_sp(Args&&... args) {
return shared_ptr<T>(p);
}
template<typename T, int __Bucket, bool __ZeroInit>
struct FreeListA {
std::vector<T*> buckets[__Bucket+1];
T* alloc(int n){
static_assert(std::is_standard_layout_v<T>);
T* p;
if(n > __Bucket || buckets[n].empty()){
p = (T*)malloc(sizeof(T) * n);
}else{
p = buckets[n].back();
buckets[n].pop_back();
}
if constexpr(__ZeroInit){
// the constructor of T should be equivalent to zero initialization
memset((void*)p, 0, sizeof(T) * n);
}
return p;
}
void dealloc(T* p, int n){
if(p == nullptr) return;
if(n > __Bucket || buckets[n].size() >= 80){
free(p);
}else{
buckets[n].push_back(p);
}
}
~FreeListA(){
for(int i=0; i<=__Bucket; i++){
for(T* p : buckets[i]) free(p);
}
}
};
struct LinkedListNode{
LinkedListNode* prev;
LinkedListNode* next;
};
template<typename T>
struct DoubleLinkedList{
static_assert(std::is_base_of_v<LinkedListNode, T>);
@ -295,6 +258,9 @@ struct MemoryPool{
}
void dealloc(void* p){
#if DEBUG_MEMORY_POOL
if(p == nullptr) throw std::runtime_error("MemoryPool::dealloc() called on nullptr");
#endif
Block* block = (Block*)((char*)p - sizeof(void*));
if(block->arena == nullptr){
free(block);
@ -328,4 +294,8 @@ struct MemoryPool{
}
};
inline MemoryPool<64> pool64;
inline MemoryPool<128> pool128;
inline MemoryPool<256> pool256;
}; // namespace pkpy

View File

@ -34,8 +34,6 @@ inline static uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vect
struct NameDict {
using Item = std::pair<StrName, PyObject*>;
inline static THREAD_LOCAL FreeListA<Item, 32, true> _pool;
uint16_t _capacity;
uint16_t _size;
float _load_factor;
@ -43,31 +41,36 @@ struct NameDict {
uint16_t _mask;
Item* _items;
void _alloc(int cap){
_items = (Item*)pool128.alloc(cap * sizeof(Item));
memset(_items, 0, cap * sizeof(Item));
}
NameDict(uint16_t capacity=2, float load_factor=0.67, uint16_t hash_seed=kHashSeeds[0]):
_capacity(capacity), _size(0), _load_factor(load_factor),
_hash_seed(hash_seed), _mask(capacity-1) {
_items = _pool.alloc(_capacity);
_alloc(capacity);
}
NameDict(const NameDict& other) {
memcpy(this, &other, sizeof(NameDict));
_items = _pool.alloc(_capacity);
_alloc(_capacity);
for(int i=0; i<_capacity; i++){
_items[i] = other._items[i];
}
}
NameDict& operator=(const NameDict& other) {
_pool.dealloc(_items, _capacity);
pool128.dealloc(_items);
memcpy(this, &other, sizeof(NameDict));
_items = _pool.alloc(_capacity);
_alloc(_capacity);
for(int i=0; i<_capacity; i++){
_items[i] = other._items[i];
}
return *this;
}
~NameDict(){ _pool.dealloc(_items, _capacity); }
~NameDict(){ pool128.dealloc(_items); }
NameDict(NameDict&&) = delete;
NameDict& operator=(NameDict&&) = delete;
@ -109,7 +112,7 @@ while(!_items[i].first.empty()) { \
_capacity = find_next_capacity(_capacity * 2);
_mask = _capacity - 1;
}
_items = _pool.alloc(_capacity);
_alloc(_capacity);
for(uint16_t i=0; i<old_capacity; i++){
if(old_items[i].first.empty()) continue;
bool ok; uint16_t j;
@ -117,7 +120,7 @@ while(!_items[i].first.empty()) { \
if(ok) UNREACHABLE();
_items[j] = old_items[i];
}
_pool.dealloc(old_items, old_capacity);
pool128.dealloc(old_items);
}
void _try_perfect_rehash(){

143
src/new_str.h Normal file
View File

@ -0,0 +1,143 @@
#pragma once
#include "common.h"
#include "memory.h"
#include <string_view>
namespace pkpy{
struct String{
char* data;
int size;
String(): data((char*)pool64.alloc(0)), size(0) {}
String(int size): data((char*)pool64.alloc(size)), size(size) {}
String(const char* str) {
size = strlen(str);
data = (char*)pool64.alloc(size);
memcpy(data, str, size);
}
String(const String& other): data((char*)pool64.alloc(other.size)), size(other.size) {
memcpy(data, other.data, size);
}
String(String&& other): data(other.data), size(other.size) {
other.data = nullptr;
}
String& operator=(const String& other){
if(data!=nullptr) pool64.dealloc(data);
size = other.size;
data = (char*)pool64.alloc(size);
memcpy(data, other.data, size);
return *this;
}
String& operator=(String&& other){
if(data!=nullptr) pool64.dealloc(data);
size = other.size;
data = other.data;
other.data = nullptr;
return *this;
}
~String(){
if(data!=nullptr) pool64.dealloc(data);
}
char operator[](int idx) const {
return data[idx];
}
int length() const {
return size;
}
String operator+(const String& other) const {
String ret(size + other.size);
memcpy(ret.data, data, size);
memcpy(ret.data + size, other.data, other.size);
return ret;
}
friend std::ostream& operator<<(std::ostream& os, const String& str){
os.write(str.data, str.size);
return os;
}
bool operator==(const String& other) const {
if(size != other.size) return false;
return memcmp(data, other.data, size) == 0;
}
bool operator!=(const String& other) const {
if(size != other.size) return true;
return memcmp(data, other.data, size) != 0;
}
bool operator<(const String& other) const {
int ret = strncmp(data, other.data, std::min(size, other.size));
if(ret != 0) return ret < 0;
return size < other.size;
}
bool operator>(const String& other) const {
int ret = strncmp(data, other.data, std::min(size, other.size));
if(ret != 0) return ret > 0;
return size > other.size;
}
bool operator<=(const String& other) const {
int ret = strncmp(data, other.data, std::min(size, other.size));
if(ret != 0) return ret < 0;
return size <= other.size;
}
bool operator>=(const String& other) const {
int ret = strncmp(data, other.data, std::min(size, other.size));
if(ret != 0) return ret > 0;
return size >= other.size;
}
String substr(int start, int len) const {
String ret(len);
memcpy(ret.data, data + start, len);
return ret;
}
String substr(int start) const {
return substr(start, size - start);
}
char* dup_c_str() const {
char* p = (char*)malloc(size + 1);
memcpy(p, data, size);
p[size] = 0;
return p;
}
std::string_view view() const {
return std::string_view(data, size);
}
std::string str() const {
return std::string(data, size);
}
String lstrip() const {
std::string copy = str();
copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) {
// std::isspace(c) does not working on windows (Debug)
return c != ' ' && c != '\t' && c != '\r' && c != '\n';
}));
return String(copy.c_str());
}
};
struct UnicodeString: String{
};
} // namespace pkpy

View File

@ -3,19 +3,18 @@
#include "common.h"
#include "memory.h"
#include "str.h"
#include "vector.h"
namespace pkpy {
using List = small_vector<PyObject*, 4>;
using List = pod_vector<PyObject*>;
class Args {
inline static THREAD_LOCAL FreeListA<PyObject*, 10, false> _pool;
PyObject** _args;
int _size;
void _alloc(int n){
this->_args = (n==0) ? nullptr : _pool.alloc(n);
this->_args = (n==0) ? nullptr : (PyObject**)pool64.alloc(n * sizeof(void*));
this->_size = n;
}
@ -48,7 +47,7 @@ public:
PyObject* operator[](int i) const { return _args[i]; }
Args& operator=(Args&& other) noexcept {
_pool.dealloc(_args, _size);
if(_args!=nullptr) pool64.dealloc(_args);
this->_args = other._args;
this->_size = other._size;
other._args = nullptr;
@ -71,10 +70,10 @@ public:
_alloc(old_size+1);
_args[0] = self;
for(int i=0; i<old_size; i++) _args[i+1] = old_args[i];
_pool.dealloc(old_args, old_size);
if(old_args!=nullptr) pool64.dealloc(old_args);
}
~Args(){ _pool.dealloc(_args, _size); }
~Args(){ if(_args!=nullptr) pool64.dealloc(_args); }
};
inline const Args& no_arg() {

View File

@ -1,65 +1,51 @@
#pragma once
#include "common.h"
#include "memory.h"
namespace pkpy{
template<typename T, int N>
struct small_vector{
template<typename T>
struct pod_vector{
static_assert(128 % sizeof(T) == 0);
static_assert(std::is_pod_v<T>);
static constexpr int N = 128 / sizeof(T);
static_assert(N > 4);
int _size;
int _capacity;
T* _data;
T _buffer[N];
small_vector(): _size(0), _capacity(N) {
static_assert(std::is_pod_v<T>);
_data = _buffer;
pod_vector(): _size(0), _capacity(N) {
_data = (T*)pool128.alloc(_capacity * sizeof(T));
}
small_vector(int size): _size(0), _capacity(N){
_data = _buffer;
reserve(size);
_size = size;
pod_vector(int size): _size(size), _capacity(std::max(N, size)) {
_data = (T*)pool128.alloc(_capacity * sizeof(T));
}
small_vector(const small_vector& other): _size(other._size), _capacity(other._capacity) {
if(other.is_small()){
_data = _buffer;
memcpy(_buffer, other._buffer, sizeof(T) * _size);
} else {
_data = (T*)malloc(sizeof(T) * _capacity);
memcpy(_data, other._data, sizeof(T) * _size);
}
pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) {
_data = (T*)pool128.alloc(_capacity * sizeof(T));
memcpy(_data, other._data, sizeof(T) * _size);
}
small_vector(small_vector&& other) noexcept {
pod_vector(pod_vector&& other) noexcept {
_size = other._size;
_capacity = other._capacity;
if(other.is_small()){
_data = _buffer;
memcpy(_buffer, other._buffer, sizeof(T) * _size);
} else {
_data = other._data;
other._data = other._buffer;
}
_data = other._data;
other._data = nullptr;
}
small_vector& operator=(small_vector&& other) noexcept {
if (!is_small()) free(_data);
pod_vector& operator=(pod_vector&& other) noexcept {
if(_data!=nullptr) pool128.dealloc(_data);
_size = other._size;
_capacity = other._capacity;
if(other.is_small()){
_data = _buffer;
memcpy(_buffer, other._buffer, sizeof(T) * _size);
} else {
_data = other._data;
other._data = other._buffer;
}
_data = other._data;
other._data = nullptr;
return *this;
}
// remove copy assignment
small_vector& operator=(const small_vector& other) = delete;
pod_vector& operator=(const pod_vector& other) = delete;
template<typename __ValueT>
void push_back(__ValueT&& t) {
@ -70,16 +56,12 @@ struct small_vector{
void reserve(int cap){
if(cap < _capacity) return;
_capacity = cap;
if (is_small()) {
_data = (T*)malloc(sizeof(T) * _capacity);
memcpy(_data, _buffer, sizeof(T) * _size);
} else {
_data = (T*)realloc(_data, sizeof(T) * _capacity);
}
if(_data!=nullptr) pool128.dealloc(_data);
_data = (T*)pool128.alloc(_capacity * sizeof(T));
}
void pop_back() { _size--; }
void extend(const small_vector& other){
void extend(const pod_vector& other){
for(int i=0; i<other.size(); i++) push_back(other[i]);
}
@ -97,7 +79,6 @@ struct small_vector{
int size() const { return _size; }
T* data() { return _data; }
const T* data() const { return _data; }
bool is_small() const { return _data == _buffer; }
void pop_back_n(int n) { _size -= n; }
void clear() { _size=0; }
@ -114,8 +95,8 @@ struct small_vector{
_size--;
}
~small_vector() {
if (!is_small()) free(_data);
~pod_vector() {
if(_data!=nullptr) pool128.dealloc(_data);
}
};
@ -136,6 +117,6 @@ public:
const Container& data() const { return vec; }
};
template <typename T, int N>
using small_stack = stack<T, small_vector<T, N>>;
template <typename T>
using pod_stack = stack<T, pod_vector<T>>;
} // namespace pkpy