390b0ede96d92c66bb149391e8e39abe865053cf
[WebKit.git] / Source / JavaScriptCore / bytecode / StructureStubInfo.h
1 /*
2  * Copyright (C) 2008, 2012-2016 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 #ifndef StructureStubInfo_h
27 #define StructureStubInfo_h
28
29 #include "CodeOrigin.h"
30 #include "Instruction.h"
31 #include "JITStubRoutine.h"
32 #include "MacroAssembler.h"
33 #include "ObjectPropertyConditionSet.h"
34 #include "Opcode.h"
35 #include "Options.h"
36 #include "RegisterSet.h"
37 #include "Structure.h"
38 #include "StructureSet.h"
39 #include "StructureStubClearingWatchpoint.h"
40
41 namespace JSC {
42
43 #if ENABLE(JIT)
44
45 class AccessCase;
46 class AccessGenerationResult;
47 class PolymorphicAccess;
48
49 enum class AccessType : int8_t {
50     Get,
51     GetPure,
52     Put,
53     In
54 };
55
56 enum class CacheType : int8_t {
57     Unset,
58     GetByIdSelf,
59     PutByIdReplace,
60     Stub
61 };
62
63 class StructureStubInfo {
64     WTF_MAKE_NONCOPYABLE(StructureStubInfo);
65     WTF_MAKE_FAST_ALLOCATED;
66 public:
67     StructureStubInfo(AccessType);
68     ~StructureStubInfo();
69
70     void initGetByIdSelf(CodeBlock*, Structure* baseObjectStructure, PropertyOffset);
71     void initPutByIdReplace(CodeBlock*, Structure* baseObjectStructure, PropertyOffset);
72     void initStub(CodeBlock*, std::unique_ptr<PolymorphicAccess>);
73
74     AccessGenerationResult addAccessCase(CodeBlock*, const Identifier&, std::unique_ptr<AccessCase>);
75
76     void reset(CodeBlock*);
77
78     void deref();
79     void aboutToDie();
80
81     // Check if the stub has weak references that are dead. If it does, then it resets itself,
82     // either entirely or just enough to ensure that those dead pointers don't get used anymore.
83     void visitWeakReferences(CodeBlock*);
84         
85     ALWAYS_INLINE bool considerCaching(Structure* structure)
86     {
87         // We never cache non-cells.
88         if (!structure)
89             return false;
90         
91         // This method is called from the Optimize variants of IC slow paths. The first part of this
92         // method tries to determine if the Optimize variant should really behave like the
93         // non-Optimize variant and leave the IC untouched.
94         //
95         // If we determine that we should do something to the IC then the next order of business is
96         // to determine if this Structure would impact the IC at all. We know that it won't, if we
97         // have already buffered something on its behalf. That's what the bufferedStructures set is
98         // for.
99         
100         everConsidered = true;
101         if (!countdown) {
102             // Check if we have been doing repatching too frequently. If so, then we should cool off
103             // for a while.
104             WTF::incrementWithSaturation(repatchCount);
105             if (repatchCount > Options::repatchCountForCoolDown()) {
106                 // We've been repatching too much, so don't do it now.
107                 repatchCount = 0;
108                 // The amount of time we require for cool-down depends on the number of times we've
109                 // had to cool down in the past. The relationship is exponential. The max value we
110                 // allow here is 2^256 - 2, since the slow paths may increment the count to indicate
111                 // that they'd like to temporarily skip patching just this once.
112                 countdown = WTF::leftShiftWithSaturation(
113                     static_cast<uint8_t>(Options::initialCoolDownCount()),
114                     numberOfCoolDowns,
115                     static_cast<uint8_t>(std::numeric_limits<uint8_t>::max() - 1));
116                 WTF::incrementWithSaturation(numberOfCoolDowns);
117                 
118                 // We may still have had something buffered. Trigger generation now.
119                 bufferingCountdown = 0;
120                 return true;
121             }
122             
123             // We don't want to return false due to buffering indefinitely.
124             if (!bufferingCountdown) {
125                 // Note that when this returns true, it's possible that we will not even get an
126                 // AccessCase because this may cause Repatch.cpp to simply do an in-place
127                 // repatching.
128                 return true;
129             }
130             
131             bufferingCountdown--;
132             
133             // Now protect the IC buffering. We want to proceed only if this is a structure that
134             // we don't already have a case buffered for. Note that if this returns true but the
135             // bufferingCountdown is not zero then we will buffer the access case for later without
136             // immediately generating code for it.
137             return bufferedStructures.add(structure);
138         }
139         countdown--;
140         return false;
141     }
142
143     CodeLocationCall callReturnLocation;
144
145     CodeOrigin codeOrigin;
146     CallSiteIndex callSiteIndex;
147
148     bool containsPC(void* pc) const;
149
150     union {
151         struct {
152             WriteBarrierBase<Structure> baseObjectStructure;
153             PropertyOffset offset;
154         } byIdSelf;
155         PolymorphicAccess* stub;
156     } u;
157     
158     // Represents those structures that already have buffered AccessCases in the PolymorphicAccess.
159     // Note that it's always safe to clear this. If we clear it prematurely, then if we see the same
160     // structure again during this buffering countdown, we will create an AccessCase object for it.
161     // That's not so bad - we'll get rid of the redundant ones once we regenerate.
162     StructureSet bufferedStructures;
163     
164     struct {
165         int8_t baseGPR;
166 #if USE(JSVALUE32_64)
167         int8_t valueTagGPR;
168         int8_t baseTagGPR;
169 #endif
170         int8_t valueGPR;
171         RegisterSet usedRegisters;
172         int32_t deltaCallToDone;
173         int32_t deltaCallToJump;
174         int32_t deltaCallToSlowCase;
175         int32_t deltaCheckImmToCall;
176 #if USE(JSVALUE64)
177         int32_t deltaCallToLoadOrStore;
178 #else
179         int32_t deltaCallToTagLoadOrStore;
180         int32_t deltaCallToPayloadLoadOrStore;
181 #endif
182     } patch;
183
184     AccessType accessType;
185     CacheType cacheType;
186     uint8_t countdown; // We repatch only when this is zero. If not zero, we decrement.
187     uint8_t repatchCount;
188     uint8_t numberOfCoolDowns;
189     uint8_t bufferingCountdown;
190     bool resetByGC : 1;
191     bool tookSlowPath : 1;
192     bool everConsidered : 1;
193 };
194
195 inline CodeOrigin getStructureStubInfoCodeOrigin(StructureStubInfo& structureStubInfo)
196 {
197     return structureStubInfo.codeOrigin;
198 }
199
200 #else
201
202 class StructureStubInfo;
203
204 #endif // ENABLE(JIT)
205
206 typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap;
207
208 } // namespace JSC
209
210 #endif // StructureStubInfo_h