1/*
2 * Copyright (C) 2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#if ENABLE(WEBASSEMBLY)
29
30#include "CompilationResult.h"
31#include "ExecutionCounter.h"
32#include "Options.h"
33#include <wtf/Atomics.h>
34#include <wtf/SegmentedVector.h>
35#include <wtf/StdLibExtras.h>
36
37namespace JSC { namespace Wasm {
38
39class OSREntryData;
40
41// This class manages the tier up counts for Wasm binaries. The main interesting thing about
42// wasm tiering up counts is that the least significant bit indicates if the tier up has already
43// started. Also, wasm code does not atomically update this count. This is because we
44// don't care too much if the countdown is slightly off. The tier up trigger is atomic, however,
45// so tier up will be triggered exactly once.
46class TierUpCount : public UpperTierExecutionCounter {
47 WTF_MAKE_NONCOPYABLE(TierUpCount);
48public:
49 enum class TriggerReason : uint8_t {
50 DontTrigger,
51 CompilationDone,
52 StartCompilation,
53 };
54
55 enum class CompilationStatus : uint8_t {
56 NotCompiled,
57 StartCompilation,
58 Compiled,
59 };
60
61 TierUpCount();
62 ~TierUpCount();
63
64 static int32_t loopIncrement() { return Options::omgTierUpCounterIncrementForLoop(); }
65 static int32_t functionEntryIncrement() { return Options::omgTierUpCounterIncrementForEntry(); }
66
67 SegmentedVector<TriggerReason, 16>& osrEntryTriggers() { return m_osrEntryTriggers; }
68 Vector<uint32_t>& outerLoops() { return m_outerLoops; }
69 Lock& getLock() { return m_lock; }
70
71 OSREntryData& addOSREntryData(uint32_t functionIndex, uint32_t loopIndex);
72
73 void optimizeAfterWarmUp(uint32_t functionIndex)
74 {
75 dataLogLnIf(Options::verboseOSR(), functionIndex, ": OMG-optimizing after warm-up.");
76 setNewThreshold(Options::thresholdForOMGOptimizeAfterWarmUp(), nullptr);
77 }
78
79 bool checkIfOptimizationThresholdReached()
80 {
81 return checkIfThresholdCrossedAndSet(nullptr);
82 }
83
84 void dontOptimizeAnytimeSoon(uint32_t functionIndex)
85 {
86 dataLogLnIf(Options::verboseOSR(), functionIndex, ": Not OMG-optimizing anytime soon.");
87 deferIndefinitely();
88 }
89
90 void optimizeNextInvocation(uint32_t functionIndex)
91 {
92 dataLogLnIf(Options::verboseOSR(), functionIndex, ": OMG-optimizing next invocation.");
93 setNewThreshold(0, nullptr);
94 }
95
96 void optimizeSoon(uint32_t functionIndex)
97 {
98 dataLogLnIf(Options::verboseOSR(), functionIndex, ": OMG-optimizing soon.");
99 // FIXME: Need adjustment once we get more information about wasm functions.
100 setNewThreshold(Options::thresholdForOMGOptimizeSoon(), nullptr);
101 }
102
103 void setOptimizationThresholdBasedOnCompilationResult(uint32_t functionIndex, CompilationResult result)
104 {
105 switch (result) {
106 case CompilationSuccessful:
107 optimizeNextInvocation(functionIndex);
108 return;
109 case CompilationFailed:
110 dontOptimizeAnytimeSoon(functionIndex);
111 return;
112 case CompilationDeferred:
113 optimizeAfterWarmUp(functionIndex);
114 return;
115 case CompilationInvalidated:
116 // This is weird - it will only happen in cases when the DFG code block (i.e.
117 // the code block that this JITCode belongs to) is also invalidated. So it
118 // doesn't really matter what we do. But, we do the right thing anyway. Note
119 // that us counting the reoptimization actually means that we might count it
120 // twice. But that's generally OK. It's better to overcount reoptimizations
121 // than it is to undercount them.
122 optimizeAfterWarmUp(functionIndex);
123 return;
124 }
125 RELEASE_ASSERT_NOT_REACHED();
126 }
127
128 Lock m_lock;
129 CompilationStatus m_compilationStatusForOMG { CompilationStatus::NotCompiled };
130 CompilationStatus m_compilationStatusForOMGForOSREntry { CompilationStatus::NotCompiled };
131 SegmentedVector<TriggerReason, 16> m_osrEntryTriggers;
132 Vector<uint32_t> m_outerLoops;
133 Vector<std::unique_ptr<OSREntryData>> m_osrEntryData;
134};
135
136} } // namespace JSC::Wasm
137
138#endif // ENABLE(WEBASSEMBLY)
139