Drop support for "use math"
Ref: https://github.com/quickjs-ng/quickjs/issues/20
This commit is contained in:
parent
9b3b3084fa
commit
1fb9a5010f
7 changed files with 49 additions and 3380 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -13,8 +13,6 @@ qjs
|
||||||
qjs-debug
|
qjs-debug
|
||||||
qjs32
|
qjs32
|
||||||
qjsc
|
qjsc
|
||||||
qjscalc
|
|
||||||
qjscalc.c
|
|
||||||
repl.c
|
repl.c
|
||||||
run-test262
|
run-test262
|
||||||
run-test262-32
|
run-test262-32
|
||||||
|
|
15
Makefile
15
Makefile
|
@ -154,9 +154,6 @@ else
|
||||||
QJSC_CC=$(CC)
|
QJSC_CC=$(CC)
|
||||||
QJSC=./qjsc$(EXE)
|
QJSC=./qjsc$(EXE)
|
||||||
endif
|
endif
|
||||||
ifndef CONFIG_WIN32
|
|
||||||
PROGS+=qjscalc
|
|
||||||
endif
|
|
||||||
ifdef CONFIG_M32
|
ifdef CONFIG_M32
|
||||||
PROGS+=qjs32 qjs32_s
|
PROGS+=qjs32 qjs32_s
|
||||||
endif
|
endif
|
||||||
|
@ -186,7 +183,6 @@ QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(
|
||||||
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
|
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
|
||||||
ifdef CONFIG_BIGNUM
|
ifdef CONFIG_BIGNUM
|
||||||
QJS_LIB_OBJS+=$(OBJDIR)/libbf.o
|
QJS_LIB_OBJS+=$(OBJDIR)/libbf.o
|
||||||
QJS_OBJS+=$(OBJDIR)/qjscalc.o
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
HOST_LIBS=-lm -ldl -lpthread
|
HOST_LIBS=-lm -ldl -lpthread
|
||||||
|
@ -232,9 +228,6 @@ qjs32_s: $(patsubst %.o, %.m32s.o, $(QJS_OBJS))
|
||||||
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
|
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
@size $@
|
@size $@
|
||||||
|
|
||||||
qjscalc: qjs
|
|
||||||
ln -sf $< $@
|
|
||||||
|
|
||||||
ifdef CONFIG_LTO
|
ifdef CONFIG_LTO
|
||||||
LTOEXT=.lto
|
LTOEXT=.lto
|
||||||
else
|
else
|
||||||
|
@ -252,9 +245,6 @@ endif # CONFIG_LTO
|
||||||
repl.c: $(QJSC) repl.js
|
repl.c: $(QJSC) repl.js
|
||||||
$(QJSC) -c -o $@ -m repl.js
|
$(QJSC) -c -o $@ -m repl.js
|
||||||
|
|
||||||
qjscalc.c: $(QJSC) qjscalc.js
|
|
||||||
$(QJSC) -fbignum -c -o $@ qjscalc.js
|
|
||||||
|
|
||||||
ifneq ($(wildcard unicode/UnicodeData.txt),)
|
ifneq ($(wildcard unicode/UnicodeData.txt),)
|
||||||
$(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \
|
$(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \
|
||||||
$(OBJDIR)/libunicode.nolto.o: libunicode-table.h
|
$(OBJDIR)/libunicode.nolto.o: libunicode-table.h
|
||||||
|
@ -305,7 +295,7 @@ unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c u
|
||||||
$(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o
|
$(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f repl.c qjscalc.c out.c
|
rm -f repl.c out.c
|
||||||
rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS)
|
rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS)
|
||||||
rm -f hello.c test_fib.c
|
rm -f hello.c test_fib.c
|
||||||
rm -f examples/*.so tests/*.so
|
rm -f examples/*.so tests/*.so
|
||||||
|
@ -316,7 +306,6 @@ install: all
|
||||||
mkdir -p "$(DESTDIR)$(prefix)/bin"
|
mkdir -p "$(DESTDIR)$(prefix)/bin"
|
||||||
$(STRIP) qjs qjsc
|
$(STRIP) qjs qjsc
|
||||||
install -m755 qjs qjsc "$(DESTDIR)$(prefix)/bin"
|
install -m755 qjs qjsc "$(DESTDIR)$(prefix)/bin"
|
||||||
ln -sf qjs "$(DESTDIR)$(prefix)/bin/qjscalc"
|
|
||||||
mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs"
|
mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs"
|
||||||
install -m644 libquickjs.a "$(DESTDIR)$(prefix)/lib/quickjs"
|
install -m644 libquickjs.a "$(DESTDIR)$(prefix)/lib/quickjs"
|
||||||
ifdef CONFIG_LTO
|
ifdef CONFIG_LTO
|
||||||
|
@ -417,7 +406,6 @@ endif
|
||||||
ifdef CONFIG_BIGNUM
|
ifdef CONFIG_BIGNUM
|
||||||
./qjs --bignum tests/test_op_overloading.js
|
./qjs --bignum tests/test_op_overloading.js
|
||||||
./qjs --bignum tests/test_bignum.js
|
./qjs --bignum tests/test_bignum.js
|
||||||
./qjs --qjscalc tests/test_qjscalc.js
|
|
||||||
endif
|
endif
|
||||||
ifdef CONFIG_M32
|
ifdef CONFIG_M32
|
||||||
./qjs32 tests/test_closure.js
|
./qjs32 tests/test_closure.js
|
||||||
|
@ -429,7 +417,6 @@ ifdef CONFIG_M32
|
||||||
ifdef CONFIG_BIGNUM
|
ifdef CONFIG_BIGNUM
|
||||||
./qjs32 --bignum tests/test_op_overloading.js
|
./qjs32 --bignum tests/test_op_overloading.js
|
||||||
./qjs32 --bignum tests/test_bignum.js
|
./qjs32 --bignum tests/test_bignum.js
|
||||||
./qjs32 --qjscalc tests/test_qjscalc.js
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
32
qjs.c
32
qjs.c
|
@ -44,8 +44,6 @@
|
||||||
extern const uint8_t qjsc_repl[];
|
extern const uint8_t qjsc_repl[];
|
||||||
extern const uint32_t qjsc_repl_size;
|
extern const uint32_t qjsc_repl_size;
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
extern const uint8_t qjsc_qjscalc[];
|
|
||||||
extern const uint32_t qjsc_qjscalc_size;
|
|
||||||
static int bignum_ext;
|
static int bignum_ext;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -293,7 +291,6 @@ void help(void)
|
||||||
" --std make 'std' and 'os' available to the loaded script\n"
|
" --std make 'std' and 'os' available to the loaded script\n"
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
" --bignum enable the bignum extensions (BigFloat, BigDecimal)\n"
|
" --bignum enable the bignum extensions (BigFloat, BigDecimal)\n"
|
||||||
" --qjscalc load the QJSCalc runtime (default if invoked as qjscalc)\n"
|
|
||||||
#endif
|
#endif
|
||||||
"-T --trace trace memory allocation\n"
|
"-T --trace trace memory allocation\n"
|
||||||
"-d --dump dump the memory usage stats\n"
|
"-d --dump dump the memory usage stats\n"
|
||||||
|
@ -321,23 +318,8 @@ int main(int argc, char **argv)
|
||||||
size_t memory_limit = 0;
|
size_t memory_limit = 0;
|
||||||
char *include_list[32];
|
char *include_list[32];
|
||||||
int i, include_count = 0;
|
int i, include_count = 0;
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
int load_jscalc;
|
|
||||||
#endif
|
|
||||||
size_t stack_size = 0;
|
size_t stack_size = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
/* load jscalc runtime if invoked as 'qjscalc' */
|
|
||||||
{
|
|
||||||
const char *p, *exename;
|
|
||||||
exename = argv[0];
|
|
||||||
p = strrchr(exename, '/');
|
|
||||||
if (p)
|
|
||||||
exename = p + 1;
|
|
||||||
load_jscalc = !strcmp(exename, "qjscalc");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* cannot use getopt because we want to pass the command line to
|
/* cannot use getopt because we want to pass the command line to
|
||||||
the script */
|
the script */
|
||||||
optind = 1;
|
optind = 1;
|
||||||
|
@ -420,10 +402,6 @@ int main(int argc, char **argv)
|
||||||
bignum_ext = 1;
|
bignum_ext = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(longopt, "qjscalc")) {
|
|
||||||
load_jscalc = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (opt == 'q' || !strcmp(longopt, "quit")) {
|
if (opt == 'q' || !strcmp(longopt, "quit")) {
|
||||||
empty_run++;
|
empty_run++;
|
||||||
|
@ -454,11 +432,6 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
if (load_jscalc)
|
|
||||||
bignum_ext = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (trace_memory) {
|
if (trace_memory) {
|
||||||
js_trace_malloc_init(&trace_data);
|
js_trace_malloc_init(&trace_data);
|
||||||
rt = JS_NewRuntime2(&trace_mf, &trace_data);
|
rt = JS_NewRuntime2(&trace_mf, &trace_data);
|
||||||
|
@ -490,11 +463,6 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty_run) {
|
if (!empty_run) {
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
if (load_jscalc) {
|
|
||||||
js_std_eval_binary(ctx, qjsc_qjscalc, qjsc_qjscalc_size, 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
js_std_add_helpers(ctx, argc - optind, argv + optind);
|
js_std_add_helpers(ctx, argc - optind, argv + optind);
|
||||||
|
|
||||||
/* make 'std' and 'os' visible to non module code */
|
/* make 'std' and 'os' visible to non module code */
|
||||||
|
|
2657
qjscalc.js
2657
qjscalc.js
File diff suppressed because it is too large
Load diff
|
@ -258,7 +258,6 @@ DEF( or, 1, 2, 1, none)
|
||||||
DEF(is_undefined_or_null, 1, 1, 1, none)
|
DEF(is_undefined_or_null, 1, 1, 1, none)
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
DEF( mul_pow10, 1, 2, 1, none)
|
DEF( mul_pow10, 1, 2, 1, none)
|
||||||
DEF( math_mod, 1, 2, 1, none)
|
|
||||||
#endif
|
#endif
|
||||||
/* must be the last non short and non temporary opcode */
|
/* must be the last non short and non temporary opcode */
|
||||||
DEF( nop, 1, 0, 0, none)
|
DEF( nop, 1, 0, 0, none)
|
||||||
|
|
464
quickjs.c
464
quickjs.c
|
@ -314,7 +314,6 @@ struct JSClass {
|
||||||
|
|
||||||
#define JS_MODE_STRICT (1 << 0)
|
#define JS_MODE_STRICT (1 << 0)
|
||||||
#define JS_MODE_STRIP (1 << 1)
|
#define JS_MODE_STRIP (1 << 1)
|
||||||
#define JS_MODE_MATH (1 << 2)
|
|
||||||
|
|
||||||
typedef struct JSStackFrame {
|
typedef struct JSStackFrame {
|
||||||
struct JSStackFrame *prev_frame; /* NULL if first stack frame */
|
struct JSStackFrame *prev_frame; /* NULL if first stack frame */
|
||||||
|
@ -325,7 +324,7 @@ typedef struct JSStackFrame {
|
||||||
const uint8_t *cur_pc; /* only used in bytecode functions : PC of the
|
const uint8_t *cur_pc; /* only used in bytecode functions : PC of the
|
||||||
instruction after the call */
|
instruction after the call */
|
||||||
int arg_count;
|
int arg_count;
|
||||||
int js_mode; /* 0 or JS_MODE_MATH for C functions */
|
int js_mode;
|
||||||
/* only used in generators. Current stack pointer value. NULL if
|
/* only used in generators. Current stack pointer value. NULL if
|
||||||
the function is running. */
|
the function is running. */
|
||||||
JSValue *cur_sp;
|
JSValue *cur_sp;
|
||||||
|
@ -1146,8 +1145,7 @@ static inline bf_t *JS_GetBigInt(JSValueConst val)
|
||||||
JSBigFloat *p = JS_VALUE_GET_PTR(val);
|
JSBigFloat *p = JS_VALUE_GET_PTR(val);
|
||||||
return &p->num;
|
return &p->num;
|
||||||
}
|
}
|
||||||
static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,
|
static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val);
|
||||||
BOOL convert_to_safe_integer);
|
|
||||||
static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val);
|
static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val);
|
||||||
static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val);
|
static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val);
|
||||||
static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val);
|
static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val);
|
||||||
|
@ -2378,14 +2376,6 @@ static inline BOOL is_strict_mode(JSContext *ctx)
|
||||||
return (sf && (sf->js_mode & JS_MODE_STRICT));
|
return (sf && (sf->js_mode & JS_MODE_STRICT));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
static inline BOOL is_math_mode(JSContext *ctx)
|
|
||||||
{
|
|
||||||
JSStackFrame *sf = ctx->rt->current_stack_frame;
|
|
||||||
return (sf && (sf->js_mode & JS_MODE_MATH));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* JSAtom support */
|
/* JSAtom support */
|
||||||
|
|
||||||
#define JS_ATOM_TAG_INT (1U << 31)
|
#define JS_ATOM_TAG_INT (1U << 31)
|
||||||
|
@ -10086,9 +10076,6 @@ static double js_strtod(const char *p, int radix, BOOL is_float)
|
||||||
#define ATOD_TYPE_BIG_INT (1 << 7)
|
#define ATOD_TYPE_BIG_INT (1 << 7)
|
||||||
#define ATOD_TYPE_BIG_FLOAT (2 << 7)
|
#define ATOD_TYPE_BIG_FLOAT (2 << 7)
|
||||||
#define ATOD_TYPE_BIG_DECIMAL (3 << 7)
|
#define ATOD_TYPE_BIG_DECIMAL (3 << 7)
|
||||||
/* assume bigint mode: floats are parsed as integers if no decimal
|
|
||||||
point nor exponent */
|
|
||||||
#define ATOD_MODE_BIGINT (1 << 9)
|
|
||||||
/* accept -0x1 */
|
/* accept -0x1 */
|
||||||
#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10)
|
#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10)
|
||||||
|
|
||||||
|
@ -10108,7 +10095,7 @@ static JSValue js_string_to_bigint(JSContext *ctx, const char *buf,
|
||||||
JS_FreeValue(ctx, val);
|
JS_FreeValue(ctx, val);
|
||||||
return JS_ThrowOutOfMemory(ctx);
|
return JS_ThrowOutOfMemory(ctx);
|
||||||
}
|
}
|
||||||
val = JS_CompactBigInt1(ctx, val, (flags & ATOD_MODE_BIGINT) != 0);
|
val = JS_CompactBigInt1(ctx, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10324,29 +10311,11 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
|
||||||
} else if (*p == 'm') {
|
} else if (*p == 'm') {
|
||||||
p++;
|
p++;
|
||||||
atod_type = ATOD_TYPE_BIG_DECIMAL;
|
atod_type = ATOD_TYPE_BIG_DECIMAL;
|
||||||
} else {
|
} else if (is_float && radix != 10) {
|
||||||
if (flags & ATOD_MODE_BIGINT) {
|
goto fail;
|
||||||
if (!is_float)
|
|
||||||
atod_type = ATOD_TYPE_BIG_INT;
|
|
||||||
if (has_legacy_octal)
|
|
||||||
goto fail;
|
|
||||||
} else {
|
|
||||||
if (is_float && radix != 10)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (atod_type == ATOD_TYPE_FLOAT64) {
|
|
||||||
if (flags & ATOD_MODE_BIGINT) {
|
|
||||||
if (!is_float)
|
|
||||||
atod_type = ATOD_TYPE_BIG_INT;
|
|
||||||
if (has_legacy_octal)
|
|
||||||
goto fail;
|
|
||||||
} else {
|
|
||||||
if (is_float && radix != 10)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else if ((atod_type == ATOD_TYPE_FLOAT64) && is_float && radix != 10) {
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(atod_type) {
|
switch(atod_type) {
|
||||||
|
@ -12018,30 +11987,22 @@ JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v)
|
||||||
|
|
||||||
JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)
|
JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)
|
||||||
{
|
{
|
||||||
if (is_math_mode(ctx) &&
|
return JS_NewBigInt64_1(ctx, v);
|
||||||
v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) {
|
|
||||||
return JS_NewInt64(ctx, v);
|
|
||||||
} else {
|
|
||||||
return JS_NewBigInt64_1(ctx, v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)
|
JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)
|
||||||
{
|
{
|
||||||
JSValue val;
|
JSValue val;
|
||||||
if (is_math_mode(ctx) && v <= MAX_SAFE_INTEGER) {
|
bf_t *a;
|
||||||
val = JS_NewInt64(ctx, v);
|
val = JS_NewBigInt(ctx);
|
||||||
} else {
|
if (JS_IsException(val))
|
||||||
bf_t *a;
|
return val;
|
||||||
val = JS_NewBigInt(ctx);
|
a = JS_GetBigInt(val);
|
||||||
if (JS_IsException(val))
|
if (bf_set_ui(a, v)) {
|
||||||
return val;
|
JS_FreeValue(ctx, val);
|
||||||
a = JS_GetBigInt(val);
|
return JS_ThrowOutOfMemory(ctx);
|
||||||
if (bf_set_ui(a, v)) {
|
|
||||||
JS_FreeValue(ctx, val);
|
|
||||||
return JS_ThrowOutOfMemory(ctx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12126,8 +12087,6 @@ static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)
|
||||||
val = JS_NewBigInt64(ctx, 0);
|
val = JS_NewBigInt64(ctx, 0);
|
||||||
} else {
|
} else {
|
||||||
flags = ATOD_INT_ONLY | ATOD_ACCEPT_BIN_OCT | ATOD_TYPE_BIG_INT;
|
flags = ATOD_INT_ONLY | ATOD_ACCEPT_BIN_OCT | ATOD_TYPE_BIG_INT;
|
||||||
if (is_math_mode(ctx))
|
|
||||||
flags |= ATOD_MODE_BIGINT;
|
|
||||||
val = js_atof(ctx, p, &p, 0, flags);
|
val = js_atof(ctx, p, &p, 0, flags);
|
||||||
p += skip_spaces(p);
|
p += skip_spaces(p);
|
||||||
if (!JS_IsException(val)) {
|
if (!JS_IsException(val)) {
|
||||||
|
@ -12163,43 +12122,18 @@ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)
|
||||||
case JS_TAG_INT:
|
case JS_TAG_INT:
|
||||||
case JS_TAG_NULL:
|
case JS_TAG_NULL:
|
||||||
case JS_TAG_UNDEFINED:
|
case JS_TAG_UNDEFINED:
|
||||||
if (!is_math_mode(ctx))
|
case JS_TAG_FLOAT64:
|
||||||
goto fail;
|
case JS_TAG_BIG_FLOAT:
|
||||||
/* fall tru */
|
goto fail;
|
||||||
case JS_TAG_BOOL:
|
case JS_TAG_BOOL:
|
||||||
r = buf;
|
r = buf;
|
||||||
bf_init(ctx->bf_ctx, r);
|
bf_init(ctx->bf_ctx, r);
|
||||||
bf_set_si(r, JS_VALUE_GET_INT(val));
|
bf_set_si(r, JS_VALUE_GET_INT(val));
|
||||||
break;
|
break;
|
||||||
case JS_TAG_FLOAT64:
|
|
||||||
{
|
|
||||||
double d = JS_VALUE_GET_FLOAT64(val);
|
|
||||||
if (!is_math_mode(ctx))
|
|
||||||
goto fail;
|
|
||||||
if (!isfinite(d))
|
|
||||||
goto fail;
|
|
||||||
r = buf;
|
|
||||||
bf_init(ctx->bf_ctx, r);
|
|
||||||
d = trunc(d);
|
|
||||||
bf_set_float64(r, d);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case JS_TAG_BIG_INT:
|
case JS_TAG_BIG_INT:
|
||||||
p = JS_VALUE_GET_PTR(val);
|
p = JS_VALUE_GET_PTR(val);
|
||||||
r = &p->num;
|
r = &p->num;
|
||||||
break;
|
break;
|
||||||
case JS_TAG_BIG_FLOAT:
|
|
||||||
if (!is_math_mode(ctx))
|
|
||||||
goto fail;
|
|
||||||
p = JS_VALUE_GET_PTR(val);
|
|
||||||
if (!bf_is_finite(&p->num))
|
|
||||||
goto fail;
|
|
||||||
r = buf;
|
|
||||||
bf_init(ctx->bf_ctx, r);
|
|
||||||
bf_set(r, &p->num);
|
|
||||||
bf_rint(r, BF_RNDZ);
|
|
||||||
JS_FreeValue(ctx, val);
|
|
||||||
break;
|
|
||||||
case JS_TAG_STRING:
|
case JS_TAG_STRING:
|
||||||
val = JS_StringToBigIntErr(ctx, val);
|
val = JS_StringToBigIntErr(ctx, val);
|
||||||
if (JS_IsException(val))
|
if (JS_IsException(val))
|
||||||
|
@ -12328,20 +12262,12 @@ static JSValue JS_NewBigInt(JSContext *ctx)
|
||||||
return JS_MKPTR(JS_TAG_BIG_INT, p);
|
return JS_MKPTR(JS_TAG_BIG_INT, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,
|
static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val)
|
||||||
BOOL convert_to_safe_integer)
|
|
||||||
{
|
{
|
||||||
int64_t v;
|
|
||||||
bf_t *a;
|
|
||||||
|
|
||||||
if (JS_VALUE_GET_TAG(val) != JS_TAG_BIG_INT)
|
if (JS_VALUE_GET_TAG(val) != JS_TAG_BIG_INT)
|
||||||
return val; /* fail safe */
|
return val; /* fail safe */
|
||||||
a = JS_GetBigInt(val);
|
bf_t *a = JS_GetBigInt(val);
|
||||||
if (convert_to_safe_integer && bf_get_int64(&v, a, 0) == 0 &&
|
if (a->expn == BF_EXP_ZERO && a->sign) {
|
||||||
v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) {
|
|
||||||
JS_FreeValue(ctx, val);
|
|
||||||
return JS_NewInt64(ctx, v);
|
|
||||||
} else if (a->expn == BF_EXP_ZERO && a->sign) {
|
|
||||||
JSBigFloat *p = JS_VALUE_GET_PTR(val);
|
JSBigFloat *p = JS_VALUE_GET_PTR(val);
|
||||||
assert(p->header.ref_count == 1);
|
assert(p->header.ref_count == 1);
|
||||||
a->sign = 0;
|
a->sign = 0;
|
||||||
|
@ -12349,13 +12275,12 @@ static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the big int to a safe integer if in math mode. normalize
|
/* Nnormalize the zero representation. Could also be used to convert the bigint
|
||||||
the zero representation. Could also be used to convert the bigint
|
|
||||||
to a short bigint value. The reference count of the value must be
|
to a short bigint value. The reference count of the value must be
|
||||||
1. Cannot fail */
|
1. Cannot fail */
|
||||||
static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val)
|
static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val)
|
||||||
{
|
{
|
||||||
return JS_CompactBigInt1(ctx, val, is_math_mode(ctx));
|
return JS_CompactBigInt1(ctx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must be kept in sync with JSOverloadableOperatorEnum */
|
/* must be kept in sync with JSOverloadableOperatorEnum */
|
||||||
|
@ -12394,7 +12319,6 @@ static int get_ovop_from_opcode(OPCodeEnum op)
|
||||||
case OP_div:
|
case OP_div:
|
||||||
return JS_OVOP_DIV;
|
return JS_OVOP_DIV;
|
||||||
case OP_mod:
|
case OP_mod:
|
||||||
case OP_math_mod:
|
|
||||||
return JS_OVOP_MOD;
|
return JS_OVOP_MOD;
|
||||||
case OP_pow:
|
case OP_pow:
|
||||||
return JS_OVOP_POW;
|
return JS_OVOP_POW;
|
||||||
|
@ -12575,63 +12499,6 @@ static __exception int js_call_binary_op_fallback(JSContext *ctx,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try to call the operation on the operatorSet field of 'obj'. Only
|
|
||||||
used for "/" and "**" on the BigInt prototype in math mode */
|
|
||||||
static __exception int js_call_binary_op_simple(JSContext *ctx,
|
|
||||||
JSValue *pret,
|
|
||||||
JSValueConst obj,
|
|
||||||
JSValueConst op1,
|
|
||||||
JSValueConst op2,
|
|
||||||
OPCodeEnum op)
|
|
||||||
{
|
|
||||||
JSValue opset1_obj, method, ret, new_op1, new_op2;
|
|
||||||
JSOperatorSetData *opset1;
|
|
||||||
JSOverloadableOperatorEnum ovop;
|
|
||||||
JSObject *p;
|
|
||||||
JSValueConst args[2];
|
|
||||||
|
|
||||||
opset1_obj = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_operatorSet);
|
|
||||||
if (JS_IsException(opset1_obj))
|
|
||||||
goto exception;
|
|
||||||
if (JS_IsUndefined(opset1_obj))
|
|
||||||
return 0;
|
|
||||||
opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);
|
|
||||||
if (!opset1)
|
|
||||||
goto exception;
|
|
||||||
ovop = get_ovop_from_opcode(op);
|
|
||||||
|
|
||||||
p = opset1->self_ops[ovop];
|
|
||||||
if (!p) {
|
|
||||||
JS_FreeValue(ctx, opset1_obj);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_op1 = JS_ToNumeric(ctx, op1);
|
|
||||||
if (JS_IsException(new_op1))
|
|
||||||
goto exception;
|
|
||||||
new_op2 = JS_ToNumeric(ctx, op2);
|
|
||||||
if (JS_IsException(new_op2)) {
|
|
||||||
JS_FreeValue(ctx, new_op1);
|
|
||||||
goto exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
|
|
||||||
args[0] = new_op1;
|
|
||||||
args[1] = new_op2;
|
|
||||||
ret = JS_CallFree(ctx, method, JS_UNDEFINED, 2, args);
|
|
||||||
JS_FreeValue(ctx, new_op1);
|
|
||||||
JS_FreeValue(ctx, new_op2);
|
|
||||||
if (JS_IsException(ret))
|
|
||||||
goto exception;
|
|
||||||
JS_FreeValue(ctx, opset1_obj);
|
|
||||||
*pret = ret;
|
|
||||||
return 1;
|
|
||||||
exception:
|
|
||||||
JS_FreeValue(ctx, opset1_obj);
|
|
||||||
*pret = JS_UNDEFINED;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return -1 if exception, 0 if no operator overloading, 1 if
|
/* return -1 if exception, 0 if no operator overloading, 1 if
|
||||||
overloaded operator called */
|
overloaded operator called */
|
||||||
static __exception int js_call_unary_op_fallback(JSContext *ctx,
|
static __exception int js_call_unary_op_fallback(JSContext *ctx,
|
||||||
|
@ -12703,7 +12570,7 @@ static int js_unary_arith_bigint(JSContext *ctx,
|
||||||
int ret, v;
|
int ret, v;
|
||||||
JSValue res;
|
JSValue res;
|
||||||
|
|
||||||
if (op == OP_plus && !is_math_mode(ctx)) {
|
if (op == OP_plus) {
|
||||||
JS_ThrowTypeError(ctx, "bigint argument with unary +");
|
JS_ThrowTypeError(ctx, "bigint argument with unary +");
|
||||||
JS_FreeValue(ctx, op1);
|
JS_FreeValue(ctx, op1);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -12755,7 +12622,7 @@ static int js_unary_arith_bigfloat(JSContext *ctx,
|
||||||
int ret, v;
|
int ret, v;
|
||||||
JSValue res;
|
JSValue res;
|
||||||
|
|
||||||
if (op == OP_plus && !is_math_mode(ctx)) {
|
if (op == OP_plus) {
|
||||||
JS_ThrowTypeError(ctx, "bigfloat argument with unary +");
|
JS_ThrowTypeError(ctx, "bigfloat argument with unary +");
|
||||||
JS_FreeValue(ctx, op1);
|
JS_FreeValue(ctx, op1);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -12804,7 +12671,7 @@ static int js_unary_arith_bigdecimal(JSContext *ctx,
|
||||||
int ret, v;
|
int ret, v;
|
||||||
JSValue res;
|
JSValue res;
|
||||||
|
|
||||||
if (op == OP_plus && !is_math_mode(ctx)) {
|
if (op == OP_plus) {
|
||||||
JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");
|
JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");
|
||||||
JS_FreeValue(ctx, op1);
|
JS_FreeValue(ctx, op1);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -12899,7 +12766,6 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JS_TAG_BIG_INT:
|
case JS_TAG_BIG_INT:
|
||||||
handle_bigint:
|
|
||||||
if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, op, op1))
|
if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, op, op1))
|
||||||
goto exception;
|
goto exception;
|
||||||
break;
|
break;
|
||||||
|
@ -12914,10 +12780,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
|
||||||
default:
|
default:
|
||||||
handle_float64:
|
handle_float64:
|
||||||
{
|
{
|
||||||
double d;
|
double d = JS_VALUE_GET_FLOAT64(op1);
|
||||||
if (is_math_mode(ctx))
|
|
||||||
goto handle_bigint;
|
|
||||||
d = JS_VALUE_GET_FLOAT64(op1);
|
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case OP_inc:
|
case OP_inc:
|
||||||
case OP_dec:
|
case OP_dec:
|
||||||
|
@ -12979,7 +12842,7 @@ static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
|
||||||
op1 = JS_ToNumericFree(ctx, op1);
|
op1 = JS_ToNumericFree(ctx, op1);
|
||||||
if (JS_IsException(op1))
|
if (JS_IsException(op1))
|
||||||
goto exception;
|
goto exception;
|
||||||
if (is_math_mode(ctx) || JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT) {
|
if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT) {
|
||||||
if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, OP_not, op1))
|
if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, OP_not, op1))
|
||||||
goto exception;
|
goto exception;
|
||||||
} else {
|
} else {
|
||||||
|
@ -13024,11 +12887,6 @@ static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op,
|
||||||
case OP_div:
|
case OP_div:
|
||||||
ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
|
ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
|
||||||
break;
|
break;
|
||||||
case OP_math_mod:
|
|
||||||
/* Euclidian remainder */
|
|
||||||
ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
|
|
||||||
BF_DIVREM_EUCLIDIAN);
|
|
||||||
break;
|
|
||||||
case OP_mod:
|
case OP_mod:
|
||||||
ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
|
ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
|
||||||
BF_RNDZ);
|
BF_RNDZ);
|
||||||
|
@ -13086,72 +12944,20 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
|
||||||
ret = bf_mul(r, a, b, BF_PREC_INF, BF_RNDZ);
|
ret = bf_mul(r, a, b, BF_PREC_INF, BF_RNDZ);
|
||||||
break;
|
break;
|
||||||
case OP_div:
|
case OP_div:
|
||||||
if (!is_math_mode(ctx)) {
|
{
|
||||||
bf_t rem_s, *rem = &rem_s;
|
bf_t rem_s, *rem = &rem_s;
|
||||||
bf_init(ctx->bf_ctx, rem);
|
bf_init(ctx->bf_ctx, rem);
|
||||||
ret = bf_divrem(r, rem, a, b, BF_PREC_INF, BF_RNDZ,
|
ret = bf_divrem(r, rem, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ);
|
||||||
BF_RNDZ);
|
|
||||||
bf_delete(rem);
|
bf_delete(rem);
|
||||||
} else {
|
|
||||||
goto math_mode_div_pow;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OP_math_mod:
|
|
||||||
/* Euclidian remainder */
|
|
||||||
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
|
|
||||||
BF_DIVREM_EUCLIDIAN) & BF_ST_INVALID_OP;
|
|
||||||
break;
|
|
||||||
case OP_mod:
|
case OP_mod:
|
||||||
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
|
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
|
||||||
BF_RNDZ) & BF_ST_INVALID_OP;
|
BF_RNDZ) & BF_ST_INVALID_OP;
|
||||||
break;
|
break;
|
||||||
case OP_pow:
|
case OP_pow:
|
||||||
if (b->sign) {
|
if (b->sign) {
|
||||||
if (!is_math_mode(ctx)) {
|
ret = BF_ST_INVALID_OP;
|
||||||
ret = BF_ST_INVALID_OP;
|
|
||||||
} else {
|
|
||||||
math_mode_div_pow:
|
|
||||||
JS_FreeValue(ctx, res);
|
|
||||||
ret = js_call_binary_op_simple(ctx, &res, ctx->class_proto[JS_CLASS_BIG_INT], op1, op2, op);
|
|
||||||
if (ret != 0) {
|
|
||||||
JS_FreeBigInt(ctx, a, &a_s);
|
|
||||||
JS_FreeBigInt(ctx, b, &b_s);
|
|
||||||
JS_FreeValue(ctx, op1);
|
|
||||||
JS_FreeValue(ctx, op2);
|
|
||||||
if (ret < 0) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
*pres = res;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* if no BigInt power operator defined, return a
|
|
||||||
bigfloat */
|
|
||||||
res = JS_NewBigFloat(ctx);
|
|
||||||
if (JS_IsException(res)) {
|
|
||||||
JS_FreeBigInt(ctx, a, &a_s);
|
|
||||||
JS_FreeBigInt(ctx, b, &b_s);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
r = JS_GetBigFloat(res);
|
|
||||||
if (op == OP_div) {
|
|
||||||
ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags) & BF_ST_MEM_ERROR;
|
|
||||||
} else {
|
|
||||||
ret = bf_pow(r, a, b, ctx->fp_env.prec,
|
|
||||||
ctx->fp_env.flags | BF_POW_JS_QUIRKS) & BF_ST_MEM_ERROR;
|
|
||||||
}
|
|
||||||
JS_FreeBigInt(ctx, a, &a_s);
|
|
||||||
JS_FreeBigInt(ctx, b, &b_s);
|
|
||||||
JS_FreeValue(ctx, op1);
|
|
||||||
JS_FreeValue(ctx, op2);
|
|
||||||
if (unlikely(ret)) {
|
|
||||||
JS_FreeValue(ctx, res);
|
|
||||||
throw_bf_exception(ctx, ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*pres = res;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ret = bf_pow(r, a, b, BF_PREC_INF, BF_RNDZ | BF_POW_JS_QUIRKS);
|
ret = bf_pow(r, a, b, BF_PREC_INF, BF_RNDZ | BF_POW_JS_QUIRKS);
|
||||||
}
|
}
|
||||||
|
@ -13268,10 +13074,6 @@ static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op,
|
||||||
case OP_div:
|
case OP_div:
|
||||||
ret = bfdec_div(r, a, b, BF_PREC_INF, BF_RNDZ);
|
ret = bfdec_div(r, a, b, BF_PREC_INF, BF_RNDZ);
|
||||||
break;
|
break;
|
||||||
case OP_math_mod:
|
|
||||||
/* Euclidian remainder */
|
|
||||||
ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_DIVREM_EUCLIDIAN);
|
|
||||||
break;
|
|
||||||
case OP_mod:
|
case OP_mod:
|
||||||
ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ);
|
ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ);
|
||||||
break;
|
break;
|
||||||
|
@ -13358,32 +13160,14 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
|
||||||
break;
|
break;
|
||||||
case OP_mul:
|
case OP_mul:
|
||||||
v = (int64_t)v1 * (int64_t)v2;
|
v = (int64_t)v1 * (int64_t)v2;
|
||||||
if (is_math_mode(ctx) &&
|
|
||||||
(v < -MAX_SAFE_INTEGER || v > MAX_SAFE_INTEGER))
|
|
||||||
goto handle_bigint;
|
|
||||||
if (v == 0 && (v1 | v2) < 0) {
|
if (v == 0 && (v1 | v2) < 0) {
|
||||||
sp[-2] = __JS_NewFloat64(ctx, -0.0);
|
sp[-2] = __JS_NewFloat64(ctx, -0.0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OP_div:
|
case OP_div:
|
||||||
if (is_math_mode(ctx))
|
|
||||||
goto handle_bigint;
|
|
||||||
sp[-2] = __JS_NewFloat64(ctx, (double)v1 / (double)v2);
|
sp[-2] = __JS_NewFloat64(ctx, (double)v1 / (double)v2);
|
||||||
return 0;
|
return 0;
|
||||||
case OP_math_mod:
|
|
||||||
if (unlikely(v2 == 0)) {
|
|
||||||
throw_bf_exception(ctx, BF_ST_DIVIDE_ZERO);
|
|
||||||
goto exception;
|
|
||||||
}
|
|
||||||
v = (int64_t)v1 % (int64_t)v2;
|
|
||||||
if (v < 0) {
|
|
||||||
if (v2 < 0)
|
|
||||||
v -= v2;
|
|
||||||
else
|
|
||||||
v += v2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OP_mod:
|
case OP_mod:
|
||||||
if (v1 < 0 || v2 <= 0) {
|
if (v1 < 0 || v2 <= 0) {
|
||||||
sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2));
|
sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2));
|
||||||
|
@ -13393,13 +13177,8 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OP_pow:
|
case OP_pow:
|
||||||
if (!is_math_mode(ctx)) {
|
sp[-2] = JS_NewFloat64(ctx, js_pow(v1, v2));
|
||||||
sp[-2] = JS_NewFloat64(ctx, js_pow(v1, v2));
|
return 0;
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
goto handle_bigint;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -13411,7 +13190,6 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
|
||||||
if (ctx->rt->bigfloat_ops.binary_arith(ctx, op, sp - 2, op1, op2))
|
if (ctx->rt->bigfloat_ops.binary_arith(ctx, op, sp - 2, op1, op2))
|
||||||
goto exception;
|
goto exception;
|
||||||
} else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
|
} else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
|
||||||
handle_bigint:
|
|
||||||
if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))
|
if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))
|
||||||
goto exception;
|
goto exception;
|
||||||
} else {
|
} else {
|
||||||
|
@ -13424,8 +13202,6 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
|
||||||
if (JS_ToFloat64Free(ctx, &d2, op2))
|
if (JS_ToFloat64Free(ctx, &d2, op2))
|
||||||
goto exception;
|
goto exception;
|
||||||
handle_float64:
|
handle_float64:
|
||||||
if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))
|
|
||||||
goto handle_bigint;
|
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case OP_sub:
|
case OP_sub:
|
||||||
dr = d1 - d2;
|
dr = d1 - d2;
|
||||||
|
@ -13439,13 +13215,6 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
|
||||||
case OP_mod:
|
case OP_mod:
|
||||||
dr = fmod(d1, d2);
|
dr = fmod(d1, d2);
|
||||||
break;
|
break;
|
||||||
case OP_math_mod:
|
|
||||||
d2 = fabs(d2);
|
|
||||||
dr = fmod(d1, d2);
|
|
||||||
/* XXX: loss of accuracy if dr < 0 */
|
|
||||||
if (dr < 0)
|
|
||||||
dr += d2;
|
|
||||||
break;
|
|
||||||
case OP_pow:
|
case OP_pow:
|
||||||
dr = js_pow(d1, d2);
|
dr = js_pow(d1, d2);
|
||||||
break;
|
break;
|
||||||
|
@ -13552,7 +13321,6 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
|
||||||
if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
|
if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
|
||||||
goto exception;
|
goto exception;
|
||||||
} else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
|
} else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
|
||||||
handle_bigint:
|
|
||||||
if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
|
if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
|
||||||
goto exception;
|
goto exception;
|
||||||
} else {
|
} else {
|
||||||
|
@ -13564,8 +13332,6 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
|
||||||
}
|
}
|
||||||
if (JS_ToFloat64Free(ctx, &d2, op2))
|
if (JS_ToFloat64Free(ctx, &d2, op2))
|
||||||
goto exception;
|
goto exception;
|
||||||
if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))
|
|
||||||
goto handle_bigint;
|
|
||||||
sp[-2] = __JS_NewFloat64(ctx, d1 + d2);
|
sp[-2] = __JS_NewFloat64(ctx, d1 + d2);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -13618,9 +13384,6 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
|
||||||
goto exception;
|
goto exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_math_mode(ctx))
|
|
||||||
goto bigint_op;
|
|
||||||
|
|
||||||
tag1 = JS_VALUE_GET_TAG(op1);
|
tag1 = JS_VALUE_GET_TAG(op1);
|
||||||
tag2 = JS_VALUE_GET_TAG(op2);
|
tag2 = JS_VALUE_GET_TAG(op2);
|
||||||
if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
|
if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
|
||||||
|
@ -13629,10 +13392,8 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
|
||||||
JS_FreeValue(ctx, op2);
|
JS_FreeValue(ctx, op2);
|
||||||
JS_ThrowTypeError(ctx, "both operands must be bigint");
|
JS_ThrowTypeError(ctx, "both operands must be bigint");
|
||||||
goto exception;
|
goto exception;
|
||||||
} else {
|
} else if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2)) {
|
||||||
bigint_op:
|
goto exception;
|
||||||
if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))
|
|
||||||
goto exception;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {
|
if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {
|
||||||
|
@ -13832,8 +13593,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
|
||||||
goto float64_compare;
|
goto float64_compare;
|
||||||
} else {
|
} else {
|
||||||
if (((tag1 == JS_TAG_BIG_INT && tag2 == JS_TAG_STRING) ||
|
if (((tag1 == JS_TAG_BIG_INT && tag2 == JS_TAG_STRING) ||
|
||||||
(tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING)) &&
|
(tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING))) {
|
||||||
!is_math_mode(ctx)) {
|
|
||||||
if (tag1 == JS_TAG_STRING) {
|
if (tag1 == JS_TAG_STRING) {
|
||||||
op1 = JS_StringToBigInt(ctx, op1);
|
op1 = JS_StringToBigInt(ctx, op1);
|
||||||
if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)
|
if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)
|
||||||
|
@ -13993,8 +13753,7 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
|
||||||
} else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) ||
|
} else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) ||
|
||||||
(tag2 == JS_TAG_STRING && tag_is_number(tag1))) {
|
(tag2 == JS_TAG_STRING && tag_is_number(tag1))) {
|
||||||
|
|
||||||
if ((tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) &&
|
if ((tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT)) {
|
||||||
!is_math_mode(ctx)) {
|
|
||||||
if (tag1 == JS_TAG_STRING) {
|
if (tag1 == JS_TAG_STRING) {
|
||||||
op1 = JS_StringToBigInt(ctx, op1);
|
op1 = JS_StringToBigInt(ctx, op1);
|
||||||
if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)
|
if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)
|
||||||
|
@ -14099,9 +13858,8 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)
|
||||||
JS_FreeValue(ctx, op1);
|
JS_FreeValue(ctx, op1);
|
||||||
goto exception;
|
goto exception;
|
||||||
}
|
}
|
||||||
/* XXX: could forbid >>> in bignum mode */
|
|
||||||
if (!is_math_mode(ctx) &&
|
if ((JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT ||
|
||||||
(JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT ||
|
|
||||||
JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_INT)) {
|
JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_INT)) {
|
||||||
JS_ThrowTypeError(ctx, "bigint operands are forbidden for >>>");
|
JS_ThrowTypeError(ctx, "bigint operands are forbidden for >>>");
|
||||||
JS_FreeValue(ctx, op1);
|
JS_FreeValue(ctx, op1);
|
||||||
|
@ -16044,16 +15802,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
|
||||||
rt->current_stack_frame = sf;
|
rt->current_stack_frame = sf;
|
||||||
ctx = p->u.cfunc.realm; /* change the current realm */
|
ctx = p->u.cfunc.realm; /* change the current realm */
|
||||||
|
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
/* we only propagate the bignum mode as some runtime functions
|
|
||||||
test it */
|
|
||||||
if (prev_sf)
|
|
||||||
sf->js_mode = prev_sf->js_mode & JS_MODE_MATH;
|
|
||||||
else
|
|
||||||
sf->js_mode = 0;
|
|
||||||
#else
|
|
||||||
sf->js_mode = 0;
|
sf->js_mode = 0;
|
||||||
#endif
|
|
||||||
sf->cur_func = (JSValue)func_obj;
|
sf->cur_func = (JSValue)func_obj;
|
||||||
sf->arg_count = argc;
|
sf->arg_count = argc;
|
||||||
arg_buf = argv;
|
arg_buf = argv;
|
||||||
|
@ -18022,11 +17771,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
v2 = JS_VALUE_GET_INT(op2);
|
v2 = JS_VALUE_GET_INT(op2);
|
||||||
r = (int64_t)v1 * v2;
|
r = (int64_t)v1 * v2;
|
||||||
if (unlikely((int)r != r)) {
|
if (unlikely((int)r != r)) {
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
if (unlikely(sf->js_mode & JS_MODE_MATH) &&
|
|
||||||
(r < -MAX_SAFE_INTEGER || r > MAX_SAFE_INTEGER))
|
|
||||||
goto binary_arith_slow;
|
|
||||||
#endif
|
|
||||||
d = (double)r;
|
d = (double)r;
|
||||||
goto mul_fp_res;
|
goto mul_fp_res;
|
||||||
}
|
}
|
||||||
|
@ -18038,10 +17782,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
sp[-2] = JS_NewInt32(ctx, r);
|
sp[-2] = JS_NewInt32(ctx, r);
|
||||||
sp--;
|
sp--;
|
||||||
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
|
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
if (unlikely(sf->js_mode & JS_MODE_MATH))
|
|
||||||
goto binary_arith_slow;
|
|
||||||
#endif
|
|
||||||
d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2);
|
d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2);
|
||||||
mul_fp_res:
|
mul_fp_res:
|
||||||
sp[-2] = __JS_NewFloat64(ctx, d);
|
sp[-2] = __JS_NewFloat64(ctx, d);
|
||||||
|
@ -18058,8 +17798,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
op2 = sp[-1];
|
op2 = sp[-1];
|
||||||
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
|
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
|
||||||
int v1, v2;
|
int v1, v2;
|
||||||
if (unlikely(sf->js_mode & JS_MODE_MATH))
|
|
||||||
goto binary_arith_slow;
|
|
||||||
v1 = JS_VALUE_GET_INT(op1);
|
v1 = JS_VALUE_GET_INT(op1);
|
||||||
v2 = JS_VALUE_GET_INT(op2);
|
v2 = JS_VALUE_GET_INT(op2);
|
||||||
sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2);
|
sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2);
|
||||||
|
@ -18070,9 +17808,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
}
|
}
|
||||||
BREAK;
|
BREAK;
|
||||||
CASE(OP_mod):
|
CASE(OP_mod):
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
CASE(OP_math_mod):
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
JSValue op1, op2;
|
JSValue op1, op2;
|
||||||
op1 = sp[-2];
|
op1 = sp[-2];
|
||||||
|
@ -18254,29 +17989,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
|
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
|
||||||
uint32_t v1, v2;
|
uint32_t v1, v2;
|
||||||
v1 = JS_VALUE_GET_INT(op1);
|
v1 = JS_VALUE_GET_INT(op1);
|
||||||
v2 = JS_VALUE_GET_INT(op2);
|
v2 = JS_VALUE_GET_INT(op2) & 0x1f;
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
{
|
|
||||||
int64_t r;
|
|
||||||
if (unlikely(sf->js_mode & JS_MODE_MATH)) {
|
|
||||||
if (v2 > 0x1f)
|
|
||||||
goto shl_slow;
|
|
||||||
r = (int64_t)v1 << v2;
|
|
||||||
if ((int)r != r)
|
|
||||||
goto shl_slow;
|
|
||||||
} else {
|
|
||||||
v2 &= 0x1f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
v2 &= 0x1f;
|
|
||||||
#endif
|
|
||||||
sp[-2] = JS_NewInt32(ctx, v1 << v2);
|
sp[-2] = JS_NewInt32(ctx, v1 << v2);
|
||||||
sp--;
|
sp--;
|
||||||
} else {
|
} else {
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
shl_slow:
|
|
||||||
#endif
|
|
||||||
if (js_binary_logic_slow(ctx, sp, opcode))
|
if (js_binary_logic_slow(ctx, sp, opcode))
|
||||||
goto exception;
|
goto exception;
|
||||||
sp--;
|
sp--;
|
||||||
|
@ -18314,10 +18030,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
v2 = JS_VALUE_GET_INT(op2);
|
v2 = JS_VALUE_GET_INT(op2);
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
if (unlikely(v2 > 0x1f)) {
|
if (unlikely(v2 > 0x1f)) {
|
||||||
if (unlikely(sf->js_mode & JS_MODE_MATH))
|
v2 &= 0x1f;
|
||||||
goto sar_slow;
|
|
||||||
else
|
|
||||||
v2 &= 0x1f;
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
v2 &= 0x1f;
|
v2 &= 0x1f;
|
||||||
|
@ -18326,9 +18039,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
(int)JS_VALUE_GET_INT(op1) >> v2);
|
(int)JS_VALUE_GET_INT(op1) >> v2);
|
||||||
sp--;
|
sp--;
|
||||||
} else {
|
} else {
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
sar_slow:
|
|
||||||
#endif
|
|
||||||
if (js_binary_logic_slow(ctx, sp, opcode))
|
if (js_binary_logic_slow(ctx, sp, opcode))
|
||||||
goto exception;
|
goto exception;
|
||||||
sp--;
|
sp--;
|
||||||
|
@ -19797,9 +19507,6 @@ enum {
|
||||||
TOK_AND_ASSIGN,
|
TOK_AND_ASSIGN,
|
||||||
TOK_XOR_ASSIGN,
|
TOK_XOR_ASSIGN,
|
||||||
TOK_OR_ASSIGN,
|
TOK_OR_ASSIGN,
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
TOK_MATH_POW_ASSIGN,
|
|
||||||
#endif
|
|
||||||
TOK_POW_ASSIGN,
|
TOK_POW_ASSIGN,
|
||||||
TOK_LAND_ASSIGN,
|
TOK_LAND_ASSIGN,
|
||||||
TOK_LOR_ASSIGN,
|
TOK_LOR_ASSIGN,
|
||||||
|
@ -19819,9 +19526,6 @@ enum {
|
||||||
TOK_STRICT_NEQ,
|
TOK_STRICT_NEQ,
|
||||||
TOK_LAND,
|
TOK_LAND,
|
||||||
TOK_LOR,
|
TOK_LOR,
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
TOK_MATH_POW,
|
|
||||||
#endif
|
|
||||||
TOK_POW,
|
TOK_POW,
|
||||||
TOK_ARROW,
|
TOK_ARROW,
|
||||||
TOK_ELLIPSIS,
|
TOK_ELLIPSIS,
|
||||||
|
@ -20906,11 +20610,6 @@ static __exception int next_token(JSParseState *s)
|
||||||
ATOD_ACCEPT_UNDERSCORES;
|
ATOD_ACCEPT_UNDERSCORES;
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
flags |= ATOD_ACCEPT_SUFFIX;
|
flags |= ATOD_ACCEPT_SUFFIX;
|
||||||
if (s->cur_func->js_mode & JS_MODE_MATH) {
|
|
||||||
flags |= ATOD_MODE_BIGINT;
|
|
||||||
if (s->cur_func->js_mode & JS_MODE_MATH)
|
|
||||||
flags |= ATOD_TYPE_BIG_FLOAT;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
radix = 0;
|
radix = 0;
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
|
@ -21076,33 +20775,6 @@ static __exception int next_token(JSParseState *s)
|
||||||
goto def_token;
|
goto def_token;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
/* in math mode, '^' is the power operator. '^^' is always the
|
|
||||||
xor operator and '**' is always the power operator */
|
|
||||||
case '^':
|
|
||||||
if (p[1] == '=') {
|
|
||||||
p += 2;
|
|
||||||
if (s->cur_func->js_mode & JS_MODE_MATH)
|
|
||||||
s->token.val = TOK_MATH_POW_ASSIGN;
|
|
||||||
else
|
|
||||||
s->token.val = TOK_XOR_ASSIGN;
|
|
||||||
} else if (p[1] == '^') {
|
|
||||||
if (p[2] == '=') {
|
|
||||||
p += 3;
|
|
||||||
s->token.val = TOK_XOR_ASSIGN;
|
|
||||||
} else {
|
|
||||||
p += 2;
|
|
||||||
s->token.val = '^';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
p++;
|
|
||||||
if (s->cur_func->js_mode & JS_MODE_MATH)
|
|
||||||
s->token.val = TOK_MATH_POW;
|
|
||||||
else
|
|
||||||
s->token.val = '^';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
case '^':
|
case '^':
|
||||||
if (p[1] == '=') {
|
if (p[1] == '=') {
|
||||||
p += 2;
|
p += 2;
|
||||||
|
@ -21111,7 +20783,6 @@ static __exception int next_token(JSParseState *s)
|
||||||
goto def_token;
|
goto def_token;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case '|':
|
case '|':
|
||||||
if (p[1] == '=') {
|
if (p[1] == '=') {
|
||||||
p += 2;
|
p += 2;
|
||||||
|
@ -25143,24 +24814,6 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (parse_flags & (PF_POW_ALLOWED | PF_POW_FORBIDDEN)) {
|
if (parse_flags & (PF_POW_ALLOWED | PF_POW_FORBIDDEN)) {
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
if (s->token.val == TOK_POW || s->token.val == TOK_MATH_POW) {
|
|
||||||
/* Extended exponentiation syntax rules: we extend the ES7
|
|
||||||
grammar in order to have more intuitive semantics:
|
|
||||||
-2**2 evaluates to -4. */
|
|
||||||
if (!(s->cur_func->js_mode & JS_MODE_MATH)) {
|
|
||||||
if (parse_flags & PF_POW_FORBIDDEN) {
|
|
||||||
JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (next_token(s))
|
|
||||||
return -1;
|
|
||||||
if (js_parse_unary(s, PF_POW_ALLOWED))
|
|
||||||
return -1;
|
|
||||||
emit_op(s, OP_pow);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (s->token.val == TOK_POW) {
|
if (s->token.val == TOK_POW) {
|
||||||
/* Strict ES7 exponentiation syntax rules: To solve
|
/* Strict ES7 exponentiation syntax rules: To solve
|
||||||
conficting semantics between different implementations
|
conficting semantics between different implementations
|
||||||
|
@ -25177,7 +24830,6 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
|
||||||
return -1;
|
return -1;
|
||||||
emit_op(s, OP_pow);
|
emit_op(s, OP_pow);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -25206,12 +24858,7 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
|
||||||
opcode = OP_div;
|
opcode = OP_div;
|
||||||
break;
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
#ifdef CONFIG_BIGNUM
|
opcode = OP_mod;
|
||||||
if (s->cur_func->js_mode & JS_MODE_MATH)
|
|
||||||
opcode = OP_math_mod;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
opcode = OP_mod;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -25610,12 +25257,6 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
|
||||||
OP_pow,
|
OP_pow,
|
||||||
};
|
};
|
||||||
op = assign_opcodes[op - TOK_MUL_ASSIGN];
|
op = assign_opcodes[op - TOK_MUL_ASSIGN];
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
if (s->cur_func->js_mode & JS_MODE_MATH) {
|
|
||||||
if (op == OP_mod)
|
|
||||||
op = OP_math_mod;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
emit_op(s, op);
|
emit_op(s, op);
|
||||||
}
|
}
|
||||||
put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE);
|
put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE);
|
||||||
|
@ -29312,10 +28953,7 @@ static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionB
|
||||||
printf(" mode:");
|
printf(" mode:");
|
||||||
if (b->js_mode & JS_MODE_STRICT)
|
if (b->js_mode & JS_MODE_STRICT)
|
||||||
printf(" strict");
|
printf(" strict");
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
if (b->js_mode & JS_MODE_MATH)
|
|
||||||
printf(" math");
|
|
||||||
#endif
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
if (b->arg_count && b->vardefs) {
|
if (b->arg_count && b->vardefs) {
|
||||||
|
@ -32897,11 +32535,6 @@ static __exception int js_parse_directives(JSParseState *s)
|
||||||
else if (!strcmp(str, "use strip")) {
|
else if (!strcmp(str, "use strip")) {
|
||||||
s->cur_func->js_mode |= JS_MODE_STRIP;
|
s->cur_func->js_mode |= JS_MODE_STRIP;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
else if (s->ctx->bignum_ext && !strcmp(str, "use math")) {
|
|
||||||
s->cur_func->js_mode |= JS_MODE_MATH;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return js_parse_seek_token(s, &pos);
|
return js_parse_seek_token(s, &pos);
|
||||||
|
@ -52539,15 +52172,12 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
case JS_CLASS_BIG_INT64_ARRAY:
|
case JS_CLASS_BIG_INT64_ARRAY:
|
||||||
if (is_bigint || (is_math_mode(ctx) && is_int &&
|
if (is_bigint) {
|
||||||
v64 >= -MAX_SAFE_INTEGER &&
|
|
||||||
v64 <= MAX_SAFE_INTEGER)) {
|
|
||||||
goto scan64;
|
goto scan64;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JS_CLASS_BIG_UINT64_ARRAY:
|
case JS_CLASS_BIG_UINT64_ARRAY:
|
||||||
if (is_bigint || (is_math_mode(ctx) && is_int &&
|
if (is_bigint) {
|
||||||
v64 >= 0 && v64 <= MAX_SAFE_INTEGER)) {
|
|
||||||
const uint64_t *pv;
|
const uint64_t *pv;
|
||||||
uint64_t v;
|
uint64_t v;
|
||||||
scan64:
|
scan64:
|
||||||
|
|
|
@ -1,256 +0,0 @@
|
||||||
"use math";
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function assert(actual, expected, message) {
|
|
||||||
if (arguments.length == 1)
|
|
||||||
expected = true;
|
|
||||||
|
|
||||||
if (actual === expected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (actual !== null && expected !== null
|
|
||||||
&& typeof actual == 'object' && typeof expected == 'object'
|
|
||||||
&& actual.toString() === expected.toString())
|
|
||||||
return;
|
|
||||||
|
|
||||||
throw Error("assertion failed: got |" + actual + "|" +
|
|
||||||
", expected |" + expected + "|" +
|
|
||||||
(message ? " (" + message + ")" : ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertThrows(err, func)
|
|
||||||
{
|
|
||||||
var ex;
|
|
||||||
ex = false;
|
|
||||||
try {
|
|
||||||
func();
|
|
||||||
} catch(e) {
|
|
||||||
ex = true;
|
|
||||||
assert(e instanceof err);
|
|
||||||
}
|
|
||||||
assert(ex, true, "exception expected");
|
|
||||||
}
|
|
||||||
|
|
||||||
// load more elaborate version of assert if available
|
|
||||||
try { __loadScript("test_assert.js"); } catch(e) {}
|
|
||||||
|
|
||||||
/*----------------*/
|
|
||||||
|
|
||||||
function pow(a, n)
|
|
||||||
{
|
|
||||||
var r, i;
|
|
||||||
r = 1;
|
|
||||||
for(i = 0; i < n; i++)
|
|
||||||
r *= a;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_integer()
|
|
||||||
{
|
|
||||||
var a, r;
|
|
||||||
a = pow(3, 100);
|
|
||||||
assert((a - 1) != a);
|
|
||||||
assert(a == 515377520732011331036461129765621272702107522001);
|
|
||||||
assert(a == 0x5a4653ca673768565b41f775d6947d55cf3813d1);
|
|
||||||
assert(Integer.isInteger(1) === true);
|
|
||||||
assert(Integer.isInteger(1.0) === false);
|
|
||||||
|
|
||||||
assert(Integer.floorLog2(0) === -1);
|
|
||||||
assert(Integer.floorLog2(7) === 2);
|
|
||||||
|
|
||||||
r = 1 << 31;
|
|
||||||
assert(r, 2147483648, "1 << 31 === 2147483648");
|
|
||||||
|
|
||||||
r = 1 << 32;
|
|
||||||
assert(r, 4294967296, "1 << 32 === 4294967296");
|
|
||||||
|
|
||||||
r = (1 << 31) < 0;
|
|
||||||
assert(r, false, "(1 << 31) < 0 === false");
|
|
||||||
|
|
||||||
assert(typeof 1 === "number");
|
|
||||||
assert(typeof 9007199254740991 === "number");
|
|
||||||
assert(typeof 9007199254740992 === "bigint");
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_float()
|
|
||||||
{
|
|
||||||
assert(typeof 1.0 === "bigfloat");
|
|
||||||
assert(1 == 1.0);
|
|
||||||
assert(1 !== 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* jscalc tests */
|
|
||||||
|
|
||||||
function test_modulo()
|
|
||||||
{
|
|
||||||
var i, p, a, b;
|
|
||||||
|
|
||||||
/* Euclidian modulo operator */
|
|
||||||
assert((-3) % 2 == 1);
|
|
||||||
assert(3 % (-2) == 1);
|
|
||||||
|
|
||||||
p = 101;
|
|
||||||
for(i = 1; i < p; i++) {
|
|
||||||
a = Integer.invmod(i, p);
|
|
||||||
assert(a >= 0 && a < p);
|
|
||||||
assert((i * a) % p == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(Integer.isPrime(2^107-1));
|
|
||||||
assert(!Integer.isPrime((2^107-1) * (2^89-1)));
|
|
||||||
a = Integer.factor((2^89-1)*2^3*11*13^2*1009);
|
|
||||||
assert(a == [ 2,2,2,11,13,13,1009,618970019642690137449562111 ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_fraction()
|
|
||||||
{
|
|
||||||
assert((1/3 + 1).toString(), "4/3")
|
|
||||||
assert((2/3)^30, 1073741824/205891132094649);
|
|
||||||
assert(1/3 < 2/3);
|
|
||||||
assert(1/3 < 1);
|
|
||||||
assert(1/3 == 1.0/3);
|
|
||||||
assert(1.0/3 < 2/3);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_mod()
|
|
||||||
{
|
|
||||||
var a, b, p;
|
|
||||||
|
|
||||||
a = Mod(3, 101);
|
|
||||||
b = Mod(-1, 101);
|
|
||||||
assert((a + b) == Mod(2, 101));
|
|
||||||
assert(a ^ 100 == Mod(1, 101));
|
|
||||||
|
|
||||||
p = 2 ^ 607 - 1; /* mersenne prime */
|
|
||||||
a = Mod(3, p) ^ (p - 1);
|
|
||||||
assert(a == Mod(1, p));
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_polynomial()
|
|
||||||
{
|
|
||||||
var a, b, q, r, t, i;
|
|
||||||
a = (1 + X) ^ 4;
|
|
||||||
assert(a == X^4+4*X^3+6*X^2+4*X+1);
|
|
||||||
|
|
||||||
r = (1 + X);
|
|
||||||
q = (1+X+X^2);
|
|
||||||
b = (1 - X^2);
|
|
||||||
a = q * b + r;
|
|
||||||
t = Polynomial.divrem(a, b);
|
|
||||||
assert(t[0] == q);
|
|
||||||
assert(t[1] == r);
|
|
||||||
|
|
||||||
a = 1 + 2*X + 3*X^2;
|
|
||||||
assert(a.apply(0.1) == 1.23);
|
|
||||||
|
|
||||||
a = 1-2*X^2+2*X^3;
|
|
||||||
assert(deriv(a) == (6*X^2-4*X));
|
|
||||||
assert(deriv(integ(a)) == a);
|
|
||||||
|
|
||||||
a = (X-1)*(X-2)*(X-3)*(X-4)*(X-0.1);
|
|
||||||
r = polroots(a);
|
|
||||||
for(i = 0; i < r.length; i++) {
|
|
||||||
b = abs(a.apply(r[i]));
|
|
||||||
assert(b <= 1e-13);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_poly_mod()
|
|
||||||
{
|
|
||||||
var a, p;
|
|
||||||
|
|
||||||
/* modulo using polynomials */
|
|
||||||
p = X^2 + X + 1;
|
|
||||||
a = PolyMod(3+X, p) ^ 10;
|
|
||||||
assert(a == PolyMod(-3725*X-18357, p));
|
|
||||||
|
|
||||||
a = PolyMod(1/X, 1+X^2);
|
|
||||||
assert(a == PolyMod(-X, X^2+1));
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_rfunc()
|
|
||||||
{
|
|
||||||
var a;
|
|
||||||
a = (X+1)/((X+1)*(X-1));
|
|
||||||
assert(a == 1/(X-1));
|
|
||||||
a = (X + 2) / (X - 2);
|
|
||||||
assert(a.apply(1/3) == -7/5);
|
|
||||||
|
|
||||||
assert(deriv((X^2-X+1)/(X-1)) == (X^2-2*X)/(X^2-2*X+1));
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_series()
|
|
||||||
{
|
|
||||||
var a, b;
|
|
||||||
a = 1+X+O(X^5);
|
|
||||||
b = a.inverse();
|
|
||||||
assert(b == 1-X+X^2-X^3+X^4+O(X^5));
|
|
||||||
assert(deriv(b) == -1+2*X-3*X^2+4*X^3+O(X^4));
|
|
||||||
assert(deriv(integ(b)) == b);
|
|
||||||
|
|
||||||
a = Series(1/(1-X), 5);
|
|
||||||
assert(a == 1+X+X^2+X^3+X^4+O(X^5));
|
|
||||||
b = a.apply(0.1);
|
|
||||||
assert(b == 1.1111);
|
|
||||||
|
|
||||||
assert(exp(3*X^2+O(X^10)) == 1+3*X^2+9/2*X^4+9/2*X^6+27/8*X^8+O(X^10));
|
|
||||||
assert(sin(X+O(X^6)) == X-1/6*X^3+1/120*X^5+O(X^6));
|
|
||||||
assert(cos(X+O(X^6)) == 1-1/2*X^2+1/24*X^4+O(X^6));
|
|
||||||
assert(tan(X+O(X^8)) == X+1/3*X^3+2/15*X^5+17/315*X^7+O(X^8));
|
|
||||||
assert((1+X+O(X^6))^(2+X) == 1+2*X+2*X^2+3/2*X^3+5/6*X^4+5/12*X^5+O(X^6));
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_matrix()
|
|
||||||
{
|
|
||||||
var a, b, r;
|
|
||||||
a = [[1, 2],[3, 4]];
|
|
||||||
b = [3, 4];
|
|
||||||
r = a * b;
|
|
||||||
assert(r == [11, 25]);
|
|
||||||
r = (a^-1) * 2;
|
|
||||||
assert(r == [[-4, 2],[3, -1]]);
|
|
||||||
|
|
||||||
assert(norm2([1,2,3]) == 14);
|
|
||||||
|
|
||||||
assert(diag([1,2,3]) == [ [ 1, 0, 0 ], [ 0, 2, 0 ], [ 0, 0, 3 ] ]);
|
|
||||||
assert(trans(a) == [ [ 1, 3 ], [ 2, 4 ] ]);
|
|
||||||
assert(trans([1,2,3]) == [[1,2,3]]);
|
|
||||||
assert(trace(a) == 5);
|
|
||||||
|
|
||||||
assert(charpoly(Matrix.hilbert(4)) == X^4-176/105*X^3+3341/12600*X^2-41/23625*X+1/6048000);
|
|
||||||
assert(det(Matrix.hilbert(4)) == 1/6048000);
|
|
||||||
|
|
||||||
a = [[1,2,1],[-2,-3,1],[3,5,0]];
|
|
||||||
assert(rank(a) == 2);
|
|
||||||
assert(ker(a) == [ [ 5 ], [ -3 ], [ 1 ] ]);
|
|
||||||
|
|
||||||
assert(dp([1, 2, 3], [3, -4, -7]) === -26);
|
|
||||||
assert(cp([1, 2, 3], [3, -4, -7]) == [ -2, 16, -10 ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assert_eq(a, ref)
|
|
||||||
{
|
|
||||||
assert(abs(a / ref - 1.0) <= 1e-15);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_trig()
|
|
||||||
{
|
|
||||||
assert_eq(sin(1/2), 0.479425538604203);
|
|
||||||
assert_eq(sin(2+3*I), 9.154499146911428-4.168906959966565*I);
|
|
||||||
assert_eq(cos(2+3*I), -4.189625690968807-9.109227893755337*I);
|
|
||||||
assert_eq((2+0.5*I)^(1.1-0.5*I), 2.494363021357619-0.23076804554558092*I);
|
|
||||||
assert_eq(sqrt(2*I), 1 + I);
|
|
||||||
}
|
|
||||||
|
|
||||||
test_integer();
|
|
||||||
test_float();
|
|
||||||
|
|
||||||
test_modulo();
|
|
||||||
test_fraction();
|
|
||||||
test_mod();
|
|
||||||
test_polynomial();
|
|
||||||
test_poly_mod();
|
|
||||||
test_rfunc();
|
|
||||||
test_series();
|
|
||||||
test_matrix();
|
|
||||||
test_trig();
|
|
Loading…
Reference in a new issue