by Sergey Lyubka, Cesanta Software, for Dublin C/C++ User Group
/* Rest of the types are omitted for clarity */
enum value_type { TYPE_NUMBER, TYPE_STRING, TYPE_OBJECT };
struct value {
enum value_type type;
union {
char boolean;
double number;
struct string *string;
struct object *object;
} placeholder;
};
/* Rest of the types are omitted for clarity */
enum value_type { TYPE_NUMBER, TYPE_STRING, TYPE_OBJECT };
struct value {
enum value_type type; /* Could be 1 byte, but will pad to 8 bytes */
union {
double number;
struct string *string;
struct object *object;
} placeholder; /* The largest type is double - 8 bytes*/
};
// Double-precision floating-point number, IEEE 754
//
// 64 bit (8 bytes) in total
// 1 bit sign
// 11 bits exponent
// 52 bits mantissa
//
// 7 6 5 4 3 2 1 0
// seeeeeee|eeeemmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm
//
// 11111111|11110000|00000000|00000000|00000000|00000000|00000000|00000001 NaN
// V7 NaN-packing:
// sign and exponent is 0xffff
// 4 bits specify type
// 48 bits specify value
//
// 11111111|1111xxxx|00000000|00000000|00000000|00000000|00000000|00000000 NaN
// NaN marker |type| 48-bit placeholder for values: pointers, strings
//
typedef uint64_t val_t;
#define V7_TAG_BOOLEAN ((uint64_t) 0xFFFC << 48)
#define V7_TAG_FUNCTION ((uint64_t) 0xFFF5 << 48) /* JavaScript function */
#define V7_TAG_OBJECT ((uint64_t) 0xFFFF << 48) /* JavaScript object */
#define V7_TAG_REGEXP ((uint64_t) 0xFFF2 << 48) /* RegExp */
...
// On 64-bit system, struct v7_string occupies 16 bytes
struct v7_string {
unsigned char *data; // sizeof(pointer)
size_t length; // SIZE_MAX is at least 0xffff - 2 bytes
};
struct v7_string *str = malloc(sizeof(*str));
// 11111111|1111xxxx|00000000|00000000|00000000|00000000|00000000|00000000
// NaN marker |type| 48-bit placeholder for values: pointers, strings
//
#define V7_TAG_STRING_I ((uint64_t) 0xFFFA << 48) /* Inlined string len < 5 */
#define V7_TAG_STRING_5 ((uint64_t) 0xFFF9 << 48) /* Inlined string len 5 */
#define V7_TAG_STRING_O ((uint64_t) 0xFFF8 << 48) /* Owned string */
#define V7_TAG_STRING_F ((uint64_t) 0xFFF7 << 48) /* Foreign string */
// Inlined string:
//
// 11111111|11111010|00000011|01101000|01101001|00100001|00000000|00000000
// NaN marker |0xa |
// 0xfffa | 3 | h | i | ! | |
// Inlined string:
//
// 11111111|11111000|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx
// NaN marker |0x8 | pointer to string data
//
//
// Resizable memory buffer that holds long strings
// |13|long string 1|12|hello world!|-----grows as new strings added --->
//
struct v7_object {
/* Fixed-size data structure */
};
struct v7_property {
/* Fixed-size data structure */
};
struct pool {
char *base;
size_t size;
char *free_list_head;
size_t node_size;
};
// Node allocated from the free list
void *r = (void *) p->free;
(* (uintptr_t *) r)--; // unmark node
p->free = * (void **) r;
return r;
Pool with two nodes allocated (note LSB 0)
Pool with three nodes allocated (note LSB 0)
// Node allocation
void *v7_alloc_cell(struct v7_pool *p) {
void *r;
if (p->free == NULL) {
v7_pool_grow(p, p->size * 1.51);
}
r = (void *) p->free;
(* (uintptr_t *) r)--; // unmark
p->free = * (void **) r;
return r;
}
contact me at
sergey.lyubka@cesanta.com