Bug 1180211 - Don't emit bytecode for empty strings in emitTemplateString. r=jorendorff
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 16 Jul 2015 12:36:27 +0200
changeset 253152 02187d02a60ae542e097d1c1d0bdcf0d2102cac2
parent 253151 d6cec98744a6569ffadcc7c3492212789f894a51
child 253153 914bcf031b0e914a6750f43741dd3adb309f86dc
push id62363
push userjandemooij@gmail.com
push dateThu, 16 Jul 2015 10:37:25 +0000
treeherdermozilla-inbound@02187d02a60a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1180211
milestone42.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 1180211 - Don't emit bytecode for empty strings in emitTemplateString. r=jorendorff
js/src/frontend/BytecodeEmitter.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -4130,38 +4130,58 @@ BytecodeEmitter::emitDestructuringOps(Pa
     return emitDestructuringOpsHelper(pattern, emitOption);
 }
 
 bool
 BytecodeEmitter::emitTemplateString(ParseNode* pn)
 {
     MOZ_ASSERT(pn->isArity(PN_LIST));
 
+    bool pushedString = false;
+
     for (ParseNode* pn2 = pn->pn_head; pn2 != NULL; pn2 = pn2->pn_next) {
-        if (pn2->getKind() != PNK_STRING && pn2->getKind() != PNK_TEMPLATE_STRING) {
+        bool isString = (pn2->getKind() == PNK_STRING || pn2->getKind() == PNK_TEMPLATE_STRING);
+
+        // Skip empty strings. These are very common: a template string like
+        // `${a}${b}` has three empty strings and without this optimization
+        // we'd emit four JSOP_ADD operations instead of just one.
+        if (isString && pn2->pn_atom->empty())
+            continue;
+
+        if (!isString) {
             // We update source notes before emitting the expression
             if (!updateSourceCoordNotes(pn2->pn_pos.begin))
                 return false;
         }
+
         if (!emitTree(pn2))
             return false;
 
-        if (pn2->getKind() != PNK_STRING && pn2->getKind() != PNK_TEMPLATE_STRING) {
+        if (!isString) {
             // We need to convert the expression to a string
             if (!emit1(JSOP_TOSTRING))
                 return false;
         }
 
-        if (pn2 != pn->pn_head) {
+        if (pushedString) {
             // We've pushed two strings onto the stack. Add them together, leaving just one.
             if (!emit1(JSOP_ADD))
                 return false;
-        }
-
-    }
+        } else {
+            pushedString = true;
+        }
+    }
+
+    if (!pushedString) {
+        // All strings were empty, this can happen for something like `${""}`.
+        // Just push an empty string.
+        if (!emitAtomOp(cx->names().empty, JSOP_STRING))
+            return false;
+    }
+
     return true;
 }
 
 bool
 BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isLetExpr)
 {
     MOZ_ASSERT(pn->isArity(PN_LIST));
     MOZ_ASSERT(isLetExpr == (emitOption == PushInitialValues));