]> git.saurik.com Git - apple/javascriptcore.git/blame - interpreter/CallFrame.cpp
JavaScriptCore-1218.0.1.tar.gz
[apple/javascriptcore.git] / interpreter / CallFrame.cpp
CommitLineData
b37bf2e1 1/*
93a37866 2 * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved.
b37bf2e1
A
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 *
9dae56ea 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
b37bf2e1
A
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
9dae56ea 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
b37bf2e1
A
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
9dae56ea
A
26#include "config.h"
27#include "CallFrame.h"
b37bf2e1 28
9dae56ea 29#include "CodeBlock.h"
ba379fdc 30#include "Interpreter.h"
93a37866 31#include "Operations.h"
b37bf2e1 32
9dae56ea 33namespace JSC {
b37bf2e1 34
ba379fdc
A
35#ifndef NDEBUG
36void CallFrame::dumpCaller()
37{
38 int signedLineNumber;
39 intptr_t sourceID;
93a37866 40 String urlString;
ba379fdc
A
41 JSValue function;
42
43 interpreter()->retrieveLastCaller(this, signedLineNumber, sourceID, urlString, function);
93a37866 44 dataLogF("Callpoint => %s:%d\n", urlString.utf8().data(), signedLineNumber);
ba379fdc 45}
14957cd0 46
93a37866 47JSStack* CallFrame::stack()
14957cd0 48{
93a37866 49 return &interpreter()->stack();
14957cd0
A
50}
51
ba379fdc
A
52#endif
53
6fe7ccc8
A
54#if USE(JSVALUE32_64)
55unsigned CallFrame::bytecodeOffsetForNonDFGCode() const
56{
57 ASSERT(codeBlock());
58 return currentVPC() - codeBlock()->instructions().begin();
59}
60
61void CallFrame::setBytecodeOffsetForNonDFGCode(unsigned offset)
62{
63 ASSERT(codeBlock());
64 setCurrentVPC(codeBlock()->instructions().begin() + offset);
65}
66#else
67Instruction* CallFrame::currentVPC() const
68{
69 return codeBlock()->instructions().begin() + bytecodeOffsetForNonDFGCode();
70}
71void CallFrame::setCurrentVPC(Instruction* vpc)
72{
73 setBytecodeOffsetForNonDFGCode(vpc - codeBlock()->instructions().begin());
74}
75#endif
76
77#if ENABLE(DFG_JIT)
78bool CallFrame::isInlineCallFrameSlow()
79{
80 if (!callee())
81 return false;
82 JSCell* calleeAsFunctionCell = getJSFunction(callee());
83 if (!calleeAsFunctionCell)
84 return false;
85 JSFunction* calleeAsFunction = jsCast<JSFunction*>(calleeAsFunctionCell);
86 return calleeAsFunction->executable() != codeBlock()->ownerExecutable();
87}
88
89CallFrame* CallFrame::trueCallFrame(AbstractPC pc)
90{
91 // Am I an inline call frame? If so, we're done.
92 if (isInlineCallFrame())
93 return this;
94
95 // If I don't have a code block, then I'm not DFG code, so I'm the true call frame.
96 CodeBlock* machineCodeBlock = codeBlock();
97 if (!machineCodeBlock)
98 return this;
99
100 // If the code block does not have any code origins, then there was no inlining, so
101 // I'm done.
102 if (!machineCodeBlock->hasCodeOrigins())
103 return this;
104
105 // At this point the PC must be due either to the DFG, or it must be unset.
106 ASSERT(pc.hasJITReturnAddress() || !pc);
107
108 // Try to determine the CodeOrigin. If we don't have a pc set then the only way
109 // that this makes sense is if the CodeOrigin index was set in the call frame.
110 // FIXME: Note that you will see "Not currently in inlined code" comments below.
111 // Currently, we do not record code origins for code that is not inlined, because
112 // the only thing that we use code origins for is determining the inline stack.
113 // But in the future, we'll want to use this same functionality (having a code
114 // origin mapping for any calls out of JIT code) to determine the PC at any point
115 // in the stack even if not in inlined code. When that happens, the code below
116 // will have to change the way it detects the presence of inlining: it will always
117 // get a code origin, but sometimes, that code origin will not have an inline call
118 // frame. In that case, this method should bail and return this.
119 CodeOrigin codeOrigin;
120 if (pc.isSet()) {
121 ReturnAddressPtr currentReturnPC = pc.jitReturnAddress();
122
123 bool hasCodeOrigin = machineCodeBlock->codeOriginForReturn(currentReturnPC, codeOrigin);
93a37866
A
124 ASSERT(hasCodeOrigin);
125 if (!hasCodeOrigin) {
126 // In release builds, if we find ourselves in a situation where the return PC doesn't
127 // correspond to a valid CodeOrigin, we return zero instead of continuing. Some of
128 // the callers of trueCallFrame() will be able to recover and do conservative things,
129 // while others will crash.
130 return 0;
131 }
6fe7ccc8
A
132 } else {
133 unsigned index = codeOriginIndexForDFG();
93a37866
A
134 ASSERT(machineCodeBlock->canGetCodeOrigin(index));
135 if (!machineCodeBlock->canGetCodeOrigin(index)) {
136 // See above. In release builds, we try to protect ourselves from crashing even
137 // though stack walking will be goofed up.
138 return 0;
139 }
6fe7ccc8
A
140 codeOrigin = machineCodeBlock->codeOrigin(index);
141 }
142
143 if (!codeOrigin.inlineCallFrame)
144 return this; // Not currently in inlined code.
145
146 for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) {
147 InlineCallFrame* nextInlineCallFrame = inlineCallFrame->caller.inlineCallFrame;
148
149 CallFrame* inlinedCaller = this + inlineCallFrame->stackOffset;
150
151 JSFunction* calleeAsFunction = inlineCallFrame->callee.get();
152
153 // Fill in the inlinedCaller
154 inlinedCaller->setCodeBlock(machineCodeBlock);
93a37866
A
155 if (calleeAsFunction)
156 inlinedCaller->setScope(calleeAsFunction->scope());
6fe7ccc8
A
157 if (nextInlineCallFrame)
158 inlinedCaller->setCallerFrame(this + nextInlineCallFrame->stackOffset);
159 else
160 inlinedCaller->setCallerFrame(this);
161
162 inlinedCaller->setInlineCallFrame(inlineCallFrame);
163 inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->arguments.size());
93a37866
A
164 if (calleeAsFunction)
165 inlinedCaller->setCallee(calleeAsFunction);
6fe7ccc8
A
166
167 inlineCallFrame = nextInlineCallFrame;
168 }
169
170 return this + codeOrigin.inlineCallFrame->stackOffset;
171}
172
173CallFrame* CallFrame::trueCallerFrame()
174{
93a37866
A
175 if (!codeBlock())
176 return callerFrame()->removeHostCallFrameFlag();
177
6fe7ccc8
A
178 // this -> The callee; this is either an inlined callee in which case it already has
179 // a pointer to the true caller. Otherwise it contains current PC in the machine
180 // caller.
181 //
182 // machineCaller -> The caller according to the machine, which may be zero or
183 // more frames above the true caller due to inlining.
184
185 // Am I an inline call frame? If so, we're done.
186 if (isInlineCallFrame())
187 return callerFrame()->removeHostCallFrameFlag();
188
189 // I am a machine call frame, so the question is: is my caller a machine call frame
190 // that has inlines or a machine call frame that doesn't?
191 CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag();
192 if (!machineCaller)
193 return 0;
194 ASSERT(!machineCaller->isInlineCallFrame());
195
196 // Figure out how we want to get the current code location.
197 if (!hasReturnPC() || returnAddressIsInCtiTrampoline(returnPC()))
198 return machineCaller->trueCallFrameFromVMCode()->removeHostCallFrameFlag();
199
200 return machineCaller->trueCallFrame(returnPC())->removeHostCallFrameFlag();
201}
93a37866
A
202
203CodeBlock* CallFrame::someCodeBlockForPossiblyInlinedCode()
204{
205 if (!isInlineCallFrame())
206 return codeBlock();
207
208 return jsCast<FunctionExecutable*>(inlineCallFrame()->executable.get())->baselineCodeBlockFor(
209 inlineCallFrame()->isCall ? CodeForCall : CodeForConstruct);
210}
211
6fe7ccc8
A
212#endif
213
214Register* CallFrame::frameExtentInternal()
215{
216 CodeBlock* codeBlock = this->codeBlock();
217 ASSERT(codeBlock);
218 return registers() + codeBlock->m_numCalleeRegisters;
219}
220
9dae56ea 221}