mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 00:02:28 +00:00
Reduce build latency and fix old cpu bugs
This commit is contained in:
parent
df8ab0aa0c
commit
533f3d1ef1
69 changed files with 43069 additions and 43683 deletions
459
third_party/quickjs/eq.c
vendored
Normal file
459
third_party/quickjs/eq.c
vendored
Normal file
|
@ -0,0 +1,459 @@
|
|||
/*
|
||||
* QuickJS Javascript Engine
|
||||
*
|
||||
* Copyright (c) 2017-2021 Fabrice Bellard
|
||||
* Copyright (c) 2017-2021 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "third_party/quickjs/internal.h"
|
||||
#include "third_party/quickjs/libregexp.h"
|
||||
#include "third_party/quickjs/quickjs.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
QuickJS (MIT License)\\n\
|
||||
Copyright (c) 2017-2021 Fabrice Bellard\\n\
|
||||
Copyright (c) 2017-2021 Charlie Gordon\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
/* clang-format off */
|
||||
|
||||
/* XXX: Should take JSValueConst arguments */
|
||||
BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
|
||||
JSStrictEqModeEnum eq_mode)
|
||||
{
|
||||
BOOL res;
|
||||
int tag1, tag2;
|
||||
double d1, d2;
|
||||
tag1 = JS_VALUE_GET_NORM_TAG(op1);
|
||||
tag2 = JS_VALUE_GET_NORM_TAG(op2);
|
||||
switch(tag1) {
|
||||
case JS_TAG_BOOL:
|
||||
if (tag1 != tag2) {
|
||||
res = FALSE;
|
||||
} else {
|
||||
res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2);
|
||||
goto done_no_free;
|
||||
}
|
||||
break;
|
||||
case JS_TAG_NULL:
|
||||
case JS_TAG_UNDEFINED:
|
||||
res = (tag1 == tag2);
|
||||
break;
|
||||
case JS_TAG_STRING:
|
||||
{
|
||||
JSString *p1, *p2;
|
||||
if (tag1 != tag2) {
|
||||
res = FALSE;
|
||||
} else {
|
||||
p1 = JS_VALUE_GET_STRING(op1);
|
||||
p2 = JS_VALUE_GET_STRING(op2);
|
||||
res = (js_string_compare(ctx, p1, p2) == 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JS_TAG_SYMBOL:
|
||||
{
|
||||
JSAtomStruct *p1, *p2;
|
||||
if (tag1 != tag2) {
|
||||
res = FALSE;
|
||||
} else {
|
||||
p1 = JS_VALUE_GET_PTR(op1);
|
||||
p2 = JS_VALUE_GET_PTR(op2);
|
||||
res = (p1 == p2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JS_TAG_OBJECT:
|
||||
if (tag1 != tag2)
|
||||
res = FALSE;
|
||||
else
|
||||
res = JS_VALUE_GET_OBJ(op1) == JS_VALUE_GET_OBJ(op2);
|
||||
break;
|
||||
case JS_TAG_INT:
|
||||
d1 = JS_VALUE_GET_INT(op1);
|
||||
if (tag2 == JS_TAG_INT) {
|
||||
d2 = JS_VALUE_GET_INT(op2);
|
||||
goto number_test;
|
||||
} else if (tag2 == JS_TAG_FLOAT64) {
|
||||
d2 = JS_VALUE_GET_FLOAT64(op2);
|
||||
goto number_test;
|
||||
} else {
|
||||
res = FALSE;
|
||||
}
|
||||
break;
|
||||
case JS_TAG_FLOAT64:
|
||||
d1 = JS_VALUE_GET_FLOAT64(op1);
|
||||
if (tag2 == JS_TAG_FLOAT64) {
|
||||
d2 = JS_VALUE_GET_FLOAT64(op2);
|
||||
} else if (tag2 == JS_TAG_INT) {
|
||||
d2 = JS_VALUE_GET_INT(op2);
|
||||
} else {
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
number_test:
|
||||
if (UNLIKELY(eq_mode >= JS_EQ_SAME_VALUE)) {
|
||||
JSFloat64Union u1, u2;
|
||||
/* NaN is not always normalized, so this test is necessary */
|
||||
if (isnan(d1) || isnan(d2)) {
|
||||
res = isnan(d1) == isnan(d2);
|
||||
} else if (eq_mode == JS_EQ_SAME_VALUE_ZERO) {
|
||||
res = (d1 == d2); /* +0 == -0 */
|
||||
} else {
|
||||
u1.d = d1;
|
||||
u2.d = d2;
|
||||
res = (u1.u64 == u2.u64); /* +0 != -0 */
|
||||
}
|
||||
} else {
|
||||
res = (d1 == d2); /* if NaN return false and +0 == -0 */
|
||||
}
|
||||
goto done_no_free;
|
||||
#ifdef CONFIG_BIGNUM
|
||||
case JS_TAG_BIG_INT:
|
||||
{
|
||||
bf_t a_s, *a, b_s, *b;
|
||||
if (tag1 != tag2) {
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
a = JS_ToBigFloat(ctx, &a_s, op1);
|
||||
b = JS_ToBigFloat(ctx, &b_s, op2);
|
||||
res = bf_cmp_eq(a, b);
|
||||
if (a == &a_s)
|
||||
bf_delete(a);
|
||||
if (b == &b_s)
|
||||
bf_delete(b);
|
||||
}
|
||||
break;
|
||||
case JS_TAG_BIG_FLOAT:
|
||||
{
|
||||
JSBigFloat *p1, *p2;
|
||||
const bf_t *a, *b;
|
||||
if (tag1 != tag2) {
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
p1 = JS_VALUE_GET_PTR(op1);
|
||||
p2 = JS_VALUE_GET_PTR(op2);
|
||||
a = &p1->num;
|
||||
b = &p2->num;
|
||||
if (UNLIKELY(eq_mode >= JS_EQ_SAME_VALUE)) {
|
||||
if (eq_mode == JS_EQ_SAME_VALUE_ZERO &&
|
||||
a->expn == BF_EXP_ZERO && b->expn == BF_EXP_ZERO) {
|
||||
res = TRUE;
|
||||
} else {
|
||||
res = (bf_cmp_full(a, b) == 0);
|
||||
}
|
||||
} else {
|
||||
res = bf_cmp_eq(a, b);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JS_TAG_BIG_DECIMAL:
|
||||
{
|
||||
JSBigDecimal *p1, *p2;
|
||||
const bfdec_t *a, *b;
|
||||
if (tag1 != tag2) {
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
p1 = JS_VALUE_GET_PTR(op1);
|
||||
p2 = JS_VALUE_GET_PTR(op2);
|
||||
a = &p1->num;
|
||||
b = &p2->num;
|
||||
res = bfdec_cmp_eq(a, b);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
JS_FreeValue(ctx, op1);
|
||||
JS_FreeValue(ctx, op2);
|
||||
done_no_free:
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2)
|
||||
{
|
||||
return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
|
||||
}
|
||||
|
||||
BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2)
|
||||
{
|
||||
return js_strict_eq2(ctx,
|
||||
JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),
|
||||
JS_EQ_SAME_VALUE);
|
||||
}
|
||||
|
||||
BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2)
|
||||
{
|
||||
return js_strict_eq2(ctx,
|
||||
JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),
|
||||
JS_EQ_SAME_VALUE_ZERO);
|
||||
}
|
||||
|
||||
int js_strict_eq_slow(JSContext *ctx, JSValue *sp, BOOL is_neq)
|
||||
{
|
||||
BOOL res;
|
||||
res = js_strict_eq(ctx, sp[-2], sp[-1]);
|
||||
sp[-2] = JS_NewBool(ctx, res ^ is_neq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL tag_is_number(uint32_t tag)
|
||||
{
|
||||
return (tag == JS_TAG_INT || tag == JS_TAG_BIG_INT ||
|
||||
tag == JS_TAG_FLOAT64 || tag == JS_TAG_BIG_FLOAT ||
|
||||
tag == JS_TAG_BIG_DECIMAL);
|
||||
}
|
||||
|
||||
static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj)
|
||||
{
|
||||
JSObject *p;
|
||||
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
|
||||
return FALSE;
|
||||
p = JS_VALUE_GET_OBJ(obj);
|
||||
return p->is_HTMLDDA;
|
||||
}
|
||||
|
||||
int js_eq_slow(JSContext *ctx, JSValue *sp, BOOL is_neq)
|
||||
{
|
||||
#ifdef CONFIG_BIGNUM
|
||||
JSValue op1, op2, ret;
|
||||
int res;
|
||||
uint32_t tag1, tag2;
|
||||
op1 = sp[-2];
|
||||
op2 = sp[-1];
|
||||
redo:
|
||||
tag1 = JS_VALUE_GET_NORM_TAG(op1);
|
||||
tag2 = JS_VALUE_GET_NORM_TAG(op2);
|
||||
if (tag_is_number(tag1) && tag_is_number(tag2)) {
|
||||
if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) {
|
||||
res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2);
|
||||
} else if ((tag1 == JS_TAG_FLOAT64 &&
|
||||
(tag2 == JS_TAG_INT || tag2 == JS_TAG_FLOAT64)) ||
|
||||
(tag2 == JS_TAG_FLOAT64 &&
|
||||
(tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64))) {
|
||||
double d1, d2;
|
||||
if (tag1 == JS_TAG_FLOAT64) {
|
||||
d1 = JS_VALUE_GET_FLOAT64(op1);
|
||||
} else {
|
||||
d1 = JS_VALUE_GET_INT(op1);
|
||||
}
|
||||
if (tag2 == JS_TAG_FLOAT64) {
|
||||
d2 = JS_VALUE_GET_FLOAT64(op2);
|
||||
} else {
|
||||
d2 = JS_VALUE_GET_INT(op2);
|
||||
}
|
||||
res = (d1 == d2);
|
||||
} else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
|
||||
res = ctx->rt->bigdecimal_ops.compare(ctx, OP_eq, op1, op2);
|
||||
if (res < 0)
|
||||
goto exception;
|
||||
} else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
|
||||
res = ctx->rt->bigfloat_ops.compare(ctx, OP_eq, op1, op2);
|
||||
if (res < 0)
|
||||
goto exception;
|
||||
} else {
|
||||
res = ctx->rt->bigint_ops.compare(ctx, OP_eq, op1, op2);
|
||||
if (res < 0)
|
||||
goto exception;
|
||||
}
|
||||
} else if (tag1 == tag2) {
|
||||
if (tag1 == JS_TAG_OBJECT) {
|
||||
/* try the fallback operator */
|
||||
res = js_call_binary_op_fallback(ctx, &ret, op1, op2,
|
||||
is_neq ? OP_neq : OP_eq,
|
||||
FALSE, HINT_NONE);
|
||||
if (res != 0) {
|
||||
JS_FreeValue(ctx, op1);
|
||||
JS_FreeValue(ctx, op2);
|
||||
if (res < 0) {
|
||||
goto exception;
|
||||
} else {
|
||||
sp[-2] = ret;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
|
||||
} else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||
|
||||
(tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {
|
||||
res = TRUE;
|
||||
} else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) ||
|
||||
(tag2 == JS_TAG_STRING && tag_is_number(tag1))) {
|
||||
if ((tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) &&
|
||||
!is_math_mode(ctx)) {
|
||||
if (tag1 == JS_TAG_STRING) {
|
||||
op1 = JS_StringToBigInt(ctx, op1);
|
||||
if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)
|
||||
goto invalid_bigint_string;
|
||||
}
|
||||
if (tag2 == JS_TAG_STRING) {
|
||||
op2 = JS_StringToBigInt(ctx, op2);
|
||||
if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT) {
|
||||
invalid_bigint_string:
|
||||
JS_FreeValue(ctx, op1);
|
||||
JS_FreeValue(ctx, op2);
|
||||
res = FALSE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
op1 = JS_ToNumericFree(ctx, op1);
|
||||
if (JS_IsException(op1)) {
|
||||
JS_FreeValue(ctx, op2);
|
||||
goto exception;
|
||||
}
|
||||
op2 = JS_ToNumericFree(ctx, op2);
|
||||
if (JS_IsException(op2)) {
|
||||
JS_FreeValue(ctx, op1);
|
||||
goto exception;
|
||||
}
|
||||
}
|
||||
res = js_strict_eq(ctx, op1, op2);
|
||||
} else if (tag1 == JS_TAG_BOOL) {
|
||||
op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));
|
||||
goto redo;
|
||||
} else if (tag2 == JS_TAG_BOOL) {
|
||||
op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2));
|
||||
goto redo;
|
||||
} else if ((tag1 == JS_TAG_OBJECT &&
|
||||
(tag_is_number(tag2) || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) ||
|
||||
(tag2 == JS_TAG_OBJECT &&
|
||||
(tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) {
|
||||
/* try the fallback operator */
|
||||
res = js_call_binary_op_fallback(ctx, &ret, op1, op2,
|
||||
is_neq ? OP_neq : OP_eq,
|
||||
FALSE, HINT_NONE);
|
||||
if (res != 0) {
|
||||
JS_FreeValue(ctx, op1);
|
||||
JS_FreeValue(ctx, op2);
|
||||
if (res < 0) {
|
||||
goto exception;
|
||||
} else {
|
||||
sp[-2] = ret;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
|
||||
if (JS_IsException(op1)) {
|
||||
JS_FreeValue(ctx, op2);
|
||||
goto exception;
|
||||
}
|
||||
op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
|
||||
if (JS_IsException(op2)) {
|
||||
JS_FreeValue(ctx, op1);
|
||||
goto exception;
|
||||
}
|
||||
goto redo;
|
||||
} else {
|
||||
/* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */
|
||||
if ((JS_IsHTMLDDA(ctx, op1) &&
|
||||
(tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||
|
||||
(JS_IsHTMLDDA(ctx, op2) &&
|
||||
(tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {
|
||||
res = TRUE;
|
||||
} else {
|
||||
res = FALSE;
|
||||
}
|
||||
JS_FreeValue(ctx, op1);
|
||||
JS_FreeValue(ctx, op2);
|
||||
}
|
||||
done:
|
||||
sp[-2] = JS_NewBool(ctx, res ^ is_neq);
|
||||
return 0;
|
||||
exception:
|
||||
sp[-2] = JS_UNDEFINED;
|
||||
sp[-1] = JS_UNDEFINED;
|
||||
return -1;
|
||||
#else /* CONFIG_BIGNUM */
|
||||
JSValue op1, op2;
|
||||
int tag1, tag2;
|
||||
BOOL res;
|
||||
op1 = sp[-2];
|
||||
op2 = sp[-1];
|
||||
redo:
|
||||
tag1 = JS_VALUE_GET_NORM_TAG(op1);
|
||||
tag2 = JS_VALUE_GET_NORM_TAG(op2);
|
||||
if (tag1 == tag2 ||
|
||||
(tag1 == JS_TAG_INT && tag2 == JS_TAG_FLOAT64) ||
|
||||
(tag2 == JS_TAG_INT && tag1 == JS_TAG_FLOAT64)) {
|
||||
res = js_strict_eq(ctx, op1, op2);
|
||||
} else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||
|
||||
(tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {
|
||||
res = TRUE;
|
||||
} else if ((tag1 == JS_TAG_STRING && (tag2 == JS_TAG_INT ||
|
||||
tag2 == JS_TAG_FLOAT64)) ||
|
||||
(tag2 == JS_TAG_STRING && (tag1 == JS_TAG_INT ||
|
||||
tag1 == JS_TAG_FLOAT64))) {
|
||||
double d1;
|
||||
double d2;
|
||||
if (JS_ToFloat64Free(ctx, &d1, op1)) {
|
||||
JS_FreeValue(ctx, op2);
|
||||
goto exception;
|
||||
}
|
||||
if (JS_ToFloat64Free(ctx, &d2, op2))
|
||||
goto exception;
|
||||
res = (d1 == d2);
|
||||
} else if (tag1 == JS_TAG_BOOL) {
|
||||
op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));
|
||||
goto redo;
|
||||
} else if (tag2 == JS_TAG_BOOL) {
|
||||
op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2));
|
||||
goto redo;
|
||||
} else if (tag1 == JS_TAG_OBJECT &&
|
||||
(tag2 == JS_TAG_INT || tag2 == JS_TAG_FLOAT64 || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) {
|
||||
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
|
||||
if (JS_IsException(op1)) {
|
||||
JS_FreeValue(ctx, op2);
|
||||
goto exception;
|
||||
}
|
||||
goto redo;
|
||||
} else if (tag2 == JS_TAG_OBJECT &&
|
||||
(tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64 || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL)) {
|
||||
op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
|
||||
if (JS_IsException(op2)) {
|
||||
JS_FreeValue(ctx, op1);
|
||||
goto exception;
|
||||
}
|
||||
goto redo;
|
||||
} else {
|
||||
/* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */
|
||||
if ((JS_IsHTMLDDA(ctx, op1) &&
|
||||
(tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||
|
||||
(JS_IsHTMLDDA(ctx, op2) &&
|
||||
(tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {
|
||||
res = TRUE;
|
||||
} else {
|
||||
res = FALSE;
|
||||
}
|
||||
JS_FreeValue(ctx, op1);
|
||||
JS_FreeValue(ctx, op2);
|
||||
}
|
||||
sp[-2] = JS_NewBool(ctx, res ^ is_neq);
|
||||
return 0;
|
||||
exception:
|
||||
sp[-2] = JS_UNDEFINED;
|
||||
sp[-1] = JS_UNDEFINED;
|
||||
return -1;
|
||||
#endif /* CONFIG_BIGNUM */
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue