blob: 03dd781ec78a52df0a0ca225989c935b1d295c4b [file] [log] [blame]
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +00001/*
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00002 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +00003 *
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
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +000029#include "CodeBlockHash.h"
30#include "CodeSpecializationKind.h"
fpizlo@apple.coma62d4822013-10-06 04:22:43 +000031#include "JSFunction.h"
fpizlo@apple.com116a0892011-11-03 08:06:42 +000032#include "ValueRecovery.h"
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +000033#include "WriteBarrier.h"
fpizlo@apple.com1688cc12012-05-23 07:29:02 +000034#include <wtf/BitVector.h>
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +000035#include <wtf/HashMap.h>
fpizlo@apple.com20d46242012-11-30 21:56:24 +000036#include <wtf/PrintStream.h>
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +000037#include <wtf/StdLibExtras.h>
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +000038#include <wtf/Vector.h>
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +000039
40namespace JSC {
41
42struct InlineCallFrame;
fpizlo@apple.com608ecbe2013-01-08 22:02:04 +000043class ExecState;
oliver@apple.come2fe4ce2013-07-25 03:59:41 +000044class ScriptExecutable;
fpizlo@apple.com39edeaf2011-10-30 22:47:31 +000045class JSFunction;
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +000046
47struct CodeOrigin {
oliver@apple.combc2930b2013-07-25 04:01:48 +000048 static const unsigned invalidBytecodeIndex = UINT_MAX;
fpizlo@apple.com5e135772012-07-12 00:12:03 +000049
oliver@apple.combc2930b2013-07-25 04:01:48 +000050 // Bytecode offset that you'd use to re-execute this instruction, and the
51 // bytecode index of the bytecode instruction that produces some result that
52 // you're interested in (used for mapping Nodes whose values you're using
53 // to bytecode instructions that have the appropriate value profile).
54 unsigned bytecodeIndex;
fpizlo@apple.comafcf9042012-01-20 20:22:18 +000055
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +000056 InlineCallFrame* inlineCallFrame;
57
58 CodeOrigin()
oliver@apple.combc2930b2013-07-25 04:01:48 +000059 : bytecodeIndex(invalidBytecodeIndex)
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +000060 , inlineCallFrame(0)
61 {
62 }
63
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +000064 CodeOrigin(WTF::HashTableDeletedValueType)
65 : bytecodeIndex(invalidBytecodeIndex)
msaboff@apple.com95894332014-01-29 19:18:54 +000066 , inlineCallFrame(deletedMarker())
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +000067 {
68 }
69
oliver@apple.combc2930b2013-07-25 04:01:48 +000070 explicit CodeOrigin(unsigned bytecodeIndex, InlineCallFrame* inlineCallFrame = 0)
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +000071 : bytecodeIndex(bytecodeIndex)
fpizlo@apple.com41f5c952011-10-17 23:54:41 +000072 , inlineCallFrame(inlineCallFrame)
73 {
oliver@apple.combc2930b2013-07-25 04:01:48 +000074 ASSERT(bytecodeIndex < invalidBytecodeIndex);
fpizlo@apple.com41f5c952011-10-17 23:54:41 +000075 }
76
oliver@apple.combc2930b2013-07-25 04:01:48 +000077 bool isSet() const { return bytecodeIndex != invalidBytecodeIndex; }
fpizlo@apple.comd4a77bb2014-04-12 18:22:27 +000078 bool operator!() const { return !isSet(); }
fpizlo@apple.comafcf9042012-01-20 20:22:18 +000079
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +000080 bool isHashTableDeletedValue() const
81 {
82 return bytecodeIndex == invalidBytecodeIndex && !!inlineCallFrame;
83 }
84
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +000085 // The inline depth is the depth of the inline stack, so 1 = not inlined,
86 // 2 = inlined one deep, etc.
87 unsigned inlineDepth() const;
88
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +000089 // If the code origin corresponds to inlined code, gives you the heap object that
90 // would have owned the code if it had not been inlined. Otherwise returns 0.
oliver@apple.come2fe4ce2013-07-25 03:59:41 +000091 ScriptExecutable* codeOriginOwner() const;
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +000092
msaboff@apple.comb70e41b2013-09-13 18:03:55 +000093 int stackOffset() const;
fpizlo@apple.com439e9e52013-01-02 23:54:42 +000094
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +000095 static unsigned inlineDepthForCallFrame(InlineCallFrame*);
96
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +000097 unsigned hash() const;
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +000098 bool operator==(const CodeOrigin& other) const;
fpizlo@apple.com769d8d32011-12-14 01:46:36 +000099 bool operator!=(const CodeOrigin& other) const { return !(*this == other); }
100
msaboff@apple.com95894332014-01-29 19:18:54 +0000101 // This checks if the two code origins correspond to the same stack trace snippets,
102 // but ignore whether the InlineCallFrame's are identical.
103 bool isApproximatelyEqualTo(const CodeOrigin& other) const;
104
105 unsigned approximateHash() const;
106
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +0000107 // Get the inline stack. This is slow, and is intended for debugging only.
108 Vector<CodeOrigin> inlineStack() const;
fpizlo@apple.com20d46242012-11-30 21:56:24 +0000109
110 void dump(PrintStream&) const;
oliver@apple.com237b1462013-07-25 04:05:36 +0000111 void dumpInContext(PrintStream&, DumpContext*) const;
msaboff@apple.com95894332014-01-29 19:18:54 +0000112
113private:
114 static InlineCallFrame* deletedMarker()
115 {
116 return bitwise_cast<InlineCallFrame*>(static_cast<uintptr_t>(1));
117 }
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +0000118};
119
120struct InlineCallFrame {
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000121 enum Kind {
122 Call,
123 Construct,
124
125 // For these, the stackOffset incorporates the argument count plus the true return PC
126 // slot.
127 GetterCall,
128 SetterCall
129 };
130
131 static Kind kindFor(CodeSpecializationKind kind)
132 {
133 switch (kind) {
134 case CodeForCall:
135 return Call;
136 case CodeForConstruct:
137 return Construct;
138 }
139 RELEASE_ASSERT_NOT_REACHED();
140 return Call;
141 }
142
143 static CodeSpecializationKind specializationKindFor(Kind kind)
144 {
145 switch (kind) {
146 case Call:
147 case GetterCall:
148 case SetterCall:
149 return CodeForCall;
150 case Construct:
151 return CodeForConstruct;
152 }
153 RELEASE_ASSERT_NOT_REACHED();
154 return CodeForCall;
155 }
156
fpizlo@apple.com29abafe2014-08-28 19:09:48 +0000157 static bool isNormalCall(Kind kind)
158 {
159 switch (kind) {
160 case Call:
161 case Construct:
162 return true;
163 default:
164 return false;
165 }
166 }
167
msaboff@apple.com95894332014-01-29 19:18:54 +0000168 Vector<ValueRecovery> arguments; // Includes 'this'.
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000169 WriteBarrier<ScriptExecutable> executable;
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000170 ValueRecovery calleeRecovery;
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +0000171 CodeOrigin caller;
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000172 BitVector capturedVars; // Indexed by the machine call frame's variable numbering.
mark.lam@apple.comb2a4eb72014-08-22 05:30:02 +0000173
174 signed stackOffset : 29;
commit-queue@webkit.orgcb8934b2014-08-20 18:11:15 +0000175 unsigned kind : 2; // real type is Kind
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000176 bool isClosureCall : 1; // If false then we know that callee/scope are constants and the DFG won't treat them as variables, i.e. they have to be recovered manually.
177 VirtualRegister argumentsRegister; // This is only set if the code uses arguments. The unmodified arguments register follows the unmodifiedArgumentsRegister() convention (see CodeBlock.h).
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000178
fpizlo@apple.com48a7bc82013-09-23 22:09:24 +0000179 // There is really no good notion of a "default" set of values for
180 // InlineCallFrame's fields. This constructor is here just to reduce confusion if
181 // we forgot to initialize explicitly.
182 InlineCallFrame()
183 : stackOffset(0)
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000184 , kind(Call)
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000185 , isClosureCall(false)
fpizlo@apple.com48a7bc82013-09-23 22:09:24 +0000186 {
187 }
188
commit-queue@webkit.orgcb8934b2014-08-20 18:11:15 +0000189 CodeSpecializationKind specializationKind() const { return specializationKindFor(static_cast<Kind>(kind)); }
fpizlo@apple.coma62d4822013-10-06 04:22:43 +0000190
191 JSFunction* calleeConstant() const
192 {
193 if (calleeRecovery.isConstant())
194 return jsCast<JSFunction*>(calleeRecovery.constant());
195 return 0;
196 }
ggaren@apple.comde696542014-08-01 20:17:25 +0000197
198 void visitAggregate(SlotVisitor& visitor)
199 {
200 visitor.append(&executable);
201 }
fpizlo@apple.com439e9e52013-01-02 23:54:42 +0000202
fpizlo@apple.com608ecbe2013-01-08 22:02:04 +0000203 // Get the callee given a machine call frame to which this InlineCallFrame belongs.
204 JSFunction* calleeForCallFrame(ExecState*) const;
205
oliver@apple.com02039462013-07-25 03:59:29 +0000206 CString inferredName() const;
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000207 CodeBlockHash hash() const;
fpizlo@apple.comf285f712014-03-13 01:50:41 +0000208 CString hashAsStringIfPossible() const;
fpizlo@apple.com20d46242012-11-30 21:56:24 +0000209
fpizlo@apple.com4a81fa42012-12-05 01:26:13 +0000210 CodeBlock* baselineCodeBlock() const;
211
mark.lam@apple.comb2a4eb72014-08-22 05:30:02 +0000212 void setStackOffset(signed offset)
213 {
214 stackOffset = offset;
215 RELEASE_ASSERT(static_cast<signed>(stackOffset) == offset);
216 }
217
mark.lam@apple.comc8151c42013-10-30 21:26:46 +0000218 ptrdiff_t callerFrameOffset() const { return stackOffset * sizeof(Register) + CallFrame::callerFrameOffset(); }
219 ptrdiff_t returnPCOffset() const { return stackOffset * sizeof(Register) + CallFrame::returnPCOffset(); }
220
fpizlo@apple.com806b5822013-01-08 01:23:38 +0000221 void dumpBriefFunctionInformation(PrintStream&) const;
fpizlo@apple.com20d46242012-11-30 21:56:24 +0000222 void dump(PrintStream&) const;
oliver@apple.com237b1462013-07-25 04:05:36 +0000223 void dumpInContext(PrintStream&, DumpContext*) const;
fpizlo@apple.com806b5822013-01-08 01:23:38 +0000224
225 MAKE_PRINT_METHOD(InlineCallFrame, dumpBriefFunctionInformation, briefFunctionInformation);
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +0000226};
227
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000228inline int CodeOrigin::stackOffset() const
fpizlo@apple.com439e9e52013-01-02 23:54:42 +0000229{
230 if (!inlineCallFrame)
231 return 0;
232
233 return inlineCallFrame->stackOffset;
234}
235
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000236inline unsigned CodeOrigin::hash() const
237{
238 return WTF::IntHash<unsigned>::hash(bytecodeIndex) +
239 WTF::PtrHash<InlineCallFrame*>::hash(inlineCallFrame);
240}
241
fpizlo@apple.comd9ded3b2011-10-22 01:22:46 +0000242inline bool CodeOrigin::operator==(const CodeOrigin& other) const
243{
244 return bytecodeIndex == other.bytecodeIndex
245 && inlineCallFrame == other.inlineCallFrame;
246}
247
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000248inline ScriptExecutable* CodeOrigin::codeOriginOwner() const
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +0000249{
250 if (!inlineCallFrame)
251 return 0;
252 return inlineCallFrame->executable.get();
253}
254
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000255struct CodeOriginHash {
256 static unsigned hash(const CodeOrigin& key) { return key.hash(); }
257 static bool equal(const CodeOrigin& a, const CodeOrigin& b) { return a == b; }
258 static const bool safeToCompareToEmptyOrDeleted = true;
259};
260
msaboff@apple.com95894332014-01-29 19:18:54 +0000261struct CodeOriginApproximateHash {
262 static unsigned hash(const CodeOrigin& key) { return key.approximateHash(); }
263 static bool equal(const CodeOrigin& a, const CodeOrigin& b) { return a.isApproximatelyEqualTo(b); }
264 static const bool safeToCompareToEmptyOrDeleted = true;
265};
266
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +0000267} // namespace JSC
268
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000269namespace WTF {
270
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000271void printInternal(PrintStream&, JSC::InlineCallFrame::Kind);
272
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000273template<typename T> struct DefaultHash;
274template<> struct DefaultHash<JSC::CodeOrigin> {
275 typedef JSC::CodeOriginHash Hash;
276};
277
278template<typename T> struct HashTraits;
279template<> struct HashTraits<JSC::CodeOrigin> : SimpleClassHashTraits<JSC::CodeOrigin> {
280 static const bool emptyValueIsZero = false;
281};
282
283} // namespace WTF
284
fpizlo@apple.com5098c8b2011-10-14 22:01:10 +0000285#endif // CodeOrigin_h
286