summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/b3/air/AirValidate.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/b3/air/AirValidate.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/b3/air/AirValidate.cpp')
-rw-r--r--Source/JavaScriptCore/b3/air/AirValidate.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/b3/air/AirValidate.cpp b/Source/JavaScriptCore/b3/air/AirValidate.cpp
new file mode 100644
index 000000000..d90de62eb
--- /dev/null
+++ b/Source/JavaScriptCore/b3/air/AirValidate.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2015-2016 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 "AirValidate.h"
+
+#if ENABLE(B3_JIT)
+
+#include "AirCode.h"
+#include "AirInstInlines.h"
+#include "B3Procedure.h"
+
+namespace JSC { namespace B3 { namespace Air {
+
+namespace {
+
+class Validater {
+public:
+ Validater(Code& code, const char* dumpBefore)
+ : m_code(code)
+ , m_dumpBefore(dumpBefore)
+ {
+ }
+
+#define VALIDATE(condition, message) do { \
+ if (condition) \
+ break; \
+ fail(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #condition, toCString message); \
+ } while (false)
+
+ void run()
+ {
+ HashSet<StackSlot*> validSlots;
+ HashSet<BasicBlock*> validBlocks;
+ HashSet<Special*> validSpecials;
+
+ for (BasicBlock* block : m_code)
+ validBlocks.add(block);
+ for (StackSlot* slot : m_code.stackSlots())
+ validSlots.add(slot);
+ for (Special* special : m_code.specials())
+ validSpecials.add(special);
+
+ for (BasicBlock* block : m_code) {
+ // Blocks that are entrypoints must not have predecessors.
+ if (m_code.isEntrypoint(block))
+ VALIDATE(!block->numPredecessors(), ("At entrypoint ", *block));
+
+ for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) {
+ Inst& inst = block->at(instIndex);
+ for (Arg& arg : inst.args) {
+ switch (arg.kind()) {
+ case Arg::Stack:
+ VALIDATE(validSlots.contains(arg.stackSlot()), ("At ", inst, " in ", *block));
+ break;
+ case Arg::Special:
+ VALIDATE(validSpecials.contains(arg.special()), ("At ", inst, " in ", *block));
+ break;
+ default:
+ break;
+ }
+ }
+ VALIDATE(inst.isValidForm(), ("At ", inst, " in ", *block));
+ if (instIndex == block->size() - 1)
+ VALIDATE(inst.isTerminal(), ("At ", inst, " in ", *block));
+ else
+ VALIDATE(!inst.isTerminal(), ("At ", inst, " in ", *block));
+
+ // forEachArg must return Arg&'s that point into the args array.
+ inst.forEachArg(
+ [&] (Arg& arg, Arg::Role, Arg::Type, Arg::Width) {
+ VALIDATE(&arg >= &inst.args[0], ("At ", arg, " in ", inst, " in ", *block));
+ VALIDATE(&arg <= &inst.args.last(), ("At ", arg, " in ", inst, " in ", *block));
+ });
+
+ switch (inst.kind.opcode) {
+ case EntrySwitch:
+ VALIDATE(block->numSuccessors() == m_code.proc().numEntrypoints(), ("At ", inst, " in ", *block));
+ break;
+ case Shuffle:
+ // We can't handle trapping shuffles because of how we lower them. That could
+ // be fixed though.
+ VALIDATE(!inst.kind.traps, ("At ", inst, " in ", *block));
+ break;
+ default:
+ break;
+ }
+ }
+ for (BasicBlock* successor : block->successorBlocks())
+ VALIDATE(validBlocks.contains(successor), ("In ", *block));
+ }
+ }
+
+private:
+ NO_RETURN_DUE_TO_CRASH void fail(
+ const char* filename, int lineNumber, const char* function, const char* condition,
+ CString message)
+ {
+ CString failureMessage;
+ {
+ StringPrintStream out;
+ out.print("AIR VALIDATION FAILURE\n");
+ out.print(" ", condition, " (", filename, ":", lineNumber, ")\n");
+ out.print(" ", message, "\n");
+ out.print(" After ", m_code.lastPhaseName(), "\n");
+ failureMessage = out.toCString();
+ }
+
+ dataLog(failureMessage);
+ if (m_dumpBefore) {
+ dataLog("Before ", m_code.lastPhaseName(), ":\n");
+ dataLog(m_dumpBefore);
+ }
+ dataLog("At time of failure:\n");
+ dataLog(m_code);
+
+ dataLog(failureMessage);
+ WTFReportAssertionFailure(filename, lineNumber, function, condition);
+ CRASH();
+ }
+
+ Code& m_code;
+ const char* m_dumpBefore;
+};
+
+} // anonymous namespace
+
+void validate(Code& code, const char* dumpBefore)
+{
+ Validater validater(code, dumpBefore);
+ validater.run();
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+