1/*
2 * Copyright (C) 2014-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 "ObjectPropertyConditionSet.h"
29#include "PropertyOffset.h"
30#include "StructureSet.h"
31
32namespace JSC {
33
34class CallLinkStatus;
35
36class PutByIdVariant {
37public:
38 enum Kind {
39 NotSet,
40 Replace,
41 Transition,
42 Setter
43 };
44
45 PutByIdVariant()
46 : m_kind(NotSet)
47 , m_offset(invalidOffset)
48 , m_newStructure(nullptr)
49 {
50 }
51
52 PutByIdVariant(const PutByIdVariant&);
53 PutByIdVariant& operator=(const PutByIdVariant&);
54
55 static PutByIdVariant replace(const StructureSet&, PropertyOffset);
56
57 static PutByIdVariant transition(
58 const StructureSet& oldStructure, Structure* newStructure,
59 const ObjectPropertyConditionSet&, PropertyOffset);
60
61 static PutByIdVariant setter(
62 const StructureSet&, PropertyOffset, const ObjectPropertyConditionSet&,
63 std::unique_ptr<CallLinkStatus>);
64
65 Kind kind() const { return m_kind; }
66
67 bool isSet() const { return kind() != NotSet; }
68 bool operator!() const { return !isSet(); }
69
70 const StructureSet& structure() const
71 {
72 ASSERT(kind() == Replace || kind() == Setter);
73 return m_oldStructure;
74 }
75
76 const StructureSet& oldStructure() const
77 {
78 ASSERT(kind() == Transition || kind() == Replace || kind() == Setter);
79 return m_oldStructure;
80 }
81
82 const StructureSet& structureSet() const
83 {
84 return oldStructure();
85 }
86
87 StructureSet& oldStructure()
88 {
89 ASSERT(kind() == Transition || kind() == Replace || kind() == Setter);
90 return m_oldStructure;
91 }
92
93 StructureSet& structureSet()
94 {
95 return oldStructure();
96 }
97
98 Structure* oldStructureForTransition() const;
99
100 Structure* newStructure() const
101 {
102 ASSERT(kind() == Transition);
103 return m_newStructure;
104 }
105
106 void fixTransitionToReplaceIfNecessary();
107
108 bool writesStructures() const;
109 bool reallocatesStorage() const;
110 bool makesCalls() const;
111
112 const ObjectPropertyConditionSet& conditionSet() const { return m_conditionSet; }
113
114 // We don't support intrinsics for Setters (it would be sweet if we did) but we need this for templated helpers.
115 Intrinsic intrinsic() const { return NoIntrinsic; }
116
117 // This is needed for templated helpers.
118 bool isPropertyUnset() const { return false; }
119
120 PropertyOffset offset() const
121 {
122 ASSERT(isSet());
123 return m_offset;
124 }
125
126 CallLinkStatus* callLinkStatus() const
127 {
128 ASSERT(kind() == Setter);
129 return m_callLinkStatus.get();
130 }
131
132 bool attemptToMerge(const PutByIdVariant& other);
133
134 void markIfCheap(SlotVisitor&);
135 bool finalize(VM&);
136
137 void dump(PrintStream&) const;
138 void dumpInContext(PrintStream&, DumpContext*) const;
139
140private:
141 bool attemptToMergeTransitionWithReplace(const PutByIdVariant& replace);
142
143 Kind m_kind;
144 PropertyOffset m_offset;
145 StructureSet m_oldStructure;
146 Structure* m_newStructure { nullptr };
147 ObjectPropertyConditionSet m_conditionSet;
148 std::unique_ptr<CallLinkStatus> m_callLinkStatus;
149};
150
151} // namespace JSC
152