author | Jason Orendorff <jorendorff@mozilla.com> |
Fri, 21 Jan 2011 13:22:26 -0600 | |
changeset 61210 | 33f07113de5fcf6bbe59ce554402b22c91cfebcb |
parent 61209 | 34359bdfcde48e5765b8806c20343174aa909da6 |
child 61211 | 96f460867847b25eedd685c7621da40d3672f7b1 |
push id | 18277 |
push user | cleary@mozilla.com |
push date | Tue, 25 Jan 2011 03:52:51 +0000 |
treeherder | mozilla-central@7ee91bd90e7a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | brendan |
bugs | 617609 |
milestone | 2.0b10pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/jscntxt.h | file | annotate | diff | comparison | revisions | |
js/src/jsemit.h | file | annotate | diff | comparison | revisions | |
js/src/jsparse.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsparse.h | file | annotate | diff | comparison | revisions |
--- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -828,17 +828,17 @@ private: #ifdef DEBUG # define FUNCTION_KIND_METER_LIST(_) \ _(allfun), _(heavy), _(nofreeupvar), _(onlyfreevar), \ _(flat), _(badfunarg), \ _(joinedsetmethod), _(joinedinitmethod), \ _(joinedreplace), _(joinedsort), _(joinedmodulepat), \ _(mreadbarrier), _(mwritebarrier), _(mwslotbarrier), \ - _(unjoined) + _(unjoined), _(indynamicscope) # define identity(x) x struct JSFunctionMeter { int32 FUNCTION_KIND_METER_LIST(identity); }; # undef identity
--- a/js/src/jsemit.h +++ b/js/src/jsemit.h @@ -258,16 +258,21 @@ struct JSStmtInfo { #define TCF_FUN_MIGHT_ALIAS_LOCALS 0x4000000 /* * The script contains singleton initialiser JSOP_OBJECT. */ #define TCF_HAS_SINGLETONS 0x8000000 /* + * Some enclosing scope is a with-statement or E4X filter-expression. + */ +#define TCF_IN_WITH 0x10000000 + +/* * Flags to check for return; vs. return expr; in a function. */ #define TCF_RETURN_FLAGS (TCF_RETURN_EXPR | TCF_RETURN_VOID) /* * Sticky deoptimization flags to propagate from FunctionBody. */ #define TCF_FUN_FLAGS (TCF_FUN_SETS_OUTER_NAME | \
--- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -296,27 +296,39 @@ Parser::newFunctionBox(JSObject *obj, JS for (JSStmtInfo *stmt = tc->topStmt; stmt; stmt = stmt->down) { if (STMT_IS_LOOP(stmt)) { funbox->inLoop = true; break; } } funbox->level = tc->staticLevel; funbox->tcflags = (TCF_IN_FUNCTION | (tc->flags & (TCF_COMPILE_N_GO | TCF_STRICT_MODE_CODE))); + if (tc->innermostWith) + funbox->tcflags |= TCF_IN_WITH; return funbox; } bool JSFunctionBox::joinable() const { return FUN_NULL_CLOSURE((JSFunction *) object) && !(tcflags & (TCF_FUN_USES_ARGUMENTS | TCF_FUN_USES_OWN_NAME)); } bool +JSFunctionBox::inAnyDynamicScope() const +{ + for (const JSFunctionBox *funbox = this; funbox; funbox = funbox->parent) { + if (funbox->tcflags & (TCF_IN_WITH | TCF_FUN_CALLS_EVAL)) + return true; + } + return false; +} + +bool JSFunctionBox::shouldUnbrand(uintN methods, uintN slowMethods) const { if (slowMethods != 0) { for (const JSFunctionBox *funbox = this; funbox; funbox = funbox->parent) { if (!(funbox->tcflags & TCF_FUN_MODULE_PATTERN)) return true; if (funbox->inLoop) return true; @@ -2459,16 +2471,19 @@ Parser::setFunctionKinds(JSFunctionBox * JSFunction *fun = (JSFunction *) funbox->object; JS_ASSERT(FUN_KIND(fun) == JSFUN_INTERPRETED); FUN_METER(allfun); if (funbox->tcflags & TCF_FUN_HEAVYWEIGHT) { FUN_METER(heavy); + } else if (funbox->inAnyDynamicScope()) { + JS_ASSERT(!FUN_NULL_CLOSURE(fun)); + FUN_METER(indynamicscope); } else if (pn->pn_type != TOK_UPVARS) { /* * No lexical dependencies => null closure, for best performance. * A null closure needs no scope chain, but alas we've coupled * principals-finding to scope (for good fundamental reasons, but * the implementation overloads the parent slot and we should fix * that). See, e.g., the JSOP_LAMBDA case in jsinterp.cpp. *
--- a/js/src/jsparse.h +++ b/js/src/jsparse.h @@ -972,16 +972,22 @@ struct JSFunctionBox : public JSObjectBo uint32 queued:1, inLoop:1, /* in a loop in parent function */ level:JSFB_LEVEL_BITS; uint32 tcflags; bool joinable() const; /* + * True if this function is inside the scope of a with-statement, an E4X + * filter-expression, or a function that uses direct eval. + */ + bool inAnyDynamicScope() const; + + /* * Unbrand an object being initialized or constructed if any method cannot * be joined to one compiler-created null closure shared among N different * closure environments. * * We despecialize from caching function objects, caching slots or shapes * instead, because an unbranded object may still have joined methods (for * which shape->isMethod), since PropertyCache::fill gives precedence to * joined methods over branded methods.