Skip to content

Commit

Permalink
implement nan box
Browse files Browse the repository at this point in the history
  • Loading branch information
ShawSumma committed Jul 19, 2024
1 parent 91ce6bd commit e60718b
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 190 deletions.
6 changes: 0 additions & 6 deletions vm/backend/backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
#include "../ir.h"
#include "../gc.h"

#define COMBINE(x, y) ((x)*VM_TAG_MAX + (y))
#define CONCAT_2(x, y) x ## _ ## y
#define CONCAT(x, y) CONCAT_2(x, y)
#define CONCAT3_2(x, y, z) x ## _ ## y ## _ ## z
#define CONCAT3(x, y) CONCAT3_2(x, y)

#define VM_INLINE inline __attribute__((always_inline))

#if VM_DEBUG_BACKEND_OPCODES
Expand Down
42 changes: 0 additions & 42 deletions vm/backend/binop.inc

This file was deleted.

52 changes: 0 additions & 52 deletions vm/backend/test.inc

This file was deleted.

1 change: 1 addition & 0 deletions vm/io.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#include "./io.h"
#include "./ir.h"

void vm_io_buffer_vformat(vm_io_buffer_t *buf, const char *fmt, va_list ap) {
if (buf->buf == NULL) {
Expand Down
48 changes: 0 additions & 48 deletions vm/ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,54 +32,6 @@ void vm_io_format_arg(vm_io_buffer_t *out, vm_arg_t val) {
}
}

void vm_io_format_type(vm_io_buffer_t *out, vm_tag_t type) {
switch (type) {
case VM_TAG_UNK: {
vm_io_buffer_format(out, "unk");
break;
}
case VM_TAG_NIL: {
vm_io_buffer_format(out, "nil");
break;
}
case VM_TAG_BOOL: {
vm_io_buffer_format(out, "bool");
break;
}
case VM_TAG_NUMBER: {
vm_io_buffer_format(out, "f64");
break;
}
case VM_TAG_STR: {
vm_io_buffer_format(out, "str");
break;
}
case VM_TAG_CLOSURE: {
vm_io_buffer_format(out, "closure");
break;
}
case VM_TAG_FUN: {
vm_io_buffer_format(out, "rawfunc");
break;
}
case VM_TAG_TAB: {
vm_io_buffer_format(out, "table");
break;
}
case VM_TAG_FFI: {
vm_io_buffer_format(out, "ffi");
break;
}
case VM_TAG_ERROR: {
vm_io_buffer_format(out, "error");
break;
}
default: {
vm_io_buffer_format(out, "<tag: invalid>");
}
}
}

void vm_io_format_branch(vm_io_buffer_t *out, vm_branch_t val) {
if (val.out.type != VM_ARG_NONE) {
vm_io_format_arg(out, val.out);
Expand Down
4 changes: 1 addition & 3 deletions vm/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ struct vm_arg_t {
struct vm_branch_t {
vm_location_range_t range;

// vm_block_t *targets[2];
vm_block_t *targets[VM_TAG_MAX];
vm_block_t *targets[2];

vm_arg_t *args;
vm_arg_t out;
Expand Down Expand Up @@ -129,7 +128,6 @@ struct vm_blocks_t {
void vm_block_realloc(vm_block_t *block, vm_instr_t instr);

void vm_io_format_arg(vm_io_buffer_t *out, vm_arg_t val);
void vm_io_format_type(vm_io_buffer_t *out, vm_tag_t tag);
void vm_io_format_branch(vm_io_buffer_t *out, vm_branch_t val);
void vm_io_format_instr(vm_io_buffer_t *out, vm_instr_t val);
void vm_io_format_block(vm_io_buffer_t *out, vm_block_t *val);
Expand Down
120 changes: 86 additions & 34 deletions vm/nanbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,28 +67,6 @@
#define NANBOX_POINTER_TYPE void*
#endif

/*
* User-defined auxillary types. Default to void*. These types must be pointer
* types or 32-bit types. (Pointers on 64-bit platforms always begin with 16
* bits of zero.)
*/
#ifndef NANBOX_AUX1_TYPE
#define NANBOX_AUX1_TYPE void*
#endif
#ifndef NANBOX_AUX2_TYPE
#define NANBOX_AUX2_TYPE void*
#endif
#ifndef NANBOX_AUX3_TYPE
#define NANBOX_AUX3_TYPE void*
#endif
#ifndef NANBOX_AUX4_TYPE
#define NANBOX_AUX4_TYPE void*
#endif
#ifndef NANBOX_AUX5_TYPE
#define NANBOX_AUX5_TYPE void*
#endif


#include <stddef.h> // size_t
#include <stdint.h> // int64_t, int32_t
#include <stdbool.h> // bool, true, false
Expand Down Expand Up @@ -255,8 +233,15 @@ typedef union NANBOX_NAME(_u) NANBOX_T;

// There are 5 * 2^48 auxillary values can be stored in the 64-bit integer
// range NANBOX_MIN_AUX..NANBOX_MAX_AUX.
#define NANBOX_MIN_AUX_TAG 0x00010000
#define NANBOX_MAX_AUX_TAG 0x0005ffff
#define NANBOX_MIN_AUX_TAG 0x0001000000000000llu
#define NANBOX_MAX_AUX_TAG 0x0005ffff00000000llu

#define NANBOX_MIN_AUX1 0x0001000000000000llu
#define NANBOX_MIN_AUX2 0x0002000000000000llu
#define NANBOX_MIN_AUX3 0x0003000000000000llu
#define NANBOX_MIN_AUX4 0x0004000000000000llu
#define NANBOX_MIN_AUX5 0x0005000000000000llu

#define NANBOX_MIN_AUX 0x0001000000000000llu
#define NANBOX_MAX_AUX 0x0005ffffffffffffllu

Expand Down Expand Up @@ -358,6 +343,68 @@ static inline bool NANBOX_NAME(_is_aux)(NANBOX_T val) {
val.as_int64 <= NANBOX_MAX_AUX;
}

static inline NANBOX_POINTER_TYPE NANBOX_NAME(_to_aux)(NANBOX_T val) {
assert(NANBOX_NAME(_is_aux)(val));
return (void *) ((size_t) val.pointer & NANBOX_MASK_POINTER);
}

static inline bool NANBOX_NAME(_is_aux1)(NANBOX_T val) {
return val.as_int64 >= NANBOX_MIN_AUX1 &&
val.as_int64 < NANBOX_MIN_AUX2;
}
static inline bool NANBOX_NAME(_is_aux2)(NANBOX_T val) {
return val.as_int64 >= NANBOX_MIN_AUX2 &&
val.as_int64 < NANBOX_MIN_AUX3;
}
static inline bool NANBOX_NAME(_is_aux3)(NANBOX_T val) {
return val.as_int64 >= NANBOX_MIN_AUX3 &&
val.as_int64 < NANBOX_MIN_AUX4;
}
static inline bool NANBOX_NAME(_is_aux4)(NANBOX_T val) {
return val.as_int64 >= NANBOX_MIN_AUX4 &&
val.as_int64 < NANBOX_MAX_AUX;
}
static inline bool NANBOX_NAME(_is_aux5)(NANBOX_T val) {
return val.as_int64 >= NANBOX_MIN_AUX5 &&
val.as_int64 <= NANBOX_MAX_AUX;
}

static inline NANBOX_T NANBOX_NAME(_from_aux1)(void *ptr) {
NANBOX_T ret;
ret.as_int64 = (uint64_t) ptr | NANBOX_MIN_AUX1;
assert(NANBOX_NAME(_is_aux1)(ret));
return ret;
}

static inline NANBOX_T NANBOX_NAME(_from_aux2)(void *ptr) {
NANBOX_T ret;
int printf(const char *, ...);
ret.as_int64 = (uint64_t) ptr | NANBOX_MIN_AUX2;
assert(NANBOX_NAME(_is_aux2)(ret));
return ret;
}

static inline NANBOX_T NANBOX_NAME(_from_aux3)(void *ptr) {
NANBOX_T ret;
ret.as_int64 = (uint64_t) ptr | NANBOX_MIN_AUX3;
assert(NANBOX_NAME(_is_aux3)(ret));
return ret;
}

static inline NANBOX_T NANBOX_NAME(_from_aux4)(void *ptr) {
NANBOX_T ret;
ret.as_int64 = (uint64_t) ptr | NANBOX_MIN_AUX4;
assert(NANBOX_NAME(_is_aux4)(ret));
return ret;
}

static inline NANBOX_T NANBOX_NAME(_from_aux5)(void *ptr) {
NANBOX_T ret;
ret.as_int64 = (uint64_t) ptr | NANBOX_MIN_AUX5;
assert(NANBOX_NAME(_is_aux5)(ret));
return ret;
}

/* end if NANBOX_64 */
#elif defined(NANBOX_32)

Expand All @@ -369,16 +416,21 @@ static inline bool NANBOX_NAME(_is_aux)(NANBOX_T val) {
* 'pointer', 'integer' and 'boolean', their values (the 'payload') are store
* in the lower 32 bits. In the case of all other tags the payload is 0.
*/
#define NANBOX_MAX_DOUBLE_TAG 0xfff80000
#define NANBOX_INT_TAG 0xfff80001
#define NANBOX_MIN_AUX_TAG 0xfff90000
#define NANBOX_MAX_AUX_TAG 0xfffdffff
#define NANBOX_POINTER_TAG 0xfffffffa
#define NANBOX_BOOLEAN_TAG 0xfffffffb
#define NANBOX_UNDEFINED_TAG 0xfffffffc
#define NANBOX_NULL_TAG 0xfffffffd
#define NANBOX_DELETED_VALUE_TAG 0xfffffffe
#define NANBOX_EMPTY_VALUE_TAG 0xffffffff
#define NANBOX_MAX_DOUBLE_TAG 0XFFF80000
#define NANBOX_INT_TAG 0XFFF80001
#define NANBOX_MIN_AUX_TAG 0XFFF90000
#define NANBOX_MAX_AUX_TAG 0XFFFDFFFF
#define NANBOX_MIN_AUX1_TAG 0XFFF90000
#define NANBOX_MIN_AUX2_TAG 0XFFFA0000
#define NANBOX_MIN_AUX3_TAG 0XFFFB0000
#define NANBOX_MIN_AUX4_TAG 0XFFFC0000
#define NANBOX_MIN_AUX5_TAG 0XFFFD0000
#define NANBOX_POINTER_TAG 0XFFFFFFFA
#define NANBOX_BOOLEAN_TAG 0XFFFFFFFB
#define NANBOX_UNDEFINED_TAG 0XFFFFFFFC
#define NANBOX_NULL_TAG 0XFFFFFFFD
#define NANBOX_DELETED_VALUE_TAG 0XFFFFFFFE
#define NANBOX_EMPTY_VALUE_TAG 0XFFFFFFFF

// The 'empty' value is guarranteed to consist of a repeated single byte,
// so that it should be easy to memset an array of nanboxes to 'empty' using
Expand Down
8 changes: 6 additions & 2 deletions vm/obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@ bool vm_obj_eq(vm_obj_t v1, vm_obj_t v2) {
} else if (vm_obj_is_ffi(v1) && vm_obj_is_ffi(v2)) {
return vm_obj_get_ffi(v1) == vm_obj_get_ffi(v2);
} else {
__builtin_trap();
return false;
}
}

size_t vm_value_hash(vm_obj_t value) {
if (vm_obj_is_nil(value)) {
return 0;
}
if (vm_obj_is_boolean(value)) {
return SIZE_MAX - (size_t)vm_obj_get_boolean(value);
}
if (vm_obj_is_number(value)) {
return (size_t)*(uint64_t *)&vm_obj_get_number(value);
double n = vm_obj_get_number(value);
return (size_t)*(uint64_t *)&n;
}
if (vm_obj_is_string(value)) {
uint64_t ret = 0xcbf29ce484222325;
Expand All @@ -53,6 +56,7 @@ size_t vm_value_hash(vm_obj_t value) {
return (size_t)vm_obj_get_table(value) >> 4;
}
__builtin_trap();
// return 0;
}

vm_table_pair_t *vm_table_lookup(vm_table_t *table, vm_obj_t key) {
Expand Down
1 change: 0 additions & 1 deletion vm/obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ bool vm_value_is_int(vm_obj_t val);

vm_table_t *vm_table_new(vm_t *vm);
vm_table_pair_t *vm_table_lookup(vm_table_t *table, vm_obj_t key);
void vm_table_iset(vm_table_t *table, uint64_t key_ival, uint64_t val_ival, vm_tag_t key_tag, vm_tag_t val_tag);
void vm_table_set(vm_table_t *table, vm_obj_t key, vm_obj_t value);
void vm_table_set_pair(vm_table_t *table, vm_table_pair_t *pair);
void vm_table_get_pair(vm_table_t *table, vm_table_pair_t *pair);
Expand Down
Loading

0 comments on commit e60718b

Please sign in to comment.