2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "CallFrame.h"
29 #include "CodeBlock.h"
30 #include "Interpreter.h"
35 void CallFrame::dumpCaller()
42 interpreter()->retrieveLastCaller(this, signedLineNumber
, sourceID
, urlString
, function
);
43 dataLog("Callpoint => %s:%d\n", urlString
.utf8().data(), signedLineNumber
);
46 RegisterFile
* CallFrame::registerFile()
48 return &interpreter()->registerFile();
54 unsigned CallFrame::bytecodeOffsetForNonDFGCode() const
57 return currentVPC() - codeBlock()->instructions().begin();
60 void CallFrame::setBytecodeOffsetForNonDFGCode(unsigned offset
)
63 setCurrentVPC(codeBlock()->instructions().begin() + offset
);
66 Instruction
* CallFrame::currentVPC() const
68 return codeBlock()->instructions().begin() + bytecodeOffsetForNonDFGCode();
70 void CallFrame::setCurrentVPC(Instruction
* vpc
)
72 setBytecodeOffsetForNonDFGCode(vpc
- codeBlock()->instructions().begin());
77 bool CallFrame::isInlineCallFrameSlow()
81 JSCell
* calleeAsFunctionCell
= getJSFunction(callee());
82 if (!calleeAsFunctionCell
)
84 JSFunction
* calleeAsFunction
= jsCast
<JSFunction
*>(calleeAsFunctionCell
);
85 return calleeAsFunction
->executable() != codeBlock()->ownerExecutable();
88 CallFrame
* CallFrame::trueCallFrame(AbstractPC pc
)
90 // Am I an inline call frame? If so, we're done.
91 if (isInlineCallFrame())
94 // If I don't have a code block, then I'm not DFG code, so I'm the true call frame.
95 CodeBlock
* machineCodeBlock
= codeBlock();
96 if (!machineCodeBlock
)
99 // If the code block does not have any code origins, then there was no inlining, so
101 if (!machineCodeBlock
->hasCodeOrigins())
104 // At this point the PC must be due either to the DFG, or it must be unset.
105 ASSERT(pc
.hasJITReturnAddress() || !pc
);
107 // Try to determine the CodeOrigin. If we don't have a pc set then the only way
108 // that this makes sense is if the CodeOrigin index was set in the call frame.
109 // FIXME: Note that you will see "Not currently in inlined code" comments below.
110 // Currently, we do not record code origins for code that is not inlined, because
111 // the only thing that we use code origins for is determining the inline stack.
112 // But in the future, we'll want to use this same functionality (having a code
113 // origin mapping for any calls out of JIT code) to determine the PC at any point
114 // in the stack even if not in inlined code. When that happens, the code below
115 // will have to change the way it detects the presence of inlining: it will always
116 // get a code origin, but sometimes, that code origin will not have an inline call
117 // frame. In that case, this method should bail and return this.
118 CodeOrigin codeOrigin
;
120 ReturnAddressPtr currentReturnPC
= pc
.jitReturnAddress();
122 bool hasCodeOrigin
= machineCodeBlock
->codeOriginForReturn(currentReturnPC
, codeOrigin
);
123 ASSERT_UNUSED(hasCodeOrigin
, hasCodeOrigin
);
125 unsigned index
= codeOriginIndexForDFG();
126 codeOrigin
= machineCodeBlock
->codeOrigin(index
);
129 if (!codeOrigin
.inlineCallFrame
)
130 return this; // Not currently in inlined code.
132 for (InlineCallFrame
* inlineCallFrame
= codeOrigin
.inlineCallFrame
; inlineCallFrame
;) {
133 InlineCallFrame
* nextInlineCallFrame
= inlineCallFrame
->caller
.inlineCallFrame
;
135 CallFrame
* inlinedCaller
= this + inlineCallFrame
->stackOffset
;
137 JSFunction
* calleeAsFunction
= inlineCallFrame
->callee
.get();
139 // Fill in the inlinedCaller
140 inlinedCaller
->setCodeBlock(machineCodeBlock
);
142 inlinedCaller
->setScopeChain(calleeAsFunction
->scope());
143 if (nextInlineCallFrame
)
144 inlinedCaller
->setCallerFrame(this + nextInlineCallFrame
->stackOffset
);
146 inlinedCaller
->setCallerFrame(this);
148 inlinedCaller
->setInlineCallFrame(inlineCallFrame
);
149 inlinedCaller
->setArgumentCountIncludingThis(inlineCallFrame
->arguments
.size());
150 inlinedCaller
->setCallee(calleeAsFunction
);
152 inlineCallFrame
= nextInlineCallFrame
;
155 return this + codeOrigin
.inlineCallFrame
->stackOffset
;
158 CallFrame
* CallFrame::trueCallerFrame()
160 // this -> The callee; this is either an inlined callee in which case it already has
161 // a pointer to the true caller. Otherwise it contains current PC in the machine
164 // machineCaller -> The caller according to the machine, which may be zero or
165 // more frames above the true caller due to inlining.
167 // Am I an inline call frame? If so, we're done.
168 if (isInlineCallFrame())
169 return callerFrame()->removeHostCallFrameFlag();
171 // I am a machine call frame, so the question is: is my caller a machine call frame
172 // that has inlines or a machine call frame that doesn't?
173 CallFrame
* machineCaller
= callerFrame()->removeHostCallFrameFlag();
176 ASSERT(!machineCaller
->isInlineCallFrame());
178 // Figure out how we want to get the current code location.
179 if (!hasReturnPC() || returnAddressIsInCtiTrampoline(returnPC()))
180 return machineCaller
->trueCallFrameFromVMCode()->removeHostCallFrameFlag();
182 return machineCaller
->trueCallFrame(returnPC())->removeHostCallFrameFlag();
186 Register
* CallFrame::frameExtentInternal()
188 CodeBlock
* codeBlock
= this->codeBlock();
190 return registers() + codeBlock
->m_numCalleeRegisters
;