1/*
2 * Copyright (C) 2012-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#include "CallLinkStatus.h"
29#include "ExitFlag.h"
30#include "ICStatusMap.h"
31#include "PutByIdVariant.h"
32#include "StubInfoSummary.h"
33
34namespace JSC {
35
36class CodeBlock;
37class VM;
38class JSGlobalObject;
39class Structure;
40class StructureChain;
41class StructureStubInfo;
42
43typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap;
44
45class PutByIdStatus {
46public:
47 enum State {
48 // It's uncached so we have no information.
49 NoInformation,
50 // It's cached as a simple store of some kind.
51 Simple,
52 // It's known to often take slow path.
53 TakesSlowPath,
54 // It's known to take paths that make calls.
55 MakesCalls
56 };
57
58 PutByIdStatus()
59 : m_state(NoInformation)
60 {
61 }
62
63 explicit PutByIdStatus(State state)
64 : m_state(state)
65 {
66 ASSERT(m_state == NoInformation || m_state == TakesSlowPath || m_state == MakesCalls);
67 }
68
69 explicit PutByIdStatus(StubInfoSummary summary)
70 {
71 switch (summary) {
72 case StubInfoSummary::NoInformation:
73 m_state = NoInformation;
74 return;
75 case StubInfoSummary::Simple:
76 case StubInfoSummary::MakesCalls:
77 RELEASE_ASSERT_NOT_REACHED();
78 return;
79 case StubInfoSummary::TakesSlowPath:
80 m_state = TakesSlowPath;
81 return;
82 case StubInfoSummary::TakesSlowPathAndMakesCalls:
83 m_state = MakesCalls;
84 return;
85 }
86 RELEASE_ASSERT_NOT_REACHED();
87 }
88
89 PutByIdStatus(const PutByIdVariant& variant)
90 : m_state(Simple)
91 {
92 m_variants.append(variant);
93 }
94
95 static PutByIdStatus computeFor(CodeBlock*, ICStatusMap&, unsigned bytecodeIndex, UniquedStringImpl* uid, ExitFlag, CallLinkStatus::ExitSiteData);
96 static PutByIdStatus computeFor(JSGlobalObject*, const StructureSet&, UniquedStringImpl* uid, bool isDirect);
97
98 static PutByIdStatus computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& contextStack, CodeOrigin, UniquedStringImpl* uid);
99
100#if ENABLE(JIT)
101 static PutByIdStatus computeForStubInfo(const ConcurrentJSLocker&, CodeBlock* baselineBlock, StructureStubInfo*, CodeOrigin, UniquedStringImpl* uid);
102#endif
103
104 State state() const { return m_state; }
105
106 bool isSet() const { return m_state != NoInformation; }
107 bool operator!() const { return m_state == NoInformation; }
108 bool isSimple() const { return m_state == Simple; }
109 bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
110 bool makesCalls() const;
111 PutByIdStatus slowVersion() const;
112
113 size_t numVariants() const { return m_variants.size(); }
114 const Vector<PutByIdVariant, 1>& variants() const { return m_variants; }
115 const PutByIdVariant& at(size_t index) const { return m_variants[index]; }
116 const PutByIdVariant& operator[](size_t index) const { return at(index); }
117
118 void markIfCheap(SlotVisitor&);
119 bool finalize(VM&);
120
121 void merge(const PutByIdStatus&);
122
123 void filter(const StructureSet&);
124
125 void dump(PrintStream&) const;
126
127private:
128#if ENABLE(JIT)
129 static PutByIdStatus computeForStubInfo(
130 const ConcurrentJSLocker&, CodeBlock*, StructureStubInfo*, UniquedStringImpl* uid,
131 CallLinkStatus::ExitSiteData);
132#endif
133 static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, UniquedStringImpl* uid);
134
135 bool appendVariant(const PutByIdVariant&);
136
137 State m_state;
138 Vector<PutByIdVariant, 1> m_variants;
139};
140
141} // namespace JSC
142