0dae85ac08b93d31cf93c4fe6578ed0d86a405d9
[WebKit-https.git] / Source / JavaScriptCore / bytecode / CodeOrigin.h
1 /*
2  * Copyright (C) 2011 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 #ifndef CodeOrigin_h
27 #define CodeOrigin_h
28
29 #include "ValueRecovery.h"
30 #include "WriteBarrier.h"
31 #include <wtf/StdLibExtras.h>
32 #include <wtf/Vector.h>
33
34 namespace JSC {
35
36 struct InlineCallFrame;
37 class ExecutableBase;
38 class JSFunction;
39
40 struct CodeOrigin {
41     uint32_t bytecodeIndex;
42     InlineCallFrame* inlineCallFrame;
43     
44     CodeOrigin()
45         : bytecodeIndex(std::numeric_limits<uint32_t>::max())
46         , inlineCallFrame(0)
47     {
48     }
49     
50     explicit CodeOrigin(uint32_t bytecodeIndex)
51         : bytecodeIndex(bytecodeIndex)
52         , inlineCallFrame(0)
53     {
54     }
55     
56     explicit CodeOrigin(uint32_t bytecodeIndex, InlineCallFrame* inlineCallFrame)
57         : bytecodeIndex(bytecodeIndex)
58         , inlineCallFrame(inlineCallFrame)
59     {
60     }
61     
62     bool isSet() const { return bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
63     
64     // The inline depth is the depth of the inline stack, so 1 = not inlined,
65     // 2 = inlined one deep, etc.
66     unsigned inlineDepth() const;
67     
68     // If the code origin corresponds to inlined code, gives you the heap object that
69     // would have owned the code if it had not been inlined. Otherwise returns 0.
70     ExecutableBase* codeOriginOwner() const;
71     
72     static unsigned inlineDepthForCallFrame(InlineCallFrame*);
73     
74     bool operator==(const CodeOrigin& other) const;
75     
76 #ifndef NDEBUG
77     // Get the inline stack. This is slow, and is intended for debugging only.
78     Vector<CodeOrigin> inlineStack() const;
79 #endif
80 };
81
82 struct InlineCallFrame {
83     Vector<ValueRecovery> arguments;
84     WriteBarrier<ExecutableBase> executable;
85     WriteBarrier<JSFunction> callee;
86     CodeOrigin caller;
87     unsigned stackOffset : 31;
88     bool isCall : 1;
89 };
90
91 struct CodeOriginAtCallReturnOffset {
92     CodeOrigin codeOrigin;
93     unsigned callReturnOffset;
94 };
95
96 inline unsigned CodeOrigin::inlineDepthForCallFrame(InlineCallFrame* inlineCallFrame)
97 {
98     unsigned result = 1;
99     for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame)
100         result++;
101     return result;
102 }
103
104 inline unsigned CodeOrigin::inlineDepth() const
105 {
106     return inlineDepthForCallFrame(inlineCallFrame);
107 }
108     
109 inline bool CodeOrigin::operator==(const CodeOrigin& other) const
110 {
111     return bytecodeIndex == other.bytecodeIndex
112         && inlineCallFrame == other.inlineCallFrame;
113 }
114     
115 #ifndef NDEBUG
116 // Get the inline stack. This is slow, and is intended for debugging only.
117 inline Vector<CodeOrigin> CodeOrigin::inlineStack() const
118 {
119     Vector<CodeOrigin> result(inlineDepth());
120     result.last() = *this;
121     unsigned index = result.size() - 2;
122     for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame)
123         result[index--] = current->caller;
124     return result;
125 }
126 #endif
127
128 inline unsigned getCallReturnOffsetForCodeOrigin(CodeOriginAtCallReturnOffset* data)
129 {
130     return data->callReturnOffset;
131 }
132
133 inline ExecutableBase* CodeOrigin::codeOriginOwner() const
134 {
135     if (!inlineCallFrame)
136         return 0;
137     return inlineCallFrame->executable.get();
138 }
139
140 } // namespace JSC
141
142 #endif // CodeOrigin_h
143