JS_STRICT_NAN_BOXING

JS_STRICT_NAN_BOXING option allows compact packaging for 32 **and ** 64 bit versions.

JS_STRICT_NAN_BOXING is the only option that enables x64 builds using MSVC
This commit is contained in:
Andrew 2020-10-11 18:24:37 -07:00
parent a953bfca2c
commit 2ead907a60
2 changed files with 113 additions and 9 deletions

View file

@ -8,7 +8,7 @@
file:close() file:close()
vars = vers:gsub("%s+", "") vars = vers:gsub("%s+", "")
file = io.open("quickjs-version.h", "w+") file = io.open("quickjs-version.h", "w+")
file:write("#define QUICKJS_VERSION \"" .. vers .. "\"\r\n") file:write("#define QUICKJS_VERSION \"" .. vers .. "\"")
file:close() file:close()
end)() end)()
@ -17,6 +17,8 @@ workspace "quickjs-msvc"
-- Premake output folder -- Premake output folder
location(path.join(".build", _ACTION)) location(path.join(".build", _ACTION))
defines {"JS_STRICT_NAN_BOXING"} -- this option enables x64 build
platforms { "x86", "x64", "arm32", "arm64" } platforms { "x86", "x64", "arm32", "arm64" }
-- Configuration settings -- Configuration settings

118
quickjs.h
View file

@ -27,6 +27,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <math.h>
#include "quickjs-version.h" #include "quickjs-version.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -41,7 +42,7 @@ extern "C" {
#else #else
#define js_likely(x) (x) #define js_likely(x) (x)
#define js_unlikely(x) (x) #define js_unlikely(x) (x)
#define js_force_inline inline #define js_force_inline __forceinline
#define __js_printf_like(a, b) #define __js_printf_like(a, b)
#endif #endif
@ -65,6 +66,109 @@ typedef uint32_t JSAtom;
#define JS_NAN_BOXING #define JS_NAN_BOXING
#endif #endif
typedef struct JSRefCountHeader {
int ref_count;
} JSRefCountHeader;
#define JS_FLOAT64_NAN NAN
#if defined(JS_STRICT_NAN_BOXING)
// This schema defines strict NAN boxing for both 32 and 64 versions
// This is a method of storing values in the IEEE 754 double-precision
// floating-point number. double type is 64-bit, comprised of 1 sign bit, 11
// exponent bits and 52 mantissa bits:
// 7 6 5 4 3 2 1 0
// seeeeeee|eeeemmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm
//
// s0000000|0000tttt|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv
// NaN marker |tag| 48-bit placeholder for values: pointers, strings
// all bits 0 | 4 |
// for non float|bit|
// Doubles contain non-zero in NaN marker field and are stored with bits inversed
// JS_UNINITIALIZED is strictly uint64_t(0)
enum {
JS_TAG_UNINITIALIZED = 0,
JS_TAG_INT = 1,
JS_TAG_BOOL = 2,
JS_TAG_NULL = 3,
JS_TAG_UNDEFINED = 4,
JS_TAG_CATCH_OFFSET = 5,
JS_TAG_EXCEPTION = 6,
JS_TAG_FLOAT64 = 7,
/* all tags with a reference count have 0b1000 bit */
JS_TAG_OBJECT = 8,
JS_TAG_FUNCTION_BYTECODE = 9, /* used internally */
JS_TAG_MODULE = 10, /* used internally */
JS_TAG_STRING = 11,
JS_TAG_SYMBOL = 12,
JS_TAG_BIG_FLOAT = 13,
JS_TAG_BIG_INT = 14,
JS_TAG_BIG_DECIMAL = 15,
};
typedef uint64_t JSValue;
#define JSValueConst JSValue
#define JS_VALUE_GET_TAG(v) (((v)>0xFFFFFFFFFFFFFull)? (unsigned)JS_TAG_FLOAT64 : (unsigned)((v) >> 48))
#define JS_VALUE_GET_INT(v) (int)(v)
#define JS_VALUE_GET_BOOL(v) (int)(v)
#ifdef JS_PTR64
#define JS_VALUE_GET_PTR(v) ((void *)((intptr_t)(v) & 0x0000FFFFFFFFFFFFull))
#else
#define JS_VALUE_GET_PTR(v) ((void *)(intptr_t)(v))
#endif
#define JS_MKVAL(tag, val) (((uint64_t)(0xF & tag) << 48) | (uint32_t)(val))
#define JS_MKPTR(tag, ptr) (((uint64_t)(0xF & tag) << 48) | ((uint64_t)(ptr) & 0x0000FFFFFFFFFFFFull))
#define JS_NAN JS_MKVAL(JS_TAG_FLOAT64,1)
static inline double JS_VALUE_GET_FLOAT64(JSValue v)
{
union { JSValue v; double d; } u;
if (v == JS_NAN)
return JS_FLOAT64_NAN;
u.v = ~v;
return u.d;
}
static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
{
union { double d; uint64_t u64; } u;
JSValue v;
u.d = d;
/* normalize NaN */
if (js_unlikely((u.u64 & 0x7ff0000000000000) == 0x7ff0000000000000))
v = JS_NAN;
else
v = ~u.u64;
return v;
}
//#define JS_TAG_IS_FLOAT64(tag) ((tag & 0x7ff0) != 0)
#define JS_TAG_IS_FLOAT64(tag) (tag == JS_TAG_FLOAT64)
/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
/* Note: JS_VALUE_GET_TAG already normalized in this packaging schema*/
#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
#define JS_VALUE_IS_NAN(v) (v == JS_NAN)
#define JS_VALUE_HAS_REF_COUNT(v) ((JS_VALUE_GET_TAG(v) & 0xFFF8) == 0x8)
#else // !JS_STRICT_NAN_BOXING
enum { enum {
/* all tags with a reference count are negative */ /* all tags with a reference count are negative */
JS_TAG_FIRST = -11, /* first negative tag */ JS_TAG_FIRST = -11, /* first negative tag */
@ -88,12 +192,6 @@ enum {
/* any larger tag is FLOAT64 if JS_NAN_BOXING */ /* any larger tag is FLOAT64 if JS_NAN_BOXING */
}; };
typedef struct JSRefCountHeader {
int ref_count;
} JSRefCountHeader;
#define JS_FLOAT64_NAN NAN
#ifdef CONFIG_CHECK_JSVALUE #ifdef CONFIG_CHECK_JSVALUE
/* JSValue consistency : it is not possible to run the code in this /* JSValue consistency : it is not possible to run the code in this
mode, but it is useful to detect simple reference counting mode, but it is useful to detect simple reference counting
@ -245,12 +343,16 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
#endif /* !JS_NAN_BOXING */ #endif /* !JS_NAN_BOXING */
#define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
#endif /* !JS_STRICT_NAN_BOXING */
#define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0) #define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0)
#define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2))) #define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2)))
#define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v)) #define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v))
#define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) #define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v))
#define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
/* special values */ /* special values */
#define JS_NULL JS_MKVAL(JS_TAG_NULL, 0) #define JS_NULL JS_MKVAL(JS_TAG_NULL, 0)