Bug 620315 - "Assertion failure: unexpected constantly false guard detected" with "use strict", 4 > this. Fix a problem where we weren't marking functions created by |new Function| as accepting a primitive this value when their body was strict mode, by removing the duplicative bit that was being checked. r=dmandelin

This commit is contained in:
Jeff Walden 2010-12-22 18:05:07 -05:00
parent d45991c529
commit 2219b8779d
11 changed files with 56 additions and 69 deletions

View File

@ -500,7 +500,7 @@ extern JS_PUBLIC_DATA(jsid) JSID_EMPTY;
#define JSFUN_HEAVYWEIGHT_TEST(f) ((f) & JSFUN_HEAVYWEIGHT)
#define JSFUN_PRIMITIVE_THIS 0x0100 /* |this| may be a primitive value */
/* 0x0100 is unused */
#define JSFUN_CONSTRUCTOR 0x0200 /* native that can be called as a ctor
without creating a this object */

View File

@ -120,11 +120,11 @@ bool_valueOf(JSContext *cx, uintN argc, Value *vp)
static JSFunctionSpec boolean_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, bool_toSource, 0, JSFUN_PRIMITIVE_THIS),
JS_FN(js_toSource_str, bool_toSource, 0, 0),
#endif
JS_FN(js_toString_str, bool_toString, 0, JSFUN_PRIMITIVE_THIS),
JS_FN(js_valueOf_str, bool_valueOf, 0, JSFUN_PRIMITIVE_THIS),
JS_FN(js_toJSON_str, bool_valueOf, 0, JSFUN_PRIMITIVE_THIS),
JS_FN(js_toString_str, bool_toString, 0, 0),
JS_FN(js_valueOf_str, bool_valueOf, 0, 0),
JS_FN(js_toJSON_str, bool_valueOf, 0, 0),
JS_FS_END
};

View File

@ -182,8 +182,6 @@ struct JSFunction : public JSObject_Slots2
inline bool inStrictMode() const;
bool acceptsPrimitiveThis() const { return flags & JSFUN_PRIMITIVE_THIS; }
uintN countVars() const {
JS_ASSERT(FUN_INTERPRETED(this));
return u.i.nvars;

View File

@ -857,13 +857,6 @@ ComputeThisFromVpInPlace(JSContext *cx, js::Value *vp)
return ComputeThisFromArgv(cx, vp + 2);
}
/* Return true if |fun| would accept |v| as its |this|, without being wrapped. */
JS_ALWAYS_INLINE bool
PrimitiveThisTest(JSFunction *fun, const Value &v)
{
return !v.isPrimitive() || fun->acceptsPrimitiveThis();
}
/*
* Abstracts the layout of the stack passed to natives from the engine and from
* natives to js::Invoke.

View File

@ -49,6 +49,8 @@
#include "jsstr.h"
#include "methodjit/MethodJIT.h"
#include "jsfuninlines.h"
inline void
JSStackFrame::initPrev(JSContext *cx)
{
@ -356,7 +358,7 @@ JSStackFrame::computeThis(JSContext *cx)
if (thisv.isObject())
return true;
if (isFunctionFrame()) {
if (fun()->acceptsPrimitiveThis())
if (fun()->inStrictMode())
return true;
/*
* Eval function frames have their own |this| slot, which is a copy of the function's

View File

@ -929,15 +929,15 @@ JS_DEFINE_TRCINFO_2(num_toString,
static JSFunctionSpec number_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, num_toSource, 0, JSFUN_PRIMITIVE_THIS),
JS_FN(js_toSource_str, num_toSource, 0, 0),
#endif
JS_TN(js_toString_str, num_toString, 1, JSFUN_PRIMITIVE_THIS, &num_toString_trcinfo),
JS_FN(js_toLocaleString_str, num_toLocaleString, 0, JSFUN_PRIMITIVE_THIS),
JS_FN(js_valueOf_str, js_num_valueOf, 0, JSFUN_PRIMITIVE_THIS),
JS_FN(js_toJSON_str, js_num_valueOf, 0, JSFUN_PRIMITIVE_THIS),
JS_FN("toFixed", num_toFixed, 1, JSFUN_PRIMITIVE_THIS),
JS_FN("toExponential", num_toExponential, 1, JSFUN_PRIMITIVE_THIS),
JS_FN("toPrecision", num_toPrecision, 1, JSFUN_PRIMITIVE_THIS),
JS_TN(js_toString_str, num_toString, 1, 0, &num_toString_trcinfo),
JS_FN(js_toLocaleString_str, num_toLocaleString, 0, 0),
JS_FN(js_valueOf_str, js_num_valueOf, 0, 0),
JS_FN(js_toJSON_str, js_num_valueOf, 0, 0),
JS_FN("toFixed", num_toFixed, 1, 0),
JS_FN("toExponential", num_toExponential, 1, 0),
JS_FN("toPrecision", num_toPrecision, 1, 0),
JS_FS_END
};

View File

@ -2757,7 +2757,7 @@ static JSFunctionSpec object_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, obj_toSource, 0,0),
#endif
JS_FN(js_toString_str, obj_toString, 0,JSFUN_PRIMITIVE_THIS),
JS_FN(js_toString_str, obj_toString, 0,0),
JS_FN(js_toLocaleString_str, obj_toLocaleString, 0,0),
JS_FN(js_valueOf_str, obj_valueOf, 0,0),
#if JS_HAS_OBJ_WATCHPOINT

View File

@ -3163,9 +3163,6 @@ Parser::functionDef(JSAtom *funAtom, FunctionType type, uintN lambda)
if (!LeaveFunction(pn, &funtc, funAtom, lambda))
return NULL;
if (funtc.inStrictMode())
fun->flags |= JSFUN_PRIMITIVE_THIS;
/* If the surrounding function is not strict code, reset the lexer. */
if (!outertc->inStrictMode())
tokenStream.setStrictMode(false);

View File

@ -3058,60 +3058,58 @@ JS_DEFINE_TRCINFO_1(str_concat,
(3, (extern, STRING_RETRY, js_ConcatStrings, CONTEXT, THIS_STRING, STRING,
1, nanojit::ACCSET_NONE)))
static const uint16 GENERIC_PRIMITIVE = JSFUN_GENERIC_NATIVE | JSFUN_PRIMITIVE_THIS;
static JSFunctionSpec string_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN("quote", str_quote, 0,GENERIC_PRIMITIVE),
JS_FN(js_toSource_str, str_toSource, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("quote", str_quote, 0,JSFUN_GENERIC_NATIVE),
JS_FN(js_toSource_str, str_toSource, 0,0),
#endif
/* Java-like methods. */
JS_FN(js_toString_str, js_str_toString, 0,JSFUN_PRIMITIVE_THIS),
JS_FN(js_valueOf_str, js_str_toString, 0,JSFUN_PRIMITIVE_THIS),
JS_FN(js_toJSON_str, js_str_toString, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("substring", str_substring, 2,GENERIC_PRIMITIVE),
JS_FN("toLowerCase", str_toLowerCase, 0,GENERIC_PRIMITIVE),
JS_FN("toUpperCase", str_toUpperCase, 0,GENERIC_PRIMITIVE),
JS_FN("charAt", js_str_charAt, 1,GENERIC_PRIMITIVE),
JS_FN("charCodeAt", js_str_charCodeAt, 1,GENERIC_PRIMITIVE),
JS_FN("indexOf", str_indexOf, 1,GENERIC_PRIMITIVE),
JS_FN("lastIndexOf", str_lastIndexOf, 1,GENERIC_PRIMITIVE),
JS_FN("trim", str_trim, 0,GENERIC_PRIMITIVE),
JS_FN("trimLeft", str_trimLeft, 0,GENERIC_PRIMITIVE),
JS_FN("trimRight", str_trimRight, 0,GENERIC_PRIMITIVE),
JS_FN("toLocaleLowerCase", str_toLocaleLowerCase, 0,GENERIC_PRIMITIVE),
JS_FN("toLocaleUpperCase", str_toLocaleUpperCase, 0,GENERIC_PRIMITIVE),
JS_FN("localeCompare", str_localeCompare, 1,GENERIC_PRIMITIVE),
JS_FN(js_toString_str, js_str_toString, 0,0),
JS_FN(js_valueOf_str, js_str_toString, 0,0),
JS_FN(js_toJSON_str, js_str_toString, 0,0),
JS_FN("substring", str_substring, 2,JSFUN_GENERIC_NATIVE),
JS_FN("toLowerCase", str_toLowerCase, 0,JSFUN_GENERIC_NATIVE),
JS_FN("toUpperCase", str_toUpperCase, 0,JSFUN_GENERIC_NATIVE),
JS_FN("charAt", js_str_charAt, 1,JSFUN_GENERIC_NATIVE),
JS_FN("charCodeAt", js_str_charCodeAt, 1,JSFUN_GENERIC_NATIVE),
JS_FN("indexOf", str_indexOf, 1,JSFUN_GENERIC_NATIVE),
JS_FN("lastIndexOf", str_lastIndexOf, 1,JSFUN_GENERIC_NATIVE),
JS_FN("trim", str_trim, 0,JSFUN_GENERIC_NATIVE),
JS_FN("trimLeft", str_trimLeft, 0,JSFUN_GENERIC_NATIVE),
JS_FN("trimRight", str_trimRight, 0,JSFUN_GENERIC_NATIVE),
JS_FN("toLocaleLowerCase", str_toLocaleLowerCase, 0,JSFUN_GENERIC_NATIVE),
JS_FN("toLocaleUpperCase", str_toLocaleUpperCase, 0,JSFUN_GENERIC_NATIVE),
JS_FN("localeCompare", str_localeCompare, 1,JSFUN_GENERIC_NATIVE),
/* Perl-ish methods (search is actually Python-esque). */
JS_FN("match", str_match, 1,GENERIC_PRIMITIVE),
JS_FN("search", str_search, 1,GENERIC_PRIMITIVE),
JS_FN("replace", str_replace, 2,GENERIC_PRIMITIVE),
JS_FN("split", str_split, 2,GENERIC_PRIMITIVE),
JS_FN("match", str_match, 1,JSFUN_GENERIC_NATIVE),
JS_FN("search", str_search, 1,JSFUN_GENERIC_NATIVE),
JS_FN("replace", str_replace, 2,JSFUN_GENERIC_NATIVE),
JS_FN("split", str_split, 2,JSFUN_GENERIC_NATIVE),
#if JS_HAS_PERL_SUBSTR
JS_FN("substr", str_substr, 2,GENERIC_PRIMITIVE),
JS_FN("substr", str_substr, 2,JSFUN_GENERIC_NATIVE),
#endif
/* Python-esque sequence methods. */
JS_TN("concat", str_concat, 1,GENERIC_PRIMITIVE, &str_concat_trcinfo),
JS_FN("slice", str_slice, 2,GENERIC_PRIMITIVE),
JS_TN("concat", str_concat, 1,JSFUN_GENERIC_NATIVE, &str_concat_trcinfo),
JS_FN("slice", str_slice, 2,JSFUN_GENERIC_NATIVE),
/* HTML string methods. */
#if JS_HAS_STR_HTML_HELPERS
JS_FN("bold", str_bold, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("italics", str_italics, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("fixed", str_fixed, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("fontsize", str_fontsize, 1,JSFUN_PRIMITIVE_THIS),
JS_FN("fontcolor", str_fontcolor, 1,JSFUN_PRIMITIVE_THIS),
JS_FN("link", str_link, 1,JSFUN_PRIMITIVE_THIS),
JS_FN("anchor", str_anchor, 1,JSFUN_PRIMITIVE_THIS),
JS_FN("strike", str_strike, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("small", str_small, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("big", str_big, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("blink", str_blink, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("sup", str_sup, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("sub", str_sub, 0,JSFUN_PRIMITIVE_THIS),
JS_FN("bold", str_bold, 0,0),
JS_FN("italics", str_italics, 0,0),
JS_FN("fixed", str_fixed, 0,0),
JS_FN("fontsize", str_fontsize, 1,0),
JS_FN("fontcolor", str_fontcolor, 1,0),
JS_FN("link", str_link, 1,0),
JS_FN("anchor", str_anchor, 1,0),
JS_FN("strike", str_strike, 0,0),
JS_FN("small", str_small, 0,0),
JS_FN("big", str_big, 0,0),
JS_FN("blink", str_blink, 0,0),
JS_FN("sup", str_sup, 0,0),
JS_FN("sub", str_sub, 0,0),
#endif
JS_FS_END

View File

@ -15720,7 +15720,7 @@ TraceRecorder::record_JSOP_CALLPROP()
if (pcval.isFunObj()) {
if (l.isPrimitive()) {
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &pcval.toFunObj());
if (!PrimitiveThisTest(fun, l))
if (fun->isInterpreted() && !fun->inStrictMode())
RETURN_STOP_A("callee does not accept primitive |this|");
}
set(&l, w.immpObjGC(&pcval.toFunObj()));

View File

@ -2022,7 +2022,6 @@ DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive)
SHOW_FLAG(LAMBDA);
SHOW_FLAG(HEAVYWEIGHT);
SHOW_FLAG(PRIMITIVE_THIS);
SHOW_FLAG(EXPR_CLOSURE);
SHOW_FLAG(TRCINFO);