From caf466b11205bf18420be58b4cb6ecb41e1a5ccc Mon Sep 17 00:00:00 2001 From: "igor%mir2.org" Date: Thu, 26 Jan 2006 08:47:51 +0000 Subject: [PATCH] Bug 319719: JS scanner checks for keywords using pregenerated C source avoiding the cost of atomizing keyword strings. This is an updated version of the previous rather bad commit to address Makefile issues. r=brendan git-svn-id: svn://10.0.0.236/trunk@188224 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js/src/Makefile.in | 11 + mozilla/js/src/Makefile.ref | 48 +++- mozilla/js/src/config.mk | 16 ++ mozilla/js/src/jsapi.c | 2 +- mozilla/js/src/jsatom.c | 9 +- mozilla/js/src/jsatom.h | 11 +- mozilla/js/src/jsbool.c | 2 +- mozilla/js/src/jscntxt.c | 2 - mozilla/js/src/jsconfig.h | 5 + mozilla/js/src/jsfun.c | 19 +- mozilla/js/src/jskeyword.tbl | 127 ++++++++++ mozilla/js/src/jskwgen.c | 460 +++++++++++++++++++++++++++++++++++ mozilla/js/src/jsobj.c | 9 +- mozilla/js/src/jsopcode.c | 36 +-- mozilla/js/src/jsscan.c | 192 ++++++--------- mozilla/js/src/jsscan.h | 4 +- mozilla/js/src/jsxml.c | 8 +- mozilla/js/src/rules.mk | 2 +- 18 files changed, 767 insertions(+), 196 deletions(-) create mode 100644 mozilla/js/src/jskeyword.tbl create mode 100644 mozilla/js/src/jskwgen.c diff --git a/mozilla/js/src/Makefile.in b/mozilla/js/src/Makefile.in index 79b9eca7390..72e714b16ac 100644 --- a/mozilla/js/src/Makefile.in +++ b/mozilla/js/src/Makefile.in @@ -104,6 +104,7 @@ CSRCS = \ EXPORTS = \ jsautocfg.h \ + jsautokw.h \ js.msg \ jsapi.h \ jsarray.h \ @@ -193,6 +194,11 @@ JSJAVA_CFLAGS = \ -I$(topsrcdir)/sun-java/include \ $(JSJAVA_STUBHEADERS) +# Define keyword generator before rules.mk, see bug 323979 comment 50 + +HOST_SIMPLE_PROGRAMS += host_jskwgen$(HOST_BIN_SUFFIX) +GARBAGE += jsautokw.h host_jskwgen$(HOST_BIN_SUFFIX) + include $(topsrcdir)/config/rules.mk DEFINES += -DEXPORT_JS_API @@ -392,3 +398,8 @@ jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.c Makefile.in endif endif +# Extra dependancies and rules for keyword switch code +jsscan.$(OBJ_SUFFIX): jsautokw.h jskeyword.tbl + +jsautokw.h: host_jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl + $< $@ diff --git a/mozilla/js/src/Makefile.ref b/mozilla/js/src/Makefile.ref index fb7d2a19a28..8e008c3f2c4 100644 --- a/mozilla/js/src/Makefile.ref +++ b/mozilla/js/src/Makefile.ref @@ -64,6 +64,9 @@ else OTHER_LIBS += -Lfdlibm/$(OBJDIR) -lfdm endif +# Look in OBJDIR to find jsautocfg.h and jsautokw.h +INCLUDES += -I$(OBJDIR) + ifdef JS_THREADSAFE DEFINES += -DJS_THREADSAFE INCLUDES += -I../../dist/$(OBJDIR)/include @@ -120,9 +123,9 @@ endif # # Server-related changes : # -ifdef NES40 -DEFINES += -DNES40 -endif +ifdef NES40 +DEFINES += -DNES40 +endif # # Line editing support. @@ -203,11 +206,13 @@ OTHER_HFILES = \ jsopcode.tbl \ js.msg \ jsshell.msg \ + jskeyword.tbl \ $(NULL) ifndef PREBUILT_CPUCFG OTHER_HFILES += $(OBJDIR)/jsautocfg.h endif +OTHER_HFILES += $(OBJDIR)/jsautokw.h HFILES = $(JS_HFILES) $(API_HFILES) $(OTHER_HFILES) @@ -255,14 +260,14 @@ FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/fdlibm.lib else FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/libfdm.a endif -JSMATH_PRELINK = $(OBJDIR)/jsmathtemp.o +JSMATH_PRELINK = $(OBJDIR)/jsmathtemp.$(OBJ_SUFFIX) # Flag for incremental linking DASH_R = -r ifeq ($(OS_ARCH),QNX) ifneq ($(OS_TARGET),NTO) # Don't use wildcard here, because we only want this resolved at link time. -OBJS += fdlibm/*.o +OBJS += fdlibm/*.$(OBJ_SUFFIX) endif endif @@ -303,6 +308,33 @@ include jsconfig.mk nsinstall-target: cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR) + +# +# Rules for keyword switch generation +# + +GARBAGE += $(OBJDIR)/jsautokw.h $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) +GARBAGE += $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) + +$(OBJDIR)/jsscan.$(OBJ_SUFFIX): $(OBJDIR)/jsautokw.h jskeyword.tbl + +$(OBJDIR)/jskwgen.$(OBJ_SUFFIX): jskwgen.c jskeyword.tbl + +$(OBJDIR)/jsautokw.h: $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl + $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) $@ + +ifdef USE_MSVC +$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) + link.exe -out:"$@" $(EXE_LINK_FLAGS) $^ +else +$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) + $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ +endif + +# +# JS shell executable +# + ifdef USE_MSVC $(PROGRAM): $(PROG_OBJS) $(LIBRARY) $(FDLIBM_LIBRARY) link.exe -out:"$@" $(EXE_LINK_FLAGS) $^ @@ -327,15 +359,11 @@ $(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg $(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o $(CC) -o $@ $(OBJDIR)/jscpucfg.o -# Look in OBJDIR to find jsautocfg.h -INCLUDES += -I$(OBJDIR) - # Add to TARGETS for clobber rule TARGETS += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg \ $(OBJDIR)/jscpucfg.o $(OBJDIR)/jsmathtemp.o endif - # special rule for jsmath.o since we want to incrementally link # against fdlibm to pull in only what is needed $(OBJDIR)/jsmath.o: jsmath.c jsmath.h jslibmath.h $(FDLIBM_LIBRARY) @@ -348,7 +376,7 @@ endif ifeq ($(OS_ARCH),QNX) ifneq ($(OS_TARGET),NTO) @cp $(JSMATH_PRELINK) $@ -else +else $(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY) endif else diff --git a/mozilla/js/src/config.mk b/mozilla/js/src/config.mk index 1eb01a52f16..3cd8644ffd9 100644 --- a/mozilla/js/src/config.mk +++ b/mozilla/js/src/config.mk @@ -149,6 +149,22 @@ CLASSPATH = $(JDK)/lib/classes.zip$(SEP)$(CLASSDIR)/$(OBJDIR) include $(DEPTH)/config/$(OS_CONFIG).mk +ifndef OBJ_SUFFIX +ifdef USE_MSVC +OBJ_SUFFIX = obj +else +OBJ_SUFFIX = o +endif +endif + +ifndef HOST_BIN_SUFFIX +ifeq ($(OS_ARCH),WINNT) +HOST_BIN_SUFFIX = .exe +else +HOST_BIN_SUFFIX = +endif +endif + # Name of the binary code directories ifdef BUILD_IDG OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).OBJD diff --git a/mozilla/js/src/jsapi.c b/mozilla/js/src/jsapi.c index c353b56b9cc..5d08178c95e 100644 --- a/mozilla/js/src/jsapi.c +++ b/mozilla/js/src/jsapi.c @@ -637,7 +637,7 @@ JS_GetTypeName(JSContext *cx, JSType type) { if ((uintN)type >= (uintN)JSTYPE_LIMIT) return NULL; - return js_type_str[type]; + return js_type_strs[type]; } /************************************************************************/ diff --git a/mozilla/js/src/jsatom.c b/mozilla/js/src/jsatom.c index ff5abe7a3a1..99453d38f89 100644 --- a/mozilla/js/src/jsatom.c +++ b/mozilla/js/src/jsatom.c @@ -71,7 +71,7 @@ extern const char js_Error_str[]; /* trivial, from jsexn.h */ * Keep this in sync with jspubtd.h -- an assertion below will insist that * its length match the JSType enum's JSTYPE_LIMIT limit value. */ -const char *js_type_str[] = { +const char *js_type_strs[] = { "undefined", js_object_str, "function", @@ -82,7 +82,7 @@ const char *js_type_str[] = { "xml", }; -const char *js_boolean_str[] = { +const char *js_boolean_strs[] = { js_false_str, js_true_str }; @@ -122,7 +122,6 @@ const char js_name_str[] = "name"; const char js_noSuchMethod_str[] = "__noSuchMethod__"; const char js_object_str[] = "object"; const char js_parent_str[] = "__parent__"; -const char js_private_str[] = "private"; const char js_proto_str[] = "__proto__"; const char js_setter_str[] = "setter"; const char js_set_str[] = "set"; @@ -294,9 +293,9 @@ js_InitPinnedAtoms(JSContext *cx, JSAtomState *state) return JS_FALSE; \ JS_END_MACRO - JS_ASSERT(sizeof js_type_str / sizeof js_type_str[0] == JSTYPE_LIMIT); + JS_ASSERT(sizeof js_type_strs / sizeof js_type_strs[0] == JSTYPE_LIMIT); for (i = 0; i < JSTYPE_LIMIT; i++) - FROB(typeAtoms[i], js_type_str[i]); + FROB(typeAtoms[i], js_type_strs[i]); FROB(booleanAtoms[0], js_false_str); FROB(booleanAtoms[1], js_true_str); diff --git a/mozilla/js/src/jsatom.h b/mozilla/js/src/jsatom.h index f8ce3f90f77..f6009c148cd 100644 --- a/mozilla/js/src/jsatom.h +++ b/mozilla/js/src/jsatom.h @@ -63,8 +63,8 @@ JS_BEGIN_EXTERN_C #define ATOM_TMPSTR 0x80 /* internal, to avoid extra string */ struct JSAtom { - JSHashEntry entry; /* key is jsval, value keyword info or - unhidden atom if ATOM_HIDDEN */ + JSHashEntry entry; /* key is jsval or unhidden atom + if ATOM_HIDDEN */ uint32 flags; /* pinned, interned, and mark flags */ jsatomid number; /* atom serial number and hash code */ }; @@ -89,9 +89,6 @@ struct JSAtom { extern JS_FRIEND_API(const char *) js_AtomToPrintableString(JSContext *cx, JSAtom *atom); -#define ATOM_KEYWORD(atom) ((struct keyword *)(atom)->entry.value) -#define ATOM_SET_KEYWORD(atom,kw) ((atom)->entry.value = (kw)) - struct JSAtomListElement { JSHashEntry entry; }; @@ -269,8 +266,8 @@ struct JSAtomState { }; /* Well-known predefined strings and their atoms. */ -extern const char *js_type_str[]; -extern const char *js_boolean_str[]; +extern const char *js_type_strs[]; +extern const char *js_boolean_strs[]; extern const char js_Arguments_str[]; extern const char js_Array_str[]; diff --git a/mozilla/js/src/jsbool.c b/mozilla/js/src/jsbool.c index 33d5c507eed..a41f2dce4ba 100644 --- a/mozilla/js/src/jsbool.c +++ b/mozilla/js/src/jsbool.c @@ -80,7 +80,7 @@ bool_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, return js_obj_toSource(cx, obj, argc, argv, rval); JS_snprintf(buf, sizeof buf, "(new %s(%s))", js_BooleanClass.name, - js_boolean_str[JSVAL_TO_BOOLEAN(v) ? 1 : 0]); + js_boolean_strs[JSVAL_TO_BOOLEAN(v) ? 1 : 0]); str = JS_NewStringCopyZ(cx, buf); if (!str) return JS_FALSE; diff --git a/mozilla/js/src/jscntxt.c b/mozilla/js/src/jscntxt.c index 3ed3ee6f720..79a929ef652 100644 --- a/mozilla/js/src/jscntxt.c +++ b/mozilla/js/src/jscntxt.c @@ -163,8 +163,6 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize) ok = (rt->atomState.liveAtoms == 0) ? js_InitAtomState(cx, &rt->atomState) : js_InitPinnedAtoms(cx, &rt->atomState); - if (ok) - ok = js_InitScanner(cx); if (ok && !rt->scriptFilenameTable) ok = js_InitRuntimeScriptState(rt); if (ok) diff --git a/mozilla/js/src/jsconfig.h b/mozilla/js/src/jsconfig.h index 5902499f90e..497e6018fc4 100644 --- a/mozilla/js/src/jsconfig.h +++ b/mozilla/js/src/jsconfig.h @@ -561,3 +561,8 @@ #error "unknown JS_VERSION" #endif + +/* Features that are present in all versions. */ +#define JS_HAS_RESERVED_JAVA_KEYWORDS 1 +#define JS_HAS_RESERVED_ECMA_KEYWORDS 1 + diff --git a/mozilla/js/src/jsfun.c b/mozilla/js/src/jsfun.c index f21dded61f8..32bbe2c9e25 100644 --- a/mozilla/js/src/jsfun.c +++ b/mozilla/js/src/jsfun.c @@ -1670,22 +1670,23 @@ static JSFunctionSpec function_methods[] = { JSBool js_IsIdentifier(JSString *str) { - size_t n; - jschar *s, c; + size_t length; + jschar c, *chars, *end, *s; - n = JSSTRING_LENGTH(str); - if (n == 0) + length = JSSTRING_LENGTH(str); + if (length == 0) return JS_FALSE; - s = JSSTRING_CHARS(str); - c = *s; + chars = JSSTRING_CHARS(str); + c = *chars; if (!JS_ISIDSTART(c)) return JS_FALSE; - for (n--; n != 0; n--) { - c = *++s; + end = chars + length; + for (s = chars + 1; s != end; ++s) { + c = *s; if (!JS_ISIDENT(c)) return JS_FALSE; } - return JS_TRUE; + return !js_IsKeyword(chars, length); } static JSBool diff --git a/mozilla/js/src/jskeyword.tbl b/mozilla/js/src/jskeyword.tbl new file mode 100644 index 00000000000..12516e7bbb2 --- /dev/null +++ b/mozilla/js/src/jskeyword.tbl @@ -0,0 +1,127 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set sw=4 ts=8 et tw=80: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +JS_KEYWORD(break, TOK_BREAK, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(case, TOK_CASE, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(continue, TOK_CONTINUE, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(default, TOK_DEFAULT, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(delete, TOK_DELETE, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(do, TOK_DO, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(else, TOK_ELSE, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(export, TOK_EXPORT, JSOP_NOP, JSVERSION_1_2) +JS_KEYWORD(false, TOK_PRIMARY, JSOP_FALSE, JSVERSION_DEFAULT) +JS_KEYWORD(for, TOK_FOR, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(function, TOK_FUNCTION, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(if, TOK_IF, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(in, TOK_IN, JSOP_IN, JSVERSION_DEFAULT) +JS_KEYWORD(new, TOK_NEW, JSOP_NEW, JSVERSION_DEFAULT) +JS_KEYWORD(null, TOK_PRIMARY, JSOP_NULL, JSVERSION_DEFAULT) +JS_KEYWORD(return, TOK_RETURN, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(switch, TOK_SWITCH, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(this, TOK_PRIMARY, JSOP_THIS, JSVERSION_DEFAULT) +JS_KEYWORD(true, TOK_PRIMARY, JSOP_TRUE, JSVERSION_DEFAULT) +JS_KEYWORD(typeof, TOK_UNARYOP, JSOP_TYPEOF, JSVERSION_DEFAULT) +JS_KEYWORD(var, TOK_VAR, JSOP_DEFVAR, JSVERSION_DEFAULT) +JS_KEYWORD(void, TOK_UNARYOP, JSOP_VOID, JSVERSION_DEFAULT) +JS_KEYWORD(while, TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(with, TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT) +#if JS_HAS_CONST +JS_KEYWORD(const, TOK_VAR, JSOP_DEFCONST, JSVERSION_DEFAULT) +#else +JS_KEYWORD(const, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +#endif + +#if JS_HAS_EXCEPTIONS +JS_KEYWORD(try, TOK_TRY, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(catch, TOK_CATCH, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(finally, TOK_FINALLY, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(throw, TOK_THROW, JSOP_NOP, JSVERSION_DEFAULT) +#else +JS_KEYWORD(try, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(catch, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(finally, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(throw, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +#endif + +#if JS_HAS_INSTANCEOF +JS_KEYWORD(instanceof, TOK_INSTANCEOF, JSOP_INSTANCEOF,JSVERSION_1_4) +#else +JS_KEYWORD(instanceof, TOK_RESERVED, JSOP_NOP, JSVERSION_1_4) +#endif + +#if JS_HAS_RESERVED_JAVA_KEYWORDS +JS_KEYWORD(abstract, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(boolean, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(byte, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(char, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(class, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(double, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(extends, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(final, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(float, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(goto, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(implements, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(import, TOK_IMPORT, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(int, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(interface, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(long, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(native, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(package, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(private, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(protected, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(public, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(short, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(static, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(super, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(synchronized,TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(throws, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(transient, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +JS_KEYWORD(volatile, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) +#endif + +#if JS_HAS_RESERVED_ECMA_KEYWORDS +JS_KEYWORD(enum, TOK_RESERVED, JSOP_NOP, JSVERSION_1_3) +#endif + +#if JS_HAS_DEBUGGER_KEYWORD +JS_KEYWORD(debugger, TOK_DEBUGGER, JSOP_NOP, JSVERSION_1_3) +#elif JS_HAS_RESERVED_ECMA_KEYWORDS +JS_KEYWORD(debugger, TOK_RESERVED, JSOP_NOP, JSVERSION_1_3) +#endif diff --git a/mozilla/js/src/jskwgen.c b/mozilla/js/src/jskwgen.c new file mode 100644 index 00000000000..5ae39bd99db --- /dev/null +++ b/mozilla/js/src/jskwgen.c @@ -0,0 +1,460 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set sw=4 ts=8 et tw=80: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is String Switch Generator for JavaScript Keywords, + * released 2005-12-09. + * + * The Initial Developer of the Original Code is + * Igor Bukanov. + * Portions created by the Initial Developer are Copyright (C) 2005-2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "jsstddef.h" +#include +#include +#include +#include +#include +#include + +#include "jsconfig.h" + +const char * const keyword_list[] = { +#define JS_KEYWORD(keyword, type, op, version) #keyword, +#include "jskeyword.tbl" +#undef JS_KEYWORD +}; + +struct gen_opt { + FILE *output; /* output file for generated source */ + unsigned use_if_threshold; /* max number of choices to generate + "if" selector instead of "switch" */ + unsigned char_tail_test_threshold; /* max number of unprocessed columns + to use inlined char compare + for remaining chars and not generic + string compare code */ + unsigned indent_level; /* current source identation level */ +}; + +static unsigned column_to_compare; + +static int +length_comparator(const void *a, const void *b) +{ + const char *str1 = keyword_list[*(unsigned *)a]; + const char *str2 = keyword_list[*(unsigned *)b]; + return (int)strlen(str1) - (int)strlen(str2); +} + +static int +column_comparator(const void *a, const void *b) +{ + const char *str1 = keyword_list[*(unsigned *)a]; + const char *str2 = keyword_list[*(unsigned *)b]; + return (int)str1[column_to_compare] - (int)str2[column_to_compare]; +} + +static unsigned +count_different_lengths(unsigned indexes[], unsigned nelem) +{ + unsigned nlength, current_length, i, l; + + current_length = 0; + nlength = 0; + for (i = 0; i != nelem; ++i) { + l = (unsigned)strlen(keyword_list[indexes[i]]); + assert(l != 0); + if (current_length != l) { + ++nlength; + current_length = l; + } + } + return nlength; +} + +static void +find_char_span_and_count(unsigned indexes[], unsigned nelem, unsigned column, + unsigned *span_result, unsigned *count_result) +{ + unsigned i, count; + unsigned char c, prev, minc, maxc; + + assert(nelem != 0); + minc = maxc = prev = (unsigned char)keyword_list[indexes[0]][column]; + count = 1; + for (i = 1; i != nelem; ++i) { + c = (unsigned char)keyword_list[indexes[i]][column]; + if (prev != c) { + prev = c; + ++count; + if (minc > c) { + minc = c; + } else if (maxc < c) { + maxc = c; + } + } + } + + *span_result = maxc - minc + 1; + *count_result = count; +} + +static unsigned +find_optimal_switch_column(struct gen_opt *opt, + unsigned indexes[], unsigned nelem, + unsigned columns[], unsigned unprocessed_columns, + int *use_if_result) +{ + unsigned i; + unsigned span, min_span, min_span_index; + unsigned nchar, min_nchar, min_nchar_index; + + assert(unprocessed_columns != 0); + i = 0; + min_nchar = min_span = (unsigned)-1; + min_nchar_index = min_span_index = 0; + do { + column_to_compare = columns[i]; + qsort(indexes, nelem, sizeof(indexes[0]), column_comparator); + find_char_span_and_count(indexes, nelem, column_to_compare, + &span, &nchar); + assert(span != 0); + if (span == 1) { + assert(nchar == 1); + *use_if_result = 1; + return 1; + } + assert(nchar != 1); + if (min_span > span) { + min_span = span; + min_span_index = i; + } + if (min_nchar > nchar) { + min_nchar = nchar; + min_nchar_index = i; + } + } while (++i != unprocessed_columns); + + if (min_nchar <= opt->use_if_threshold) { + *use_if_result = 1; + i = min_nchar_index; + } else { + *use_if_result = 0; + i = min_span_index; + } + + /* + * Restore order corresponding to i if it was destroyed by + * subsequent sort. + */ + if (i != unprocessed_columns - 1) { + column_to_compare = columns[i]; + qsort(indexes, nelem, sizeof(indexes[0]), column_comparator); + } + + return i; +} + + +static void +p(struct gen_opt *opt, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(opt->output, format, ap); + va_end(ap); +} + +/* Size for '\xxx' where xxx is octal escape */ +#define MIN_QUOTED_CHAR_BUFFER 7 + +static char * +qchar(char c, char *quoted_buffer) +{ + char *s; + + s = quoted_buffer; + *s++ = '\''; + switch (c) { + case '\n': c = 'n'; goto one_char_escape; + case '\r': c = 'r'; goto one_char_escape; + case '\t': c = 't'; goto one_char_escape; + case '\f': c = 't'; goto one_char_escape; + case '\0': c = '0'; goto one_char_escape; + case '\'': goto one_char_escape; + one_char_escape: + *s++ = '\\'; + break; + default: + if (!isprint(c)) { + *s++ = '\\'; + *s++ = (char)('0' + (0x3 & (((unsigned char)c) >> 6))); + *s++ = (char)('0' + (0x7 & (((unsigned char)c) >> 3))); + c = (char)('0' + (0x7 & ((unsigned char)c))); + } + } + *s++ = c; + *s++ = '\''; + *s = '\0'; + assert(s + 1 <= quoted_buffer + MIN_QUOTED_CHAR_BUFFER); + return quoted_buffer; +} + +static void +nl(struct gen_opt *opt) +{ + putc('\n', opt->output); +} + +static void +indent(struct gen_opt *opt) +{ + unsigned n = opt->indent_level; + while (n != 0) { + --n; + fputs(" ", opt->output); + } +} + +static void +line(struct gen_opt *opt, const char *format, ...) +{ + va_list ap; + + indent(opt); + va_start(ap, format); + vfprintf(opt->output, format, ap); + va_end(ap); + nl(opt); +} + +static void +generate_letter_switch_r(struct gen_opt *opt, + unsigned indexes[], unsigned nelem, + unsigned columns[], unsigned unprocessed_columns) +{ + char qbuf[MIN_QUOTED_CHAR_BUFFER]; + + assert(nelem != 0); + if (nelem == 1) { + unsigned kw_index = indexes[0]; + const char *keyword = keyword_list[kw_index]; + + if (unprocessed_columns == 0) { + line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword); + } else if (unprocessed_columns > opt->char_tail_test_threshold) { + line(opt, "JSKW_TEST_GUESS(%u) /* %s */", kw_index, keyword); + } else { + unsigned i, column; + + indent(opt); p(opt, "if ("); + for (i = 0; i != unprocessed_columns; ++i) { + column = columns[i]; + qchar(keyword[column], qbuf); + p(opt, "%sJSKW_AT(%u)==%s", (i == 0) ? "" : " && ", + column, qbuf); + } + p(opt, ") {"); nl(opt); + ++opt->indent_level; + line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword); + --opt->indent_level; + line(opt, "}"); + line(opt, "JSKW_NO_MATCH()"); + } + } else { + unsigned optimal_column_index, optimal_column; + unsigned i; + int use_if; + char current; + + assert(unprocessed_columns != 0); + optimal_column_index = find_optimal_switch_column(opt, indexes, nelem, + columns, + unprocessed_columns, + &use_if); + optimal_column = columns[optimal_column_index]; + columns[optimal_column_index] = columns[unprocessed_columns - 1]; + + if (!use_if) + line(opt, "switch (JSKW_AT(%u)) {", optimal_column); + + current = keyword_list[indexes[0]][optimal_column]; + for (i = 0; i != nelem;) { + unsigned same_char_begin = i; + char next = current; + + for (++i; i != nelem; ++i) { + next = keyword_list[indexes[i]][optimal_column]; + if (next != current) + break; + } + qchar(current, qbuf); + if (use_if) { + line(opt, "if (JSKW_AT(%u) == %s) {", optimal_column, qbuf); + } else { + line(opt, " case %s:", qbuf); + } + ++opt->indent_level; + generate_letter_switch_r(opt, indexes + same_char_begin, + i - same_char_begin, + columns, unprocessed_columns - 1); + --opt->indent_level; + if (use_if) { + line(opt, "}"); + } + current = next; + } + + if (!use_if) { + line(opt, "}"); + } + + columns[optimal_column_index] = optimal_column; + + line(opt, "JSKW_NO_MATCH()"); + } +} + +static void +generate_letter_switch(struct gen_opt *opt, + unsigned indexes[], unsigned nelem, + unsigned current_length) +{ + unsigned *columns; + unsigned i; + + columns = malloc(sizeof(columns[0]) * current_length); + if (!columns) { + perror("malloc"); + exit(EXIT_FAILURE); + } + for (i = 0; i != current_length; ++i) { + columns[i] = i; + } + generate_letter_switch_r(opt, indexes, nelem, columns, current_length); + free(columns); +} + + +static void +generate_switch(struct gen_opt *opt) +{ + unsigned *indexes; + unsigned nlength; + unsigned i, current; + int use_if; + unsigned nelem; + + nelem = sizeof(keyword_list)/sizeof(keyword_list[0]); + + line(opt, "/*"); + line(opt, " * Generating switch for the list of %u entries:", nelem); + for (i = 0; i != nelem; ++i) { + line(opt, " * %s", keyword_list[i]); + } + line(opt, " */"); + + indexes = malloc(sizeof(indexes[0]) * nelem); + if (!indexes) { + perror("malloc"); + exit(EXIT_FAILURE); + } + for (i = 0; i != nelem; ++i) + indexes[i] = i; + qsort(indexes, nelem, sizeof(indexes[i]), length_comparator); + nlength = count_different_lengths(indexes, nelem); + + use_if = (nlength <= opt->use_if_threshold); + + if (!use_if) + line(opt, "switch (JSKW_LENGTH()) {"); + + current = (unsigned)strlen(keyword_list[indexes[0]]); + for (i = 0; i != nelem;) { + unsigned same_length_begin = i; + unsigned next = current; + + for (++i; i != nelem; ++i) { + next = (unsigned)strlen(keyword_list[indexes[i]]); + if (next != current) + break; + } + if (use_if) { + line(opt, "if (JSKW_LENGTH() == %u) {", current); + } else { + line(opt, " case %u:", current); + } + ++opt->indent_level; + generate_letter_switch(opt, indexes + same_length_begin, + i - same_length_begin, + current); + --opt->indent_level; + if (use_if) { + line(opt, "}"); + } + current = next; + } + if (!use_if) + line(opt, "}"); + line(opt, "JSKW_NO_MATCH()"); + free(indexes); +} + +int main(int argc, char **argv) +{ + struct gen_opt opt; + + if (argc < 2) { + opt.output = stdout; + } else { + opt.output = fopen(argv[1], "w"); + if (!opt.output) { + perror("fopen"); + exit(EXIT_FAILURE); + } + } + opt.indent_level = 1; + opt.use_if_threshold = 3; + opt.char_tail_test_threshold = 4; + + generate_switch(&opt); + + if (opt.output != stdout) { + if (fclose(opt.output)) { + perror("fclose"); + exit(EXIT_FAILURE); + } + } + + return EXIT_SUCCESS; +} diff --git a/mozilla/js/src/jsobj.c b/mozilla/js/src/jsobj.c index d4bea210245..a7ef1607f37 100644 --- a/mozilla/js/src/jsobj.c +++ b/mozilla/js/src/jsobj.c @@ -836,12 +836,11 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, *rval = STRING_TO_JSVAL(idstr); /* local root */ /* - * If id is a string that's a reserved identifier, or else id is not - * an identifier at all, then it needs to be quoted. Also, negative - * integer ids must be quoted. + * If id is a string that's not an identifier, then it needs to be + * quoted. Also, negative integer ids must be quoted. */ if (atom - ? (ATOM_KEYWORD(atom) || !js_IsIdentifier(idstr)) + ? !js_IsIdentifier(idstr) : (JSID_IS_OBJECT(id) || JSID_TO_INT(id) < 0)) { idstr = js_QuoteString(cx, idstr, (jschar)'\''); if (!idstr) { @@ -3421,7 +3420,7 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp) JS_GetStringBytes(str), (hint == JSTYPE_VOID) ? "primitive type" - : js_type_str[hint]); + : js_type_strs[hint]); } return JS_FALSE; } diff --git a/mozilla/js/src/jsopcode.c b/mozilla/js/src/jsopcode.c index 4f5ecf3994a..f24391d09cb 100644 --- a/mozilla/js/src/jsopcode.c +++ b/mozilla/js/src/jsopcode.c @@ -70,22 +70,7 @@ #include "jsscript.h" #include "jsstr.h" -const char js_const_str[] = "const"; -const char js_var_str[] = "var"; -const char js_function_str[] = "function"; -const char js_in_str[] = "in"; -const char js_instanceof_str[] = "instanceof"; -const char js_new_str[] = "new"; -const char js_delete_str[] = "delete"; -const char js_typeof_str[] = "typeof"; -const char js_void_str[] = "void"; -const char js_null_str[] = "null"; -const char js_this_str[] = "this"; -const char js_false_str[] = "false"; -const char js_true_str[] = "true"; -const char js_default_str[] = "default"; - -const char *js_incop_str[] = {"++", "--"}; +static const char js_incop_strs[][3] = {"++", "--"}; /* Pollute the namespace locally for MSVC Win16, but not for WatCom. */ #ifdef __WINDOWS_386__ @@ -914,8 +899,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) * Callers know that ATOM_IS_STRING(atom), and we leave it to the optimizer to * common ATOM_TO_STRING(atom) here and near the call sites. */ -#define ATOM_IS_IDENTIFIER(atom) \ - (!ATOM_KEYWORD(atom) && js_IsIdentifier(ATOM_TO_STRING(atom))) +#define ATOM_IS_IDENTIFIER(atom) js_IsIdentifier(ATOM_TO_STRING(atom)) /* * Given an atom already fetched from jp->script's atom map, quote/escape its @@ -1846,7 +1830,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) return JS_FALSE; RETRACT(&ss->sprinter, lval); todo = Sprint(&ss->sprinter, "%s%s", - js_incop_str[!(cs->format & JOF_INC)], lval); + js_incop_strs[!(cs->format & JOF_INC)], lval); break; case JSOP_INCPROP: @@ -1854,7 +1838,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) GET_ATOM_QUOTE_AND_FMT("%s%s[%s]", "%s%s.%s", rval); lval = POP_STR(); todo = Sprint(&ss->sprinter, fmt, - js_incop_str[!(cs->format & JOF_INC)], + js_incop_strs[!(cs->format & JOF_INC)], lval, rval); break; @@ -1867,11 +1851,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) (js_CodeSpec[lastop].format & JOF_XMLNAME) ? "%s%s.%s" : "%s%s[%s]", - js_incop_str[!(cs->format & JOF_INC)], + js_incop_strs[!(cs->format & JOF_INC)], lval, xval); } else { todo = Sprint(&ss->sprinter, "%s%s", - js_incop_str[!(cs->format & JOF_INC)], lval); + js_incop_strs[!(cs->format & JOF_INC)], lval); } break; @@ -1898,7 +1882,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) return JS_FALSE; todo = STR2OFF(&ss->sprinter, lval); SprintPut(&ss->sprinter, - js_incop_str[!(cs->format & JOF_INC)], + js_incop_strs[!(cs->format & JOF_INC)], 2); break; @@ -1907,7 +1891,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) GET_ATOM_QUOTE_AND_FMT("%s[%s]%s", "%s.%s%s", rval); lval = POP_STR(); todo = Sprint(&ss->sprinter, fmt, lval, rval, - js_incop_str[!(cs->format & JOF_INC)]); + js_incop_strs[!(cs->format & JOF_INC)]); break; case JSOP_ELEMINC: @@ -1920,10 +1904,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) ? "%s.%s%s" : "%s[%s]%s", lval, xval, - js_incop_str[!(cs->format & JOF_INC)]); + js_incop_strs[!(cs->format & JOF_INC)]); } else { todo = Sprint(&ss->sprinter, "%s%s", - lval, js_incop_str[!(cs->format & JOF_INC)]); + lval, js_incop_strs[!(cs->format & JOF_INC)]); } break; diff --git a/mozilla/js/src/jsscan.c b/mozilla/js/src/jsscan.c index 10324eebe96..8bcaffda027 100644 --- a/mozilla/js/src/jsscan.c +++ b/mozilla/js/src/jsscan.c @@ -74,133 +74,80 @@ #include "jsxml.h" #endif -#define RESERVE_JAVA_KEYWORDS -#define RESERVE_ECMA_KEYWORDS - #define MAX_KEYWORD_LENGTH 12 -static struct keyword { - const char *name; +#define JS_KEYWORD(keyword, type, op, version) \ + const char js_##keyword##_str[] = #keyword; +#include "jskeyword.tbl" +#undef JS_KEYWORD + +struct keyword { + const char *chars; /* C string with keyword text */ JSTokenType tokentype; /* JSTokenType */ JSOp op; /* JSOp */ JSVersion version; /* JSVersion */ -} keywords[] = { - {"break", TOK_BREAK, JSOP_NOP, JSVERSION_DEFAULT}, - {"case", TOK_CASE, JSOP_NOP, JSVERSION_DEFAULT}, - {"continue", TOK_CONTINUE, JSOP_NOP, JSVERSION_DEFAULT}, - {js_default_str, TOK_DEFAULT, JSOP_NOP, JSVERSION_DEFAULT}, - {js_delete_str, TOK_DELETE, JSOP_NOP, JSVERSION_DEFAULT}, - {"do", TOK_DO, JSOP_NOP, JSVERSION_DEFAULT}, - {"else", TOK_ELSE, JSOP_NOP, JSVERSION_DEFAULT}, - {"export", TOK_EXPORT, JSOP_NOP, JSVERSION_1_2}, - {js_false_str, TOK_PRIMARY, JSOP_FALSE, JSVERSION_DEFAULT}, - {"for", TOK_FOR, JSOP_NOP, JSVERSION_DEFAULT}, - {js_function_str, TOK_FUNCTION, JSOP_NOP, JSVERSION_DEFAULT}, - {"if", TOK_IF, JSOP_NOP, JSVERSION_DEFAULT}, - {js_in_str, TOK_IN, JSOP_IN, JSVERSION_DEFAULT}, - {js_new_str, TOK_NEW, JSOP_NEW, JSVERSION_DEFAULT}, - {js_null_str, TOK_PRIMARY, JSOP_NULL, JSVERSION_DEFAULT}, - {"return", TOK_RETURN, JSOP_NOP, JSVERSION_DEFAULT}, - {"switch", TOK_SWITCH, JSOP_NOP, JSVERSION_DEFAULT}, - {js_this_str, TOK_PRIMARY, JSOP_THIS, JSVERSION_DEFAULT}, - {js_true_str, TOK_PRIMARY, JSOP_TRUE, JSVERSION_DEFAULT}, - {js_typeof_str, TOK_UNARYOP, JSOP_TYPEOF,JSVERSION_DEFAULT}, - {js_var_str, TOK_VAR, JSOP_DEFVAR,JSVERSION_DEFAULT}, - {js_void_str, TOK_UNARYOP, JSOP_VOID, JSVERSION_DEFAULT}, - {"while", TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT}, - {"with", TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT}, - -#if JS_HAS_CONST - {js_const_str, TOK_VAR, JSOP_DEFCONST,JSVERSION_DEFAULT}, -#else - {js_const_str, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, -#endif - -#if JS_HAS_EXCEPTIONS - {"try", TOK_TRY, JSOP_NOP, JSVERSION_DEFAULT}, - {"catch", TOK_CATCH, JSOP_NOP, JSVERSION_DEFAULT}, - {"finally", TOK_FINALLY, JSOP_NOP, JSVERSION_DEFAULT}, - {"throw", TOK_THROW, JSOP_NOP, JSVERSION_DEFAULT}, -#else - {"try", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"catch", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"finally", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"throw", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, -#endif - -#if JS_HAS_INSTANCEOF - {js_instanceof_str, TOK_INSTANCEOF, JSOP_INSTANCEOF,JSVERSION_1_4}, -#else - {js_instanceof_str, TOK_RESERVED, JSOP_NOP, JSVERSION_1_4}, -#endif - -#ifdef RESERVE_JAVA_KEYWORDS - {"abstract", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"boolean", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"byte", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"char", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"class", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"double", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"extends", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"final", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"float", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"goto", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"implements", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"import", TOK_IMPORT, JSOP_NOP, JSVERSION_DEFAULT}, - {"int", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"interface", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"long", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"native", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"package", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"private", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"protected", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"public", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"short", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"static", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"super", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"synchronized", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"throws", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"transient", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"volatile", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, -#endif - -#ifdef RESERVE_ECMA_KEYWORDS - {"enum", TOK_RESERVED, JSOP_NOP, JSVERSION_1_3}, -#endif - -#if JS_HAS_DEBUGGER_KEYWORD - {"debugger", TOK_DEBUGGER, JSOP_NOP, JSVERSION_1_3}, -#elif defined(RESERVE_ECMA_KEYWORDS) - {"debugger", TOK_RESERVED, JSOP_NOP, JSVERSION_1_3}, -#endif - {0, TOK_EOF, JSOP_NOP, JSVERSION_DEFAULT} }; -JSBool -js_InitScanner(JSContext *cx) -{ - struct keyword *kw; - size_t length; - JSAtom *atom; +static const struct keyword keyword_defs[] = { +#define JS_KEYWORD(keyword, type, op, version) \ + {js_##keyword##_str, type, op, version}, +#include "jskeyword.tbl" +#undef JS_KEYWORD +}; - for (kw = keywords; kw->name; kw++) { - length = strlen(kw->name); - JS_ASSERT(length <= MAX_KEYWORD_LENGTH); - atom = js_Atomize(cx, kw->name, length, ATOM_PINNED); - if (!atom) - return JS_FALSE; - ATOM_SET_KEYWORD(atom, kw); - } - return JS_TRUE; +#define KEYWORD_COUNT (sizeof keyword_defs / sizeof keyword_defs[0]) + +static const struct keyword * +FindKeyword(const jschar *s, size_t length) +{ + register size_t i; + const struct keyword *kw; + const char *chars; + + JS_ASSERT(length != 0); + +#define JSKW_LENGTH() length +#define JSKW_AT(column) s[column] +#define JSKW_GOT_MATCH(index) i = (index); goto got_match; +#define JSKW_TEST_GUESS(index) i = (index); goto test_guess; +#define JSKW_NO_MATCH() goto no_match; +#include "jsautokw.h" +#undef JSKW_NO_MATCH +#undef JSKW_TEST_GUESS +#undef JSKW_GOT_MATCH +#undef JSKW_AT +#undef JSKW_LENGTH + + got_match: + return &keyword_defs[i]; + + test_guess: + kw = &keyword_defs[i]; + chars = kw->chars; + do { + if (*s++ != (unsigned char)(*chars++)) + goto no_match; + } while (--length != 0); + return kw; + + no_match: + return NULL; +} + +JSBool +js_IsKeyword(const jschar *str, size_t length) +{ + JS_ASSERT(length != 0); + return FindKeyword(str, length) != NULL; } JS_FRIEND_API(void) js_MapKeywords(void (*mapfun)(const char *)) { - struct keyword *kw; + size_t i; - for (kw = keywords; kw->name; kw++) - mapfun(kw->name); + for (i = 0; i != KEYWORD_COUNT; ++i) + mapfun(keyword_defs[i].chars); } JSTokenStream * @@ -755,7 +702,7 @@ js_ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags, &report, JS_TRUE, ap); va_end(ap); - /* + /* * We have to do this here because js_ReportCompileErrorNumberUC doesn't * need to do this. */ @@ -779,7 +726,7 @@ js_ReportCompileErrorNumberUC(JSContext *cx, void *handle, uintN flags, if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx)) return JS_TRUE; - + va_start(ap, errorNumber); warning = ReportCompileErrorNumber(cx, handle, flags, errorNumber, &report, JS_FALSE, ap); @@ -1114,6 +1061,7 @@ js_GetToken(JSContext *cx, JSTokenStream *ts) JSToken *tp; JSAtom *atom; JSBool hadUnicodeEscape; + const struct keyword *kw; #define INIT_TOKENBUF() (ts->tokenbuf.ptr = ts->tokenbuf.base) #define NUL_TERM_TOKENBUF() (*ts->tokenbuf.ptr = 0) @@ -1335,14 +1283,8 @@ retry: } UngetChar(ts, c); - atom = TOKENBUF_TO_ATOM(); - if (!atom) - goto error; - if (!hadUnicodeEscape && ATOM_KEYWORD(atom)) { - struct keyword *kw; - - JS_ASSERT(!(atom->flags & ATOM_HIDDEN)); - kw = ATOM_KEYWORD(atom); + if (!hadUnicodeEscape && + (kw = FindKeyword(TOKENBUF_BASE(), TOKENBUF_LENGTH()))) { if (kw->tokentype == TOK_RESERVED) { char buf[MAX_KEYWORD_LENGTH + 1]; size_t buflen = sizeof(buf) - 1; @@ -1364,6 +1306,10 @@ retry: goto out; } } + + atom = TOKENBUF_TO_ATOM(); + if (!atom) + goto error; tp->t_op = JSOP_NAME; tp->t_atom = atom; tt = TOK_NAME; diff --git a/mozilla/js/src/jsscan.h b/mozilla/js/src/jsscan.h index ee39bbc0af8..3860682a296 100644 --- a/mozilla/js/src/jsscan.h +++ b/mozilla/js/src/jsscan.h @@ -301,10 +301,10 @@ extern JS_FRIEND_API(int) js_fgets(char *buf, int size, FILE *file); /* - * Initialize the scanner, installing JS keywords into cx's global scope. + * Return true if the given char array forms JavaScript keyword. */ extern JSBool -js_InitScanner(JSContext *cx); +js_IsKeyword(const jschar *str, size_t length); /* * Friend-exported API entry point to call a mapping function on each reserved diff --git a/mozilla/js/src/jsxml.c b/mozilla/js/src/jsxml.c index 4fe5a4f77a7..6f32e8e6507 100644 --- a/mozilla/js/src/jsxml.c +++ b/mozilla/js/src/jsxml.c @@ -2402,7 +2402,7 @@ GetNamespace(JSContext *cx, JSXMLQName *qn, const JSXMLArray *inScopeNSes) qn->prefix ? js_ValueToPrintableString(cx, STRING_TO_JSVAL(qn->prefix)) - : js_type_str[JSTYPE_VOID]); + : js_type_strs[JSTYPE_VOID]); return NULL; } @@ -2906,9 +2906,9 @@ ToXMLString(JSContext *cx, jsval v) if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XML_CONVERSION, - js_type_str[JSVAL_IS_NULL(v) - ? JSTYPE_NULL - : JSTYPE_VOID]); + js_type_strs[JSVAL_IS_NULL(v) + ? JSTYPE_NULL + : JSTYPE_VOID]); return NULL; } diff --git a/mozilla/js/src/rules.mk b/mozilla/js/src/rules.mk index e04a8edfabc..8d484db9a5f 100644 --- a/mozilla/js/src/rules.mk +++ b/mozilla/js/src/rules.mk @@ -177,7 +177,7 @@ endif +$(LOOP_OVER_DIRS) clean: - rm -rf $(OBJS) + rm -rf $(OBJS) $(GARBAGE) @cd fdlibm; $(MAKE) -f Makefile.ref clean clobber: