1/*
2 * Copyright (C) 2013-2018 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(DFG_JIT)
29
30#include "CodeBlockJettisoningWatchpoint.h"
31#include "DFGAdaptiveInferredPropertyValueWatchpoint.h"
32#include "DFGAdaptiveStructureWatchpoint.h"
33#include "DFGJumpReplacement.h"
34#include "DFGOSREntry.h"
35#include "InlineCallFrameSet.h"
36#include "JSCast.h"
37#include "ProfilerCompilation.h"
38#include "RecordedStatuses.h"
39#include <wtf/Bag.h>
40#include <wtf/Noncopyable.h>
41
42namespace JSC {
43
44class CodeBlock;
45class Identifier;
46class TrackedReferences;
47
48namespace DFG {
49
50struct Node;
51class Plan;
52
53// CommonData holds the set of data that both DFG and FTL code blocks need to know
54// about themselves.
55
56struct WeakReferenceTransition {
57 WeakReferenceTransition() { }
58
59 WeakReferenceTransition(VM& vm, JSCell* owner, JSCell* codeOrigin, JSCell* from, JSCell* to)
60 : m_from(vm, owner, from)
61 , m_to(vm, owner, to)
62 {
63 if (!!codeOrigin)
64 m_codeOrigin.set(vm, owner, codeOrigin);
65 }
66
67 WriteBarrier<JSCell> m_codeOrigin;
68 WriteBarrier<JSCell> m_from;
69 WriteBarrier<JSCell> m_to;
70};
71
72class CommonData {
73 WTF_MAKE_NONCOPYABLE(CommonData);
74public:
75 CommonData()
76 : isStillValid(true)
77 , frameRegisterCount(std::numeric_limits<unsigned>::max())
78 , requiredRegisterCountForExit(std::numeric_limits<unsigned>::max())
79 { }
80 ~CommonData();
81
82 void notifyCompilingStructureTransition(Plan&, CodeBlock*, Node*);
83 CallSiteIndex addCodeOrigin(CodeOrigin);
84 CallSiteIndex addUniqueCallSiteIndex(CodeOrigin);
85 CallSiteIndex lastCallSite() const;
86
87 DisposableCallSiteIndex addDisposableCallSiteIndex(CodeOrigin);
88 void removeDisposableCallSiteIndex(DisposableCallSiteIndex);
89
90 void shrinkToFit();
91
92 bool invalidate(); // Returns true if we did invalidate, or false if the code block was already invalidated.
93 bool hasInstalledVMTrapsBreakpoints() const { return isStillValid && hasVMTrapsBreakpointsInstalled; }
94 void installVMTrapBreakpoints(CodeBlock* owner);
95 bool isVMTrapBreakpoint(void* address);
96
97 CatchEntrypointData* catchOSREntryDataForBytecodeIndex(BytecodeIndex bytecodeIndex)
98 {
99 return tryBinarySearch<CatchEntrypointData, BytecodeIndex>(
100 catchEntrypoints, catchEntrypoints.size(), bytecodeIndex,
101 [] (const CatchEntrypointData* item) { return item->bytecodeIndex; });
102 }
103
104 void appendCatchEntrypoint(BytecodeIndex bytecodeIndex, MacroAssemblerCodePtr<ExceptionHandlerPtrTag> machineCode, Vector<FlushFormat>&& argumentFormats)
105 {
106 catchEntrypoints.append(CatchEntrypointData { machineCode, WTFMove(argumentFormats), bytecodeIndex });
107 }
108
109 void finalizeCatchEntrypoints();
110
111 unsigned requiredRegisterCountForExecutionAndExit() const
112 {
113 return std::max(frameRegisterCount, requiredRegisterCountForExit);
114 }
115
116 void validateReferences(const TrackedReferences&);
117
118 static ptrdiff_t frameRegisterCountOffset() { return OBJECT_OFFSETOF(CommonData, frameRegisterCount); }
119
120 void clearWatchpoints();
121
122 RefPtr<InlineCallFrameSet> inlineCallFrames;
123 Vector<CodeOrigin, 0, UnsafeVectorOverflow> codeOrigins;
124
125 Vector<Identifier> dfgIdentifiers;
126 Vector<WeakReferenceTransition> transitions;
127 Vector<WriteBarrier<JSCell>> weakReferences;
128 Vector<WriteBarrier<Structure>> weakStructureReferences;
129 Vector<CatchEntrypointData> catchEntrypoints;
130 Bag<CodeBlockJettisoningWatchpoint> watchpoints;
131 Bag<AdaptiveStructureWatchpoint> adaptiveStructureWatchpoints;
132 Bag<AdaptiveInferredPropertyValueWatchpoint> adaptiveInferredPropertyValueWatchpoints;
133 RecordedStatuses recordedStatuses;
134 Vector<JumpReplacement> jumpReplacements;
135
136 ScratchBuffer* catchOSREntryBuffer;
137 RefPtr<Profiler::Compilation> compilation;
138 bool livenessHasBeenProved; // Initialized and used on every GC.
139 bool allTransitionsHaveBeenMarked; // Initialized and used on every GC.
140 bool isStillValid;
141 bool hasVMTrapsBreakpointsInstalled { false };
142
143#if USE(JSVALUE32_64)
144 std::unique_ptr<Bag<double>> doubleConstants;
145#endif
146
147 unsigned frameRegisterCount;
148 unsigned requiredRegisterCountForExit;
149
150private:
151 HashSet<unsigned, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> callSiteIndexFreeList;
152
153};
154
155CodeBlock* codeBlockForVMTrapPC(void* pc);
156
157} } // namespace JSC::DFG
158
159#endif // ENABLE(DFG_JIT)
160