Add FuzzerAgent that reads predictions from a file
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Dec 2019 06:44:16 +0000 (06:44 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Dec 2019 06:44:16 +0000 (06:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=203898

Patch by Tuomas Karkkainen <tuomas.webkit@apple.com> on 2019-12-01
Reviewed by Mark Lam.

This patch adds a FuzzerAgent that reads predictions from a file. The predictions in the file are
correlated with the prediction sites using the name of the JavaScript source file, the opcode, and
start and end offsets in the source. There is also a separate FuzzerAgent that can be used to create
the prediction files.

* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* runtime/FileBasedFuzzerAgent.cpp: Added.
* runtime/FileBasedFuzzerAgent.h: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
* runtime/FileBasedFuzzerAgentBase.cpp: Added.
* runtime/FileBasedFuzzerAgentBase.h: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
* runtime/FuzzerPredictions.cpp: Added.
* runtime/FuzzerPredictions.h: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
* runtime/Options.cpp:
* runtime/OptionsList.h:
* runtime/PredictionFileCreatingFuzzerAgent.cpp: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
* runtime/PredictionFileCreatingFuzzerAgent.h: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
* runtime/RandomizingFuzzerAgent.cpp:
* runtime/VM.cpp:

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

15 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/FuzzerPredictions.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/FuzzerPredictions.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/Options.cpp
Source/JavaScriptCore/runtime/OptionsList.h
Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp
Source/JavaScriptCore/runtime/VM.cpp

index 3cb8558..b8e07c1 100644 (file)
@@ -1,3 +1,30 @@
+2019-12-01  Tuomas Karkkainen  <tuomas.webkit@apple.com>
+
+        Add FuzzerAgent that reads predictions from a file
+        https://bugs.webkit.org/show_bug.cgi?id=203898
+
+        Reviewed by Mark Lam.
+
+        This patch adds a FuzzerAgent that reads predictions from a file. The predictions in the file are
+        correlated with the prediction sites using the name of the JavaScript source file, the opcode, and
+        start and end offsets in the source. There is also a separate FuzzerAgent that can be used to create
+        the prediction files.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * runtime/FileBasedFuzzerAgent.cpp: Added.
+        * runtime/FileBasedFuzzerAgent.h: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
+        * runtime/FileBasedFuzzerAgentBase.cpp: Added.
+        * runtime/FileBasedFuzzerAgentBase.h: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
+        * runtime/FuzzerPredictions.cpp: Added.
+        * runtime/FuzzerPredictions.h: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
+        * runtime/Options.cpp:
+        * runtime/OptionsList.h:
+        * runtime/PredictionFileCreatingFuzzerAgent.cpp: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
+        * runtime/PredictionFileCreatingFuzzerAgent.h: Copied from Source/JavaScriptCore/runtime/RandomizingFuzzerAgent.cpp.
+        * runtime/RandomizingFuzzerAgent.cpp:
+        * runtime/VM.cpp:
+
 2019-12-01  Caio Lima  <ticaiolima@gmail.com>
 
         [JSC][MIPS] CallFrame is being clobbered on InternalFunction execution
index 5e8773b..d9e79a8 100644 (file)
                C4F4B6F41A05C944005CAB76 /* cpp_generator.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D01A05C76F005CAB76 /* cpp_generator.py */; settings = {ATTRIBUTES = (Private, ); }; };
                C4F4B6F51A05C984005CAB76 /* generate_objc_protocol_types_implementation.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D71A05C76F005CAB76 /* generate_objc_protocol_types_implementation.py */; settings = {ATTRIBUTES = (Private, ); }; };
                C4F4B6F61A05C984005CAB76 /* objc_generator_templates.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D81A05C76F005CAB76 /* objc_generator_templates.py */; settings = {ATTRIBUTES = (Private, ); }; };
+               CE20BD05237D3E230046E520 /* FileBasedFuzzerAgentBase.h in Headers */ = {isa = PBXBuildFile; fileRef = CE20BD03237D3AD40046E520 /* FileBasedFuzzerAgentBase.h */; };
+               CE20BD07237D3E480046E520 /* PredictionFileCreatingFuzzerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = CE20BD01237D3AD40046E520 /* PredictionFileCreatingFuzzerAgent.h */; };
                CEAE7D7B889B477BA93ABA6C /* ScriptFetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852151A9C3842389B3215B7 /* ScriptFetcher.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               CECFAD362372DAD000291599 /* FuzzerPredictions.h in Headers */ = {isa = PBXBuildFile; fileRef = CECFAD342372DAA700291599 /* FuzzerPredictions.h */; };
+               CECFAD372372DAD400291599 /* FileBasedFuzzerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = CECFAD322372DAA700291599 /* FileBasedFuzzerAgent.h */; };
                D9722752DC54459B9125B539 /* JSModuleLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 77B25CB2C3094A92A38E1DB3 /* JSModuleLoader.h */; };
                DC00039319D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h in Headers */ = {isa = PBXBuildFile; fileRef = DC00039019D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h */; };
                DC0184191D10C1890057B053 /* JITWorklist.h in Headers */ = {isa = PBXBuildFile; fileRef = DC0184181D10C1870057B053 /* JITWorklist.h */; };
                C4F4B6D61A05C76F005CAB76 /* generate_cpp_protocol_types_implementation.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = generate_cpp_protocol_types_implementation.py; sourceTree = "<group>"; };
                C4F4B6D71A05C76F005CAB76 /* generate_objc_protocol_types_implementation.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = generate_objc_protocol_types_implementation.py; sourceTree = "<group>"; };
                C4F4B6D81A05C76F005CAB76 /* objc_generator_templates.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = objc_generator_templates.py; sourceTree = "<group>"; };
+               CE20BD01237D3AD40046E520 /* PredictionFileCreatingFuzzerAgent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PredictionFileCreatingFuzzerAgent.h; sourceTree = "<group>"; };
+               CE20BD02237D3AD40046E520 /* PredictionFileCreatingFuzzerAgent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PredictionFileCreatingFuzzerAgent.cpp; sourceTree = "<group>"; };
+               CE20BD03237D3AD40046E520 /* FileBasedFuzzerAgentBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileBasedFuzzerAgentBase.h; sourceTree = "<group>"; };
+               CE20BD04237D3AD40046E520 /* FileBasedFuzzerAgentBase.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FileBasedFuzzerAgentBase.cpp; sourceTree = "<group>"; };
+               CECFAD322372DAA700291599 /* FileBasedFuzzerAgent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileBasedFuzzerAgent.h; sourceTree = "<group>"; };
+               CECFAD332372DAA700291599 /* FileBasedFuzzerAgent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FileBasedFuzzerAgent.cpp; sourceTree = "<group>"; };
+               CECFAD342372DAA700291599 /* FuzzerPredictions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FuzzerPredictions.h; sourceTree = "<group>"; };
+               CECFAD352372DAA700291599 /* FuzzerPredictions.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FuzzerPredictions.cpp; sourceTree = "<group>"; };
                D21202280AD4310C00ED79B6 /* DateConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateConversion.cpp; sourceTree = "<group>"; };
                D21202290AD4310C00ED79B6 /* DateConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateConversion.h; sourceTree = "<group>"; };
                DC00039019D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPreciseLocalClobberize.h; path = dfg/DFGPreciseLocalClobberize.h; sourceTree = "<group>"; };
                                147341E91DC2CF2500AA29BA /* ExecutableBase.cpp */,
                                147341CB1DC02D7200AA29BA /* ExecutableBase.h */,
                                E35A0B9C220AD87A00AC4474 /* ExecutableBaseInlines.h */,
+                               CECFAD332372DAA700291599 /* FileBasedFuzzerAgent.cpp */,
+                               CECFAD322372DAA700291599 /* FileBasedFuzzerAgent.h */,
+                               CE20BD04237D3AD40046E520 /* FileBasedFuzzerAgentBase.cpp */,
+                               CE20BD03237D3AD40046E520 /* FileBasedFuzzerAgentBase.h */,
                                A7A8AF2917ADB5F3005AB174 /* Float32Array.h */,
                                A7A8AF2A17ADB5F3005AB174 /* Float64Array.h */,
                                BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */,
                                62D2D38E1ADF103F000206C1 /* FunctionRareData.h */,
                                E33A94952255322A00D42B06 /* FuzzerAgent.cpp */,
                                E33A94922255322900D42B06 /* FuzzerAgent.h */,
+                               CECFAD352372DAA700291599 /* FuzzerPredictions.cpp */,
+                               CECFAD342372DAA700291599 /* FuzzerPredictions.h */,
                                70B791851C024432002481E2 /* GeneratorFunctionConstructor.cpp */,
                                70B791861C024432002481E2 /* GeneratorFunctionConstructor.h */,
                                70B791871C024432002481E2 /* GeneratorFunctionPrototype.cpp */,
                                0FE228EB1436AB2300196C48 /* Options.h */,
                                FE3842312324D51B009DD445 /* OptionsList.h */,
                                37C738D11EDB5672003F2B0B /* ParseInt.h */,
+                               CE20BD02237D3AD40046E520 /* PredictionFileCreatingFuzzerAgent.cpp */,
+                               CE20BD01237D3AD40046E520 /* PredictionFileCreatingFuzzerAgent.h */,
                                868916A9155F285400CB2B9A /* PrivateName.h */,
                                147341DF1DC2CE9600AA29BA /* ProgramExecutable.cpp */,
                                147341D31DC02E6D00AA29BA /* ProgramExecutable.h */,
                                A18193E41B4E0CDB00FC1029 /* IntlCollatorPrototype.lut.h in Headers */,
                                A1587D6E1B4DC14100D69849 /* IntlDateTimeFormat.h in Headers */,
                                A1587D701B4DC14100D69849 /* IntlDateTimeFormatConstructor.h in Headers */,
+                               CE20BD05237D3E230046E520 /* FileBasedFuzzerAgentBase.h in Headers */,
                                A1587D751B4DC1C600D69849 /* IntlDateTimeFormatConstructor.lut.h in Headers */,
                                A1587D721B4DC14100D69849 /* IntlDateTimeFormatPrototype.h in Headers */,
                                A1587D761B4DC1C600D69849 /* IntlDateTimeFormatPrototype.lut.h in Headers */,
                                0F7C5FB81D888A0C0044F5E2 /* MarkedBlockInlines.h in Headers */,
                                141448CB13A176EC00F5BA1A /* MarkedBlockSet.h in Headers */,
                                14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */,
+                               CE20BD07237D3E480046E520 /* PredictionFileCreatingFuzzerAgent.h in Headers */,
                                0F7DF1351E2970DC0095951B /* MarkedSpaceInlines.h in Headers */,
                                0F660E381E0517BB0031462C /* MarkingConstraint.h in Headers */,
                                0F660E3A1E0517C10031462C /* MarkingConstraintSet.h in Headers */,
                                534E03561E53BEDE00213F64 /* ProxyableAccessCase.h in Headers */,
                                79B00CBD1C6AB07E0088C65D /* ProxyConstructor.h in Headers */,
                                79B00CBF1C6AB07E0088C65D /* ProxyObject.h in Headers */,
+                               CECFAD372372DAD400291599 /* FileBasedFuzzerAgent.h in Headers */,
                                79160DBE1C8E3EC8008C085A /* ProxyRevoke.h in Headers */,
                                0F5780A218FE1E98001E72D9 /* PureNaN.h in Headers */,
                                0F15CD231BA5F9860031FFD3 /* PutByIdFlags.h in Headers */,
                                FE3022D31E3D73A500BAC493 /* SigillCrashAnalyzer.h in Headers */,
                                0F4D8C781FCA3CFA001D32AC /* SimpleMarkingConstraint.h in Headers */,
                                0F2B670517B6B5AB00A7AE3F /* SimpleTypedArrayController.h in Headers */,
+                               CECFAD362372DAD000291599 /* FuzzerPredictions.h in Headers */,
                                14BA78F113AAB88F005B7C2C /* SlotVisitor.h in Headers */,
                                C2160FE715F7E95E00942DFC /* SlotVisitorInlines.h in Headers */,
                                A709F2F017A0AC0400512E98 /* SlowPathCall.h in Headers */,
index ec03727..8d706c9 100644 (file)
@@ -766,6 +766,8 @@ runtime/ExceptionFuzz.cpp
 runtime/ExceptionHelpers.cpp
 runtime/ExceptionScope.cpp
 runtime/ExecutableBase.cpp
+runtime/FileBasedFuzzerAgent.cpp
+runtime/FileBasedFuzzerAgentBase.cpp
 runtime/FunctionConstructor.cpp
 runtime/FunctionExecutable.cpp
 runtime/FunctionExecutableDump.cpp
@@ -773,6 +775,7 @@ runtime/FunctionHasExecutedCache.cpp
 runtime/FunctionPrototype.cpp
 runtime/FunctionRareData.cpp
 runtime/FuzzerAgent.cpp
+runtime/FuzzerPredictions.cpp
 runtime/GeneratorFunctionConstructor.cpp
 runtime/GeneratorFunctionPrototype.cpp
 runtime/GeneratorPrototype.cpp
@@ -903,6 +906,7 @@ runtime/ObjectPrototype.cpp
 runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp
 runtime/Operations.cpp
 runtime/Options.cpp
+runtime/PredictionFileCreatingFuzzerAgent.cpp
 runtime/ProgramExecutable.cpp
 runtime/PromiseTimer.cpp
 runtime/PropertyDescriptor.cpp
diff --git a/Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp b/Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.cpp
new file mode 100644 (file)
index 0000000..a7cd4c1
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2019 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 "FileBasedFuzzerAgent.h"
+
+#include "CodeBlock.h"
+#include "FuzzerPredictions.h"
+#include <wtf/AnsiColors.h>
+
+namespace JSC {
+
+FileBasedFuzzerAgent::FileBasedFuzzerAgent(VM& vm)
+    : FileBasedFuzzerAgentBase(vm)
+{
+}
+
+SpeculatedType FileBasedFuzzerAgent::getPredictionInternal(CodeBlock* codeBlock, PredictionTarget& target, SpeculatedType original)
+{
+    FuzzerPredictions& fuzzerPredictions = ensureGlobalFuzzerPredictions();
+    Optional<SpeculatedType> generated = fuzzerPredictions.predictionFor(target.lookupKey);
+
+    SourceProvider* provider = codeBlock->source().provider();
+    auto sourceUpToDivot = provider->source().substring(target.divot - target.startOffset, target.startOffset);
+    auto sourceAfterDivot = provider->source().substring(target.divot, target.endOffset);
+
+    switch (target.opcodeId) {
+    // FIXME: these can not be targeted at all due to the bugs below
+    case op_to_this: // broken https://bugs.webkit.org/show_bug.cgi?id=203555
+    case op_get_argument: // broken https://bugs.webkit.org/show_bug.cgi?id=203554
+        return original;
+
+    // FIXME: the output of codeBlock->expressionRangeForBytecodeIndex() allows for some of
+    // these opcodes to have predictions, but not all instances can be reliably targeted.
+    case op_bitand: // partially broken https://bugs.webkit.org/show_bug.cgi?id=203604
+    case op_bitor: // partially broken https://bugs.webkit.org/show_bug.cgi?id=203604
+    case op_bitxor: // partially broken https://bugs.webkit.org/show_bug.cgi?id=203604
+    case op_bitnot: // partially broken
+    case op_get_from_scope: // partially broken https://bugs.webkit.org/show_bug.cgi?id=203603
+    case op_get_from_arguments: // partially broken https://bugs.webkit.org/show_bug.cgi?id=203608
+    case op_get_by_val: // partially broken https://bugs.webkit.org/show_bug.cgi?id=203665
+    case op_rshift: // partially broken https://bugs.webkit.org/show_bug.cgi?id=203664
+    case op_lshift: // partially broken https://bugs.webkit.org/show_bug.cgi?id=203664
+    case op_to_number: // partially broken
+    case op_get_by_id: // sometimes occurs implicitly for things related to Symbol.iterator
+        if (!generated)
+            return original;
+        break;
+
+    case op_call: // op_call appears implicitly in for-of loops, generators, spread/rest elements, destructuring assignment
+        if (!generated) {
+            if (sourceAfterDivot.containsIgnoringASCIICase("of "))
+                return original;
+            if (sourceAfterDivot.containsIgnoringASCIICase("..."))
+                return original;
+            if (sourceAfterDivot.containsIgnoringASCIICase("yield"))
+                return original;
+            if (sourceAfterDivot.startsWith('[') && sourceAfterDivot.endsWith("]"))
+                return original;
+            if (sourceUpToDivot.containsIgnoringASCIICase("yield"))
+                return original;
+            if (sourceUpToDivot == "...")
+                return original;
+            if (!target.startOffset && !target.endOffset)
+                return original;
+        }
+        break;
+
+    case op_get_by_val_with_this:
+    case op_get_direct_pname:
+    case op_construct:
+    case op_construct_varargs:
+    case op_call_varargs:
+    case op_call_eval:
+    case op_tail_call:
+    case op_tail_call_varargs:
+    case op_get_by_id_with_this:
+        break;
+
+    default:
+        RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("Unhandled opcode %s", toString(target.opcodeId).utf8().data());
+    }
+    if (!generated) {
+        if (Options::dumpFuzzerAgentPredictions())
+            dataLogLn(MAGENTA(BOLD(target.bytecodeIndex)), " ", BOLD(YELLOW(target.opcodeId)), " missing prediction for: ", RED(BOLD(target.lookupKey)), " ", GREEN(target.sourceFilename), ":", CYAN(target.line), ":", CYAN(target.column), " divot: ", target.divot, " -", target.startOffset, " +", target.endOffset, " name: '", YELLOW(codeBlock->inferredName()), "' source: '", BLUE(sourceUpToDivot), BLUE(BOLD(sourceAfterDivot)), "'");
+
+        RELEASE_ASSERT_WITH_MESSAGE(!Options::requirePredictionForFileBasedFuzzerAgent(), "Missing expected prediction in FuzzerAgent");
+        return original;
+    }
+    if (Options::dumpFuzzerAgentPredictions())
+        dataLogLn(YELLOW(target.opcodeId), " ", CYAN(target.lookupKey), " original: ", CYAN(BOLD(SpeculationDump(original))), " generated: ", MAGENTA(BOLD(SpeculationDump(*generated))));
+    return *generated;
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.h b/Source/JavaScriptCore/runtime/FileBasedFuzzerAgent.h
new file mode 100644 (file)
index 0000000..c92911f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include "FileBasedFuzzerAgentBase.h"
+
+namespace JSC {
+
+class VM;
+
+class FileBasedFuzzerAgent final : public FileBasedFuzzerAgentBase {
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    FileBasedFuzzerAgent(VM&);
+
+protected:
+    SpeculatedType getPredictionInternal(CodeBlock*, PredictionTarget&, SpeculatedType original) override;
+};
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp b/Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.cpp
new file mode 100644 (file)
index 0000000..4718097
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 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 "FileBasedFuzzerAgentBase.h"
+
+#include "CodeBlock.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace JSC {
+
+FileBasedFuzzerAgentBase::FileBasedFuzzerAgentBase(VM&)
+{
+}
+
+String FileBasedFuzzerAgentBase::createLookupKey(const String& sourceFilename, OpcodeID opcodeId, int startLocation, int endLocation)
+{
+    StringBuilder lookupKey;
+    lookupKey.append(sourceFilename);
+    lookupKey.append("|");
+    lookupKey.append(toString(opcodeAliasForLookupKey(opcodeId)));
+    lookupKey.append("|");
+    lookupKey.append(startLocation);
+    lookupKey.append("|");
+    lookupKey.append(endLocation);
+    return lookupKey.toString();
+}
+
+OpcodeID FileBasedFuzzerAgentBase::opcodeAliasForLookupKey(const OpcodeID& opcodeId)
+{
+    if (opcodeId == op_call_varargs || opcodeId == op_call_eval || opcodeId == op_tail_call || opcodeId == op_tail_call_varargs)
+        return op_call;
+    if (opcodeId == op_get_direct_pname || opcodeId == op_get_by_val_with_this)
+        return op_get_by_val;
+    if (opcodeId == op_construct_varargs)
+        return op_construct;
+    return opcodeId;
+}
+
+SpeculatedType FileBasedFuzzerAgentBase::getPrediction(CodeBlock* codeBlock, const CodeOrigin& codeOrigin, SpeculatedType original)
+{
+    auto locker = holdLock(m_lock);
+
+    ScriptExecutable* ownerExecutable = codeBlock->ownerExecutable();
+    const auto& sourceURL = ownerExecutable->sourceURL();
+    if (sourceURL.isEmpty())
+        return original;
+
+    PredictionTarget predictionTarget;
+    BytecodeIndex bytecodeIndex = codeOrigin.bytecodeIndex();
+    codeBlock->expressionRangeForBytecodeIndex(bytecodeIndex, predictionTarget.divot, predictionTarget.startOffset, predictionTarget.endOffset, predictionTarget.line, predictionTarget.column);
+
+    Vector<String> urlParts = sourceURL.split('/');
+    predictionTarget.sourceFilename = urlParts.isEmpty() ? sourceURL : urlParts.last();
+
+    const InstructionStream& instructions = codeBlock->instructions();
+    const Instruction* anInstruction = instructions.at(bytecodeIndex).ptr();
+    predictionTarget.opcodeId = anInstruction->opcodeID();
+
+    int startLocation = predictionTarget.divot - predictionTarget.startOffset;
+    int endLocation = predictionTarget.divot + predictionTarget.endOffset;
+    predictionTarget.lookupKey = createLookupKey(predictionTarget.sourceFilename, predictionTarget.opcodeId, startLocation, endLocation);
+    return getPredictionInternal(codeBlock, predictionTarget, original);
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.h b/Source/JavaScriptCore/runtime/FileBasedFuzzerAgentBase.h
new file mode 100644 (file)
index 0000000..76f0dd9
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include "FuzzerAgent.h"
+#include "Opcode.h"
+#include <wtf/Lock.h>
+
+namespace JSC {
+
+class VM;
+
+struct PredictionTarget {
+    BytecodeIndex bytecodeIndex;
+    int divot;
+    int startOffset;
+    int endOffset;
+    unsigned line;
+    unsigned column;
+    OpcodeID opcodeId;
+    String sourceFilename;
+    String lookupKey;
+};
+
+class FileBasedFuzzerAgentBase : public FuzzerAgent {
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    FileBasedFuzzerAgentBase(VM&);
+
+protected:
+    Lock m_lock;
+    virtual SpeculatedType getPredictionInternal(CodeBlock*, PredictionTarget&, SpeculatedType original) = 0;
+
+public:
+    SpeculatedType getPrediction(CodeBlock*, const CodeOrigin&, SpeculatedType original) final;
+
+protected:
+    static String createLookupKey(const String& sourceFilename, OpcodeID, int startLocation, int endLocation);
+    static OpcodeID opcodeAliasForLookupKey(const OpcodeID&);
+};
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/FuzzerPredictions.cpp b/Source/JavaScriptCore/runtime/FuzzerPredictions.cpp
new file mode 100644 (file)
index 0000000..ab9b1d2
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 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 "FuzzerPredictions.h"
+
+namespace JSC {
+
+static String readFileIntoString(const char* fileName)
+{
+    FILE* file = fopen(fileName, "r");
+    RELEASE_ASSERT_WITH_MESSAGE(file, "Failed to open file %s", fileName);
+    RELEASE_ASSERT(fseek(file, 0, SEEK_END) != -1);
+    long bufferCapacity = ftell(file);
+    RELEASE_ASSERT(bufferCapacity != -1);
+    RELEASE_ASSERT(fseek(file, 0, SEEK_SET) != -1);
+    Vector<char> buffer;
+    buffer.resize(bufferCapacity);
+    size_t readSize = fread(buffer.data(), 1, buffer.size(), file);
+    fclose(file);
+    RELEASE_ASSERT(readSize == buffer.size());
+    return String(buffer.data(), buffer.size());
+}
+
+FuzzerPredictions::FuzzerPredictions(const char* filename)
+{
+    RELEASE_ASSERT_WITH_MESSAGE(filename, "prediction file must be specified using --fuzzerPredictionsFile=");
+
+    String predictions = readFileIntoString(filename);
+    const Vector<String>& lines = predictions.split('\n');
+    for (const auto& line : lines) {
+        // Predictions are stored in a text file, one prediction per line in the colon delimited format:
+        // <lookup key>:<prediction in hex without leading 0x>
+        // The lookup key is a pipe separated string with the format:
+        // <filename>|<opcode>|<start offset>|<end offset>
+
+        // The start and end offsets are 7-bit unsigned integers.
+        // If start offset > 127, then both start and end offsets are 0.
+        // If end offset > 127, then the end offset is 0.
+
+        // Example predictions:
+        // foo.js|op_construct|702|721:1000084
+        // foo.js|op_call|748|760:408800
+        // foo.js|op_bitnot|770|770:280000000
+
+        // Predictions can be generated using PredictionFileCreatingFuzzerAgent.
+        // Some opcodes are aliased together to make generating the predictions more straightforward.
+        // For the aliases see: FileBasedFuzzerAgentBase::opcodeAliasForLookupKey()
+
+        // FIXME: The current implementation only supports one prediction per lookup key.
+
+        const Vector<String>& lineParts = line.split(':');
+        RELEASE_ASSERT_WITH_MESSAGE(lineParts.size() == 2, "Expected line with two parts delimited by a colon. Found line with %lu parts.", lineParts.size());
+        const String& lookupKey = lineParts[0];
+        const String& predictionString = lineParts[1];
+        bool ok;
+        SpeculatedType prediction = predictionString.toUInt64Strict(&ok, 0x10);
+        RELEASE_ASSERT_WITH_MESSAGE(ok, "Could not parse prediction from '%s'", predictionString.utf8().data());
+        RELEASE_ASSERT(speculationChecked(prediction, SpecFullTop));
+        m_predictions.set(lookupKey, prediction);
+    }
+}
+
+Optional<SpeculatedType> FuzzerPredictions::predictionFor(const String& key)
+{
+    auto it = m_predictions.find(key);
+    if (it == m_predictions.end())
+        return WTF::nullopt;
+    return it->value;
+}
+
+FuzzerPredictions& ensureGlobalFuzzerPredictions()
+{
+    static LazyNeverDestroyed<FuzzerPredictions> fuzzerPredictions;
+    static std::once_flag initializeFuzzerPredictionsFlag;
+    std::call_once(initializeFuzzerPredictionsFlag, [] {
+        const char* fuzzerPredictionsFilename = Options::fuzzerPredictionsFile();
+        fuzzerPredictions.construct(fuzzerPredictionsFilename);
+    });
+    return fuzzerPredictions;
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/FuzzerPredictions.h b/Source/JavaScriptCore/runtime/FuzzerPredictions.h
new file mode 100644 (file)
index 0000000..0db96a4
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <bytecode/CodeBlock.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class FuzzerPredictions {
+public:
+    JS_EXPORT_PRIVATE FuzzerPredictions(const char*);
+
+    Optional<SpeculatedType> predictionFor(const String&);
+
+private:
+    HashMap<String, SpeculatedType> m_predictions;
+};
+
+JS_EXPORT_PRIVATE FuzzerPredictions& ensureGlobalFuzzerPredictions();
+
+} // namespace JSC
index c196b30..bd316b5 100644 (file)
@@ -448,7 +448,7 @@ static void recomputeDependentOptions()
         || Options::verboseCFA()
         || Options::verboseDFGFailure()
         || Options::verboseFTLFailure()
-        || Options::dumpRandomizingFuzzerAgentPredictions())
+        || Options::dumpFuzzerAgentPredictions())
         Options::alwaysComputeHash() = true;
     
     if (!Options::useConcurrentGC())
index 4714c91..03f2852 100644 (file)
@@ -394,8 +394,12 @@ constexpr bool enableWebAssemblyStreamingApi = false;
     v(Unsigned, seedOfVMRandomForFuzzer, 0, Normal, "0 means not fuzzing this; use a cryptographically random seed") \
     v(Bool, useRandomizingFuzzerAgent, false, Normal, nullptr) \
     v(Unsigned, seedOfRandomizingFuzzerAgent, 1, Normal, nullptr) \
-    v(Bool, dumpRandomizingFuzzerAgentPredictions, false, Normal, nullptr) \
+    v(Bool, dumpFuzzerAgentPredictions, false, Normal, nullptr) \
     v(Bool, useDoublePredictionFuzzerAgent, false, Normal, nullptr) \
+    v(Bool, useFileBasedFuzzerAgent, false, Normal, nullptr) \
+    v(Bool, usePredictionFileCreatingFuzzerAgent, false, Normal, nullptr) \
+    v(Bool, requirePredictionForFileBasedFuzzerAgent, false, Normal, nullptr) \
+    v(OptionString, fuzzerPredictionsFile, nullptr, Normal, "file with list of predictions for FileBasedFuzzerAgent") \
     \
     v(Bool, logPhaseTimes, false, Normal, nullptr) \
     v(Double, rareBlockPenalty, 0.001, Normal, nullptr) \
diff --git a/Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp b/Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.cpp
new file mode 100644 (file)
index 0000000..319c532
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 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 "PredictionFileCreatingFuzzerAgent.h"
+
+namespace JSC {
+
+PredictionFileCreatingFuzzerAgent::PredictionFileCreatingFuzzerAgent(VM& vm)
+    : FileBasedFuzzerAgentBase(vm)
+{
+}
+
+SpeculatedType PredictionFileCreatingFuzzerAgent::getPredictionInternal(CodeBlock*, PredictionTarget& predictionTarget, SpeculatedType original)
+{
+    switch (predictionTarget.opcodeId) {
+    case op_to_this:
+    case op_bitand:
+    case op_bitor:
+    case op_bitxor:
+    case op_bitnot:
+    case op_lshift:
+    case op_rshift:
+    case op_get_by_val:
+    case op_get_argument:
+    case op_get_from_arguments:
+    case op_get_from_scope:
+    case op_to_number:
+    case op_get_by_id:
+    case op_get_by_id_with_this:
+    case op_get_by_val_with_this:
+    case op_get_direct_pname:
+    case op_construct:
+    case op_construct_varargs:
+    case op_call:
+    case op_call_eval:
+    case op_call_varargs:
+    case op_tail_call:
+    case op_tail_call_varargs:
+        dataLogF("%s:%llx\n", predictionTarget.lookupKey.utf8().data(), original);
+        break;
+
+    default:
+        RELEASE_ASSERT_WITH_MESSAGE(false, "unhandled opcode: %s", toString(predictionTarget.opcodeId).utf8().data());
+    }
+    return original;
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.h b/Source/JavaScriptCore/runtime/PredictionFileCreatingFuzzerAgent.h
new file mode 100644 (file)
index 0000000..d422ead
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include "FileBasedFuzzerAgentBase.h"
+
+namespace JSC {
+
+class VM;
+
+class PredictionFileCreatingFuzzerAgent final : public FileBasedFuzzerAgentBase {
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    PredictionFileCreatingFuzzerAgent(VM&);
+
+protected:
+    SpeculatedType getPredictionInternal(CodeBlock*, PredictionTarget&, SpeculatedType original) override;
+};
+
+} // namespace JSC
index 3d22595..c9c54e7 100644 (file)
@@ -42,7 +42,7 @@ SpeculatedType RandomizingFuzzerAgent::getPrediction(CodeBlock* codeBlock, const
     uint32_t high = m_random.getUint32();
     uint32_t low = m_random.getUint32();
     SpeculatedType generated = static_cast<SpeculatedType>((static_cast<uint64_t>(high) << 32) | low) & SpecFullTop;
-    if (Options::dumpRandomizingFuzzerAgentPredictions())
+    if (Options::dumpFuzzerAgentPredictions())
         dataLogLn("getPrediction name:(", codeBlock->inferredName(), "#", codeBlock->hashAsStringIfPossible(), "),bytecodeIndex:(", codeOrigin.bytecodeIndex(), "),original:(", SpeculationDump(original), "),generated:(", SpeculationDump(generated), ")");
     return generated;
 }
index 5f3f849..216bf91 100644 (file)
@@ -50,6 +50,7 @@
 #include "ExecutableToCodeBlockEdge.h"
 #include "FTLThunks.h"
 #include "FastMallocAlignedMemoryAllocator.h"
+#include "FileBasedFuzzerAgent.h"
 #include "FunctionCodeBlock.h"
 #include "FunctionConstructor.h"
 #include "FunctionExecutable.h"
 #include "Nodes.h"
 #include "ObjCCallbackFunction.h"
 #include "Parser.h"
+#include "PredictionFileCreatingFuzzerAgent.h"
 #include "ProfilerDatabase.h"
 #include "ProgramCodeBlock.h"
 #include "ProgramExecutable.h"
@@ -463,6 +465,10 @@ VM::VM(VMType vmType, HeapType heapType)
         setFuzzerAgent(makeUnique<RandomizingFuzzerAgent>(*this));
     if (Options::useDoublePredictionFuzzerAgent())
         setFuzzerAgent(makeUnique<DoublePredictionFuzzerAgent>(*this));
+    if (Options::useFileBasedFuzzerAgent())
+        setFuzzerAgent(makeUnique<FileBasedFuzzerAgent>(*this));
+    if (Options::usePredictionFileCreatingFuzzerAgent())
+        setFuzzerAgent(makeUnique<PredictionFileCreatingFuzzerAgent>(*this));
 
     if (Options::alwaysGeneratePCToCodeOriginMap())
         setShouldBuildPCToCodeOriginMapping();