]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecode/CallLinkStatus.cpp
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / bytecode / CallLinkStatus.cpp
1 /*
2 * Copyright (C) 2012, 2013 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 "CallLinkStatus.h"
28
29 #include "CodeBlock.h"
30 #include "LLIntCallLinkInfo.h"
31 #include "Operations.h"
32 #include <wtf/CommaPrinter.h>
33
34 namespace JSC {
35
36 CallLinkStatus::CallLinkStatus(JSValue value)
37 : m_callTarget(value)
38 , m_executable(0)
39 , m_structure(0)
40 , m_couldTakeSlowPath(false)
41 , m_isProved(false)
42 {
43 if (!value || !value.isCell())
44 return;
45
46 m_structure = value.asCell()->structure();
47
48 if (!value.asCell()->inherits(&JSFunction::s_info))
49 return;
50
51 m_executable = jsCast<JSFunction*>(value.asCell())->executable();
52 }
53
54 JSFunction* CallLinkStatus::function() const
55 {
56 if (!m_callTarget || !m_callTarget.isCell())
57 return 0;
58
59 if (!m_callTarget.asCell()->inherits(&JSFunction::s_info))
60 return 0;
61
62 return jsCast<JSFunction*>(m_callTarget.asCell());
63 }
64
65 InternalFunction* CallLinkStatus::internalFunction() const
66 {
67 if (!m_callTarget || !m_callTarget.isCell())
68 return 0;
69
70 if (!m_callTarget.asCell()->inherits(&InternalFunction::s_info))
71 return 0;
72
73 return jsCast<InternalFunction*>(m_callTarget.asCell());
74 }
75
76 Intrinsic CallLinkStatus::intrinsicFor(CodeSpecializationKind kind) const
77 {
78 if (!m_executable)
79 return NoIntrinsic;
80
81 return m_executable->intrinsicFor(kind);
82 }
83
84 CallLinkStatus CallLinkStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex)
85 {
86 UNUSED_PARAM(profiledBlock);
87 UNUSED_PARAM(bytecodeIndex);
88 #if ENABLE(LLINT)
89 Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
90 LLIntCallLinkInfo* callLinkInfo = instruction[4].u.callLinkInfo;
91
92 return CallLinkStatus(callLinkInfo->lastSeenCallee.get());
93 #else
94 return CallLinkStatus();
95 #endif
96 }
97
98 CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
99 {
100 UNUSED_PARAM(profiledBlock);
101 UNUSED_PARAM(bytecodeIndex);
102 #if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
103 if (!profiledBlock->numberOfCallLinkInfos())
104 return computeFromLLInt(profiledBlock, bytecodeIndex);
105
106 if (profiledBlock->couldTakeSlowCase(bytecodeIndex))
107 return CallLinkStatus::takesSlowPath();
108
109 CallLinkInfo& callLinkInfo = profiledBlock->getCallLinkInfo(bytecodeIndex);
110 if (callLinkInfo.stub)
111 return CallLinkStatus(callLinkInfo.stub->executable(), callLinkInfo.stub->structure());
112
113 JSFunction* target = callLinkInfo.lastSeenCallee.get();
114 if (!target)
115 return computeFromLLInt(profiledBlock, bytecodeIndex);
116
117 if (callLinkInfo.hasSeenClosure)
118 return CallLinkStatus(target->executable(), target->structure());
119
120 return CallLinkStatus(target);
121 #else
122 return CallLinkStatus();
123 #endif
124 }
125
126 void CallLinkStatus::dump(PrintStream& out) const
127 {
128 if (!isSet()) {
129 out.print("Not Set");
130 return;
131 }
132
133 CommaPrinter comma;
134
135 if (m_isProved)
136 out.print(comma, "Statically Proved");
137
138 if (m_couldTakeSlowPath)
139 out.print(comma, "Could Take Slow Path");
140
141 if (m_callTarget)
142 out.print(comma, "Known target: ", m_callTarget);
143
144 if (m_executable)
145 out.print(comma, "Executable/CallHash: ", RawPointer(m_executable), "/", m_executable->hashFor(CodeForCall));
146
147 if (m_structure)
148 out.print(comma, "Structure: ", RawPointer(m_structure));
149 }
150
151 } // namespace JSC
152