Bug 883656 - Handle lazy functions in b[a] lambda pattern matching, r=luke.
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 17 Jun 2013 10:12:36 -0600
changeset 146794 4319f2110d9015bfd655ddb690abd121d75b6481
parent 146793 459376ae11c778af5a828ec0803907837f1900b3
child 146795 849e6303ac21642973f3a2c43a68774e15777411
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs883656
milestone24.0a1
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
Bug 883656 - Handle lazy functions in b[a] lambda pattern matching, r=luke.
js/src/jsstr.cpp
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -2681,67 +2681,71 @@ static const uint32_t ReplaceOptArg = 2;
 
 /*
  * Pattern match the script to check if it is is indexing into a particular
  * object, e.g. 'function(a) { return b[a]; }'. Avoid calling the script in
  * such cases, which are used by javascript packers (particularly the popular
  * Dean Edwards packer) to efficiently encode large scripts. We only handle the
  * code patterns generated by such packers here.
  */
-static JSObject *
-LambdaIsGetElem(JSObject &lambda)
+static bool
+LambdaIsGetElem(JSContext *cx, JSObject &lambda, MutableHandleObject pobj)
 {
     if (!lambda.isFunction())
-        return NULL;
+        return true;
 
     JSFunction *fun = lambda.toFunction();
-    if (!fun->hasScript())
-        return NULL;
-
-    JSScript *script = fun->nonLazyScript();
+    if (!fun->isInterpreted())
+        return true;
+
+    JSScript *script = fun->getOrCreateScript(cx);
+    if (!script)
+        return false;
+
     jsbytecode *pc = script->code;
 
     /*
      * JSOP_GETALIASEDVAR tells us exactly where to find the base object 'b'.
      * Rule out the (unlikely) possibility of a heavyweight function since it
      * would make our scope walk off by 1.
      */
     if (JSOp(*pc) != JSOP_GETALIASEDVAR || fun->isHeavyweight())
-        return NULL;
+        return true;
     ScopeCoordinate sc(pc);
     ScopeObject *scope = &fun->environment()->asScope();
     for (unsigned i = 0; i < sc.hops; ++i)
         scope = &scope->enclosingScope().asScope();
     Value b = scope->aliasedVar(sc);
     pc += JSOP_GETALIASEDVAR_LENGTH;
 
     /* Look for 'a' to be the lambda's first argument. */
     if (JSOp(*pc) != JSOP_GETARG || GET_SLOTNO(pc) != 0)
-        return NULL;
+        return true;
     pc += JSOP_GETARG_LENGTH;
 
     /* 'b[a]' */
     if (JSOp(*pc) != JSOP_GETELEM)
-        return NULL;
+        return true;
     pc += JSOP_GETELEM_LENGTH;
 
     /* 'return b[a]' */
     if (JSOp(*pc) != JSOP_RETURN)
-        return NULL;
+        return true;
 
     /* 'b' must behave like a normal object. */
     if (!b.isObject())
-        return NULL;
+        return true;
 
     JSObject &bobj = b.toObject();
     Class *clasp = bobj.getClass();
     if (!clasp->isNative() || clasp->ops.lookupProperty || clasp->ops.getProperty)
-        return NULL;
-
-    return &bobj;
+        return true;
+
+    pobj.set(&bobj);
+    return true;
 }
 
 JSBool
 js::str_replace(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     ReplaceData rdata(cx);
@@ -2754,18 +2758,18 @@ js::str_replace(JSContext *cx, unsigned 
 
     /* Extract replacement string/function. */
     if (args.length() >= ReplaceOptArg && js_IsCallable(args[1])) {
         rdata.lambda = &args[1].toObject();
         rdata.elembase = NULL;
         rdata.repstr = NULL;
         rdata.dollar = rdata.dollarEnd = NULL;
 
-        if (JSObject *base = LambdaIsGetElem(*rdata.lambda))
-            rdata.elembase = base;
+        if (!LambdaIsGetElem(cx, *rdata.lambda, &rdata.elembase))
+            return false;
     } else {
         rdata.lambda = NULL;
         rdata.elembase = NULL;
         rdata.repstr = ArgToRootedString(cx, args, 1);
         if (!rdata.repstr)
             return false;
 
         /* We're about to store pointers into the middle of our string. */