Bug 1215992 - Terminate control flow for THROWSETCONST/THROWSETALIASEDCONST in IonBuilder. r=shu
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 21 Oct 2015 10:09:40 +0200
changeset 303921 d1e0b2e1b8ea2e241eebc747c9f2ca85858642f3
parent 303920 dae20f86bbaad1e8b432afd01f925e9890757378
child 303922 e5963ad16857693557118108bd3e0d0beddf9c01
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1215992
milestone44.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 1215992 - Terminate control flow for THROWSETCONST/THROWSETALIASEDCONST in IonBuilder. r=shu
js/src/jit-test/tests/ion/bug1215992.js
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1215992.js
@@ -0,0 +1,6 @@
+// |jit-test| error: ReferenceError
+(function() {
+    const x = "";
+    x = y;
+    return x = z;
+})();
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1581,16 +1581,20 @@ IonBuilder::snoopControlFlow(JSOp op)
 
       case JSOP_RETURN:
       case JSOP_RETRVAL:
         return processReturn(op);
 
       case JSOP_THROW:
         return processThrow();
 
+      case JSOP_THROWSETCONST:
+      case JSOP_THROWSETALIASEDCONST:
+        return processThrowSetConst();
+
       case JSOP_GOTO:
       {
         jssrcnote* sn = info().getNote(gsn, pc);
         switch (sn ? SN_TYPE(sn) : SRC_NULL) {
           case SRC_BREAK:
           case SRC_BREAK2LABEL:
             return processBreak(op, sn);
 
@@ -1625,16 +1629,18 @@ IonBuilder::snoopControlFlow(JSOp op)
         break;
     }
     return ControlStatus_None;
 }
 
 bool
 IonBuilder::inspectOpcode(JSOp op)
 {
+    MOZ_ASSERT(analysis_.maybeInfo(pc), "Compiling unreachable op");
+
     switch (op) {
       case JSOP_NOP:
       case JSOP_LINENO:
       case JSOP_LOOPENTRY:
         return true;
 
       case JSOP_LABEL:
         return jsop_label();
@@ -1767,20 +1773,16 @@ IonBuilder::inspectOpcode(JSOp op)
       case JSOP_GETLOCAL:
         current->pushLocal(GET_LOCALNO(pc));
         return true;
 
       case JSOP_SETLOCAL:
         current->setLocal(GET_LOCALNO(pc));
         return true;
 
-      case JSOP_THROWSETCONST:
-      case JSOP_THROWSETALIASEDCONST:
-        return jsop_throwsetconst();
-
       case JSOP_CHECKLEXICAL:
         return jsop_checklexical();
 
       case JSOP_INITLEXICAL:
         current->setLocal(GET_LOCALNO(pc));
         return true;
 
       case JSOP_INITGLEXICAL: {
@@ -12731,23 +12733,30 @@ IonBuilder::jsop_deffun(uint32_t index)
     MOZ_ASSERT(analysis().usesScopeChain());
 
     MDefFun* deffun = MDefFun::New(alloc(), fun, current->scopeChain());
     current->add(deffun);
 
     return resumeAfter(deffun);
 }
 
-bool
-IonBuilder::jsop_throwsetconst()
+IonBuilder::ControlStatus
+IonBuilder::processThrowSetConst()
 {
     current->peek(-1)->setImplicitlyUsedUnchecked();
     MInstruction* lexicalError = MThrowRuntimeLexicalError::New(alloc(), JSMSG_BAD_CONST_ASSIGN);
     current->add(lexicalError);
-    return resumeAfter(lexicalError);
+    if (!resumeAfter(lexicalError))
+        return ControlStatus_Error;
+
+    current->end(MUnreachable::New(alloc()));
+
+    // Make sure no one tries to use this block now.
+    setCurrent(nullptr);
+    return processControlEnd();
 }
 
 bool
 IonBuilder::jsop_checklexical()
 {
     uint32_t slot = info().localSlot(GET_LOCALNO(pc));
     MDefinition* lexical = addLexicalCheck(current->getSlot(slot));
     if (!lexical)
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -258,16 +258,17 @@ class IonBuilder
     ControlStatus processCondSwitchBody(CFGState& state);
     ControlStatus processSwitchBreak(JSOp op);
     ControlStatus processSwitchEnd(DeferredEdge* breaks, jsbytecode* exitpc);
     ControlStatus processAndOrEnd(CFGState& state);
     ControlStatus processLabelEnd(CFGState& state);
     ControlStatus processTryEnd(CFGState& state);
     ControlStatus processReturn(JSOp op);
     ControlStatus processThrow();
+    ControlStatus processThrowSetConst();
     ControlStatus processContinue(JSOp op);
     ControlStatus processBreak(JSOp op, jssrcnote* sn);
     ControlStatus maybeLoop(JSOp op, jssrcnote* sn);
     bool pushLoop(CFGState::State state, jsbytecode* stopAt, MBasicBlock* entry, bool osr,
                   jsbytecode* loopHead, jsbytecode* initialPc,
                   jsbytecode* bodyStart, jsbytecode* bodyEnd, jsbytecode* exitpc,
                   jsbytecode* continuepc = nullptr);
     bool analyzeNewLoopTypes(MBasicBlock* entry, jsbytecode* start, jsbytecode* end);
@@ -653,17 +654,16 @@ class IonBuilder
     bool jsop_pos();
     bool jsop_neg();
     bool jsop_tostring();
     bool jsop_setarg(uint32_t arg);
     bool jsop_defvar(uint32_t index);
     bool jsop_deflexical(uint32_t index);
     bool jsop_deffun(uint32_t index);
     bool jsop_notearg();
-    bool jsop_throwsetconst();
     bool jsop_checklexical();
     bool jsop_checkaliasedlet(ScopeCoordinate sc);
     bool jsop_funcall(uint32_t argc);
     bool jsop_funapply(uint32_t argc);
     bool jsop_funapplyarguments(uint32_t argc);
     bool jsop_call(uint32_t argc, bool constructing);
     bool jsop_eval(uint32_t argc);
     bool jsop_ifeq(JSOp op);