Do bytecode validation as part of testing
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 27 Nov 2013 23:15:48 +0000 (23:15 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 27 Nov 2013 23:15:48 +0000 (23:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=124913

Source/JavaScriptCore:

Reviewed by Oliver Hunt.

Also fix some small bugs in the bytecode liveness analysis that I found by doing
this validation thingy.

* bytecode/BytecodeLivenessAnalysis.cpp:
(JSC::isValidRegisterForLiveness):
(JSC::BytecodeLivenessAnalysis::runLivenessFixpoint):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::validate):
(JSC::CodeBlock::beginValidationDidFail):
(JSC::CodeBlock::endValidationDidFail):
* bytecode/CodeBlock.h:
* runtime/Executable.cpp:
(JSC::ScriptExecutable::prepareForExecutionImpl):
* runtime/Options.h:

Source/WTF:

Reviewed by Oliver Hunt.

* GNUmakefile.list.am:
* WTF.vcxproj/WTF.vcxproj:
* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/FastBitVector.cpp: Added.
(WTF::FastBitVector::dump):
* wtf/FastBitVector.h:
(WTF::FastBitVector::resize):
(WTF::FastBitVector::bitCount):
(WTF::FastBitVector::arrayLength):

Tools:

Reviewed by Oliver Hunt.

* Scripts/run-jsc-stress-tests:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@159825 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/dfg/DFGOSREntry.cpp
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Options.h
Source/WTF/ChangeLog
Source/WTF/GNUmakefile.list.am
Source/WTF/WTF.vcxproj/WTF.vcxproj
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/CMakeLists.txt
Source/WTF/wtf/FastBitVector.cpp [new file with mode: 0644]
Source/WTF/wtf/FastBitVector.h
Tools/ChangeLog
Tools/Scripts/run-jsc-stress-tests

index 5285d2598e9a6530b0080fb0cd871f6217542032..712176622f885977287904171afcbdc8367fe82a 100644 (file)
@@ -1,3 +1,25 @@
+2013-11-26  Filip Pizlo  <fpizlo@apple.com>
+
+        Do bytecode validation as part of testing
+        https://bugs.webkit.org/show_bug.cgi?id=124913
+
+        Reviewed by Oliver Hunt.
+        
+        Also fix some small bugs in the bytecode liveness analysis that I found by doing
+        this validation thingy.
+
+        * bytecode/BytecodeLivenessAnalysis.cpp:
+        (JSC::isValidRegisterForLiveness):
+        (JSC::BytecodeLivenessAnalysis::runLivenessFixpoint):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::validate):
+        (JSC::CodeBlock::beginValidationDidFail):
+        (JSC::CodeBlock::endValidationDidFail):
+        * bytecode/CodeBlock.h:
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::prepareForExecutionImpl):
+        * runtime/Options.h:
+
 2013-11-27  Andreas Kling  <akling@apple.com>
 
         Structure::m_staticFunctionReified should be a single bit.
index 28ffd10d4688dd9edb54c06f14dc81c3f54c351d..a119de080e5c9f9bf7fbca965f292d9ebde289d7 100644 (file)
@@ -42,11 +42,19 @@ BytecodeLivenessAnalysis::BytecodeLivenessAnalysis(CodeBlock* codeBlock)
 
 static bool isValidRegisterForLiveness(CodeBlock* codeBlock, int operand)
 {
+    if (codeBlock->isConstantRegisterIndex(operand))
+        return false;
+    
     VirtualRegister virtualReg(operand);
-    return !codeBlock->isConstantRegisterIndex(operand) // Don't care about constants.
-        && virtualReg.isLocal() // Don't care about arguments.
-        && (!codeBlock->captureCount() // If we have no captured variables, we're good to go.
-            || (virtualReg.offset() > codeBlock->captureStart() || (virtualReg.offset() <= codeBlock->captureEnd())));
+    if (!virtualReg.isLocal())
+        return false;
+    
+    if (codeBlock->captureCount()
+        && operand <= codeBlock->captureStart()
+        && operand > codeBlock->captureEnd())
+        return false;
+    
+    return true;
 }
 
 static void setForOperand(CodeBlock* codeBlock, FastBitVector& bits, int operand)
@@ -465,14 +473,17 @@ static void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecode
         return;
     }
     case op_tear_off_arguments: {
-        if (isValidRegisterForLiveness(codeBlock, instruction[1].u.operand - 1))
-            setForOperand(codeBlock, defs, instruction[1].u.operand - 1);
+        int operand = unmodifiedArgumentsRegister(
+            VirtualRegister(instruction[1].u.operand)).offset();
+        if (isValidRegisterForLiveness(codeBlock, operand))
+            setForOperand(codeBlock, defs, operand);
         return;
     }
     case op_enter: {
         defs.setAll();
         return;
     } }
+    RELEASE_ASSERT_NOT_REACHED();
 }
 
 static unsigned getLeaderOffsetForBasicBlock(RefPtr<BytecodeBasicBlock>* basicBlock)
@@ -572,7 +583,7 @@ static void computeLocalLivenessForBlock(CodeBlock* codeBlock, BytecodeBasicBloc
 void BytecodeLivenessAnalysis::runLivenessFixpoint()
 {
     UnlinkedCodeBlock* unlinkedCodeBlock = m_codeBlock->unlinkedCodeBlock();
-    unsigned numberOfVariables = unlinkedCodeBlock->m_numVars + 
+    unsigned numberOfVariables =
         unlinkedCodeBlock->m_numCalleeRegisters - m_codeBlock->captureCount();
 
     for (unsigned i = 0; i < m_basicBlocks.size(); i++) {
index b6fd4d20b250b85d9159502cd11fe1346825e842..f91006f50bfbe4d555227c50cd7b7fac6a286edb 100644 (file)
@@ -3422,4 +3422,58 @@ String CodeBlock::nameForRegister(VirtualRegister virtualRegister)
     return "";
 }
 
+void CodeBlock::validate()
+{
+    BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint.
+    
+    FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(0);
+    
+    if (liveAtHead.numBits() != static_cast<size_t>(m_numCalleeRegisters)) {
+        beginValidationDidFail();
+        dataLog("    Wrong number of bits in result!\n");
+        dataLog("    Result: ", liveAtHead, "\n");
+        dataLog("    Bit count: ", liveAtHead.numBits(), "\n");
+        endValidationDidFail();
+    }
+    
+    for (unsigned i = m_numCalleeRegisters; i--;) {
+        bool isCaptured = false;
+        VirtualRegister reg = virtualRegisterForLocal(i);
+        
+        if (captureCount())
+            isCaptured = reg.offset() <= captureStart() && reg.offset() > captureEnd();
+        
+        if (isCaptured) {
+            if (!liveAtHead.get(i)) {
+                beginValidationDidFail();
+                dataLog("    Variable loc", i, " is expected to be live because it is captured, but it isn't live.\n");
+                dataLog("    Result: ", liveAtHead, "\n");
+                endValidationDidFail();
+            }
+        } else {
+            if (liveAtHead.get(i)) {
+                beginValidationDidFail();
+                dataLog("    Variable loc", i, " is expected to be dead.\n");
+                dataLog("    Result: ", liveAtHead, "\n");
+                endValidationDidFail();
+            }
+        }
+    }
+}
+
+void CodeBlock::beginValidationDidFail()
+{
+    dataLog("Validation failure in ", *this, ":\n");
+    dataLog("\n");
+}
+
+void CodeBlock::endValidationDidFail()
+{
+    dataLog("\n");
+    dumpBytecode();
+    dataLog("\n");
+    dataLog("Validation failure.\n");
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
 } // namespace JSC
index dba6e1def160cb71ea0a4a90d2c397a953006268..f5a4f50830aeaa4b8b43dc39cebd8a03cbda4e99 100644 (file)
@@ -704,6 +704,8 @@ public:
             m_livenessAnalysis = std::make_unique<BytecodeLivenessAnalysis>(this);
         return *m_livenessAnalysis;
     }
+    
+    void validate();
 
     // Jump Tables
 
@@ -1028,6 +1030,9 @@ private:
         if (!m_rareData)
             m_rareData = adoptPtr(new RareData);
     }
+    
+    void beginValidationDidFail();
+    NO_RETURN_DUE_TO_CRASH void endValidationDidFail();
 
 #if ENABLE(JIT)
     void resetStubInternal(RepatchBuffer&, StructureStubInfo&);
index d4fc95dbf3e91439cb935f0ae6c5a79ab763bba4..2efb008d092897183aa8b31ef0ed159958cc367e 100644 (file)
@@ -44,7 +44,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
     ASSERT(codeBlock->alternative());
     ASSERT(codeBlock->alternative()->jitType() == JITCode::BaselineJIT);
     ASSERT(!codeBlock->jitCodeMap());
-
+    
     if (Options::verboseOSR()) {
         dataLog(
             "DFG OSR in ", *codeBlock->alternative(), " -> ", *codeBlock,
index 8a10959e2ce249e1ba69edf1c10f620c6f2a2932..35ea833eb0a7dd0286f7e7e60caf59b91c738c66 100644 (file)
@@ -298,6 +298,9 @@ JSObject* ScriptExecutable::prepareForExecutionImpl(
         return exception;
     }
     
+    if (Options::validateBytecode())
+        codeBlock->validate();
+    
     bool shouldUseLLInt;
 #if !ENABLE(JIT)
     // No JIT implies use of the C Loop LLINT. Override the options to reflect this. 
index 62f3f3eb413684cf561039184d4ff7d523c5dd45..4aaa80e1a2e4ccef66d108aa2bd359f6974e5790 100644 (file)
@@ -100,6 +100,7 @@ typedef OptionRange optionRange;
     \
     v(bool, dumpGeneratedBytecodes, false) \
     v(bool, dumpBytecodeLivenessResults, false) \
+    v(bool, validateBytecode, false) \
     \
     /* showDisassembly implies showDFGDisassembly. */ \
     v(bool, showDisassembly, false) \
index 5bfd76d48e81d24d36616813b8e1c1699880d418..4b6f1a9b902ecf5fe7d26aaf8e829b3354d396bc 100644 (file)
@@ -1,3 +1,21 @@
+2013-11-26  Filip Pizlo  <fpizlo@apple.com>
+
+        Do bytecode validation as part of testing
+        https://bugs.webkit.org/show_bug.cgi?id=124913
+
+        Reviewed by Oliver Hunt.
+
+        * GNUmakefile.list.am:
+        * WTF.vcxproj/WTF.vcxproj:
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/FastBitVector.cpp: Added.
+        (WTF::FastBitVector::dump):
+        * wtf/FastBitVector.h:
+        (WTF::FastBitVector::resize):
+        (WTF::FastBitVector::bitCount):
+        (WTF::FastBitVector::arrayLength):
+
 2013-11-27  Tamas Gergely  <tgergely.u-szeged@partner.samsung.com>
 
         Remove Sparc specific code.
index 33e55cc3ca8fc0a245049fe882e5d3a9f4b9f04c..fd56f4f1e995cea808d7f079ca8d1f49ad1e161c 100644 (file)
@@ -48,6 +48,7 @@ wtf_sources += \
     Source/WTF/wtf/Encoder.h \
     Source/WTF/wtf/EnumClass.h \
     Source/WTF/wtf/ExportMacros.h \
+    Source/WTF/wtf/FastBitVector.cpp \
     Source/WTF/wtf/FastBitVector.h \
     Source/WTF/wtf/FastMalloc.cpp \
     Source/WTF/wtf/FastMalloc.h \
index 24726990202306a9d8d12b762fac28fc25fa466f..43b70fa44380a445089f683e9f62d66a2e9583a1 100644 (file)
@@ -70,6 +70,7 @@
     <ClCompile Include="..\wtf\dtoa\fixed-dtoa.cc" />
     <ClCompile Include="..\wtf\dtoa\strtod.cc" />
     <ClCompile Include="..\wtf\DynamicAnnotations.cpp" />
+    <ClCompile Include="..\wtf\FastBitVector.cpp" />
     <ClCompile Include="..\wtf\FastMalloc.cpp" />
     <ClCompile Include="..\wtf\FilePrintStream.cpp" />
     <ClCompile Include="..\wtf\FunctionDispatcher.cpp" />
index adcb4a2a537ba094496c9bd0222025d44e1474f9..8468803810777d233b746711ba144cc16f83f5f8 100644 (file)
@@ -25,6 +25,7 @@
                0F2B66A617B6B4FB00A7AE3F /* DeferrableRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A417B6B4F700A7AE3F /* DeferrableRefCounted.h */; };
                0F2B66A717B6B4FD00A7AE3F /* FlipBytes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A517B6B4F700A7AE3F /* FlipBytes.h */; };
                0F87105A16643F190090B0AD /* RawPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F87105916643F190090B0AD /* RawPointer.h */; };
+               0F885E0F1845AEA900F1E3FA /* FastBitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F885E0E1845AE9F00F1E3FA /* FastBitVector.cpp */; };
                0F8F2B91172E00FC007DBDA5 /* CompilationThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */; };
                0F8F2B92172E0103007DBDA5 /* CompilationThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */; };
                0F8F2B9C172F2596007DBDA5 /* ConversionMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B9B172F2594007DBDA5 /* ConversionMode.h */; };
                0F2B66A417B6B4F700A7AE3F /* DeferrableRefCounted.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeferrableRefCounted.h; sourceTree = "<group>"; };
                0F2B66A517B6B4F700A7AE3F /* FlipBytes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FlipBytes.h; sourceTree = "<group>"; };
                0F87105916643F190090B0AD /* RawPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RawPointer.h; sourceTree = "<group>"; };
+               0F885E0E1845AE9F00F1E3FA /* FastBitVector.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FastBitVector.cpp; sourceTree = "<group>"; };
                0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CompilationThread.cpp; sourceTree = "<group>"; };
                0F8F2B90172E00F0007DBDA5 /* CompilationThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompilationThread.h; sourceTree = "<group>"; };
                0F8F2B9B172F2594007DBDA5 /* ConversionMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConversionMode.h; sourceTree = "<group>"; };
                                A8A4729E151A825A004123FF /* Encoder.h */,
                                44F66007171AFAA900E4AD19 /* EnumClass.h */,
                                A8A4729F151A825A004123FF /* ExportMacros.h */,
+                               0F885E0E1845AE9F00F1E3FA /* FastBitVector.cpp */,
                                0FD81AC4154FB22E00983E72 /* FastBitVector.h */,
                                A8A472A1151A825A004123FF /* FastMalloc.cpp */,
                                A8A472A2151A825A004123FF /* FastMalloc.h */,
                                A8A473AE151A825B004123FF /* diy-fp.cc in Sources */,
                                A8A473B0151A825B004123FF /* double-conversion.cc in Sources */,
                                A8A473BA151A825B004123FF /* dtoa.cpp in Sources */,
+                               0F885E0F1845AEA900F1E3FA /* FastBitVector.cpp in Sources */,
                                A8A473BC151A825B004123FF /* DynamicAnnotations.cpp in Sources */,
                                A8A473B3151A825B004123FF /* fast-dtoa.cc in Sources */,
                                A8A473C3151A825B004123FF /* FastMalloc.cpp in Sources */,
index ab2e4bf5cdd88c3e6dcc7cf4a8da282e07af506f..4c7a7d33a3036f7a1fc2ef4666cae924109dc6ac 100644 (file)
@@ -156,6 +156,7 @@ set(WTF_SOURCES
     DateMath.cpp
     DecimalNumber.cpp
     DynamicAnnotations.cpp
+    FastBitVector.cpp
     FastMalloc.cpp
     FilePrintStream.cpp
     FunctionDispatcher.cpp
diff --git a/Source/WTF/wtf/FastBitVector.cpp b/Source/WTF/wtf/FastBitVector.cpp
new file mode 100644 (file)
index 0000000..3abccea
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "FastBitVector.h"
+
+#include "PrintStream.h"
+
+namespace WTF {
+
+void FastBitVector::dump(PrintStream& out) const
+{
+    for (unsigned i = 0; i < m_numBits; ++i)
+        out.print(get(i) ? "1" : "-");
+}
+
+} // namespace WTF
+
index 3c8080846d3e393caf2cf18e6ae54ce591bfe304..f96180d9e559c2a069af83c2944255357c77a41a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,6 +32,8 @@
 
 namespace WTF {
 
+class PrintStream;
+
 class FastBitVector {
 public:
     FastBitVector()
@@ -72,7 +74,7 @@ public:
         // Use fastCalloc instead of fastRealloc because we expect the common
         // use case for this method to be initializing the size of the bitvector.
         
-        size_t newLength = (numBits + 31) >> 5;
+        size_t newLength = arrayLength(numBits);
         uint32_t* newArray = static_cast<uint32_t*>(fastCalloc(newLength, 4));
         memcpy(newArray, m_array, arrayLength() * 4);
         if (m_array)
@@ -166,8 +168,20 @@ public:
         ASSERT_WITH_SECURITY_IMPLICATION(i < m_numBits);
         return !!(m_array[i >> 5] & (1 << (i & 31)));
     }
+    
+    size_t bitCount() const
+    {
+        size_t result = 0;
+        for (unsigned i = arrayLength(); i--;)
+            result += WTF::bitCount(m_array[i]);
+        return result;
+    }
+    
+    WTF_EXPORT_PRIVATE void dump(PrintStream&) const;
+    
 private:
-    size_t arrayLength() const { return (m_numBits + 31) >> 5; }
+    static size_t arrayLength(size_t numBits) { return (numBits + 31) >> 5; }
+    size_t arrayLength() const { return arrayLength(m_numBits); }
     
     uint32_t* m_array; // No, this can't be an std::unique_ptr<uint32_t[]>.
     size_t m_numBits;
index a8d69da484c2fe9b4894f2236e768100d2413adb..e6a9735cb363278849bbf81ab84d7d5b7164276e 100644 (file)
@@ -1,3 +1,12 @@
+2013-11-26  Filip Pizlo  <fpizlo@apple.com>
+
+        Do bytecode validation as part of testing
+        https://bugs.webkit.org/show_bug.cgi?id=124913
+
+        Reviewed by Oliver Hunt.
+
+        * Scripts/run-jsc-stress-tests:
+
 2013-11-27  Andres Gomez  <agomez@igalia.com>
 
         [GTK] Tools/Scripts/update-webkitgtk-libs fails due to missing fontutils dependencies for building the "xserver" module
index 6b83c8b353a669c525000ffc92d731bd2bb6b59a..c333c80e94b82351ef06db7ddc79598bdd0d6a6b 100755 (executable)
@@ -401,12 +401,12 @@ def runNoLLInt
     run("no-llint", "--useLLInt=false")
 end
 
-def runNoCJIT
-    run("no-cjit", "--enableConcurrentJIT=false")
+def runNoCJITValidate
+    run("no-cjit", "--enableConcurrentJIT=false", "--validateBytecode=true", "--validateGraph=true")
 end
 
 def runNoCJITValidatePhases
-    run("no-cjit-validate-phases", "--enableConcurrentJIT=false", "--validateGraphAtEachPhase=true")
+    run("no-cjit-validate-phases", "--enableConcurrentJIT=false", "--validateBytecode=true", "--validateGraphAtEachPhase=true")
 end
 
 def runDefaultFTL
@@ -468,7 +468,7 @@ end
 
 def defaultQuickRun
     runDefault
-    runNoCJIT
+    runNoCJITValidate
     if $enableFTL
         runDefaultFTL
         runFTLNoCJIT
@@ -558,15 +558,15 @@ def runMozillaTestBaselineJIT(mode, *extraFiles)
     runMozillaTest("baseline", mode, extraFiles, "--useLLInt=false", "--useDFGJIT=false")
 end
 
-def runMozillaTestDFGEagerNoCJIT(mode, *extraFiles)
-    runMozillaTest("dfg-eager-no-cjit", mode, extraFiles, "--enableConcurrentJIT=false", *EAGER_OPTIONS)
+def runMozillaTestDFGEagerNoCJITValidatePhases(mode, *extraFiles)
+    runMozillaTest("dfg-eager-no-cjit-validate-phases", mode, extraFiles, "--enableConcurrentJIT=false", "--validateBytecode=true", "--validateGraphAtEachPhase=true", *EAGER_OPTIONS)
 end
 
 def defaultRunMozillaTest(mode, *extraFiles)
     runMozillaTestDefault(mode, *extraFiles)
     runMozillaTestLLInt(mode, *extraFiles)
     runMozillaTestBaselineJIT(mode, *extraFiles)
-    runMozillaTestDFGEagerNoCJIT(mode, *extraFiles)
+    runMozillaTestDFGEagerNoCJITValidatePhases(mode, *extraFiles)
 end
 
 def skip