diff --git a/Makefile b/Makefile index 231ad202d..715219e89 100644 --- a/Makefile +++ b/Makefile @@ -58,16 +58,9 @@ amalgamated_v7: v7.h v7.c m32_v7: $(TOP_HEADERS) $(TOP_SOURCES) v7.h $(CC) $(TOP_SOURCES) -o v7 -DV7_EXE -DV7_EXPOSE_PRIVATE $(CFLAGS) -m32 -lm -js: v7 - @./v7 tests/v7_basic_test.js - @rhino -version 130 tests/v7_basic_test.js - -t: v7 - ./v7 tests/run_ecma262_tests.js - w: v7.c + wine cl v7.c /Zi -DV7_EXE -DV7_EXPOSE_PRIVATE wine cl tests/unit_test.c $(TOP_SOURCES) $(V7_FLAGS) /Zi -DV7_EXPOSE_PRIVATE - wine unit_test.exe clean: @$(MAKE) -C tests clean diff --git a/src/ast.h b/src/ast.h index 8af52685b..0aef701f8 100644 --- a/src/ast.h +++ b/src/ast.h @@ -137,10 +137,10 @@ typedef unsigned long ast_off_t; struct ast_node_def { const char *name; /* tag name, for debugging and serialization */ - uint8_t has_varint; /* has a varint body */ - uint8_t has_inlined; /* inlined data whose size is in the varint field */ - uint8_t num_skips; /* number of skips */ - uint8_t num_subtrees; /* number of fixed subtrees */ + unsigned char has_varint; /* has a varint body */ + unsigned char has_inlined; /* inlined data whose size is in the varint field */ + unsigned char num_skips; /* number of skips */ + unsigned char num_subtrees; /* number of fixed subtrees */ }; extern const struct ast_node_def ast_node_defs[]; diff --git a/src/date.c b/src/date.c index 7d328d876..1c50bda28 100644 --- a/src/date.c +++ b/src/date.c @@ -4,14 +4,6 @@ */ #include "internal.h" -#include -#include -#include -#include -#include -#include -#include -#include #ifdef __APPLE__ int64_t strtoll(const char *, char **, int); @@ -228,10 +220,8 @@ struct timeparts { /*+++ this functions is used to get current date/time & timezone */ -static void d_gettime(etime_t *time) { - struct timeval tv; - gettimeofday(&tv, NULL); - *time = (etime_t) tv.tv_sec * 1000 + (etime_t) tv.tv_usec / 1000; +static void d_gettime(etime_t *t) { + *t = time(NULL); } static const char *d_gettzname() { diff --git a/src/gc.c b/src/gc.c index cb88c5c92..bcef72272 100644 --- a/src/gc.c +++ b/src/gc.c @@ -172,8 +172,8 @@ V7_PRIVATE void gc_mark(struct v7 *v7, val_t v) { static void gc_dump_arena_stats(const char *msg, struct gc_arena *a) { if (a->verbose) { - fprintf(stderr, "%s: total allocations %lu, max %lu, alive %u\n", msg, - (unsigned long) a->allocations, a->size, a->alive); + fprintf(stderr, "%s: total allocations %lu, max %lu, alive %lu\n", msg, + a->allocations, a->size, a->alive); } } diff --git a/src/gc.h b/src/gc.h index 9b3f50c6a..f3d22401d 100644 --- a/src/gc.h +++ b/src/gc.h @@ -9,7 +9,6 @@ #include "internal.h" #include "vm.h" - /* Disable GC on 32-bit platform for now */ #if ULONG_MAX == 4294967295 #define V7_DISABLE_GC @@ -28,8 +27,12 @@ struct gc_cell { uintptr_t word; }; +#ifdef _WIN32 +#define GC_TMP_FRAME(v) struct gc_tmp_frame v = new_tmp_frame(v7); +#else #define GC_TMP_FRAME(v) __attribute__((cleanup(tmp_frame_cleanup), unused)) \ struct gc_tmp_frame v = new_tmp_frame(v7); +#endif #if defined(__cplusplus) extern "C" { diff --git a/src/internal.h b/src/internal.h index 1dd396450..1e066d251 100644 --- a/src/internal.h +++ b/src/internal.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #ifdef _WIN32 #define vsnprintf _vsnprintf @@ -35,10 +37,15 @@ #define isnan(x) _isnan(x) #define isinf(x) (!_finite(x)) #define __unused -typedef unsigned __int64 uint64_t; +typedef __int64 int64_t; +typedef int int32_t; typedef unsigned int uint32_t; +typedef unsigned short uint16_t; typedef unsigned char uint8_t; +typedef unsigned long uintptr_t; +#define __func__ "" #else +#include #include #endif diff --git a/src/interpreter.c b/src/interpreter.c index a811e17eb..25433504c 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -153,6 +153,12 @@ static double i_int_bin_op(struct v7 *v7, enum ast_tag tag, double a, } } +#ifdef _WIN32 +static int signbit(double x) { + return x > 0; +} +#endif + static double i_num_bin_op(struct v7 *v7, enum ast_tag tag, double a, double b) { switch (tag) { diff --git a/src/math.c b/src/math.c index 87d36d44c..736ee90c0 100644 --- a/src/math.c +++ b/src/math.c @@ -22,6 +22,12 @@ V7_PRIVATE val_t Math_##name(struct v7 *v7, val_t this_obj, val_t args) { \ return func(v7, args, name); \ } +#ifdef _WIN32 +static double round(double n) { + return n; +} +#endif + DEFINE_WRAPPER(fabs, m_one_arg) DEFINE_WRAPPER(acos, m_one_arg) DEFINE_WRAPPER(asin, m_one_arg) diff --git a/src/mm.h b/src/mm.h index ff546f725..9b01f019f 100644 --- a/src/mm.h +++ b/src/mm.h @@ -14,8 +14,8 @@ struct gc_arena { char *free; /* head of free list */ size_t cell_size; - uint64_t allocations; /* cumulative counter of allocations */ - uint32_t alive; /* number of living cells */ + unsigned long allocations; /* cumulative counter of allocations */ + unsigned long alive; /* number of living cells */ int verbose; const char *name; /* for debugging purposes */ diff --git a/src/vm.c b/src/vm.c index f32048c52..bc5d1ccc9 100644 --- a/src/vm.c +++ b/src/vm.c @@ -101,7 +101,7 @@ int v7_is_error(struct v7 *v7, val_t v) { } V7_PRIVATE val_t v7_pointer_to_value(void *p) { - return ((uint64_t) p & ((1L << 48) -1)); + return (uint64_t) p & ~V7_TAG_MASK; } V7_PRIVATE void *v7_to_pointer(val_t v) { @@ -223,7 +223,7 @@ v7_val_t v7_create_regexp(struct v7 *v7, const char *re, size_t re_len, v7_val_t v7_create_function(struct v7 *v7) { struct v7_function *f = new_function(v7); val_t proto = v7_create_undefined(), fval = v7_function_to_value(f); - GC_TMP_FRAME(tf); + struct gc_tmp_frame tf = new_tmp_frame(v7); if (f == NULL) { return V7_NULL; } @@ -238,6 +238,7 @@ v7_val_t v7_create_function(struct v7 *v7) { v7_set_property(v7, proto, "constructor", 11, V7_PROPERTY_DONT_ENUM, fval); v7_set_property(v7, fval, "prototype", 9, V7_PROPERTY_DONT_ENUM | V7_PROPERTY_DONT_DELETE, proto); + tmp_frame_cleanup(&tf); return fval; } @@ -648,12 +649,13 @@ int v7_del_property(struct v7 *v7, val_t obj, const char *name, size_t len) { V7_PRIVATE v7_val_t v7_create_cfunction_object(struct v7 *v7, v7_cfunction_t f, int num_args) { val_t obj = create_object(v7, v7->cfunction_prototype); - GC_TMP_FRAME(tf); + struct gc_tmp_frame tf = new_tmp_frame(v7); tmp_stack_push(&tf, &obj); v7_set_property(v7, obj, "", 0, V7_PROPERTY_HIDDEN, v7_create_cfunction(f)); v7_set_property(v7, obj, "length", 6, V7_PROPERTY_READ_ONLY | V7_PROPERTY_DONT_ENUM | V7_PROPERTY_DONT_DELETE, v7_create_number(num_args)); + tmp_frame_cleanup(&tf); return obj; } @@ -792,7 +794,8 @@ v7_val_t v7_create_string(struct v7 *v7, const char *p, size_t len, int own) { embed_string(m, m->len, (char *) &p, sizeof(p)); } - return v7_pointer_to_value((void *) offset) | tag; + /* NOTE(lsm): don't use v7_pointer_to_value, 32-bit ptrs will truncate */ + return (offset & ~V7_TAG_MASK) | tag; } /* @@ -874,7 +877,8 @@ V7_PRIVATE val_t s_concat(struct v7 *v7, val_t a, val_t b) { memcpy(s, a_ptr, a_len); memcpy(s + a_len, b_ptr, b_len); - return v7_pointer_to_value((void *) offset) | tag; + /* NOTE(lsm): don't use v7_pointer_to_value, 32-bit ptrs will truncate */ + return (offset & ~V7_TAG_MASK) | tag; } V7_PRIVATE val_t s_substr(struct v7 *v7, val_t s, long start, long len) { diff --git a/tests/ecma_report.txt b/tests/ecma_report.txt index e6ee65664..2b2212017 100644 --- a/tests/ecma_report.txt +++ b/tests/ecma_report.txt @@ -2069,7 +2069,7 @@ 2065 PASS ch11/11.6/11.6.1/S11.6.1_A2.1_T2.js (tail -c +1598918 tests/ecmac.db|head -c 439) 2066 PASS ch11/11.6/11.6.1/S11.6.1_A2.1_T3.js (tail -c +1599358 tests/ecmac.db|head -c 439) 2067 FAIL ch11/11.6/11.6.1/S11.6.1_A2.2_T1.js (tail -c +1599798 tests/ecmac.db|head -c 2951): [{"message":"#5: 1 + {toString: function() {return 1}} === 2. Actual: 1{"toString":[function()]}"}] -2068 FAIL ch11/11.6/11.6.1/S11.6.1_A2.2_T2.js (tail -c +1602750 tests/ecmac.db|head -c 1064): [{"message":"#1: var date = new Date(); date + date === date.toString() + date.toString(). Actual: 2.8501e+12"}] +2068 FAIL ch11/11.6/11.6.1/S11.6.1_A2.2_T2.js (tail -c +1602750 tests/ecmac.db|head -c 1064): [{"message":"#1: var date = new Date(); date + date === date.toString() + date.toString(). Actual: 2.8501e+09"}] 2069 FAIL ch11/11.6/11.6.1/S11.6.1_A2.2_T3.js (tail -c +1603815 tests/ecmac.db|head -c 1141): [{"message":"#1: function f1() {return 0;}; f1 + 1 === f1.toString() + 1"}] 2070 PASS ch11/11.6/11.6.1/S11.6.1_A2.3_T1.js (tail -c +1604957 tests/ecmac.db|head -c 858) 2071 PASS ch11/11.6/11.6.1/S11.6.1_A2.4_T1.js (tail -c +1605816 tests/ecmac.db|head -c 464) @@ -9692,7 +9692,7 @@ d-G]/.exec("a") throw SyntaxError. Actual: {"message":"[RegExp] is not defined"} 9638 PASS ch15/15.4/15.4.5/15.4.5.2/S15.4.5.2_A2_T1.js (tail -c +8768885 tests/ecmac.db|head -c 778) 9639 PASS ch15/15.4/15.4.5/15.4.5.2/S15.4.5.2_A3_T1.js (tail -c +8769664 tests/ecmac.db|head -c 810) 9640 PASS ch15/15.4/15.4.5/15.4.5.2/S15.4.5.2_A3_T2.js (tail -c +8770475 tests/ecmac.db|head -c 1508) -9641 FAIL ch15/15.4/15.4.5/15.4.5.2/S15.4.5.2_A3_T3.js (tail -c +8771984 tests/ecmac.db|head -c 795): [{"message":"#2.2: x = []; x.length = 4294967296 throw RangeError. Actual: {"message":"#2.1: x = []; x.length = 4294967296 throw RangeError. Actual: x.length === 4.29497e+09"}"}] +9641 FAIL ch15/15.4/15.4.5/15.4.5.2/S15.4.5.2_A3_T3.js (tail -c +8771984 tests/ecmac.db|head -c 795): [{"message":"#1: x = []; x.length = 4294967295; x.length === 4294967295"}] 9642 PASS ch15/15.4/15.4.5/15.4.5.2/S15.4.5.2_A3_T4.js (tail -c +8772780 tests/ecmac.db|head -c 1074) 9643 FAIL ch15/15.5/15.5.1/S15.5.1.1_A1_T1.js (tail -c +8773855 tests/ecmac.db|head -c 922): [{"message":"#2: __str = String(function(){}()); __str === "undefined". Actual: __str ==="}] 9644 PASS ch15/15.5/15.5.1/S15.5.1.1_A1_T10.js (tail -c +8774778 tests/ecmac.db|head -c 1477) diff --git a/tests/unit_test.c b/tests/unit_test.c index 72ba1f65e..d0cb3a5ea 100644 --- a/tests/unit_test.c +++ b/tests/unit_test.c @@ -24,9 +24,12 @@ #include #include #include -#include #include +#ifndef _WIN32 +#include +#endif + #include "../v7.h" #include "../src/internal.h" #include "../src/gc.h" @@ -590,7 +593,8 @@ static const char *test_runtime(void) { ASSERT(val_type(v7, v) == V7_TYPE_STRING); v7_to_string(v7, &v, &n); ASSERT(n == 3); - ASSERT(check_value(v7, v, "\"foo\"")); + s = "\"foo\""; + ASSERT(check_value(v7, v, s)); v = v7_create_object(v7); ASSERT(val_type(v7, v) == V7_TYPE_GENERIC_OBJECT); @@ -611,12 +615,14 @@ static const char *test_runtime(void) { ASSERT(v7_set_property(v7, v, "foo", -1, 0, v7_create_string(v7, "bar", 3, 1)) == 0); ASSERT((p = v7_get_property(v7, v, "foo", -1)) != NULL); - ASSERT(check_value(v7, p->value, "\"bar\"")); + s = "\"bar\""; + ASSERT(check_value(v7, p->value, s)); ASSERT(v7_set_property(v7, v, "foo", -1, 0, v7_create_string(v7, "zar", 3, 1)) == 0); ASSERT((p = v7_get_property(v7, v, "foo", -1)) != NULL); - ASSERT(check_value(v7, p->value, "\"zar\"")); + s = "\"zar\""; + ASSERT(check_value(v7, p->value, s)); ASSERT(v7_del_property(v7, v, "foo", ~0) == 0); ASSERT(v7_to_object(v)->properties == NULL); @@ -641,18 +647,22 @@ static const char *test_runtime(void) { v = v7_create_object(v7); ASSERT(v7_set_property(v7, v, "foo", -1, 0, v) == 0); - ASSERT(check_value(v7, v, "{\"foo\":[Circular]}")); + s = "{\"foo\":[Circular]}"; + ASSERT(check_value(v7, v, s)); v = v7_create_object(v7); ASSERT(v7_set_property(v7, v, "foo", -1, V7_PROPERTY_DONT_DELETE, v7_create_number(1.0)) == 0); - ASSERT(check_value(v7, v, "{\"foo\":1}")); + s = "{\"foo\":1}"; + ASSERT(check_value(v7, v, s)); ASSERT(v7_set(v7, v, "foo", -1, v7_create_number(2.0)) == 0); - ASSERT(check_value(v7, v, "{\"foo\":2}")); + s = "{\"foo\":2}"; + ASSERT(check_value(v7, v, s)); ASSERT(v7_to_double(v7_get(v7, v, "foo", -1)) == 2.0); ASSERT(v7_get_property(v7, v, "foo", -1)->attributes & V7_PROPERTY_DONT_DELETE); ASSERT(v7_set_property(v7, v, "foo", -1, V7_PROPERTY_READ_ONLY, v7_create_number(1.0)) == 0); ASSERT(v7_set(v7, v, "foo", -1, v7_create_number(2.0)) != 0); - ASSERT(check_value(v7, v, "{\"foo\":1}")); + s = "{\"foo\":1}"; + ASSERT(check_value(v7, v, s)); v = v7_create_string(v7, "fooakbar", 8, 1); for (i = 0; i < 100; i++) { @@ -1014,7 +1024,8 @@ static const char *test_ecmac(void) { snprintf(tail_cmd, sizeof(tail_cmd), "%.*s (tail -c +%lu tests/ecmac.db|head -c %lu)", chap_len, chap_begin == NULL ? "" : chap_begin, - current_case - db + 1, next_case - current_case); + (unsigned long) (current_case - db + 1), + (unsigned long) (next_case - current_case)); #if 0 printf("-- Parsing %d: \"%s\"\n", i, current_case); @@ -1110,6 +1121,7 @@ static const char *test_string_encoding(void) { static const char *test_interpreter(void) { struct v7 *v7 = v7_create(); val_t v; + const char *s; v7_set_property(v7, v7->global_object, "x", -1, 0, v7_create_number(42.0)); @@ -1123,9 +1135,10 @@ static const char *test_interpreter(void) { ASSERT(v7_exec(v7, &v, "1+2") == V7_OK); ASSERT(check_value(v7, v, "3")); ASSERT(v7_exec(v7, &v, "'1'+'2'") == V7_OK); - ASSERT(check_value(v7, v, "\"12\"")); + s = "\"12\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "'1'+2") == V7_OK); - ASSERT(check_value(v7, v, "\"12\"")); + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "false+1") == V7_OK); ASSERT(check_value(v7, v, "1")); @@ -1406,19 +1419,25 @@ static const char *test_interpreter(void) { ASSERT(check_value(v7, v, "2")); ASSERT(v7_exec(v7, &v, "typeof dummyx") == V7_OK); - ASSERT(check_value(v7, v, "\"undefined\"")); + s = "\"undefined\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "typeof null") == V7_OK); - ASSERT(check_value(v7, v, "\"object\"")); + s = "\"object\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "typeof 1") == V7_OK); - ASSERT(check_value(v7, v, "\"number\"")); + s = "\"number\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "typeof (1+2)") == V7_OK); - ASSERT(check_value(v7, v, "\"number\"")); + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "typeof 'test'") == V7_OK); - ASSERT(check_value(v7, v, "\"string\"")); + s = "\"string\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "typeof [1,2]") == V7_OK); - ASSERT(check_value(v7, v, "\"object\"")); + s = "\"object\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "typeof function(){}") == V7_OK); - ASSERT(check_value(v7, v, "\"function\"")); + s = "\"function\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "void(1+2)") == V7_OK); ASSERT(check_value(v7, v, "undefined")); @@ -1436,11 +1455,12 @@ static const char *test_interpreter(void) { ASSERT(check_value(v7, v, "false")); ASSERT(v7_exec(v7, &v, "x=1; delete x; typeof x") == V7_OK); - ASSERT(check_value(v7, v, "\"undefined\"")); + s = "\"undefined\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "x=1; (function(){x=2;delete x; return typeof x})()") == V7_OK); - ASSERT(check_value(v7, v, "\"undefined\"")); + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "x=1; (function(){x=2;delete x})(); typeof x") == V7_OK); - ASSERT(check_value(v7, v, "\"undefined\"")); + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "x=1; (function(){var x=2;delete x})(); x") == V7_OK); ASSERT(check_value(v7, v, "1")); ASSERT(v7_exec(v7, &v, "o={a:1};delete o.a;o") == V7_OK); @@ -1451,7 +1471,8 @@ static const char *test_interpreter(void) { ASSERT(check_value(v7, v, "42")); ASSERT(v7_exec(v7, &v, "o={};a=[o];o.a=a;a") == V7_OK); - ASSERT(check_value(v7, v, "[{\"a\":[Circular]}]")); + s = "[{\"a\":[Circular]}]"; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "new TypeError instanceof Error") == V7_OK); ASSERT(check_value(v7, v, "true")); @@ -1474,7 +1495,8 @@ static const char *test_interpreter(void) { ASSERT(v7_exec(v7, &v, "(function(){try {throw new Error}catch(e){c=e}})();c instanceof Error") == V7_OK); ASSERT(check_value(v7, v, "true")); ASSERT(v7_exec(v7, &v, "delete e;(function(){try {throw new Error}catch(e){}})();typeof e") == V7_OK); - ASSERT(check_value(v7, v, "\"undefined\"")); + s = "\"undefined\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "x=(function(){c=1;try {throw 1}catch(e){c=0};return c})()") == V7_OK); ASSERT(check_value(v7, v, "0")); ASSERT(v7_exec(v7, &v, "x=(function(){var c=1;try {throw 1}catch(e){c=0};return c})()") == V7_OK); @@ -1487,17 +1509,22 @@ static const char *test_interpreter(void) { ASSERT(v7_exec(v7, &v, "Object.keys(new Boolean(1))") == V7_OK); ASSERT(check_value(v7, v, "[]")); ASSERT(v7_exec(v7, &v, "b={c:1};a=Object.create(b); a.d=4;Object.keys(a)") == V7_OK); - ASSERT(check_value(v7, v, "[\"d\"]")); + s = "[\"d\"]"; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "Object.getOwnPropertyNames(new Boolean(1))") == V7_OK); ASSERT(check_value(v7, v, "[]")); ASSERT(v7_exec(v7, &v, "b={c:1};a=Object.create(b); a.d=4;Object.getOwnPropertyNames(a)") == V7_OK); - ASSERT(check_value(v7, v, "[\"d\"]")); - ASSERT(v7_exec(v7, &v, "o={};Object.defineProperty(o, \"x\", {value:2});[o.x,o]") == V7_OK); + ASSERT(check_value(v7, v, s)); + s = "o={};Object.defineProperty(o, \"x\", {value:2});[o.x,o]"; + ASSERT(v7_exec(v7, &v, s) == V7_OK); ASSERT(check_value(v7, v, "[2,{}]")); ASSERT(v7_exec(v7, &v, "o={};Object.defineProperties(o,{x:{value:2},y:{value:3,enumerable:true}});[o.x,o.y,o]") == V7_OK); - ASSERT(check_value(v7, v, "[2,3,{\"y\":3}]")); - ASSERT(v7_exec(v7, &v, "o={};Object.defineProperty(o, \"x\", {value:2,enumerable:true});[o.x,o]") == V7_OK); - ASSERT(check_value(v7, v, "[2,{\"x\":2}]")); + s = "[2,3,{\"y\":3}]"; + ASSERT(check_value(v7, v, s)); + s = "o={};Object.defineProperty(o, \"x\", {value:2,enumerable:true});[o.x,o]"; + ASSERT(v7_exec(v7, &v, s) == V7_OK); + s = "[2,{\"x\":2}]"; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "o={};Object.defineProperty(o,'a',{value:1});o.propertyIsEnumerable('a')") == V7_OK); ASSERT(check_value(v7, v, "false")); ASSERT(v7_exec(v7, &v, "o={};Object.defineProperty(o,'a',{value:1,enumerable:true});o.propertyIsEnumerable('a')") == V7_OK); @@ -1539,18 +1566,21 @@ static const char *test_interpreter(void) { ASSERT(check_value(v7, v, "42")); ASSERT(v7_exec(v7, &v, "a='aa', b='bb';(function(){return a + ' ' + b;})()") == V7_OK); - ASSERT(check_value(v7, v, "\"aa bb\"")); + s = "\"aa bb\""; + ASSERT(check_value(v7, v, s)); + s = "{\"fall\":2,\"one\":1}"; ASSERT(v7_exec(v7, &v, "o={};switch(1) {case 1: o.one=1; case 2: o.fall=2; break; case 3: o.three=1; };o") == V7_OK); - ASSERT(check_value(v7, v, "{\"fall\":2,\"one\":1}")); + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "o={};for(i=0;i<1;i++) switch(1) {case 1: o.one=1; case 2: o.fall=2; continue; case 3: o.three=1; };o") == V7_OK); - ASSERT(check_value(v7, v, "{\"fall\":2,\"one\":1}")); + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "(function(){o={};switch(1) {case 1: o.one=1; case 2: o.fall=2; return o; case 3: o.three=1; }})()") == V7_OK); - ASSERT(check_value(v7, v, "{\"fall\":2,\"one\":1}")); + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "o={};switch(1) {case 1: o.one=1; default: o.fall=2; break; case 3: o.three=1; };o") == V7_OK); - ASSERT(check_value(v7, v, "{\"fall\":2,\"one\":1}")); + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "o={};switch(10) {case 1: o.one=1; case 2: o.fall=2; break; case 3: o.three=1; break; default: o.def=1};o") == V7_OK); - ASSERT(check_value(v7, v, "{\"def\":1}")); + s = "{\"def\":1}"; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "o={get x(){return 42}};o.x") == V7_OK); ASSERT(check_value(v7, v, "42")); @@ -1566,7 +1596,8 @@ static const char *test_interpreter(void) { ASSERT(check_value(v7, v, "[42,[]]")); ASSERT(v7_exec(v7, &v, "String(new Number(42))") == V7_OK); - ASSERT(check_value(v7, v, "\"42\"")); + s = "\"42\""; + ASSERT(check_value(v7, v, s)); ASSERT(v7_exec(v7, &v, "L: for(i=0;i<10;i++){for(j=4;j<10;j++){if(i==j) break L}};i") == V7_OK); ASSERT(check_value(v7, v, "4")); @@ -1594,7 +1625,8 @@ static const char *test_interpreter(void) { ASSERT(v7_exec(v7, &v, "1 && {}") == V7_OK); ASSERT(check_value(v7, v, "{}")); ASSERT(v7_exec(v7, &v, "'' && {}") == V7_OK); - ASSERT(check_value(v7, v, "\"\"")); + s = "\"\""; + ASSERT(check_value(v7, v, s)); /* here temporarily because test_stdlib has memory violations */ ASSERT(v7_exec(v7, &v, "a=[2,1];a.sort();a") == V7_OK); diff --git a/v7.c b/v7.c index fa1f9c8b1..f966ceafb 100644 --- a/v7.c +++ b/v7.c @@ -34,9 +34,11 @@ enum v7_err { struct v7; /* Opaque structure. V7 engine handler. */ struct v7_val; /* Opaque structure. Holds V7 value, which has v7_type type. */ - -/* TODO(lsm): fix this. */ +#ifdef _WIN32 +typedef unsigned __int64 uint64_t; +#else #include +#endif typedef uint64_t v7_val_t; typedef v7_val_t (*v7_cfunction_t)(struct v7 *, v7_val_t, v7_val_t); @@ -505,10 +507,10 @@ typedef unsigned long ast_off_t; struct ast_node_def { const char *name; /* tag name, for debugging and serialization */ - uint8_t has_varint; /* has a varint body */ - uint8_t has_inlined; /* inlined data whose size is in the varint field */ - uint8_t num_skips; /* number of skips */ - uint8_t num_subtrees; /* number of fixed subtrees */ + unsigned char has_varint; /* has a varint body */ + unsigned char has_inlined; /* inlined data whose size is in the varint field */ + unsigned char num_skips; /* number of skips */ + unsigned char num_subtrees; /* number of fixed subtrees */ }; extern const struct ast_node_def ast_node_defs[]; @@ -602,8 +604,8 @@ struct gc_arena { char *free; /* head of free list */ size_t cell_size; - uint64_t allocations; /* cumulative counter of allocations */ - uint32_t alive; /* number of living cells */ + unsigned long allocations; /* cumulative counter of allocations */ + unsigned long alive; /* number of living cells */ int verbose; const char *name; /* for debugging purposes */ @@ -632,6 +634,7 @@ struct gc_arena { #include #include #include +#include #include #include #include @@ -639,6 +642,7 @@ struct gc_arena { #include #include #include +#include #ifdef _WIN32 #define vsnprintf _vsnprintf @@ -646,10 +650,15 @@ struct gc_arena { #define isnan(x) _isnan(x) #define isinf(x) (!_finite(x)) #define __unused -typedef unsigned __int64 uint64_t; +typedef __int64 int64_t; +typedef int int32_t; typedef unsigned int uint32_t; +typedef unsigned short uint16_t; typedef unsigned char uint8_t; +typedef unsigned long uintptr_t; +#define __func__ "" #else +#include #include #endif @@ -1065,7 +1074,6 @@ V7_PRIVATE double i_as_num(struct v7 *, val_t); #define GC_H_INCLUDED - /* Disable GC on 32-bit platform for now */ #if ULONG_MAX == 4294967295 #define V7_DISABLE_GC @@ -1084,8 +1092,12 @@ struct gc_cell { uintptr_t word; }; +#ifdef _WIN32 +#define GC_TMP_FRAME(v) struct gc_tmp_frame v = new_tmp_frame(v7); +#else #define GC_TMP_FRAME(v) __attribute__((cleanup(tmp_frame_cleanup), unused)) \ struct gc_tmp_frame v = new_tmp_frame(v7); +#endif #if defined(__cplusplus) extern "C" { @@ -3779,6 +3791,12 @@ V7_PRIVATE val_t Math_##name(struct v7 *v7, val_t this_obj, val_t args) { \ return func(v7, args, name); \ } +#ifdef _WIN32 +static double round(double n) { + return n; +} +#endif + DEFINE_WRAPPER(fabs, m_one_arg) DEFINE_WRAPPER(acos, m_one_arg) DEFINE_WRAPPER(asin, m_one_arg) @@ -5151,7 +5169,7 @@ int v7_is_error(struct v7 *v7, val_t v) { } V7_PRIVATE val_t v7_pointer_to_value(void *p) { - return ((uint64_t) p & ((1L << 48) -1)); + return (uint64_t) p & ~V7_TAG_MASK; } V7_PRIVATE void *v7_to_pointer(val_t v) { @@ -5273,7 +5291,7 @@ v7_val_t v7_create_regexp(struct v7 *v7, const char *re, size_t re_len, v7_val_t v7_create_function(struct v7 *v7) { struct v7_function *f = new_function(v7); val_t proto = v7_create_undefined(), fval = v7_function_to_value(f); - GC_TMP_FRAME(tf); + struct gc_tmp_frame tf = new_tmp_frame(v7); if (f == NULL) { return V7_NULL; } @@ -5288,6 +5306,7 @@ v7_val_t v7_create_function(struct v7 *v7) { v7_set_property(v7, proto, "constructor", 11, V7_PROPERTY_DONT_ENUM, fval); v7_set_property(v7, fval, "prototype", 9, V7_PROPERTY_DONT_ENUM | V7_PROPERTY_DONT_DELETE, proto); + tmp_frame_cleanup(&tf); return fval; } @@ -5698,12 +5717,13 @@ int v7_del_property(struct v7 *v7, val_t obj, const char *name, size_t len) { V7_PRIVATE v7_val_t v7_create_cfunction_object(struct v7 *v7, v7_cfunction_t f, int num_args) { val_t obj = create_object(v7, v7->cfunction_prototype); - GC_TMP_FRAME(tf); + struct gc_tmp_frame tf = new_tmp_frame(v7); tmp_stack_push(&tf, &obj); v7_set_property(v7, obj, "", 0, V7_PROPERTY_HIDDEN, v7_create_cfunction(f)); v7_set_property(v7, obj, "length", 6, V7_PROPERTY_READ_ONLY | V7_PROPERTY_DONT_ENUM | V7_PROPERTY_DONT_DELETE, v7_create_number(num_args)); + tmp_frame_cleanup(&tf); return obj; } @@ -5842,7 +5862,8 @@ v7_val_t v7_create_string(struct v7 *v7, const char *p, size_t len, int own) { embed_string(m, m->len, (char *) &p, sizeof(p)); } - return v7_pointer_to_value((void *) offset) | tag; + /* NOTE(lsm): don't use v7_pointer_to_value, 32-bit ptrs will truncate */ + return (offset & ~V7_TAG_MASK) | tag; } /* @@ -5924,7 +5945,8 @@ V7_PRIVATE val_t s_concat(struct v7 *v7, val_t a, val_t b) { memcpy(s, a_ptr, a_len); memcpy(s + a_len, b_ptr, b_len); - return v7_pointer_to_value((void *) offset) | tag; + /* NOTE(lsm): don't use v7_pointer_to_value, 32-bit ptrs will truncate */ + return (offset & ~V7_TAG_MASK) | tag; } V7_PRIVATE val_t s_substr(struct v7 *v7, val_t s, long start, long len) { @@ -6178,8 +6200,8 @@ V7_PRIVATE void gc_mark(struct v7 *v7, val_t v) { static void gc_dump_arena_stats(const char *msg, struct gc_arena *a) { if (a->verbose) { - fprintf(stderr, "%s: total allocations %lu, max %lu, alive %u\n", msg, - (unsigned long) a->allocations, a->size, a->alive); + fprintf(stderr, "%s: total allocations %lu, max %lu, alive %lu\n", msg, + a->allocations, a->size, a->alive); } } @@ -7242,6 +7264,12 @@ static double i_int_bin_op(struct v7 *v7, enum ast_tag tag, double a, } } +#ifdef _WIN32 +static int signbit(double x) { + return x > 0; +} +#endif + static double i_num_bin_op(struct v7 *v7, enum ast_tag tag, double a, double b) { switch (tag) { @@ -10739,14 +10767,6 @@ int main(int argc, char *argv[]) { * All rights reserved */ -#include -#include -#include -#include -#include -#include -#include -#include #ifdef __APPLE__ int64_t strtoll(const char *, char **, int); @@ -10963,10 +10983,8 @@ struct timeparts { /*+++ this functions is used to get current date/time & timezone */ -static void d_gettime(etime_t *time) { - struct timeval tv; - gettimeofday(&tv, NULL); - *time = (etime_t) tv.tv_sec * 1000 + (etime_t) tv.tv_usec / 1000; +static void d_gettime(etime_t *t) { + *t = time(NULL); } static const char *d_gettzname() { diff --git a/v7.h b/v7.h index 5e3fc4f62..879558671 100644 --- a/v7.h +++ b/v7.h @@ -34,9 +34,11 @@ enum v7_err { struct v7; /* Opaque structure. V7 engine handler. */ struct v7_val; /* Opaque structure. Holds V7 value, which has v7_type type. */ - -/* TODO(lsm): fix this. */ +#ifdef _WIN32 +typedef unsigned __int64 uint64_t; +#else #include +#endif typedef uint64_t v7_val_t; typedef v7_val_t (*v7_cfunction_t)(struct v7 *, v7_val_t, v7_val_t);