Skip to content

Commit

Permalink
WIP: Fixes GC bugs, adds additional GC profile/debug tools
Browse files Browse the repository at this point in the history
- First steps toward a real garbage collector. Fixes some big issues
  with mark and sweep. There are still some other GC issues that crop up
  when it's run many times, particularly with large callstacks caused by
  recursion. I'm working on additional improvements.
  • Loading branch information
ndreynolds committed Jul 12, 2014
1 parent 6f3d60a commit a385db2
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 60 deletions.
11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

CC = gcc
CFLAGS = -Wall -Wextra -Wno-unused-parameter -O3 -std=c99 -pedantic -D_XOPEN_SOURCE
CFLAGS = -dD -Wall -Wextra -Wno-unused-parameter -O3 -std=c99 -pedantic -D_XOPEN_SOURCE

YACC = bison
YACC_FLAGS = -y -d -t -v
Expand All @@ -28,8 +28,9 @@ OBJ_FILES = y.tab.o lex.yy.o src/eval.o src/str.o src/regexp.o src/cli.o \
src/nodes.o src/args.o src/flathead.o src/debug.o src/gc.o src/props.o \
src/runtime/runtime.o src/runtime/lib/Math.o src/runtime/lib/RegExp.o \
src/runtime/lib/Error.o src/runtime/lib/String.o src/runtime/lib/console.o \
src/runtime/lib/Function.o src/runtime/lib/Object.o src/runtime/lib/Boolean.o \
src/runtime/lib/Number.o src/runtime/lib/Date.o src/runtime/lib/Array.o
src/runtime/lib/gc.o src/runtime/lib/Function.o src/runtime/lib/Object.o \
src/runtime/lib/Boolean.o src/runtime/lib/Number.o src/runtime/lib/Date.o \
src/runtime/lib/Array.o

OUT_FILE = bin/flat
YACC_FILE = src/grammar.y
Expand Down Expand Up @@ -76,8 +77,8 @@ all: default
debug: CFLAGS += -g -O0
debug: clean default

malloc-debug: CC = gcc-4.7
malloc-debug: LIBS += -lefence
malloc-debug: CC = gcc-4.9
malloc-debug: LIBS += -lduma
malloc-debug: debug


Expand Down
2 changes: 1 addition & 1 deletion src/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ fh_debug(FILE *stream, js_val *val, int indent, bool newline)
else if (IS_FUNC(val))
cfprintf(stream, ANSI_BLUE, "[Function]");
else if (IS_DATE(val))
fh_debug(stream, fh_to_primitive(val, 0), indent, false);
fprintf(stream, "[Date %ld]", (long)val->object.primitive->number.val);
else
debug_obj(stream, val, indent, false);
break;
Expand Down
10 changes: 6 additions & 4 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ member_exp(js_val *ctx, ast_node *member)
int i = member->e1->val, len = parent->string.length;
if (i < len && i >= 0) {
char *str = malloc(sizeof(char) + 1);
str[1] = '\0';
sprintf(str, "%c", parent->string.ptr[i]);
return JSSTR(str);
}
Expand Down Expand Up @@ -466,10 +467,10 @@ switch_stmt(js_val *ctx, ast_node *node)
js_val *val, *result, *test = fh_eval(ctx, node->e1);

ast_node *current,
*caseblock = node->e2,
*clauses_a = caseblock->e1,
*defaultclause = caseblock->e2,
*clauses_b = caseblock->e3;
*caseblock = node->e2,
*clauses_a = caseblock->e1,
*defaultclause = caseblock->e2,
*clauses_b = caseblock->e3;

bool matched = false;

Expand Down Expand Up @@ -806,6 +807,7 @@ call(js_val *ctx, js_val *this, js_val *func, eval_state *state, js_args *args)
state->caller_info = "(anonymous function)";

js_val *func_scope = setup_call_env(ctx, this, func, args);
state->scope = func_scope;
return fh_eval(func_scope, func->object.node->e2);
}

Expand Down
40 changes: 36 additions & 4 deletions src/flathead.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ fh_new_val(js_type type)
val->type = type;
val->signal = S_NONE;
val->proto = NULL;
val->marked = false;

return val;
}
Expand Down Expand Up @@ -71,6 +72,7 @@ fh_new_string(char *x)
js_val *val = fh_new_val(T_STRING);

val->string.ptr = malloc((strlen(x) + 1) * sizeof(char));
val->string.ptr[strlen(x)] = '\0';
strcpy(val->string.ptr, x);
fh_set_len(val, strlen(x));
val->proto = fh_try_get_proto("String");
Expand Down Expand Up @@ -99,6 +101,11 @@ fh_new_object()
val->object.extensible = false;
val->object.parent = NULL;
val->object.primitive = NULL;
val->object.bound_this = NULL;
val->object.bound_args = NULL;
val->object.scope = NULL;
val->object.instance = NULL;
val->object.node = NULL;
val->proto = fh->object_proto;

return val;
Expand Down Expand Up @@ -129,6 +136,7 @@ fh_new_function(struct ast_node *node)
fh_set(val, "caller", JSNULL());

val->object.native = false;
val->object.provide_this = false;
val->object.generator = false;
val->object.node = node;
val->object.scope = NULL;
Expand Down Expand Up @@ -198,6 +206,7 @@ fh_new_error(char *name, const char *tpl, ...)
va_end(ap);

char *msg = malloc(size + 1);
msg[size] = '\0';

// Now build the error message
va_start(ap, tpl);
Expand Down Expand Up @@ -253,6 +262,7 @@ fh_new_state(int line, int column)

state->ctx = NULL;
state->this = NULL;
state->scope = NULL;
state->parent = NULL;
state->construct = false;
state->catch = false;
Expand All @@ -275,6 +285,7 @@ fh_new_global_state()
state->global = NULL;
state->function_proto = NULL;
state->object_proto = NULL;
state->callstack = NULL;

state->script_name = "main";

Expand Down Expand Up @@ -414,6 +425,7 @@ fh_to_string(js_val *val)
fmt = "%g";
int size = snprintf(NULL, 0, fmt, val->number.val) + 1;
char *num = malloc(size);
num[size] = '\0';
snprintf(num, size, fmt, val->number.val);
return JSSTR(num);
}
Expand All @@ -428,17 +440,23 @@ fh_to_object(js_val *val)
{
if (IS_UNDEF(val) || IS_NULL(val))
fh_throw(NULL, fh_new_error(E_TYPE, "cannot convert %s to object", fh_typeof(val)));
if (IS_OBJ(val))
if (IS_OBJ(val))
return val;

js_val *obj = JSOBJ();
obj->object.primitive = val;
if (IS_BOOL(val))
if (IS_BOOL(val)) {
fh_set_class(obj, "Boolean");
if (IS_NUM(val))
obj->proto = fh_try_get_proto("Boolean");
}
if (IS_NUM(val)) {
fh_set_class(obj, "Number");
if (IS_STR(val))
obj->proto = fh_try_get_proto("Number");
}
if (IS_STR(val)) {
fh_set_class(obj, "String");
obj->proto = fh_try_get_proto("String");
}
return obj;
}

Expand Down Expand Up @@ -558,6 +576,12 @@ fh_has_instance(js_val *func, js_val *val)
return JSBOOL(0);
}

js_val *
fh_implicit_this_value(js_val *obj)
{
return obj->object.provide_this ? obj->object.bound_this : JSUNDEF();
}

js_val *
fh_has_property(js_val *obj, char *prop)
{
Expand All @@ -568,6 +592,14 @@ fh_has_property(js_val *obj, char *prop)
js_val *
fh_try_get_proto(char *type)
{
// Try to avoid a lookup.
if (STREQ(type, "Function") && fh->function_proto)
return fh->function_proto;
if (STREQ(type, "Object") && fh->object_proto)
return fh->object_proto;
if (STREQ(type, "Array") && fh->array_proto)
return fh->array_proto;

js_val *global = fh->global;
if (global != NULL) {
js_val *obj = fh_get(global, type);
Expand Down
4 changes: 4 additions & 0 deletions src/flathead.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ typedef struct eval_state {
bool catch;
struct js_val *ctx;
struct js_val *this;
struct js_val *scope;
jmp_buf jmp;
struct eval_state *parent;
} eval_state;
Expand Down Expand Up @@ -206,6 +207,7 @@ typedef struct js_val * (js_native_function)(struct js_val *, struct js_args *,
typedef struct {
bool native;
bool generator;
bool provide_this;
bool extensible; // [[Extensible]]
char class[10]; // [[Class]]
struct js_val *primitive; // [[PrimitiveValue]]
Expand All @@ -232,6 +234,7 @@ typedef struct js_val {
ctl_signal signal;
struct js_val *proto;
bool marked;
bool flagged;
js_prop *map;
} js_val;

Expand Down Expand Up @@ -269,6 +272,7 @@ js_val * fh_to_object(js_val *);
js_val * fh_cast(js_val *, js_type);

js_val * fh_has_instance(js_val *, js_val *);
js_val * fh_implicit_this_value(js_val *obj);
js_val * fh_has_property(js_val *, char *);
char * fh_typeof(js_val *);
void fh_set_len(js_val *, unsigned long);
Expand Down
Loading

0 comments on commit a385db2

Please sign in to comment.