Merge.
Merge.
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -355,29 +355,16 @@ endif
# our build system doesn't handle subdir srcs very gracefully today
export::
mkdir -p nanojit
DEFINES += -DEXPORT_JS_API
INCLUDES += -I$(srcdir)
-# MSVC '-Gy' cc flag and '/OPT:REF' linker flag cause JS_GetArgument and
-# JS_GetLocalVariable to be folded to the same address by the linker,
-# leading to a crash on startup. See bug 151066. So, in optimized builds,
-# add the /OPT:NOICF flag, which turns off 'identical COMDAT folding'.
-#
-# N.B.: 'identical COMDAT folding' that folds functions whose addresses
-# are taken violates the ISO C and C++ standards.
-ifndef MOZ_DEBUG
-ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
-LDFLAGS += -OPT:NOICF
-endif
-endif
-
GARBAGE += jscpucfg.o jsautocfg.h jsautocfg.tmp jscpucfg
ifneq (,$(CROSS_COMPILE)$(filter-out WINNT,$(OS_ARCH)))
TARGETS += jscpucfg$(HOST_BIN_SUFFIX)
endif
ifdef JS_SAFE_ARENA
DEFINES += -DJS_USE_SAFE_ARENA
@@ -595,17 +582,17 @@ js-config: js-config.in Makefile $(DEPTH
&& mv js-config.tmp $@ && chmod +x $@
SCRIPTS = js-config
SDK_BINARY = js-config
install:: $(INSTALLED_HEADERS)
$(SYSINSTALL) $^ $(includedir)/$(MODULE)
-install:: $(SCRIPTS) $(PROGRAM)
+install:: $(SCRIPTS)
$(SYSINSTALL) $^ $(bindir)
install:: $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY)
ifneq (,$(LIBRARY))
$(SYSINSTALL) $(LIBRARY) $(libdir)
endif
ifneq (,$(SHARED_LIBRARY))
$(SYSINSTALL) $(SHARED_LIBRARY) $(libdir)
@@ -638,15 +625,25 @@ ifdef HAVE_DTRACE
sed 's/if _DTRACE_VERSION/ifdef INCLUDE_MOZILLA_DTRACE/' \
javascript-trace.h.in > javascript-trace.h
# We can't automatically generate dependencies on auto-generated headers;
# we have to list them explicitly.
$(addsuffix .$(OBJ_SUFFIX),jsdtracef jsinterp jsobj): $(CURDIR)/javascript-trace.h
endif
-imacro_asm.js: imacro_asm.js.in
- $(CC) -c -x c -E -P -I$(srcdir) $? > $@
+ifdef GNU_CC
+imacro_asm.js: imacro_asm.js.in jsopcode.tbl
+ $(CC) -c -x c -E -P -I$(srcdir) $< > $@
+
+GARBAGE += imacros.c.out imacro_asm.js
-GARBAGE += imacro_asm.js
+ifndef CROSS_COMPILE
+# Build imacros.c.out after descending into DIRS and building the js shell.
+# This may result in an updated imacros.c.out file that requires a re-build
+# to stabilize.
+libs:: imacros.c.out
+ @cmp -s imacros.c.out $(srcdir)/$< || cp imacros.c.out $(srcdir)
-%.c.out: %.jsasm $(PROGRAM) imacro_asm.js
- ./$(PROGRAM) imacro_asm.js $< > $@
+%.c.out: %.jsasm imacro_asm.js
+ $(DIST)/bin/js imacro_asm.js $< > $@
+endif
+endif
--- a/js/src/imacro_asm.js.in
+++ b/js/src/imacro_asm.js.in
@@ -119,26 +119,16 @@ function immediate(op) {
if (info.flags.indexOf("JOF_UINT16") >= 0) {
if (imm1Expr)
return '(_ & 0xff00) >> 8, (_ & 0xff)'.replace(/_/g, op.imm1);
return ((op.imm1 & 0xff00) >> 8) + ", " + (op.imm1 & 0xff);
}
throw new Error(info.jsop + " format not yet implemented");
}
-const line_regexp_parts = [
- "^(?:(\\w+):)?",
- "\\s*(\\.?\\w+)",
- "(?:\\s+(\\w+|\\([^)]*\\)))?",
- "(?:\\s+([\\w-]+|\\([^)]*\\)))?",
- "(?:\\s*(?:#.*))?$"
-];
-
-const line_regexp = new RegExp(line_regexp_parts.join(""));
-
/*
* Syntax (spaces are significant only to delimit tokens):
*
* Assembly ::= (Directive? '\n')*
* Directive ::= (name ':')? Operation
* Operation ::= opname Operands?
* Operands ::= Operand (',' Operand)*
* Operand ::= name | number | '(' Expr ')'
@@ -148,21 +138,31 @@ const line_regexp = new RegExp(line_rege
* We simplify given line structure and the maximum of one immediate operand,
* by parsing using split and regexps. For ease of parsing, parentheses are
* banned in an Expr for now, even in quotes or a C++ comment.
*
* Pseudo-ops start with . and include .igroup and .imacro, terminated by .end.
* .imacro must nest in .igroup, neither nests in itself. See imacros.jsasm for
* examples.
*/
+const line_regexp_parts = [
+ "^(?:(\\w+):)?", // optional label at start of line
+ "\\s*(\\.?\\w+)", // optional spaces, (pseudo-)opcode
+ "(?:\\s+(\\w+|\\([^)]*\\)))?", // optional first immediate operand
+ "(?:\\s+([\\w-]+|\\([^)]*\\)))?", // optional second immediate operand
+ "(?:\\s*(?:#.*))?$" // optional spaces and comment
+];
+
+const line_regexp = new RegExp(line_regexp_parts.join(""));
+
function assemble(filename) {
let igroup = null, imacro = null;
let opcode2extra = [];
- print("/* GENERATED BY imacro_asm.js from " + filename + " -- DO NOT EDIT!!! */");
+ print("/* GENERATED BY imacro_asm.js -- DO NOT EDIT!!! */");
let s = snarf(filename);
let a = s.split('\n');
for (let i = 0; i < a.length; i++) {
if (/^\s*(?:#.*)?$/.test(a[i]))
continue;
let m = line_regexp.exec(a[i]);
if (!m)
@@ -290,21 +290,21 @@ function assemble(filename) {
if (!opname2info.hasOwnProperty(opname))
throw new Error("unknown opcode " + opname + (label ? " (label " + label + ")" : ""));
let info = opname2info[opname];
if (info.oplen == -1)
throw new Error("unimplemented opcode " + opname);
- if (label) {
- if (!imacro)
- throw new Error("label " + label + " outside of .imacro");
+ if (!imacro)
+ throw new Error("opcode " + opname + " outside of .imacro");
+
+ if (label)
imacro.labeldefs[label] = imacro.offset;
- }
let op = {offset: imacro.offset, info: info, imm1: imm1, imm2: imm2};
if (info.flags.indexOf("JOF_JUMP") >= 0) {
if (imacro.labeldefs.hasOwnProperty(imm1)) {
// Backward reference can be resolved right away, no backpatching needed.
op.target = imacro.labeldefs[imm1] - op.offset;
} else {
// Link op into the .target-linked backpatch chain at labelrefs[imm1].
--- a/js/src/imacros.c.out
+++ b/js/src/imacros.c.out
@@ -1,9 +1,9 @@
-/* GENERATED BY imacro_asm.js from imacros.jsasm -- DO NOT EDIT!!! */
+/* GENERATED BY imacro_asm.js -- DO NOT EDIT!!! */
static struct {
jsbytecode any_obj[37];
jsbytecode obj_any[39];
} equality_imacros = {
{
/* 0*/ JSOP_DUP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
@@ -704,17 +704,17 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_PROPINC */
0, /* JSOP_ELEMINC */
0, /* JSOP_NAMEDEC */
0, /* JSOP_PROPDEC */
0, /* JSOP_ELEMDEC */
0, /* JSOP_GETPROP */
0, /* JSOP_SETPROP */
2, /* JSOP_GETELEM */
- 2, /* JSOP_SETELEM */
+ 3, /* JSOP_SETELEM */
0, /* JSOP_CALLNAME */
0, /* JSOP_CALL */
0, /* JSOP_NAME */
0, /* JSOP_DOUBLE */
0, /* JSOP_STRING */
0, /* JSOP_ZERO */
0, /* JSOP_ONE */
0, /* JSOP_NULL */
@@ -726,31 +726,31 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_TABLESWITCH */
0, /* JSOP_LOOKUPSWITCH */
0, /* JSOP_STRICTEQ */
0, /* JSOP_STRICTNE */
0, /* JSOP_NULLTHIS */
3, /* JSOP_ITER */
2, /* JSOP_NEXTITER */
0, /* JSOP_ENDITER */
- 7, /* JSOP_APPLY */
+ 8, /* JSOP_APPLY */
0, /* JSOP_SWAP */
0, /* JSOP_OBJECT */
0, /* JSOP_POP */
0, /* JSOP_NEW */
0, /* JSOP_TRAP */
0, /* JSOP_GETARG */
0, /* JSOP_SETARG */
0, /* JSOP_GETLOCAL */
0, /* JSOP_SETLOCAL */
0, /* JSOP_UINT16 */
0, /* JSOP_NEWINIT */
0, /* JSOP_ENDINIT */
0, /* JSOP_INITPROP */
- 2, /* JSOP_INITELEM */
+ 3, /* JSOP_INITELEM */
0, /* JSOP_DEFSHARP */
0, /* JSOP_USESHARP */
0, /* JSOP_INCARG */
0, /* JSOP_DECARG */
0, /* JSOP_ARGINC */
0, /* JSOP_ARGDEC */
0, /* JSOP_INCLOCAL */
0, /* JSOP_DECLOCAL */
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1596,73 +1596,94 @@ js_CheckRedeclaration(JSContext *cx, JSO
{
JSObject *obj2;
JSProperty *prop;
uintN oldAttrs, report;
JSBool isFunction;
jsval value;
const char *type, *name;
+ /*
+ * Both objp and propp must be either null or given. When given, *propp
+ * must be null. This way we avoid an extra "if (propp) *propp = NULL" for
+ * the common case of a non-existing property.
+ */
+ JS_ASSERT(!objp == !propp);
+ JS_ASSERT_IF(propp, !*propp);
+
+ /* The JSPROP_INITIALIZER case below may generate a warning. Since we must
+ * drop the property before reporting it, we insists on !propp to avoid
+ * looking up the property again after the reporting is done.
+ */
+ JS_ASSERT_IF(attrs & JSPROP_INITIALIZER, attrs == JSPROP_INITIALIZER);
+ JS_ASSERT_IF(attrs == JSPROP_INITIALIZER, !propp);
+
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
return JS_FALSE;
- if (propp) {
- *objp = obj2;
- *propp = prop;
- }
if (!prop)
return JS_TRUE;
- /*
- * Use prop as a speedup hint to OBJ_GET_ATTRIBUTES, but drop it on error.
- * An assertion at label bad: will insist that it is null.
- */
+ /* Use prop as a speedup hint to OBJ_GET_ATTRIBUTES. */
if (!OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &oldAttrs)) {
OBJ_DROP_PROPERTY(cx, obj2, prop);
-#ifdef DEBUG
- prop = NULL;
-#endif
- goto bad;
+ return JS_FALSE;
}
/*
- * From here, return true, or else goto bad on failure to null out params.
* If our caller doesn't want prop, drop it (we don't need it any longer).
*/
if (!propp) {
OBJ_DROP_PROPERTY(cx, obj2, prop);
prop = NULL;
+ } else {
+ *objp = obj2;
+ *propp = prop;
}
if (attrs == JSPROP_INITIALIZER) {
/* Allow the new object to override properties. */
if (obj2 != obj)
return JS_TRUE;
+
+ /* The property must be dropped already. */
+ JS_ASSERT(!prop);
report = JSREPORT_WARNING | JSREPORT_STRICT;
} else {
/* We allow redeclaring some non-readonly properties. */
if (((oldAttrs | attrs) & JSPROP_READONLY) == 0) {
- /*
- * Allow redeclaration of variables and functions, but insist that
- * the new value is not a getter if the old value was, ditto for
- * setters -- unless prop is impermanent (in which case anyone
- * could delete it and redefine it, willy-nilly).
- */
+ /* Allow redeclaration of variables and functions. */
if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
return JS_TRUE;
+
+ /*
+ * Allow adding a getter only if a property already has a setter
+ * but no getter and similarly for adding a setter. That is, we
+ * allow only the following transitions:
+ *
+ * no-property --> getter --> getter + setter
+ * no-property --> setter --> getter + setter
+ */
if ((~(oldAttrs ^ attrs) & (JSPROP_GETTER | JSPROP_SETTER)) == 0)
return JS_TRUE;
+
+ /*
+ * Allow redeclaration of an impermanent property (in which case
+ * anyone could delete it and redefine it, willy-nilly).
+ */
if (!(oldAttrs & JSPROP_PERMANENT))
return JS_TRUE;
}
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
report = JSREPORT_ERROR;
isFunction = (oldAttrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0;
if (!isFunction) {
if (!OBJ_GET_PROPERTY(cx, obj, id, &value))
- goto bad;
+ return JS_FALSE;
isFunction = VALUE_IS_FUNCTION(cx, value);
}
}
type = (attrs == JSPROP_INITIALIZER)
? "property"
: (oldAttrs & attrs & JSPROP_GETTER)
? js_getter_str
@@ -1670,29 +1691,21 @@ js_CheckRedeclaration(JSContext *cx, JSO
? js_setter_str
: (oldAttrs & JSPROP_READONLY)
? js_const_str
: isFunction
? js_function_str
: js_var_str;
name = js_ValueToPrintableString(cx, ID_TO_VALUE(id));
if (!name)
- goto bad;
+ return JS_FALSE;
return JS_ReportErrorFlagsAndNumber(cx, report,
js_GetErrorMessage, NULL,
JSMSG_REDECLARED_VAR,
type, name);
-
-bad:
- if (propp) {
- *objp = NULL;
- *propp = NULL;
- }
- JS_ASSERT(!prop);
- return JS_FALSE;
}
JSBool
js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval)
{
jsval ltag = JSVAL_TAG(lval), rtag = JSVAL_TAG(rval);
jsdouble ld, rd;
@@ -5654,16 +5667,17 @@ js_Interpret(JSContext *cx)
attrs = JSPROP_ENUMERATE;
if (!(fp->flags & JSFRAME_EVAL))
attrs |= JSPROP_PERMANENT;
if (op == JSOP_DEFCONST)
attrs |= JSPROP_READONLY;
/* Lookup id in order to check for redeclaration problems. */
id = ATOM_TO_JSID(atom);
+ prop = NULL;
if (!js_CheckRedeclaration(cx, obj, id, attrs, &obj2, &prop))
goto error;
/* Bind a variable only if it's not yet defined. */
if (!prop) {
if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
JS_PropertyStub, JS_PropertyStub,
attrs, &prop)) {
@@ -5676,21 +5690,21 @@ js_Interpret(JSContext *cx)
/*
* Try to optimize a property we either just created, or found
* directly in the global object, that is permanent, has a slot,
* and has stub getter and setter, into a "fast global" accessed
* by the JSOP_*GVAR opcodes.
*/
if (!fp->fun &&
index < GlobalVarCount(fp) &&
- (attrs & JSPROP_PERMANENT) &&
obj2 == obj &&
OBJ_IS_NATIVE(obj)) {
sprop = (JSScopeProperty *) prop;
- if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) &&
+ if ((sprop->attrs & JSPROP_PERMANENT) &&
+ SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) &&
SPROP_HAS_STUB_GETTER(sprop) &&
SPROP_HAS_STUB_SETTER(sprop)) {
/*
* Fast globals use frame variables to map the global
* name's atom index to the permanent fp->varobj slot
* number, tagged as a jsval. The atom index for the
* global's name literal is identical to its variable
* index.