b774df8fa70a0b7ee8296206f5bbffa88867fe3c
[WebKit-https.git] / Source / JavaScriptCore / jit / PolymorphicCallStubRoutine.cpp
1 /*
2  * Copyright (C) 2015 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 #include "config.h"
27 #include "PolymorphicCallStubRoutine.h"
28
29 #if ENABLE(JIT)
30
31 #include "CallLinkInfo.h"
32 #include "CodeBlock.h"
33 #include "JSCInlines.h"
34 #include "LinkBuffer.h"
35
36 namespace JSC {
37
38 PolymorphicCallNode::~PolymorphicCallNode()
39 {
40     if (isOnList())
41         remove();
42 }
43
44 void PolymorphicCallNode::unlink(VM& vm)
45 {
46     if (m_callLinkInfo) {
47         if (Options::dumpDisassembly())
48             dataLog("Unlinking polymorphic call at ", m_callLinkInfo->callReturnLocation(), ", ", m_callLinkInfo->codeOrigin(), "\n");
49
50         m_callLinkInfo->unlink(vm);
51     }
52
53     if (isOnList())
54         remove();
55 }
56
57 void PolymorphicCallNode::clearCallLinkInfo()
58 {
59     if (Options::dumpDisassembly())
60         dataLog("Clearing call link info for polymorphic call at ", m_callLinkInfo->callReturnLocation(), ", ", m_callLinkInfo->codeOrigin(), "\n");
61
62     m_callLinkInfo = nullptr;
63 }
64
65 void PolymorphicCallCase::dump(PrintStream& out) const
66 {
67     out.print("<variant = ", m_variant, ", codeBlock = ", pointerDump(m_codeBlock), ">");
68 }
69
70 PolymorphicCallStubRoutine::PolymorphicCallStubRoutine(
71     const MacroAssemblerCodeRef& codeRef, VM& vm, const JSCell* owner, ExecState* callerFrame,
72     CallLinkInfo& info, const Vector<PolymorphicCallCase>& cases,
73     std::unique_ptr<uint32_t[]> fastCounts)
74     : GCAwareJITStubRoutine(codeRef, vm)
75     , m_fastCounts(WTF::move(fastCounts))
76 {
77     for (PolymorphicCallCase callCase : cases) {
78         m_variants.append(WriteBarrier<JSCell>(vm, owner, callCase.variant().rawCalleeCell()));
79         if (shouldDumpDisassemblyFor(callerFrame->codeBlock()))
80             dataLog("Linking polymorphic call in ", *callerFrame->codeBlock(), " at ", callerFrame->codeOrigin(), " to ", callCase.variant(), ", codeBlock = ", pointerDump(callCase.codeBlock()), "\n");
81         if (CodeBlock* codeBlock = callCase.codeBlock())
82             codeBlock->linkIncomingPolymorphicCall(callerFrame, m_callNodes.add(&info));
83     }
84     m_variants.shrinkToFit();
85     WTF::storeStoreFence();
86 }
87
88 PolymorphicCallStubRoutine::~PolymorphicCallStubRoutine() { }
89
90 CallVariantList PolymorphicCallStubRoutine::variants() const
91 {
92     CallVariantList result;
93     for (size_t i = 0; i < m_variants.size(); ++i)
94         result.append(CallVariant(m_variants[i].get()));
95     return result;
96 }
97
98 CallEdgeList PolymorphicCallStubRoutine::edges() const
99 {
100     // We wouldn't have these if this was an FTL stub routine. We shouldn't be asking for profiling
101     // from the FTL.
102     RELEASE_ASSERT(m_fastCounts);
103     
104     CallEdgeList result;
105     for (size_t i = 0; i < m_variants.size(); ++i)
106         result.append(CallEdge(CallVariant(m_variants[i].get()), m_fastCounts[i]));
107     return result;
108 }
109
110 void PolymorphicCallStubRoutine::clearCallNodesFor(CallLinkInfo* info)
111 {
112     for (Bag<PolymorphicCallNode>::iterator iter = m_callNodes.begin(); !!iter; ++iter) {
113         PolymorphicCallNode& node = **iter;
114         // All nodes should point to info, but okay to be a little paranoid.
115         if (node.hasCallLinkInfo(info))
116             node.clearCallLinkInfo();
117     }
118 }
119
120 bool PolymorphicCallStubRoutine::visitWeak(VM&)
121 {
122     for (auto& variant : m_variants) {
123         if (!Heap::isMarked(variant.get()))
124             return false;
125     }
126     return true;
127 }
128
129 void PolymorphicCallStubRoutine::markRequiredObjectsInternal(SlotVisitor& visitor)
130 {
131     for (auto& variant : m_variants)
132         visitor.append(&variant);
133 }
134
135 } // namespace JSC
136
137 #endif // ENABLE(JIT)