1/*
2 * Copyright (C) 2012-2018 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 "CallLinkInfo.h"
29#include "CallVariant.h"
30#include "CodeOrigin.h"
31#include "ConcurrentJSLock.h"
32#include "ExitFlag.h"
33#include "ICStatusMap.h"
34#include "JSCJSValue.h"
35
36namespace JSC {
37
38class CodeBlock;
39class InternalFunction;
40class JSFunction;
41class Structure;
42class CallLinkInfo;
43
44class CallLinkStatus {
45 WTF_MAKE_FAST_ALLOCATED;
46public:
47 CallLinkStatus()
48 {
49 }
50
51 static CallLinkStatus takesSlowPath()
52 {
53 CallLinkStatus result;
54 result.m_couldTakeSlowPath = true;
55 return result;
56 }
57
58 explicit CallLinkStatus(JSValue);
59
60 CallLinkStatus(CallVariant variant)
61 : m_variants(1, variant)
62 {
63 }
64
65 struct ExitSiteData {
66 ExitFlag takesSlowPath;
67 ExitFlag badFunction;
68 };
69 static ExitSiteData computeExitSiteData(CodeBlock*, unsigned bytecodeIndex);
70
71 static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex, const ICStatusMap&, ExitSiteData);
72 static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex, const ICStatusMap&);
73
74#if ENABLE(JIT)
75 // Computes the status assuming that we never took slow path and never previously
76 // exited.
77 static CallLinkStatus computeFor(const ConcurrentJSLocker&, CodeBlock*, CallLinkInfo&);
78
79 // Computes the status accounting for exits.
80 static CallLinkStatus computeFor(
81 const ConcurrentJSLocker&, CodeBlock*, CallLinkInfo&, ExitSiteData, ExitingInlineKind = ExitFromAnyInlineKind);
82#endif
83
84 static CallLinkStatus computeFor(
85 CodeBlock*, CodeOrigin, const ICStatusMap&, const ICStatusContextStack&);
86
87 void setProvenConstantCallee(CallVariant);
88
89 bool isSet() const { return !m_variants.isEmpty() || m_couldTakeSlowPath; }
90
91 explicit operator bool() const { return isSet(); }
92
93 bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
94
95 void setCouldTakeSlowPath(bool value) { m_couldTakeSlowPath = value; }
96
97 CallVariantList variants() const { return m_variants; }
98 unsigned size() const { return m_variants.size(); }
99 CallVariant at(unsigned i) const { return m_variants[i]; }
100 CallVariant operator[](unsigned i) const { return at(i); }
101 bool isProved() const { return m_isProved; }
102 bool isBasedOnStub() const { return m_isBasedOnStub; }
103 bool canOptimize() const { return !m_variants.isEmpty(); }
104
105 bool isClosureCall() const; // Returns true if any callee is a closure call.
106
107 unsigned maxNumArguments() const { return m_maxNumArguments; }
108
109 bool finalize(VM&);
110
111 void merge(const CallLinkStatus&);
112
113 void filter(VM&, JSValue);
114
115 void dump(PrintStream&) const;
116
117private:
118 void makeClosureCall();
119
120 static CallLinkStatus computeFromLLInt(const ConcurrentJSLocker&, CodeBlock*, unsigned bytecodeIndex);
121#if ENABLE(JIT)
122 static CallLinkStatus computeFromCallLinkInfo(
123 const ConcurrentJSLocker&, CallLinkInfo&);
124#endif
125
126 void accountForExits(ExitSiteData, ExitingInlineKind);
127
128 CallVariantList m_variants;
129 bool m_couldTakeSlowPath { false };
130 bool m_isProved { false };
131 bool m_isBasedOnStub { false };
132 unsigned m_maxNumArguments { 0 };
133};
134
135} // namespace JSC
136