Commit 2eb67eca authored by fpizlo@apple.com's avatar fpizlo@apple.com

Do bytecode validation as part of testing

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: http://svn.webkit.org/repository/webkit/trunk@159825 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 7ed5920b
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.
......
......@@ -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++) {
......
......@@ -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
......@@ -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&);
......
......@@ -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,
......
......@@ -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.
......
......@@ -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) \
......
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.
......
......@@ -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 \
......
......@@ -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" />
......
......@@ -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 */; };
......@@ -290,6 +291,7 @@
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>"; };
......@@ -695,6 +697,7 @@
A8A4729E151A825A004123FF /* Encoder.h */,
44F66007171AFAA900E4AD19 /* EnumClass.h */,
A8A4729F151A825A004123FF /* ExportMacros.h */,
0F885E0E1845AE9F00F1E3FA /* FastBitVector.cpp */,
0FD81AC4154FB22E00983E72 /* FastBitVector.h */,
A8A472A1151A825A004123FF /* FastMalloc.cpp */,
A8A472A2151A825A004123FF /* FastMalloc.h */,
......@@ -1225,6 +1228,7 @@
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 */,
......
......@@ -156,6 +156,7 @@ set(WTF_SOURCES
DateMath.cpp
DecimalNumber.cpp
DynamicAnnotations.cpp
FastBitVector.cpp
FastMalloc.cpp
FilePrintStream.cpp
FunctionDispatcher.cpp
......
/*
* 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
/*
* 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;
......
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
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment