shithub: libmujs

Download patch

ref: d366e4b85299d5951d137ba3bf37155954acb448
parent: 1c52e8b7b403802b11f85ec68a221ab2cd31bdb5
author: Tor Andersson <tor@ccxvii.net>
date: Sun Mar 9 12:13:18 EDT 2014

Don't pass argc to functions. Use js_gettop instead.

--- a/js.h
+++ b/js.h
@@ -28,7 +28,7 @@
 
 typedef void *(*js_Alloc)(void *memctx, void *ptr, unsigned int size);
 typedef void (*js_Panic)(js_State *J);
-typedef void (*js_CFunction)(js_State *J, unsigned int argc);
+typedef void (*js_CFunction)(js_State *J);
 
 /* Basic functions */
 js_State *js_newstate(js_Alloc alloc, void *actx);
--- a/jsarray.c
+++ b/jsarray.c
@@ -45,13 +45,13 @@
 	js_delproperty(J, idx, buf);
 }
 
-static void jsB_new_Array(js_State *J, unsigned int argc)
+static void jsB_new_Array(js_State *J)
 {
-	unsigned int i;
+	unsigned int i, top = js_gettop(J);
 
 	js_newarray(J);
 
-	if (argc == 1) {
+	if (top == 2) {
 		if (js_isnumber(J, 1)) {
 			js_copy(J, 1);
 			js_setproperty(J, -2, "length");
@@ -60,7 +60,7 @@
 			js_setindex(J, -2, 0);
 		}
 	} else {
-		for (i = 1; i <= argc; ++i) {
+		for (i = 1; i < top; ++i) {
 			js_copy(J, i);
 			js_setindex(J, -2, i - 1);
 		}
@@ -67,14 +67,15 @@
 	}
 }
 
-static void Ap_concat(js_State *J, unsigned int argc)
+static void Ap_concat(js_State *J)
 {
-	unsigned int n, k, len, i;
+	unsigned int i, top = js_gettop(J);
+	unsigned int n, k, len;
 
 	js_newarray(J);
 	n = 0;
 
-	for (i = 0; i <= argc; ++i) {
+	for (i = 0; i < top; ++i) {
 		js_copy(J, i);
 		if (js_isarray(J, -1)) {
 			len = js_getlength(J, -1);
@@ -88,7 +89,7 @@
 	}
 }
 
-static void Ap_join(js_State *J, unsigned int argc)
+static void Ap_join(js_State *J)
 {
 	char * volatile out = NULL;
 	const char *sep;
@@ -143,7 +144,7 @@
 	js_free(J, out);
 }
 
-static void Ap_pop(js_State *J, unsigned int argc)
+static void Ap_pop(js_State *J)
 {
 	unsigned int n;
 
@@ -159,13 +160,14 @@
 	}
 }
 
-static void Ap_push(js_State *J, unsigned int argc)
+static void Ap_push(js_State *J)
 {
-	unsigned int i, n;
+	unsigned int i, top = js_gettop(J);
+	unsigned int n;
 
 	n = js_getlength(J, 0);
 
-	for (i = 1; i <= argc; ++i, ++n) {
+	for (i = 1; i < top; ++i, ++n) {
 		js_copy(J, i);
 		js_setindex(J, 0, n);
 	}
@@ -175,7 +177,7 @@
 	js_pushnumber(J, n);
 }
 
-static void Ap_reverse(js_State *J, unsigned int argc)
+static void Ap_reverse(js_State *J)
 {
 	unsigned int len, middle, lower;
 
@@ -203,7 +205,7 @@
 	js_copy(J, 0);
 }
 
-static void Ap_shift(js_State *J, unsigned int argc)
+static void Ap_shift(js_State *J)
 {
 	unsigned int k, len;
 
@@ -228,7 +230,7 @@
 	js_setlength(J, 0, len - 1);
 }
 
-static void Ap_slice(js_State *J, unsigned int argc)
+static void Ap_slice(js_State *J)
 {
 	unsigned int len, s, e, n;
 	double sv, ev;
@@ -286,7 +288,7 @@
 	return 0;
 }
 
-static void Ap_sort(js_State *J, unsigned int argc)
+static void Ap_sort(js_State *J)
 {
 	unsigned int len, i, k;
 	int hasx, hasy, hasfn;
@@ -315,8 +317,9 @@
 	js_copy(J, 0);
 }
 
-static void Ap_splice(js_State *J, unsigned int argc)
+static void Ap_splice(js_State *J)
 {
+	unsigned int top = js_gettop(J);
 	unsigned int len, start, del, add, k;
 	double f;
 
@@ -337,7 +340,7 @@
 			js_setindex(J, -2, k);
 
 	/* shift the tail to resize the hole left by deleted items */
-	add = argc - 2;
+	add = top - 3;
 	if (add < del) {
 		for (k = start; k < len - del; ++k) {
 			if (js_hasindex(J, 0, k + del))
@@ -365,15 +368,16 @@
 	js_setlength(J, 0, len - del + add);
 }
 
-static void Ap_unshift(js_State *J, unsigned int argc)
+static void Ap_unshift(js_State *J)
 {
-	unsigned int i, k, len;
+	unsigned int i, top = js_gettop(J);
+	unsigned int k, len;
 
 	len = js_getlength(J, 0);
 
 	for (k = len; k > 0; --k) {
 		int from = k - 1;
-		int to = k + argc - 1;
+		int to = k + top - 2;
 		if (js_hasindex(J, 0, from))
 			js_setindex(J, 0, to);
 		else
@@ -380,23 +384,24 @@
 			js_delindex(J, 0, to);
 	}
 
-	for (i = 1; i <= argc; ++i) {
+	for (i = 1; i < top; ++i) {
 		js_copy(J, i);
 		js_setindex(J, 0, i - 1);
 	}
 
-	js_setlength(J, 0, len + argc);
+	js_setlength(J, 0, len + top - 1);
 
-	js_pushnumber(J, len + argc);
+	js_pushnumber(J, len + top - 1);
 }
 
-static void Ap_toString(js_State *J, unsigned int argc)
+static void Ap_toString(js_State *J)
 {
-	js_pop(J, argc);
-	Ap_join(J, 0);
+	unsigned int top = js_gettop(J);
+	js_pop(J, top - 1);
+	Ap_join(J);
 }
 
-static void Ap_indexOf(js_State *J, unsigned int argc)
+static void Ap_indexOf(js_State *J)
 {
 	int k, len, from;
 
@@ -419,7 +424,7 @@
 	js_pushnumber(J, -1);
 }
 
-static void Ap_lastIndexOf(js_State *J, unsigned int argc)
+static void Ap_lastIndexOf(js_State *J)
 {
 	int k, len, from;
 
@@ -442,8 +447,9 @@
 	js_pushnumber(J, -1);
 }
 
-static void Ap_every(js_State *J, unsigned int argc)
+static void Ap_every(js_State *J)
 {
+	int hasthis = js_gettop(J) >= 3;
 	int k, len;
 
 	if (!js_iscallable(J, 1))
@@ -453,7 +459,7 @@
 	for (k = 0; k < len; ++k) {
 		if (js_hasindex(J, 0, k)) {
 			js_copy(J, 1);
-			if (argc > 1)
+			if (hasthis)
 				js_copy(J, 2);
 			else
 				js_pushundefined(J);
@@ -470,8 +476,9 @@
 	js_pushboolean(J, 1);
 }
 
-static void Ap_some(js_State *J, unsigned int argc)
+static void Ap_some(js_State *J)
 {
+	int hasthis = js_gettop(J) >= 3;
 	int k, len;
 
 	if (!js_iscallable(J, 1))
@@ -481,7 +488,7 @@
 	for (k = 0; k < len; ++k) {
 		if (js_hasindex(J, 0, k)) {
 			js_copy(J, 1);
-			if (argc > 1)
+			if (hasthis)
 				js_copy(J, 2);
 			else
 				js_pushundefined(J);
@@ -498,8 +505,9 @@
 	js_pushboolean(J, 0);
 }
 
-static void Ap_forEach(js_State *J, unsigned int argc)
+static void Ap_forEach(js_State *J)
 {
+	int hasthis = js_gettop(J) >= 3;
 	int k, len;
 
 	if (!js_iscallable(J, 1))
@@ -509,7 +517,7 @@
 	for (k = 0; k < len; ++k) {
 		if (js_hasindex(J, 0, k)) {
 			js_copy(J, 1);
-			if (argc > 1)
+			if (hasthis)
 				js_copy(J, 2);
 			else
 				js_pushundefined(J);
@@ -524,8 +532,9 @@
 	js_pushundefined(J);
 }
 
-static void Ap_map(js_State *J, unsigned int argc)
+static void Ap_map(js_State *J)
 {
+	int hasthis = js_gettop(J) >= 3;
 	int k, len;
 
 	if (!js_iscallable(J, 1))
@@ -537,7 +546,7 @@
 	for (k = 0; k < len; ++k) {
 		if (js_hasindex(J, 0, k)) {
 			js_copy(J, 1);
-			if (argc > 1)
+			if (hasthis)
 				js_copy(J, 2);
 			else
 				js_pushundefined(J);
@@ -551,8 +560,9 @@
 	}
 }
 
-static void Ap_filter(js_State *J, unsigned int argc)
+static void Ap_filter(js_State *J)
 {
+	int hasthis = js_gettop(J) >= 3;
 	int k, to, len;
 
 	if (!js_iscallable(J, 1))
@@ -565,7 +575,7 @@
 	for (k = 0; k < len; ++k) {
 		if (js_hasindex(J, 0, k)) {
 			js_copy(J, 1);
-			if (argc > 1)
+			if (hasthis)
 				js_copy(J, 2);
 			else
 				js_pushundefined(J);
@@ -583,8 +593,9 @@
 	}
 }
 
-static void Ap_reduce(js_State *J, unsigned int argc)
+static void Ap_reduce(js_State *J)
 {
+	int hasinitial = js_gettop(J) >= 3;
 	int k, len;
 
 	if (!js_iscallable(J, 1))
@@ -593,11 +604,11 @@
 	len = js_getlength(J, 0);
 	k = 0;
 
-	if (len == 0 && argc < 2)
+	if (len == 0 && !hasinitial)
 		js_typeerror(J, "no initial value");
 
 	/* initial value of accumulator */
-	if (argc >= 2)
+	if (hasinitial)
 		js_copy(J, 2);
 	else {
 		while (k < len)
@@ -623,8 +634,9 @@
 	/* return accumulator */
 }
 
-static void Ap_reduceRight(js_State *J, unsigned int argc)
+static void Ap_reduceRight(js_State *J)
 {
+	int hasinitial = js_gettop(J) >= 3;
 	int k, len;
 
 	if (!js_iscallable(J, 1))
@@ -633,11 +645,11 @@
 	len = js_getlength(J, 0);
 	k = len - 1;
 
-	if (len == 0 && argc < 2)
+	if (len == 0 && !hasinitial)
 		js_typeerror(J, "no initial value");
 
 	/* initial value of accumulator */
-	if (argc >= 2)
+	if (hasinitial)
 		js_copy(J, 2);
 	else {
 		while (k >= 0)
@@ -663,7 +675,7 @@
 	/* return accumulator */
 }
 
-static void A_isArray(js_State *J, unsigned int argc)
+static void A_isArray(js_State *J)
 {
 	if (js_isobject(J, 1)) {
 		js_Object *T = js_toobject(J, 1);
--- a/jsboolean.c
+++ b/jsboolean.c
@@ -2,17 +2,17 @@
 #include "jsvalue.h"
 #include "jsbuiltin.h"
 
-static void jsB_new_Boolean(js_State *J, unsigned int argc)
+static void jsB_new_Boolean(js_State *J)
 {
 	js_newboolean(J, js_toboolean(J, 1));
 }
 
-static void jsB_Boolean(js_State *J, unsigned int argc)
+static void jsB_Boolean(js_State *J)
 {
 	js_pushboolean(J, js_toboolean(J, 1));
 }
 
-static void Bp_toString(js_State *J, unsigned int argc)
+static void Bp_toString(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	if (self->type != JS_CBOOLEAN) js_typeerror(J, "not a boolean");
@@ -19,7 +19,7 @@
 	js_pushliteral(J, self->u.boolean ? "true" : "false");
 }
 
-static void Bp_valueOf(js_State *J, unsigned int argc)
+static void Bp_valueOf(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	if (self->type != JS_CBOOLEAN) js_typeerror(J, "not a boolean");
--- a/jsbuiltin.c
+++ b/jsbuiltin.c
@@ -28,7 +28,7 @@
 	js_defproperty(J, -2, name, JS_DONTENUM);
 }
 
-static void jsB_eval(js_State *J, unsigned int argc)
+static void jsB_eval(js_State *J)
 {
 	if (!js_isstring(J, -1)) {
 		js_copy(J, 1);
@@ -39,7 +39,7 @@
 	js_call(J, 0);
 }
 
-static void jsB_parseInt(js_State *J, unsigned int argc)
+static void jsB_parseInt(js_State *J)
 {
 	const char *s = js_tostring(J, 1);
 	double radix = js_isdefined(J, 2) ? js_tonumber(J, 2) : 10;
@@ -60,7 +60,7 @@
 		js_pushnumber(J, n);
 }
 
-static void jsB_parseFloat(js_State *J, unsigned int argc)
+static void jsB_parseFloat(js_State *J)
 {
 	const char *s = js_tostring(J, 1);
 	char *e;
@@ -82,13 +82,13 @@
 	}
 }
 
-static void jsB_isNaN(js_State *J, unsigned int argc)
+static void jsB_isNaN(js_State *J)
 {
 	double n = js_tonumber(J, 1);
 	js_pushboolean(J, isnan(n));
 }
 
-static void jsB_isFinite(js_State *J, unsigned int argc)
+static void jsB_isFinite(js_State *J)
 {
 	double n = js_tonumber(J, 1);
 	js_pushboolean(J, isfinite(n));
@@ -164,22 +164,22 @@
 #define URIMARK "-_.!~*`()"
 #define URIUNESCAPED URIALPHA URIDIGIT URIMARK
 
-static void jsB_decodeURI(js_State *J, unsigned int argc)
+static void jsB_decodeURI(js_State *J)
 {
 	Decode(J, js_tostring(J, 1), URIRESERVED "#");
 }
 
-static void jsB_decodeURIComponent(js_State *J, unsigned int argc)
+static void jsB_decodeURIComponent(js_State *J)
 {
 	Decode(J, js_tostring(J, 1), "");
 }
 
-static void jsB_encodeURI(js_State *J, unsigned int argc)
+static void jsB_encodeURI(js_State *J)
 {
 	Encode(J, js_tostring(J, 1), URIUNESCAPED URIRESERVED "#");
 }
 
-static void jsB_encodeURIComponent(js_State *J, unsigned int argc)
+static void jsB_encodeURIComponent(js_State *J)
 {
 	Encode(J, js_tostring(J, 1), URIUNESCAPED);
 }
--- a/jsdate.c
+++ b/jsdate.c
@@ -11,6 +11,8 @@
 #include <sys/time.h>
 #endif
 
+#define js_optnumber(J,I,V) (js_isdefined(J,I) ? js_tonumber(J,I) : V)
+
 static double Now(void)
 {
 #if defined(_WIN32)
@@ -369,48 +371,49 @@
 	js_pushnumber(J, self->u.number);
 }
 
-static void D_parse(js_State *J, unsigned int argc)
+static void D_parse(js_State *J)
 {
 	double t = parseDateTime(js_tostring(J, 1));
 	js_pushnumber(J, t);
 }
 
-static void D_UTC(js_State *J, unsigned int argc)
+static void D_UTC(js_State *J)
 {
 	double y, m, d, H, M, S, ms, t;
 	y = js_tonumber(J, 1);
 	if (y < 100) y += 1900;
 	m = js_tonumber(J, 2);
-	d = argc > 2 ? js_tonumber(J, 3) : 1;
-	H = argc > 3 ? js_tonumber(J, 4) : 0;
-	M = argc > 4 ? js_tonumber(J, 5) : 0;
-	S = argc > 5 ? js_tonumber(J, 6) : 0;
-	ms = argc > 6 ? js_tonumber(J, 7) : 0;
+	d = js_optnumber(J, 3, 1);
+	H = js_optnumber(J, 4, 0);
+	M = js_optnumber(J, 5, 0);
+	S = js_optnumber(J, 6, 0);
+	ms = js_optnumber(J, 7, 0);
 	t = MakeDate(MakeDay(y, m, d), MakeTime(H, M, S, ms));
 	t = TimeClip(t);
 	js_pushnumber(J, t);
 }
 
-static void D_now(js_State *J, unsigned int argc)
+static void D_now(js_State *J)
 {
 	js_pushnumber(J, Now());
 }
 
-static void jsB_Date(js_State *J, unsigned int argc)
+static void jsB_Date(js_State *J)
 {
 	char buf[64];
 	js_pushstring(J, fmtdatetime(buf, LocalTime(Now()), LocalTZA()));
 }
 
-static void jsB_new_Date(js_State *J, unsigned int argc)
+static void jsB_new_Date(js_State *J)
 {
+	unsigned int top = js_gettop(J);
 	js_Object *obj;
 	js_Value v;
 	double t;
 
-	if (argc == 0)
+	if (top == 1)
 		t = Now();
-	else if (argc == 1) {
+	else if (top == 2) {
 		v = js_toprimitive(J, 1, JS_HNONE);
 		if (v.type == JS_TSTRING)
 			t = parseDateTime(v.u.string);
@@ -421,11 +424,11 @@
 		y = js_tonumber(J, 1);
 		if (y < 100) y += 1900;
 		m = js_tonumber(J, 2);
-		d = argc > 2 ? js_tonumber(J, 3) : 1;
-		H = argc > 3 ? js_tonumber(J, 4) : 0;
-		M = argc > 4 ? js_tonumber(J, 5) : 0;
-		S = argc > 5 ? js_tonumber(J, 6) : 0;
-		ms = argc > 6 ? js_tonumber(J, 7) : 0;
+		d = js_optnumber(J, 3, 1);
+		H = js_optnumber(J, 4, 0);
+		M = js_optnumber(J, 5, 0);
+		S = js_optnumber(J, 6, 0);
+		ms = js_optnumber(J, 7, 0);
 		t = MakeDate(MakeDay(y, m, d), MakeTime(H, M, S, ms));
 		t = TimeClip(UTC(t));
 	}
@@ -436,13 +439,13 @@
 	js_pushobject(J, obj);
 }
 
-static void Dp_valueOf(js_State *J, unsigned int argc)
+static void Dp_valueOf(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, t);
 }
 
-static void Dp_toString(js_State *J, unsigned int argc)
+static void Dp_toString(js_State *J)
 {
 	char buf[64];
 	double t = js_todate(J, 0);
@@ -449,7 +452,7 @@
 	js_pushstring(J, fmtdatetime(buf, LocalTime(t), LocalTZA()));
 }
 
-static void Dp_toDateString(js_State *J, unsigned int argc)
+static void Dp_toDateString(js_State *J)
 {
 	char buf[64];
 	double t = js_todate(J, 0);
@@ -456,7 +459,7 @@
 	js_pushstring(J, fmtdate(buf, LocalTime(t)));
 }
 
-static void Dp_toTimeString(js_State *J, unsigned int argc)
+static void Dp_toTimeString(js_State *J)
 {
 	char buf[64];
 	double t = js_todate(J, 0);
@@ -463,7 +466,7 @@
 	js_pushstring(J, fmttime(buf, LocalTime(t), LocalTZA()));
 }
 
-static void Dp_toUTCString(js_State *J, unsigned int argc)
+static void Dp_toUTCString(js_State *J)
 {
 	char buf[64];
 	double t = js_todate(J, 0);
@@ -470,7 +473,7 @@
 	js_pushstring(J, fmtdatetime(buf, t, 0));
 }
 
-static void Dp_toISOString(js_State *J, unsigned int argc)
+static void Dp_toISOString(js_State *J)
 {
 	char buf[64];
 	double t = js_todate(J, 0);
@@ -479,114 +482,114 @@
 	js_pushstring(J, fmtdatetime(buf, t, 0));
 }
 
-static void Dp_getFullYear(js_State *J, unsigned int argc)
+static void Dp_getFullYear(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, YearFromTime(LocalTime(t)));
 }
 
-static void Dp_getMonth(js_State *J, unsigned int argc)
+static void Dp_getMonth(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, MonthFromTime(LocalTime(t)));
 }
 
-static void Dp_getDate(js_State *J, unsigned int argc)
+static void Dp_getDate(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, DateFromTime(LocalTime(t)));
 }
 
-static void Dp_getDay(js_State *J, unsigned int argc)
+static void Dp_getDay(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, WeekDay(LocalTime(t)));
 }
 
-static void Dp_getHours(js_State *J, unsigned int argc)
+static void Dp_getHours(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, HourFromTime(LocalTime(t)));
 }
 
-static void Dp_getMinutes(js_State *J, unsigned int argc)
+static void Dp_getMinutes(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, MinFromTime(LocalTime(t)));
 }
 
-static void Dp_getSeconds(js_State *J, unsigned int argc)
+static void Dp_getSeconds(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, SecFromTime(LocalTime(t)));
 }
 
-static void Dp_getMilliseconds(js_State *J, unsigned int argc)
+static void Dp_getMilliseconds(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, msFromTime(LocalTime(t)));
 }
 
-static void Dp_getUTCFullYear(js_State *J, unsigned int argc)
+static void Dp_getUTCFullYear(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, YearFromTime(t));
 }
 
-static void Dp_getUTCMonth(js_State *J, unsigned int argc)
+static void Dp_getUTCMonth(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, MonthFromTime(t));
 }
 
-static void Dp_getUTCDate(js_State *J, unsigned int argc)
+static void Dp_getUTCDate(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, DateFromTime(t));
 }
 
-static void Dp_getUTCDay(js_State *J, unsigned int argc)
+static void Dp_getUTCDay(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, WeekDay(t));
 }
 
-static void Dp_getUTCHours(js_State *J, unsigned int argc)
+static void Dp_getUTCHours(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, HourFromTime(t));
 }
 
-static void Dp_getUTCMinutes(js_State *J, unsigned int argc)
+static void Dp_getUTCMinutes(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, MinFromTime(t));
 }
 
-static void Dp_getUTCSeconds(js_State *J, unsigned int argc)
+static void Dp_getUTCSeconds(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, SecFromTime(t));
 }
 
-static void Dp_getUTCMilliseconds(js_State *J, unsigned int argc)
+static void Dp_getUTCMilliseconds(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, msFromTime(t));
 }
 
-static void Dp_getTimezoneOffset(js_State *J, unsigned int argc)
+static void Dp_getTimezoneOffset(js_State *J)
 {
 	double t = js_todate(J, 0);
 	js_pushnumber(J, (t - LocalTime(t)) / msPerMinute);
 }
 
-static void Dp_setTime(js_State *J, unsigned int argc)
+static void Dp_setTime(js_State *J)
 {
 	js_setdate(J, 0, js_tonumber(J, 1));
 }
 
-static void Dp_setMilliseconds(js_State *J, unsigned int argc)
+static void Dp_setMilliseconds(js_State *J)
 {
 	double t = LocalTime(js_todate(J, 0));
 	double h = HourFromTime(t);
@@ -596,37 +599,37 @@
 	js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
 }
 
-static void Dp_setSeconds(js_State *J, unsigned int argc)
+static void Dp_setSeconds(js_State *J)
 {
 	double t = LocalTime(js_todate(J, 0));
 	double h = HourFromTime(t);
 	double m = MinFromTime(t);
 	double s = js_tonumber(J, 1);
-	double ms = argc > 1 ? js_tonumber(J, 2) : msFromTime(t);
+	double ms = js_optnumber(J, 2, msFromTime(t));
 	js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
 }
 
-static void Dp_setMinutes(js_State *J, unsigned int argc)
+static void Dp_setMinutes(js_State *J)
 {
 	double t = LocalTime(js_todate(J, 0));
 	double h = HourFromTime(t);
 	double m = js_tonumber(J, 1);
-	double s = argc > 1 ? js_tonumber(J, 2) : SecFromTime(t);
-	double ms = argc > 2 ? js_tonumber(J, 3) : msFromTime(t);
+	double s = js_optnumber(J, 2, SecFromTime(t));
+	double ms = js_optnumber(J, 3, msFromTime(t));
 	js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
 }
 
-static void Dp_setHours(js_State *J, unsigned int argc)
+static void Dp_setHours(js_State *J)
 {
 	double t = LocalTime(js_todate(J, 0));
 	double h = js_tonumber(J, 1);
-	double m = argc > 1 ? js_tonumber(J, 2) : HourFromTime(t);
-	double s = argc > 2 ? js_tonumber(J, 3) : SecFromTime(t);
-	double ms = argc > 3 ? js_tonumber(J, 4) : msFromTime(t);
+	double m = js_optnumber(J, 2, HourFromTime(t));
+	double s = js_optnumber(J, 3, SecFromTime(t));
+	double ms = js_optnumber(J, 4, msFromTime(t));
 	js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
 }
 
-static void Dp_setDate(js_State *J, unsigned int argc)
+static void Dp_setDate(js_State *J)
 {
 	double t = LocalTime(js_todate(J, 0));
 	double y = YearFromTime(t);
@@ -635,25 +638,25 @@
 	js_setdate(J, 0, UTC(MakeDate(MakeDay(y, m, d), TimeWithinDay(t))));
 }
 
-static void Dp_setMonth(js_State *J, unsigned int argc)
+static void Dp_setMonth(js_State *J)
 {
 	double t = LocalTime(js_todate(J, 0));
 	double y = YearFromTime(t);
 	double m = js_tonumber(J, 1);
-	double d = argc > 1 ? js_tonumber(J, 3) : DateFromTime(t);
+	double d = js_optnumber(J, 3, DateFromTime(t));
 	js_setdate(J, 0, UTC(MakeDate(MakeDay(y, m, d), TimeWithinDay(t))));
 }
 
-static void Dp_setFullYear(js_State *J, unsigned int argc)
+static void Dp_setFullYear(js_State *J)
 {
 	double t = LocalTime(js_todate(J, 0));
 	double y = js_tonumber(J, 1);
-	double m = argc > 1 ? js_tonumber(J, 2) : MonthFromTime(t);
-	double d = argc > 2 ? js_tonumber(J, 3) : DateFromTime(t);
+	double m = js_optnumber(J, 2, MonthFromTime(t));
+	double d = js_optnumber(J, 3, DateFromTime(t));
 	js_setdate(J, 0, UTC(MakeDate(MakeDay(y, m, d), TimeWithinDay(t))));
 }
 
-static void Dp_setUTCMilliseconds(js_State *J, unsigned int argc)
+static void Dp_setUTCMilliseconds(js_State *J)
 {
 	double t = js_todate(J, 0);
 	double h = HourFromTime(t);
@@ -663,37 +666,37 @@
 	js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
 }
 
-static void Dp_setUTCSeconds(js_State *J, unsigned int argc)
+static void Dp_setUTCSeconds(js_State *J)
 {
 	double t = js_todate(J, 0);
 	double h = HourFromTime(t);
 	double m = MinFromTime(t);
 	double s = js_tonumber(J, 1);
-	double ms = argc > 1 ? js_tonumber(J, 2) : msFromTime(t);
+	double ms = js_optnumber(J, 2, msFromTime(t));
 	js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
 }
 
-static void Dp_setUTCMinutes(js_State *J, unsigned int argc)
+static void Dp_setUTCMinutes(js_State *J)
 {
 	double t = js_todate(J, 0);
 	double h = HourFromTime(t);
 	double m = js_tonumber(J, 1);
-	double s = argc > 1 ? js_tonumber(J, 2) : SecFromTime(t);
-	double ms = argc > 2 ? js_tonumber(J, 3) : msFromTime(t);
+	double s = js_optnumber(J, 2, SecFromTime(t));
+	double ms = js_optnumber(J, 3, msFromTime(t));
 	js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
 }
 
-static void Dp_setUTCHours(js_State *J, unsigned int argc)
+static void Dp_setUTCHours(js_State *J)
 {
 	double t = js_todate(J, 0);
 	double h = js_tonumber(J, 1);
-	double m = argc > 1 ? js_tonumber(J, 2) : HourFromTime(t);
-	double s = argc > 2 ? js_tonumber(J, 3) : SecFromTime(t);
-	double ms = argc > 3 ? js_tonumber(J, 4) : msFromTime(t);
+	double m = js_optnumber(J, 2, HourFromTime(t));
+	double s = js_optnumber(J, 3, SecFromTime(t));
+	double ms = js_optnumber(J, 4, msFromTime(t));
 	js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
 }
 
-static void Dp_setUTCDate(js_State *J, unsigned int argc)
+static void Dp_setUTCDate(js_State *J)
 {
 	double t = js_todate(J, 0);
 	double y = YearFromTime(t);
@@ -702,25 +705,25 @@
 	js_setdate(J, 0, MakeDate(MakeDay(y, m, d), TimeWithinDay(t)));
 }
 
-static void Dp_setUTCMonth(js_State *J, unsigned int argc)
+static void Dp_setUTCMonth(js_State *J)
 {
 	double t = js_todate(J, 0);
 	double y = YearFromTime(t);
 	double m = js_tonumber(J, 1);
-	double d = argc > 1 ? js_tonumber(J, 3) : DateFromTime(t);
+	double d = js_optnumber(J, 3, DateFromTime(t));
 	js_setdate(J, 0, MakeDate(MakeDay(y, m, d), TimeWithinDay(t)));
 }
 
-static void Dp_setUTCFullYear(js_State *J, unsigned int argc)
+static void Dp_setUTCFullYear(js_State *J)
 {
 	double t = js_todate(J, 0);
 	double y = js_tonumber(J, 1);
-	double m = argc > 1 ? js_tonumber(J, 2) : MonthFromTime(t);
-	double d = argc > 2 ? js_tonumber(J, 3) : DateFromTime(t);
+	double m = js_optnumber(J, 2, MonthFromTime(t));
+	double d = js_optnumber(J, 3, DateFromTime(t));
 	js_setdate(J, 0, MakeDate(MakeDay(y, m, d), TimeWithinDay(t)));
 }
 
-static void Dp_toJSON(js_State *J, unsigned int argc)
+static void Dp_toJSON(js_State *J)
 {
 	js_Object *obj = js_toobject(J, 0);
 	js_Value tv = js_toprimitive(J, 0, JS_HNUMBER);
--- a/jserror.c
+++ b/jserror.c
@@ -5,7 +5,7 @@
 #define QQ(X) #X
 #define Q(X) QQ(X)
 
-static void Ep_toString(js_State *J, unsigned int argc)
+static void Ep_toString(js_State *J)
 {
 	const char *name = "Error";
 	const char *message = "";
@@ -36,7 +36,7 @@
 	}
 }
 
-static int jsB_ErrorX(js_State *J, unsigned int argc, js_Object *prototype)
+static int jsB_ErrorX(js_State *J, js_Object *prototype)
 {
 	js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype));
 	if (js_isdefined(J, 1)) {
@@ -54,8 +54,8 @@
 }
 
 #define DERROR(name, Name) \
-	static void jsB_##Name(js_State *J, unsigned int argc) { \
-		jsB_ErrorX(J, argc, J->Name##_prototype); \
+	static void jsB_##Name(js_State *J) { \
+		jsB_ErrorX(J, J->Name##_prototype); \
 	} \
 	void js_new##name(js_State *J, const char *s) { \
 		js_newerrorx(J, s, J->Name##_prototype); \
--- a/jsfunction.c
+++ b/jsfunction.c
@@ -4,26 +4,26 @@
 #include "jsvalue.h"
 #include "jsbuiltin.h"
 
-static void jsB_Function(js_State *J, unsigned int argc)
+static void jsB_Function(js_State *J)
 {
+	unsigned int i, top = js_gettop(J);
 	const char *source;
 	js_Buffer *sb;
 	js_Ast *parse;
 	js_Function *fun;
-	unsigned int i;
 
 	if (js_isundefined(J, 1))
 		source = "";
 	else {
-		source = js_tostring(J, argc);
 		sb = NULL;
-		if (argc > 1) {
-			for (i = 1; i < argc; ++i) {
+		if (top > 2) {
+			for (i = 1; i < top - 1; ++i) {
 				if (i > 1) js_putc(J, &sb, ',');
 				js_puts(J, &sb, js_tostring(J, i));
 			}
 			js_putc(J, &sb, ')');
 		}
+		source = js_tostring(J, top - 1);
 	}
 
 	if (js_try(J)) {
@@ -42,12 +42,12 @@
 	js_newfunction(J, fun, J->GE);
 }
 
-static void jsB_Function_prototype(js_State *J, unsigned int argc)
+static void jsB_Function_prototype(js_State *J)
 {
 	js_pushundefined(J);
 }
 
-static void Fp_toString(js_State *J, unsigned int argc)
+static void Fp_toString(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	char *s;
@@ -82,7 +82,7 @@
 	}
 }
 
-static void Fp_apply(js_State *J, unsigned int argc)
+static void Fp_apply(js_State *J)
 {
 	int i, n;
 
@@ -99,23 +99,22 @@
 	js_call(J, n);
 }
 
-static void Fp_call(js_State *J, unsigned int argc)
+static void Fp_call(js_State *J)
 {
-	unsigned int i;
+	unsigned int i, top = js_gettop(J);
 
 	if (!js_iscallable(J, 0))
 		js_typeerror(J, "not a function");
 
-	js_copy(J, 0);
-	js_copy(J, 1);
-	for (i = 2; i <= argc; ++i)
+	for (i = 0; i < top; ++i)
 		js_copy(J, i);
 
-	js_call(J, argc - 1);
+	js_call(J, top - 2);
 }
 
-static void callbound(js_State *J, unsigned int argc)
+static void callbound(js_State *J)
 {
+	unsigned int top = js_gettop(J);
 	unsigned int i, fun, args, n;
 
 	fun = js_gettop(J);
@@ -130,14 +129,15 @@
 		js_getindex(J, args, i);
 	js_remove(J, args);
 
-	for (i = 1; i <= argc; ++i)
+	for (i = 1; i < top; ++i)
 		js_copy(J, i);
 
-	js_call(J, n + argc);
+	js_call(J, n + top - 1);
 }
 
-static void constructbound(js_State *J, unsigned int argc)
+static void constructbound(js_State *J)
 {
+	unsigned int top = js_gettop(J);
 	unsigned int i, fun, args, n;
 
 	fun = js_gettop(J);
@@ -151,22 +151,23 @@
 		js_getindex(J, args, i);
 	js_remove(J, args);
 
-	for (i = 1; i <= argc; ++i)
+	for (i = 1; i < top; ++i)
 		js_copy(J, i);
 
-	js_construct(J, n + argc);
+	js_construct(J, n + top - 1);
 }
 
-static void Fp_bind(js_State *J, unsigned int argc)
+static void Fp_bind(js_State *J)
 {
-	unsigned int i, n;
+	unsigned int i, top = js_gettop(J);
+	unsigned int n;
 
 	if (!js_iscallable(J, 0))
 		js_typeerror(J, "not a function");
 
 	n = js_getlength(J, 0);
-	if (argc - 1 < n)
-		n -= argc - 1;
+	if (n > top - 2)
+		n -= top - 2;
 	else
 		n = 0;
 
@@ -186,9 +187,9 @@
 
 	/* bound arguments */
 	js_newarray(J);
-	for (i = 2; i <= argc; ++i) {
+	for (i = 2; i < top; ++i) {
 		js_copy(J, i);
-		js_setindex(J, -2, i-2);
+		js_setindex(J, -2, i - 2);
 	}
 	js_defproperty(J, -2, "__BoundArguments__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
 }
--- a/jsmath.c
+++ b/jsmath.c
@@ -2,106 +2,106 @@
 #include "jsvalue.h"
 #include "jsbuiltin.h"
 
-static void Math_abs(js_State *J, unsigned int argc)
+static void Math_abs(js_State *J)
 {
 	js_pushnumber(J, abs(js_tonumber(J, 1)));
 }
 
-static void Math_acos(js_State *J, unsigned int argc)
+static void Math_acos(js_State *J)
 {
 	js_pushnumber(J, acos(js_tonumber(J, 1)));
 }
 
-static void Math_asin(js_State *J, unsigned int argc)
+static void Math_asin(js_State *J)
 {
 	js_pushnumber(J, asin(js_tonumber(J, 1)));
 }
 
-static void Math_atan(js_State *J, unsigned int argc)
+static void Math_atan(js_State *J)
 {
 	js_pushnumber(J, atan(js_tonumber(J, 1)));
 }
 
-static void Math_atan2(js_State *J, unsigned int argc)
+static void Math_atan2(js_State *J)
 {
 	js_pushnumber(J, atan2(js_tonumber(J, 1), js_tonumber(J, 2)));
 }
 
-static void Math_ceil(js_State *J, unsigned int argc)
+static void Math_ceil(js_State *J)
 {
 	js_pushnumber(J, ceil(js_tonumber(J, 1)));
 }
 
-static void Math_cos(js_State *J, unsigned int argc)
+static void Math_cos(js_State *J)
 {
 	js_pushnumber(J, cos(js_tonumber(J, 1)));
 }
 
-static void Math_exp(js_State *J, unsigned int argc)
+static void Math_exp(js_State *J)
 {
 	js_pushnumber(J, exp(js_tonumber(J, 1)));
 }
 
-static void Math_floor(js_State *J, unsigned int argc)
+static void Math_floor(js_State *J)
 {
 	js_pushnumber(J, floor(js_tonumber(J, 1)));
 }
 
-static void Math_log(js_State *J, unsigned int argc)
+static void Math_log(js_State *J)
 {
 	js_pushnumber(J, log(js_tonumber(J, 1)));
 }
 
-static void Math_pow(js_State *J, unsigned int argc)
+static void Math_pow(js_State *J)
 {
 	js_pushnumber(J, pow(js_tonumber(J, 1), js_tonumber(J, 2)));
 }
 
-static void Math_random(js_State *J, unsigned int argc)
+static void Math_random(js_State *J)
 {
 	js_pushnumber(J, (double)rand() / (RAND_MAX - 1));
 }
 
-static void Math_round(js_State *J, unsigned int argc)
+static void Math_round(js_State *J)
 {
 	js_pushnumber(J, round(js_tonumber(J, 1)));
 }
 
-static void Math_sin(js_State *J, unsigned int argc)
+static void Math_sin(js_State *J)
 {
 	js_pushnumber(J, sin(js_tonumber(J, 1)));
 }
 
-static void Math_sqrt(js_State *J, unsigned int argc)
+static void Math_sqrt(js_State *J)
 {
 	js_pushnumber(J, sqrt(js_tonumber(J, 1)));
 }
 
-static void Math_tan(js_State *J, unsigned int argc)
+static void Math_tan(js_State *J)
 {
 	js_pushnumber(J, tan(js_tonumber(J, 1)));
 }
 
-static void Math_max(js_State *J, unsigned int argc)
+static void Math_max(js_State *J)
 {
-	double n = js_tonumber(J, 1);
-	unsigned int i;
-	for (i = 2; i <= argc; ++i) {
-		double m = js_tonumber(J, i);
-		n = n > m ? n : m;
+	unsigned int i, n = js_gettop(J);
+	double x = js_tonumber(J, 1);
+	for (i = 2; i < n; ++i) {
+		double y = js_tonumber(J, i);
+		x = x > y ? x : y;
 	}
-	js_pushnumber(J, n);
+	js_pushnumber(J, x);
 }
 
-static void Math_min(js_State *J, unsigned int argc)
+static void Math_min(js_State *J)
 {
-	double n = js_tonumber(J, 1);
-	unsigned int i;
-	for (i = 2; i <= argc; ++i) {
-		double m = js_tonumber(J, i);
-		n = n < m ? n : m;
+	unsigned int i, n = js_gettop(J);
+	double x = js_tonumber(J, 1);
+	for (i = 2; i < n; ++i) {
+		double y = js_tonumber(J, i);
+		x = x < y ? x : y;
 	}
-	js_pushnumber(J, n);
+	js_pushnumber(J, x);
 }
 
 void jsB_initmath(js_State *J)
--- a/jsnumber.c
+++ b/jsnumber.c
@@ -2,17 +2,17 @@
 #include "jsvalue.h"
 #include "jsbuiltin.h"
 
-static void jsB_new_Number(js_State *J, unsigned int argc)
+static void jsB_new_Number(js_State *J)
 {
 	js_newnumber(J, js_isdefined(J, 1) ? js_tonumber(J, 1) : 0);
 }
 
-static void jsB_Number(js_State *J, unsigned int argc)
+static void jsB_Number(js_State *J)
 {
 	js_pushnumber(J, js_isdefined(J, 1) ? js_tonumber(J, 1) : 0);
 }
 
-static void Np_valueOf(js_State *J, unsigned int argc)
+static void Np_valueOf(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
@@ -19,7 +19,7 @@
 	js_pushnumber(J, self->u.number);
 }
 
-static void Np_toString(js_State *J, unsigned int argc)
+static void Np_toString(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	int radix = js_isundefined(J, 1) ? 10 : js_tointeger(J, 1);
@@ -44,7 +44,7 @@
 	}
 }
 
-static void Np_toFixed(js_State *J, unsigned int argc)
+static void Np_toFixed(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	int width = js_tointeger(J, 1);
@@ -52,7 +52,7 @@
 	numtostr(J, "%.*f", width, self->u.number);
 }
 
-static void Np_toExponential(js_State *J, unsigned int argc)
+static void Np_toExponential(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	int width = js_tointeger(J, 1);
@@ -60,7 +60,7 @@
 	numtostr(J, "%.*e", width, self->u.number);
 }
 
-static void Np_toPrecision(js_State *J, unsigned int argc)
+static void Np_toPrecision(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	int width = js_tointeger(J, 1);
--- a/jsobject.c
+++ b/jsobject.c
@@ -2,23 +2,23 @@
 #include "jsvalue.h"
 #include "jsbuiltin.h"
 
-static void jsB_new_Object(js_State *J, unsigned int argc)
+static void jsB_new_Object(js_State *J)
 {
-	if (argc == 0 || js_isundefined(J, 1) || js_isnull(J, 1))
+	if (js_isundefined(J, 1) || js_isnull(J, 1))
 		js_newobject(J);
 	else
 		js_pushobject(J, js_toobject(J, 1));
 }
 
-static void jsB_Object(js_State *J, unsigned int argc)
+static void jsB_Object(js_State *J)
 {
-	if (argc == 0 || js_isundefined(J, 1) || js_isnull(J, 1))
+	if (js_isundefined(J, 1) || js_isnull(J, 1))
 		js_newobject(J);
 	else
 		js_pushobject(J, js_toobject(J, 1));
 }
 
-static void Op_toString(js_State *J, unsigned int argc)
+static void Op_toString(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	switch (self->type) {
@@ -46,12 +46,12 @@
 	}
 }
 
-static void Op_valueOf(js_State *J, unsigned int argc)
+static void Op_valueOf(js_State *J)
 {
 	js_copy(J, 0);
 }
 
-static void Op_hasOwnProperty(js_State *J, unsigned int argc)
+static void Op_hasOwnProperty(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	const char *name = js_tostring(J, 1);
@@ -59,7 +59,7 @@
 	js_pushboolean(J, ref != NULL);
 }
 
-static void Op_isPrototypeOf(js_State *J, unsigned int argc)
+static void Op_isPrototypeOf(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	if (js_isobject(J, 1)) {
@@ -75,7 +75,7 @@
 	js_pushboolean(J, 0);
 }
 
-static void Op_propertyIsEnumerable(js_State *J, unsigned int argc)
+static void Op_propertyIsEnumerable(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	const char *name = js_tostring(J, 1);
@@ -83,7 +83,7 @@
 	js_pushboolean(J, ref && !(ref->atts & JS_DONTENUM));
 }
 
-static void O_getPrototypeOf(js_State *J, unsigned int argc)
+static void O_getPrototypeOf(js_State *J)
 {
 	js_Object *obj;
 	if (!js_isobject(J, 1))
@@ -95,7 +95,7 @@
 		js_pushnull(J);
 }
 
-static void O_getOwnPropertyDescriptor(js_State *J, unsigned int argc)
+static void O_getOwnPropertyDescriptor(js_State *J)
 {
 	js_Object *obj;
 	js_Property *ref;
@@ -131,7 +131,7 @@
 	}
 }
 
-static void O_getOwnPropertyNames(js_State *J, unsigned int argc)
+static void O_getOwnPropertyNames(js_State *J)
 {
 	js_Object *obj;
 	js_Property *ref;
@@ -231,7 +231,7 @@
 	js_pop(J, 2);
 }
 
-static void O_defineProperty(js_State *J, unsigned int argc)
+static void O_defineProperty(js_State *J)
 {
 	if (!js_isobject(J, 1)) js_typeerror(J, "not an object");
 	if (!js_isobject(J, 3)) js_typeerror(J, "not an object");
@@ -239,7 +239,7 @@
 	js_copy(J, 1);
 }
 
-static void O_defineProperties(js_State *J, unsigned int argc)
+static void O_defineProperties(js_State *J)
 {
 	js_Object *props;
 	js_Property *ref;
@@ -259,7 +259,7 @@
 	js_copy(J, 1);
 }
 
-static void O_create(js_State *J, unsigned int argc)
+static void O_create(js_State *J)
 {
 	js_Object *obj;
 	js_Object *proto;
@@ -288,7 +288,7 @@
 	}
 }
 
-static void O_keys(js_State *J, unsigned int argc)
+static void O_keys(js_State *J)
 {
 	js_Object *obj;
 	js_Property *ref;
@@ -317,7 +317,7 @@
 	}
 }
 
-static void O_preventExtensions(js_State *J, unsigned int argc)
+static void O_preventExtensions(js_State *J)
 {
 	if (!js_isobject(J, 1))
 		js_typeerror(J, "not an object");
@@ -325,7 +325,7 @@
 	js_copy(J, 1);
 }
 
-static void O_isExtensible(js_State *J, unsigned int argc)
+static void O_isExtensible(js_State *J)
 {
 	if (!js_isobject(J, 1))
 		js_typeerror(J, "not an object");
@@ -332,7 +332,7 @@
 	js_pushboolean(J, js_toobject(J, 1)->extensible);
 }
 
-static void O_seal(js_State *J, unsigned int argc)
+static void O_seal(js_State *J)
 {
 	js_Object *obj;
 	js_Property *ref;
@@ -349,7 +349,7 @@
 	js_copy(J, 1);
 }
 
-static void O_isSealed(js_State *J, unsigned int argc)
+static void O_isSealed(js_State *J)
 {
 	js_Object *obj;
 	js_Property *ref;
@@ -373,7 +373,7 @@
 	js_pushboolean(J, 1);
 }
 
-static void O_freeze(js_State *J, unsigned int argc)
+static void O_freeze(js_State *J)
 {
 	js_Object *obj;
 	js_Property *ref;
@@ -390,7 +390,7 @@
 	js_copy(J, 1);
 }
 
-static void O_isFrozen(js_State *J, unsigned int argc)
+static void O_isFrozen(js_State *J)
 {
 	js_Object *obj;
 	js_Property *ref;
--- a/json.c
+++ b/json.c
@@ -92,7 +92,7 @@
 	}
 }
 
-static void JSON_parse(js_State *J, unsigned int argc)
+static void JSON_parse(js_State *J)
 {
 	const char *source = js_tostring(J, 1);
 	jsY_initlex(J, "JSON", source);
@@ -234,10 +234,10 @@
 	return 1;
 }
 
-static void JSON_stringify(js_State *J, unsigned int argc)
+static void JSON_stringify(js_State *J)
 {
 	js_Buffer *sb = NULL;
-	if (argc > 0) {
+	if (js_isdefined(J, 1)) {
 		js_copy(J, 1);
 		if (fmtvalue(J, &sb, "")) {
 			js_putc(J, &sb, 0);
--- a/jsregexp.c
+++ b/jsregexp.c
@@ -63,7 +63,7 @@
 	js_pushnull(J);
 }
 
-static void Rp_test(js_State *J, unsigned int argc)
+static void Rp_test(js_State *J)
 {
 	js_Regexp *re;
 	const char *text;
@@ -99,7 +99,7 @@
 	js_pushboolean(J, 0);
 }
 
-static void jsB_new_RegExp(js_State *J, unsigned int argc)
+static void jsB_new_RegExp(js_State *J)
 {
 	js_Regexp *old;
 	const char *pattern;
@@ -140,14 +140,14 @@
 	js_newregexp(J, pattern, flags);
 }
 
-static void jsB_RegExp(js_State *J, unsigned int argc)
+static void jsB_RegExp(js_State *J)
 {
-	if (js_isregexp(J, 1) && argc == 1)
+	if (js_gettop(J) == 2 && js_isregexp(J, 1))
 		return;
-	jsB_new_RegExp(J, argc);
+	jsB_new_RegExp(J);
 }
 
-static void Rp_toString(js_State *J, unsigned int argc)
+static void Rp_toString(js_State *J)
 {
 	js_Regexp *re;
 	char *out;
@@ -172,7 +172,7 @@
 	js_free(J, out);
 }
 
-static void Rp_exec(js_State *J, unsigned int argc)
+static void Rp_exec(js_State *J)
 {
 	js_RegExp_prototype_exec(J, js_toregexp(J, 0), js_tostring(J, 1));
 }
--- a/jsrun.c
+++ b/jsrun.c
@@ -886,7 +886,7 @@
 	for (i = n; i < min; ++i)
 		js_pushundefined(J);
 
-	F(J, n);
+	F(J);
 	v = js_tovalue(J, -1);
 	TOP = --BOT; /* clear stack */
 	js_pushvalue(J, v);
--- a/jsstring.c
+++ b/jsstring.c
@@ -48,17 +48,17 @@
 	return i;
 }
 
-static void jsB_new_String(js_State *J, unsigned int argc)
+static void jsB_new_String(js_State *J)
 {
 	js_newstring(J, js_isdefined(J, 1) ? js_tostring(J, 1) : "");
 }
 
-static void jsB_String(js_State *J, unsigned int argc)
+static void jsB_String(js_State *J)
 {
 	js_pushliteral(J, js_isdefined(J, 1) ? js_tostring(J, 1) : "");
 }
 
-static void Sp_toString(js_State *J, unsigned int argc)
+static void Sp_toString(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
@@ -65,7 +65,7 @@
 	js_pushliteral(J, self->u.s.string);
 }
 
-static void Sp_valueOf(js_State *J, unsigned int argc)
+static void Sp_valueOf(js_State *J)
 {
 	js_Object *self = js_toobject(J, 0);
 	if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
@@ -72,7 +72,7 @@
 	js_pushliteral(J, self->u.s.string);
 }
 
-static void Sp_charAt(js_State *J, unsigned int argc)
+static void Sp_charAt(js_State *J)
 {
 	char buf[UTFmax + 1];
 	const char *s = js_tostring(J, 0);
@@ -86,7 +86,7 @@
 	}
 }
 
-static void Sp_charCodeAt(js_State *J, unsigned int argc)
+static void Sp_charCodeAt(js_State *J)
 {
 	const char *s = js_tostring(J, 0);
 	int pos = js_tointeger(J, 1);
@@ -97,13 +97,14 @@
 		js_pushnumber(J, NAN);
 }
 
-static void Sp_concat(js_State *J, unsigned int argc)
+static void Sp_concat(js_State *J)
 {
+	unsigned int i, top = js_gettop(J);
+	unsigned int n;
 	char * volatile out;
 	const char *s;
-	unsigned int i, n;
 
-	if (argc == 0)
+	if (top == 1)
 		return;
 
 	s = js_tostring(J, 0);
@@ -116,7 +117,7 @@
 		js_throw(J);
 	}
 
-	for (i = 1; i <= argc; ++i) {
+	for (i = 1; i < top; ++i) {
 		s = js_tostring(J, i);
 		n += strlen(s);
 		out = realloc(out, n + 1);
@@ -128,7 +129,7 @@
 	js_free(J, out);
 }
 
-static void Sp_indexOf(js_State *J, unsigned int argc)
+static void Sp_indexOf(js_State *J)
 {
 	const char *haystack = js_tostring(J, 0);
 	const char *needle = js_tostring(J, 1);
@@ -147,7 +148,7 @@
 	js_pushnumber(J, -1);
 }
 
-static void Sp_lastIndexOf(js_State *J, unsigned int argc)
+static void Sp_lastIndexOf(js_State *J)
 {
 	const char *haystack = js_tostring(J, 0);
 	const char *needle = js_tostring(J, 1);
@@ -164,7 +165,7 @@
 	js_pushnumber(J, last);
 }
 
-static void Sp_localeCompare(js_State *J, unsigned int argc)
+static void Sp_localeCompare(js_State *J)
 {
 	const char *a = js_tostring(J, 0);
 	const char *b = js_tostring(J, 1);
@@ -171,7 +172,7 @@
 	js_pushnumber(J, strcmp(a, b));
 }
 
-static void Sp_slice(js_State *J, unsigned int argc)
+static void Sp_slice(js_State *J)
 {
 	const char *str = js_tostring(J, 0);
 	const char *ss, *ee;
@@ -196,7 +197,7 @@
 	js_pushlstring(J, ss, ee - ss);
 }
 
-static void Sp_substring(js_State *J, unsigned int argc)
+static void Sp_substring(js_State *J)
 {
 	const char *str = js_tostring(J, 0);
 	const char *ss, *ee;
@@ -218,7 +219,7 @@
 	js_pushlstring(J, ss, ee - ss);
 }
 
-static void Sp_toLowerCase(js_State *J, unsigned int argc)
+static void Sp_toLowerCase(js_State *J)
 {
 	const char *src = js_tostring(J, 0);
 	char *dst = js_malloc(J, UTFmax * strlen(src) + 1);
@@ -240,7 +241,7 @@
 	js_free(J, dst);
 }
 
-static void Sp_toUpperCase(js_State *J, unsigned int argc)
+static void Sp_toUpperCase(js_State *J)
 {
 	const char *src = js_tostring(J, 0);
 	char *dst = js_malloc(J, UTFmax * strlen(src) + 1);
@@ -268,7 +269,7 @@
 		c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
 }
 
-static void Sp_trim(js_State *J, unsigned int argc)
+static void Sp_trim(js_State *J)
 {
 	const char *s, *e;
 	s = js_tostring(J, 0);
@@ -280,13 +281,13 @@
 	js_pushlstring(J, s, e - s);
 }
 
-static void S_fromCharCode(js_State *J, unsigned int argc)
+static void S_fromCharCode(js_State *J)
 {
-	unsigned int i;
+	unsigned int i, top = js_gettop(J);
 	Rune c;
 	char *s, *p;
 
-	s = p = js_malloc(J, argc * UTFmax + 1);
+	s = p = js_malloc(J, (top-1) * UTFmax + 1);
 
 	if (js_try(J)) {
 		js_free(J, s);
@@ -293,7 +294,7 @@
 		js_throw(J);
 	}
 
-	for (i = 1; i <= argc; ++i) {
+	for (i = 1; i < top; ++i) {
 		c = js_touint16(J, i);
 		p += runetochar(p, &c);
 	}
@@ -304,7 +305,7 @@
 	js_free(J, s);
 }
 
-static void Sp_match(js_State *J, unsigned int argc)
+static void Sp_match(js_State *J)
 {
 	js_Regexp *re;
 	const char *text;
@@ -350,7 +351,7 @@
 	}
 }
 
-static void Sp_search(js_State *J, unsigned int argc)
+static void Sp_search(js_State *J)
 {
 	js_Regexp *re;
 	const char *text;
@@ -373,7 +374,7 @@
 		js_pushnumber(J, -1);
 }
 
-static void Sp_replace_regexp(js_State *J, unsigned int argc)
+static void Sp_replace_regexp(js_State *J)
 {
 	js_Regexp *re;
 	const char *source, *s, *r;
@@ -473,7 +474,7 @@
 	js_free(J, sb);
 }
 
-static void Sp_replace_string(js_State *J, unsigned int argc)
+static void Sp_replace_string(js_State *J)
 {
 	const char *source, *needle, *s, *r;
 	js_Buffer *sb = NULL;
@@ -532,15 +533,15 @@
 	js_free(J, sb);
 }
 
-static void Sp_replace(js_State *J, unsigned int argc)
+static void Sp_replace(js_State *J)
 {
 	if (js_isregexp(J, 1))
-		Sp_replace_regexp(J, argc);
+		Sp_replace_regexp(J);
 	else
-		Sp_replace_string(J, argc);
+		Sp_replace_string(J);
 }
 
-static void Sp_split_regexp(js_State *J, unsigned int argc)
+static void Sp_split_regexp(js_State *J)
 {
 	js_Regexp *re;
 	const char *text;
@@ -599,7 +600,7 @@
 	js_setindex(J, -2, len);
 }
 
-static void Sp_split_string(js_State *J, unsigned int argc)
+static void Sp_split_string(js_State *J)
 {
 	const char *str = js_tostring(J, 0);
 	const char *sep = js_tostring(J, 1);
@@ -636,7 +637,7 @@
 	}
 }
 
-static void Sp_split(js_State *J, unsigned int argc)
+static void Sp_split(js_State *J)
 {
 	if (js_isundefined(J, 1)) {
 		js_newarray(J);
@@ -643,9 +644,9 @@
 		js_copy(J, 0);
 		js_setindex(J, -2, 0);
 	} else if (js_isregexp(J, 1)) {
-		Sp_split_regexp(J, argc);
+		Sp_split_regexp(J);
 	} else {
-		Sp_split_string(J, argc);
+		Sp_split_string(J);
 	}
 }
 
--- a/main.c
+++ b/main.c
@@ -4,7 +4,7 @@
 
 #define PS1 "> "
 
-static void jsB_gc(js_State *J, unsigned int argc)
+static void jsB_gc(js_State *J)
 {
 	int report = js_toboolean(J, 1);
 	js_gc(J, report);
@@ -11,7 +11,7 @@
 	js_pushundefined(J);
 }
 
-static void jsB_load(js_State *J, unsigned int argc)
+static void jsB_load(js_State *J)
 {
 	const char *filename = js_tostring(J, 1);
 	int rv = js_dofile(J, filename);
@@ -18,10 +18,10 @@
 	js_pushboolean(J, !rv);
 }
 
-static void jsB_print(js_State *J, unsigned int argc)
+static void jsB_print(js_State *J)
 {
-	unsigned int i;
-	for (i = 1; i <= argc; ++i) {
+	unsigned int i, top = js_gettop(J);
+	for (i = 1; i < top; ++i) {
 		const char *s = js_tostring(J, i);
 		if (i > 1) putchar(' ');
 		fputs(s, stdout);