]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecode/CodeOrigin.h
JavaScriptCore-1097.3.tar.gz
[apple/javascriptcore.git] / 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 // Bytecode offset that you'd use to re-execute this instruction.
42 unsigned bytecodeIndex : 29;
43 // Bytecode offset corresponding to the opcode that gives the result (needed to handle
44 // op_call/op_call_put_result and op_method_check/op_get_by_id).
45 unsigned valueProfileOffset : 3;
46
47 InlineCallFrame* inlineCallFrame;
48
49 CodeOrigin()
50 : bytecodeIndex(std::numeric_limits<uint32_t>::max())
51 , valueProfileOffset(0)
52 , inlineCallFrame(0)
53 {
54 }
55
56 explicit CodeOrigin(unsigned bytecodeIndex, InlineCallFrame* inlineCallFrame = 0, unsigned valueProfileOffset = 0)
57 : bytecodeIndex(bytecodeIndex)
58 , valueProfileOffset(valueProfileOffset)
59 , inlineCallFrame(inlineCallFrame)
60 {
61 ASSERT(bytecodeIndex < (1u << 29));
62 ASSERT(valueProfileOffset < (1u << 3));
63 }
64
65 bool isSet() const { return bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
66
67 unsigned bytecodeIndexForValueProfile() const
68 {
69 return bytecodeIndex + valueProfileOffset;
70 }
71
72 // The inline depth is the depth of the inline stack, so 1 = not inlined,
73 // 2 = inlined one deep, etc.
74 unsigned inlineDepth() const;
75
76 // If the code origin corresponds to inlined code, gives you the heap object that
77 // would have owned the code if it had not been inlined. Otherwise returns 0.
78 ExecutableBase* codeOriginOwner() const;
79
80 static unsigned inlineDepthForCallFrame(InlineCallFrame*);
81
82 bool operator==(const CodeOrigin& other) const;
83
84 bool operator!=(const CodeOrigin& other) const { return !(*this == other); }
85
86 // Get the inline stack. This is slow, and is intended for debugging only.
87 Vector<CodeOrigin> inlineStack() const;
88 };
89
90 struct InlineCallFrame {
91 Vector<ValueRecovery> arguments;
92 WriteBarrier<ExecutableBase> executable;
93 WriteBarrier<JSFunction> callee;
94 CodeOrigin caller;
95 unsigned stackOffset : 31;
96 bool isCall : 1;
97 };
98
99 struct CodeOriginAtCallReturnOffset {
100 CodeOrigin codeOrigin;
101 unsigned callReturnOffset;
102 };
103
104 inline unsigned CodeOrigin::inlineDepthForCallFrame(InlineCallFrame* inlineCallFrame)
105 {
106 unsigned result = 1;
107 for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame)
108 result++;
109 return result;
110 }
111
112 inline unsigned CodeOrigin::inlineDepth() const
113 {
114 return inlineDepthForCallFrame(inlineCallFrame);
115 }
116
117 inline bool CodeOrigin::operator==(const CodeOrigin& other) const
118 {
119 return bytecodeIndex == other.bytecodeIndex
120 && inlineCallFrame == other.inlineCallFrame;
121 }
122
123 // Get the inline stack. This is slow, and is intended for debugging only.
124 inline Vector<CodeOrigin> CodeOrigin::inlineStack() const
125 {
126 Vector<CodeOrigin> result(inlineDepth());
127 result.last() = *this;
128 unsigned index = result.size() - 2;
129 for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame)
130 result[index--] = current->caller;
131 return result;
132 }
133
134 inline unsigned getCallReturnOffsetForCodeOrigin(CodeOriginAtCallReturnOffset* data)
135 {
136 return data->callReturnOffset;
137 }
138
139 inline ExecutableBase* CodeOrigin::codeOriginOwner() const
140 {
141 if (!inlineCallFrame)
142 return 0;
143 return inlineCallFrame->executable.get();
144 }
145
146 } // namespace JSC
147
148 #endif // CodeOrigin_h
149