diff --git a/book/optimization.md b/book/optimization.md index d7ae4bd66..4c91456dc 100644 --- a/book/optimization.md +++ b/book/optimization.md @@ -26,11 +26,15 @@ https://github.com/munificent/craftinginterpreters/issues/565 https://nikic.github.io/2012/02/02/Pointer-magic-for-efficient-dynamic-value-representations.html -### unsorted +--- + +mention inlining small strings + +--- ... -^code define-nan-tagging (1 before, 1 after) +## modulo ... @@ -42,11 +46,11 @@ https://nikic.github.io/2012/02/02/Pointer-magic-for-efficient-dynamic-value-rep ... -^code free-table (1 before, 1 after) +### find entry ... -^code find-entry (1 before, 1 after) +^code find-entry ... @@ -54,27 +58,27 @@ https://nikic.github.io/2012/02/02/Pointer-magic-for-efficient-dynamic-value-rep ... -^code next-index (1 before, 1 after) +^code next-index (4 before, 1 after) ... -^code get-find-entry (1 before, 1 after) +### adjust capacity ... -^code adjust-capacity (1 before, 1 after) +^code adjust-find-entry (2 before, 1 after) ... -^code re-hash (1 before, 1 after) +^code adjust-capacity (1 after) ... -^code adjust-find-entry (1 before, 1 after) +^code re-hash (1 before, 1 after) ... -^code adjust-free (1 before, 1 after) +^code adjust-free (3 before, 1 after) ... @@ -82,11 +86,19 @@ https://nikic.github.io/2012/02/02/Pointer-magic-for-efficient-dynamic-value-rep ... -^code table-set-grow (1 before, 1 after) +### table get set delete + +... + +^code get-find-entry (2 before, 1 after) + +... + +^code set-find-entry (3 before, 2 after) ... -^code set-find-entry (1 before, 1 after) +^code table-set-grow (1 before, 1 after) ... @@ -94,15 +106,19 @@ https://nikic.github.io/2012/02/02/Pointer-magic-for-efficient-dynamic-value-rep ... +### other changes + +... + ^code add-all-loop (1 before, 1 after) ... -^code find-string-index (1 before, 1 after) +^code find-string-index (4 before, 2 after) ... -^code find-string-next (1 before, 1 after) +^code find-string-next (3 before, 1 after) ... @@ -114,13 +130,131 @@ https://nikic.github.io/2012/02/02/Pointer-magic-for-efficient-dynamic-value-rep ... -^code nan-tagging (1 before, 1 after) +^code free-table (1 before, 1 after) + +... + +## nan tagging + +... + +^code define-nan-tagging (2 before, 1 after) + +... + +^code nan-tagging (2 before, 1 after) + +... + +^code end-if-nan-tagging (1 before, 2 after) + +... + +### numbers + +**todo: remove comments** + +... + +^code number-val (1 before, 2 after) + +... + +^code num-to-value (1 before, 2 after) + +... + +^code double-union (1 before, 2 after) + +// A union to let us reinterpret a double as raw bits and back. + +... + +^code as-number (2 before, 2 after) + +... + +^code value-to-num (1 before, 2 after) -**todo: split into smaller** +... + +^code is-number (1 before, 2 after) + +// If the NaN bits are set, it's not a number. + +... + +^code qnan (1 before, 2 after) + +// The bits that must be set to indicate a quiet NaN. + +... + +### nil and singleton values + +... + +^code nil-val (2 before, 1 after) + +... + +^code tags (1 before, 2 after) + +// Tag values for the different singleton values. + +... + +^code is-nil (2 before, 1 after) + +... + +### booleans + +... + +^code false-true-vals (2 before, 1 after) ... -^code end-if-nan-tagging (1 before, 1 after) +^code bool-val (2 before, 1 after) + +... + +^code as-bool (2 before, 1 after) + +... + +^code is-bool (2 before, 1 after) + +... + +### objects + +... + +^code obj-val (1 before, 2 after) + +// The triple casting is necessary here to satisfy some compilers: +// 1. (uintptr_t) Convert the pointer to a number of the right size. +// 2. (uint64_t) Pad it up to 64 bits in 32-bit builds. +// 3. Or in the bits to make a tagged Nan. +// 4. Cast to a typedef'd value. + +... + +^code sign-bit (1 before, 2 after) + +// A mask that selects the sign bit. + +... + +^code as-obj (1 before, 2 after) + +... + +^code is-obj (1 before, 2 after) + +### value functions ... @@ -139,4 +273,3 @@ https://nikic.github.io/2012/02/02/Pointer-magic-for-efficient-dynamic-value-rep ^code end-values-equal (1 before, 1 after) ... - diff --git a/c/value.h b/c/value.h index 9088a3ce1..184ffee11 100644 --- a/c/value.h +++ b/c/value.h @@ -13,61 +13,86 @@ typedef struct sObjString ObjString; //< Strings forward-declare-obj //> Optimization nan-tagging #ifdef NAN_TAGGING +//> sign-bit -// A mask that selects the sign bit. #define SIGN_BIT ((uint64_t)1 << 63) +//< sign-bit +//> qnan -// The bits that must be set to indicate a quiet NaN. #define QNAN ((uint64_t)0x7ffc000000000000) +//< qnan +//> tags -// Tag values for the different singleton values. #define TAG_NIL 1 // 01. #define TAG_FALSE 2 // 10. #define TAG_TRUE 3 // 11. +//< tags typedef uint64_t Value; - -#define IS_BOOL(v) (((v) & FALSE_VAL) == FALSE_VAL) -#define IS_NIL(v) ((v) == NIL_VAL) -// If the NaN bits are set, it's not a number. -#define IS_NUMBER(v) (((v) & QNAN) != QNAN) -#define IS_OBJ(v) (((v) & (QNAN | SIGN_BIT)) == (QNAN | SIGN_BIT)) - -#define AS_BOOL(v) ((v) == TRUE_VAL) -#define AS_NUMBER(v) valueToNum(v) -#define AS_OBJ(v) ((Obj*)(uintptr_t)((v) & ~(SIGN_BIT | QNAN))) - -#define BOOL_VAL(boolean) ((boolean) ? TRUE_VAL : FALSE_VAL) -#define FALSE_VAL ((Value)(uint64_t)(QNAN | TAG_FALSE)) -#define TRUE_VAL ((Value)(uint64_t)(QNAN | TAG_TRUE)) -#define NIL_VAL ((Value)(uint64_t)(QNAN | TAG_NIL)) -#define NUMBER_VAL(num) numToValue(num) -// The triple casting is necessary here to satisfy some compilers: -// 1. (uintptr_t) Convert the pointer to a number of the right size. -// 2. (uint64_t) Pad it up to 64 bits in 32-bit builds. -// 3. Or in the bits to make a tagged Nan. -// 4. Cast to a typedef'd value. +//> is-number + +//> is-bool +#define IS_BOOL(v) (((v) & FALSE_VAL) == FALSE_VAL) +//< is-bool +//> is-nil +#define IS_NIL(v) ((v) == NIL_VAL) +//< is-nil +#define IS_NUMBER(v) (((v) & QNAN) != QNAN) +//< is-number +//> is-obj +#define IS_OBJ(v) (((v) & (QNAN | SIGN_BIT)) == (QNAN | SIGN_BIT)) +//< is-obj +//> as-number + +//> as-bool +#define AS_BOOL(v) ((v) == TRUE_VAL) +//< as-bool +#define AS_NUMBER(v) valueToNum(v) +//< as-number +//> as-obj +#define AS_OBJ(v) ((Obj*)(uintptr_t)((v) & ~(SIGN_BIT | QNAN))) +//< as-obj +//> number-val + +//> bool-val +#define BOOL_VAL(b) ((b) ? TRUE_VAL : FALSE_VAL) +//< bool-val +//> false-true-vals +#define FALSE_VAL ((Value)(uint64_t)(QNAN | TAG_FALSE)) +#define TRUE_VAL ((Value)(uint64_t)(QNAN | TAG_TRUE)) +//< false-true-vals +//> nil-val +#define NIL_VAL ((Value)(uint64_t)(QNAN | TAG_NIL)) +//< nil-val +#define NUMBER_VAL(num) numToValue(num) +//< number-val +//> obj-val #define OBJ_VAL(obj) \ (Value)(SIGN_BIT | QNAN | (uint64_t)(uintptr_t)(obj)) +//< obj-val +//> double-union -// A union to let us reinterpret a double as raw bits and back. typedef union { - uint64_t bits64; - uint32_t bits32[2]; + uint64_t bits; double num; } DoubleUnion; +//< double-union +//> value-to-num static inline double valueToNum(Value value) { DoubleUnion data; - data.bits64 = value; + data.bits = value; return data.num; } +//< value-to-num +//> num-to-value static inline Value numToValue(double num) { DoubleUnion data; data.num = num; - return data.bits64; + return data.bits; } +//< num-to-value #else diff --git a/site/contents.html b/site/contents.html index 41d08eca3..63efa3b6f 100644 --- a/site/contents.html +++ b/site/contents.html @@ -215,7 +215,6 @@