132c27960266f7f0fef59ca6de256345f02f5324
[WebKit-https.git] / Source / JavaScriptCore / runtime / FunctionRareData.h
1 /*
2  * Copyright (C) 2015-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 #include "InternalFunctionAllocationProfile.h"
29 #include "JSCast.h"
30 #include "ObjectAllocationProfile.h"
31 #include "Watchpoint.h"
32
33 namespace JSC {
34
35 class JSGlobalObject;
36 class LLIntOffsetsExtractor;
37 namespace DFG {
38 class SpeculativeJIT;
39 class JITCompiler;
40 }
41
42 class FunctionRareData final : public JSCell {
43     friend class JIT;
44     friend class DFG::SpeculativeJIT;
45     friend class DFG::JITCompiler;
46     friend class VM;
47     
48 public:
49     typedef JSCell Base;
50     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
51
52     static FunctionRareData* create(VM&);
53
54     static const bool needsDestruction = true;
55     static void destroy(JSCell*);
56
57     static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
58
59     static void visitChildren(JSCell*, SlotVisitor&);
60
61     DECLARE_INFO;
62
63     static inline ptrdiff_t offsetOfObjectAllocationProfile()
64     {
65         return OBJECT_OFFSETOF(FunctionRareData, m_objectAllocationProfile);
66     }
67
68     ObjectAllocationProfile* objectAllocationProfile()
69     {
70         return &m_objectAllocationProfile;
71     }
72
73     Structure* objectAllocationStructure() { return m_objectAllocationProfile.structure(); }
74     JSObject* objectAllocationPrototype() { return m_objectAllocationProfile.prototype(); }
75
76     InlineWatchpointSet& allocationProfileWatchpointSet()
77     {
78         return m_objectAllocationProfileWatchpoint;
79     }
80
81     void clear(const char* reason);
82
83     void initializeObjectAllocationProfile(VM&, JSGlobalObject*, JSObject* prototype, size_t inlineCapacity, JSFunction* constructor);
84
85     bool isObjectAllocationProfileInitialized() { return !m_objectAllocationProfile.isNull(); }
86
87     Structure* internalFunctionAllocationStructure() { return m_internalFunctionAllocationProfile.structure(); }
88     Structure* createInternalFunctionAllocationStructureFromBase(VM& vm, JSGlobalObject* globalObject, JSObject* prototype, Structure* baseStructure)
89     {
90         return m_internalFunctionAllocationProfile.createAllocationStructureFromBase(vm, globalObject, this, prototype, baseStructure);
91     }
92     void clearInternalFunctionAllocationProfile()
93     {
94         m_internalFunctionAllocationProfile.clear();
95     }
96
97     Structure* getBoundFunctionStructure() { return m_boundFunctionStructure.get(); }
98     void setBoundFunctionStructure(VM& vm, Structure* structure) { m_boundFunctionStructure.set(vm, this, structure); }
99
100     bool hasReifiedLength() const { return m_hasReifiedLength; }
101     void setHasReifiedLength() { m_hasReifiedLength = true; }
102     bool hasReifiedName() const { return m_hasReifiedName; }
103     void setHasReifiedName() { m_hasReifiedName = true; }
104
105     bool hasAllocationProfileClearingWatchpoint() const { return !!m_allocationProfileClearingWatchpoint; }
106     Watchpoint* createAllocationProfileClearingWatchpoint()
107     {
108         RELEASE_ASSERT(!hasAllocationProfileClearingWatchpoint());
109         m_allocationProfileClearingWatchpoint = std::make_unique<AllocationProfileClearingWatchpoint>(this);
110         return m_allocationProfileClearingWatchpoint.get();
111     }
112
113 protected:
114     FunctionRareData(VM&);
115     ~FunctionRareData();
116
117 private:
118
119     class AllocationProfileClearingWatchpoint final : public Watchpoint {
120     public:
121         AllocationProfileClearingWatchpoint(FunctionRareData* rareData)
122             : m_rareData(rareData)
123         { }
124     protected:
125         void fireInternal(VM&, const FireDetail&) override;
126     private:
127         FunctionRareData* m_rareData;
128     };
129
130     friend class LLIntOffsetsExtractor;
131
132     // Ideally, there would only be one allocation profile for subclassing but due to Reflect.construct we
133     // have two. There are some pros and cons in comparison to our current system to using the same profile
134     // for both JS constructors and subclasses of builtin constructors:
135     //
136     // 1) + Uses less memory.
137     // 2) + Conceptually simplier as there is only one profile.
138     // 3) - We would need a check in all JSFunction object creations (both with classes and without) that the
139     //      new.target's profiled structure has a JSFinalObject ClassInfo. This is needed, for example, if we have
140     //      `Reflect.construct(Array, args, myConstructor)` since myConstructor will be the new.target of Array
141     //      the Array constructor will set the allocation profile of myConstructor to hold an Array structure
142     //
143     // We don't really care about 1) since this memory is rare and small in total. 2) is unfortunate but is
144     // probably outweighed by the cost of 3).
145     ObjectAllocationProfile m_objectAllocationProfile;
146     InlineWatchpointSet m_objectAllocationProfileWatchpoint;
147     InternalFunctionAllocationProfile m_internalFunctionAllocationProfile;
148     WriteBarrier<Structure> m_boundFunctionStructure;
149     std::unique_ptr<AllocationProfileClearingWatchpoint> m_allocationProfileClearingWatchpoint;
150     bool m_hasReifiedLength { false };
151     bool m_hasReifiedName { false };
152 };
153
154 } // namespace JSC