Berry sync upstream #369 (#20330)

This commit is contained in:
s-hadinger 2023-12-28 17:00:35 +01:00 committed by GitHub
parent 21de682f58
commit 67b36030dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 135 additions and 53 deletions

View File

@ -0,0 +1,38 @@
cmake_minimum_required(VERSION 3.10)
project(Berry C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(BERRY_COC ${CMAKE_CURRENT_SOURCE_DIR}/tools/coc/coc)
set(BERRY_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(BERRY_CONFIG_DIR default CACHE FILEPATH "The directory of berry_conf.h.")
set(BERRY_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/${BERRY_CONFIG_DIR}/berry_conf.h)
set(BERRY_GENERATE ${CMAKE_CURRENT_SOURCE_DIR}/generate)
if (${CMAKE_HOST_WIN32})
set(BERRY_COC python ${BERRY_COC})
endif ()
file(MAKE_DIRECTORY generate)
# berry library
file(GLOB SOURCES src/*.c)
add_library(libberry ${SOURCES})
target_include_directories(libberry PUBLIC src ${BERRY_CONFIG_DIR})
add_custom_target(berry-coc
COMMAND ${BERRY_COC} -o ${BERRY_GENERATE} ${BERRY_SOURCE_DIR} -c ${BERRY_CONFIG}
DEPENDS ${SOURCES} COMMAND_EXPAND_LISTS
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generate coc objects"
)
add_dependencies(libberry berry-coc)
# berry default exe
file(GLOB SOURCES_EXE default/*.c)
add_executable(berry ${SOURCES_EXE})
target_link_libraries(berry PUBLIC libberry)

View File

@ -59,6 +59,13 @@
FULL_VERSION " (build in " __DATE__ ", " __TIME__ ")\n" \
"[" COMPILER "] on " OS_NAME " (default)\n" \
#if defined(_WIN32)
#define PATH_SEPARATOR ";"
#else
#define PATH_SEPARATOR ":"
#endif
/* command help information */
#define help_information \
"Usage: berry [options] [script [args]]\n" \
@ -66,6 +73,7 @@
" -i enter interactive mode after executing 'file'\n" \
" -l all variables in 'file' are parsed as local\n" \
" -e load 'script' source string and execute\n" \
" -m <path> custom module search path(s) separated by '" PATH_SEPARATOR "'\n"\
" -c <file> compile script 'file' to bytecode file\n" \
" -o <file> save bytecode to 'file'\n" \
" -g force named globals in VM\n" \
@ -87,6 +95,7 @@
#define arg_g (1 << 7)
#define arg_s (1 << 8)
#define arg_err (1 << 9)
#define arg_m (1 << 10)
struct arg_opts {
int idx;
@ -95,6 +104,7 @@ struct arg_opts {
const char *errarg;
const char *src;
const char *dst;
const char *modulepath;
};
/* check if the character is a letter */
@ -257,6 +267,10 @@ static int parse_arg(struct arg_opts *opt, int argc, char *argv[])
case 'e': args |= arg_e; break;
case 'g': args |= arg_g; break;
case 's': args |= arg_s; break;
case 'm':
args |= arg_m;
opt->modulepath = opt->optarg;
break;
case '?': return args | arg_err;
case 'c':
args |= arg_c;
@ -286,12 +300,47 @@ static void push_args(bvm *vm, int argc, char *argv[])
be_pop(vm, 1);
}
#if defined(_WIN32)
#define BERRY_ROOT "\\Windows\\system32"
static const char *module_paths[] = {
BERRY_ROOT "\\berry\\packages",
};
#else
#define BERRY_ROOT "/usr/local"
static const char *module_paths[] = {
BERRY_ROOT "/lib/berry/packages",
};
#endif
static void berry_paths(bvm * vm)
{
size_t i;
for (i = 0; i < array_count(module_paths); ++i) {
be_module_path_set(vm, module_paths[i]);
}
}
static void berry_custom_paths(bvm *vm, const char *modulepath)
{
const char delim[] = PATH_SEPARATOR;
char *copy = malloc(strlen(modulepath) + 1);
strcpy(copy, modulepath);
char *ptr = strtok(copy, delim);
while (ptr != NULL) {
be_module_path_set(vm, ptr);
ptr = strtok(NULL, delim);
}
free(copy);
}
/*
* command format: berry [options] [script [args]]
* command options:
* -i: enter interactive mode after executing 'script'
* -b: load code from bytecode file
* -e: load 'script' source and execute
* -m: specify custom module search path(s)
* command format: berry options
* command options:
* -v: show version information
@ -305,7 +354,7 @@ static int analysis_args(bvm *vm, int argc, char *argv[])
{
int args = 0;
struct arg_opts opt = { 0 };
opt.pattern = "vhilegsc?o?";
opt.pattern = "m?vhilegsc?o?";
args = parse_arg(&opt, argc, argv);
argc -= opt.idx;
argv += opt.idx;
@ -315,6 +364,16 @@ static int analysis_args(bvm *vm, int argc, char *argv[])
be_pop(vm, 1);
return -1;
}
if (args & arg_m) {
berry_custom_paths(vm, opt.modulepath);
args &= ~arg_m;
}
else {
// use default module paths
berry_paths(vm);
}
if (args & arg_g) {
comp_set_named_gbl(vm); /* forced named global in VM code */
args &= ~arg_g; /* clear the flag for this option not to interfere with other options */
@ -339,31 +398,11 @@ static int analysis_args(bvm *vm, int argc, char *argv[])
return load_script(vm, argc, argv, args);
}
#if defined(_WIN32)
#define BERRY_ROOT "\\Windows\\system32"
static const char *module_paths[] = {
BERRY_ROOT "\\berry\\packages",
};
#else
#define BERRY_ROOT "/usr/local"
static const char *module_paths[] = {
BERRY_ROOT "/lib/berry/packages",
};
#endif
static void berry_paths(bvm * vm)
{
size_t i;
for (i = 0; i < array_count(module_paths); ++i) {
be_module_path_set(vm, module_paths[i]);
}
}
int main(int argc, char *argv[])
{
int res;
bvm *vm = be_vm_new(); /* create a virtual machine instance */
berry_paths(vm);
res = analysis_args(vm, argc, argv);
be_vm_delete(vm); /* free all objects and vm */
return res;

View File

@ -26,12 +26,43 @@
#define realloc BE_EXPLICIT_REALLOC
#endif
static void* malloc_from_pool(bvm *vm, size_t size);
static void free_from_pool(bvm *vm, void* ptr, size_t old_size);
#define POOL16_SIZE 16
#define POOL32_SIZE 32
#ifdef _MSC_VER
#include <intrin.h>
#pragma intrinsic(_BitScanForward)
#endif
#if defined(__GNUC__)
#define popcount(v) __builtin_popcount(v)
#define ffs(v) __builtin_ffs(v)
#elif defined(_MSC_VER)
#define popcount(v) __popcnt(v)
static int ffs(unsigned x)
{
unsigned long i;
return _BitScanForward(&i, x) ? i : 0;
}
#else
/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */
static int popcount(uint32_t n)
{
n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u);
n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u);
n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu);
n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu);
n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu);
return n;
}
#error "unsupport compiler for ffs()"
#endif
static void* malloc_from_pool(bvm *vm, size_t size);
static void free_from_pool(bvm *vm, void* ptr, size_t old_size);
BERRY_API void* be_os_malloc(size_t size)
{
return malloc(size);
@ -66,7 +97,7 @@ BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size)
if (!ptr || (old_size == 0)) {
block = malloc_from_pool(vm, new_size);
}
/* Case 2: deallocate */
else if (new_size == 0) {
#if BE_USE_PERF_COUNTERS
@ -176,11 +207,7 @@ static void* malloc_from_pool(bvm *vm, size_t size) {
/* look for an empty slot */
if (pool16->bitmap != 0x0000) {
/* there is a free slot */
#ifdef __GNUC__
int bit = __builtin_ffs(pool16->bitmap) - 1;
#else
int bit = ffs(pool16->bitmap) - 1;
#endif
if (bit >= 0) {
/* we found a free slot */
// bitClear(pool16->bitmap, bit);
@ -208,11 +235,7 @@ static void* malloc_from_pool(bvm *vm, size_t size) {
/* look for an empty slot */
if (pool32->bitmap != 0x0000) {
/* there is a free slot */
#ifdef __GNUC__
int bit = __builtin_ffs(pool32->bitmap) - 1;
#else
int bit = ffs(pool32->bitmap) - 1;
#endif
if (bit >= 0) {
/* we found a free slot */
// bitClear(pool32->bitmap, bit);
@ -327,24 +350,6 @@ BERRY_API void be_gc_free_memory_pools(bvm *vm) {
vm->gc.pool32 = NULL;
}
/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */
static int pop0(uint32_t n) __attribute__((unused));
static int pop0(uint32_t n) {
n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u);
n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u);
n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu);
n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu);
n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu);
return n;
}
#ifdef __GNUC__
#define count_bits_1(v) __builtin_popcount(v)
#else
#define count_bits_1(v) pop0(v)
#endif
BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slots_allocated) {
size_t used = 0;
size_t allocated = 0;
@ -352,14 +357,14 @@ BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slot
gc16_t* pool16 = vm->gc.pool16;
while (pool16) {
allocated += POOL16_SLOTS;
used += POOL16_SLOTS - count_bits_1(pool16->bitmap);
used += POOL16_SLOTS - popcount(pool16->bitmap);
pool16 = pool16->next;
}
gc32_t* pool32 = vm->gc.pool32;
while (pool32) {
allocated += POOL32_SLOTS;
used += POOL32_SLOTS - count_bits_1(pool32->bitmap);
used += POOL32_SLOTS - popcount(pool32->bitmap);
pool32 = pool32->next;
}
if (slots_used) { *slots_used = used; }