]> git.saurik.com Git - apple/javascriptcore.git/blob - jit/PolymorphicCallStubRoutine.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / 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(RepatchBuffer& repatchBuffer)
45 {
46 if (m_callLinkInfo) {
47 if (Options::showDisassembly())
48 dataLog("Unlinking polymorphic call at ", m_callLinkInfo->callReturnLocation(), ", ", m_callLinkInfo->codeOrigin(), "\n");
49
50 m_callLinkInfo->unlink(repatchBuffer);
51 }
52
53 if (isOnList())
54 remove();
55 }
56
57 void PolymorphicCallNode::clearCallLinkInfo()
58 {
59 if (Options::showDisassembly())
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 (shouldShowDisassemblyFor(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(RepatchBuffer&)
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)