blob: e854fadd11423ea79ed7d229d3114df68a0066b1 [file] [log] [blame]
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001/*
fpizlo@apple.com39303e02016-04-05 22:17:35 +00002 * Copyright (C) 2008, 2013-2014, 2016 Apple Inc. All rights reserved.
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +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 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
mjs@apple.com92047332014-03-15 04:08:27 +000013 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000014 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30#include "DebuggerCallFrame.h"
31
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000032#include "CodeBlock.h"
commit-queue@webkit.org31d2ef02014-09-05 21:08:14 +000033#include "DebuggerEvalEnabler.h"
mark.lam@apple.com268dda72014-08-29 00:48:59 +000034#include "DebuggerScope.h"
ggaren@apple.com901a8a22008-11-17 20:57:18 +000035#include "Interpreter.h"
joepeck@webkit.org70d6a302016-05-10 19:16:19 +000036#include "JSCInlines.h"
mark.lam@apple.com65a636f2014-02-01 01:24:39 +000037#include "JSFunction.h"
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +000038#include "JSLexicalEnvironment.h"
joepeck@webkit.org70d6a302016-05-10 19:16:19 +000039#include "JSWithScope.h"
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000040#include "Parser.h"
sbarati@apple.comce5b05e2016-05-16 23:31:39 +000041#include "ShadowChickenInlines.h"
mark.lam@apple.come72693d2013-09-24 23:52:57 +000042#include "StackVisitor.h"
mark.lam@apple.com268dda72014-08-29 00:48:59 +000043#include "StrongInlines.h"
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000044
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000045namespace JSC {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000046
mark.lam@apple.come72693d2013-09-24 23:52:57 +000047class LineAndColumnFunctor {
48public:
fpizlo@apple.com39303e02016-04-05 22:17:35 +000049 StackVisitor::Status operator()(StackVisitor& visitor) const
mark.lam@apple.come72693d2013-09-24 23:52:57 +000050 {
51 visitor->computeLineAndColumn(m_line, m_column);
52 return StackVisitor::Done;
53 }
54
55 unsigned line() const { return m_line; }
56 unsigned column() const { return m_column; }
57
58private:
fpizlo@apple.com39303e02016-04-05 22:17:35 +000059 mutable unsigned m_line;
60 mutable unsigned m_column;
mark.lam@apple.come72693d2013-09-24 23:52:57 +000061};
62
sbarati@apple.comce5b05e2016-05-16 23:31:39 +000063Ref<DebuggerCallFrame> DebuggerCallFrame::create(CallFrame* callFrame)
mark.lam@apple.come72693d2013-09-24 23:52:57 +000064{
sbarati@apple.comce5b05e2016-05-16 23:31:39 +000065 Vector<ShadowChicken::Frame> frames;
66 callFrame->vm().shadowChicken().iterate(callFrame->vm(), callFrame, [&] (const ShadowChicken::Frame& frame) -> bool {
67 frames.append(frame);
68 return true;
69 });
70
71 RELEASE_ASSERT(frames.size());
sbarati@apple.comed3e9f52016-05-27 20:26:06 +000072 ASSERT(!frames[0].isTailDeleted); // The top frame should never be tail deleted.
sbarati@apple.comce5b05e2016-05-16 23:31:39 +000073
74 RefPtr<DebuggerCallFrame> currentParent = nullptr;
sbarati@apple.comed3e9f52016-05-27 20:26:06 +000075 ExecState* exec = callFrame->lexicalGlobalObject()->globalExec();
76 // This walks the stack from the entry stack frame to the top of the stack.
sbarati@apple.comce5b05e2016-05-16 23:31:39 +000077 for (unsigned i = frames.size(); i--; ) {
78 const ShadowChicken::Frame& frame = frames[i];
79 if (!frame.isTailDeleted)
80 exec = frame.frame;
sbarati@apple.comce5b05e2016-05-16 23:31:39 +000081 Ref<DebuggerCallFrame> currentFrame = adoptRef(*new DebuggerCallFrame(exec, frame));
82 currentFrame->m_caller = currentParent;
83 currentParent = WTFMove(currentFrame);
84 }
85 return *currentParent;
86}
87
88DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame, const ShadowChicken::Frame& frame)
89 : m_validMachineFrame(callFrame)
90 , m_shadowChickenFrame(frame)
91{
92 m_position = currentPosition();
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +000093}
94
gyuyoung.kim@webkit.orgbe3842f2015-06-13 03:52:06 +000095RefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame()
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +000096{
97 ASSERT(isValid());
98 if (!isValid())
gyuyoung.kim@webkit.orgbe3842f2015-06-13 03:52:06 +000099 return nullptr;
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000100
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000101 return m_caller;
102}
103
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000104ExecState* DebuggerCallFrame::globalExec()
105{
106 return scope()->globalObject()->globalExec();
107}
108
mark.lam@apple.com30721252013-11-21 05:29:42 +0000109JSC::JSGlobalObject* DebuggerCallFrame::vmEntryGlobalObject() const
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000110{
111 ASSERT(isValid());
112 if (!isValid())
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000113 return nullptr;
114 return m_validMachineFrame->vmEntryGlobalObject();
mark.lam@apple.come72693d2013-09-24 23:52:57 +0000115}
116
mark.lam@apple.com26c53402013-11-08 20:03:50 +0000117SourceID DebuggerCallFrame::sourceID() const
mark.lam@apple.com649480f2013-09-12 16:27:55 +0000118{
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000119 ASSERT(isValid());
120 if (!isValid())
mark.lam@apple.com26c53402013-11-08 20:03:50 +0000121 return noSourceID;
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000122 if (isTailDeleted())
123 return m_shadowChickenFrame.codeBlock->ownerScriptExecutable()->sourceID();
124 return sourceIDForCallFrame(m_validMachineFrame);
mark.lam@apple.com649480f2013-09-12 16:27:55 +0000125}
126
ggaren@apple.com0030e132012-09-12 06:14:56 +0000127String DebuggerCallFrame::functionName() const
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000128{
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000129 ASSERT(isValid());
130 if (!isValid())
ggaren@apple.com0030e132012-09-12 06:14:56 +0000131 return String();
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000132
133 if (isTailDeleted()) {
134 if (JSFunction* func = jsDynamicCast<JSFunction*>(m_shadowChickenFrame.callee))
135 return func->calculatedDisplayName(m_validMachineFrame);
136 return m_shadowChickenFrame.codeBlock->inferredName().data();
137 }
138
139 return m_validMachineFrame->friendlyFunctionName();
aroben@apple.com261f1ff2009-05-15 18:13:28 +0000140}
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000141
mark.lam@apple.com268dda72014-08-29 00:48:59 +0000142DebuggerScope* DebuggerCallFrame::scope()
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000143{
144 ASSERT(isValid());
145 if (!isValid())
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000146 return nullptr;
mark.lam@apple.com65a636f2014-02-01 01:24:39 +0000147
mark.lam@apple.com268dda72014-08-29 00:48:59 +0000148 if (!m_scope) {
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000149 VM& vm = m_validMachineFrame->vm();
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +0000150 JSScope* scope;
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000151 CodeBlock* codeBlock = m_validMachineFrame->codeBlock();
152 if (isTailDeleted())
153 scope = m_shadowChickenFrame.scope;
154 else if (codeBlock && codeBlock->scopeRegister().isValid())
155 scope = m_validMachineFrame->scope(codeBlock->scopeRegister().offset());
156 else if (JSCallee* callee = jsDynamicCast<JSCallee*>(m_validMachineFrame->callee()))
msaboff@apple.com95c43152015-02-26 06:05:02 +0000157 scope = callee->scope();
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +0000158 else
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000159 scope = m_validMachineFrame->lexicalGlobalObject()->globalLexicalEnvironment();
mark.lam@apple.com8fe56b82014-08-09 06:50:19 +0000160
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +0000161 m_scope.set(vm, DebuggerScope::create(vm, scope));
mark.lam@apple.com268dda72014-08-29 00:48:59 +0000162 }
163 return m_scope.get();
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000164}
165
timothy@apple.comc14b52c2008-06-17 22:33:07 +0000166DebuggerCallFrame::Type DebuggerCallFrame::type() const
167{
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000168 ASSERT(isValid());
169 if (!isValid())
170 return ProgramType;
171
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000172 if (isTailDeleted())
173 return FunctionType;
174
175 if (jsDynamicCast<JSFunction*>(m_validMachineFrame->callee()))
timothy@apple.comc14b52c2008-06-17 22:33:07 +0000176 return FunctionType;
177
178 return ProgramType;
179}
180
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000181JSValue DebuggerCallFrame::thisValue() const
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000182{
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000183 ASSERT(isValid());
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000184 if (!isValid())
185 return jsUndefined();
186
187 CodeBlock* codeBlock = nullptr;
188 JSValue thisValue;
189 if (isTailDeleted()) {
190 thisValue = m_shadowChickenFrame.thisValue;
191 codeBlock = m_shadowChickenFrame.codeBlock;
192 } else {
193 thisValue = m_validMachineFrame->thisValue();
194 codeBlock = m_validMachineFrame->codeBlock();
195 }
196
197 if (!thisValue)
198 return jsUndefined();
199
200 ECMAMode ecmaMode = NotStrictMode;
201 if (codeBlock && codeBlock->isStrictMode())
202 ecmaMode = StrictMode;
203 return thisValue.toThis(m_validMachineFrame, ecmaMode);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000204}
205
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000206// Evaluate some JavaScript code in the scope of this frame.
joepeck@webkit.org70d6a302016-05-10 19:16:19 +0000207JSValue DebuggerCallFrame::evaluateWithScopeExtension(const String& script, JSObject* scopeExtensionObject, NakedPtr<Exception>& exception)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000208{
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000209 ASSERT(isValid());
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000210 CallFrame* callFrame = m_validMachineFrame;
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000211 if (!callFrame)
joepeck@webkit.org70d6a302016-05-10 19:16:19 +0000212 return jsUndefined();
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000213
214 JSLockHolder lock(callFrame);
215
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000216 CodeBlock* codeBlock = nullptr;
217 if (isTailDeleted())
218 codeBlock = m_shadowChickenFrame.codeBlock;
219 else
220 codeBlock = callFrame->codeBlock();
221 if (!codeBlock)
joepeck@webkit.org70d6a302016-05-10 19:16:19 +0000222 return jsUndefined();
oliver@apple.comba10bec2011-03-08 23:17:32 +0000223
commit-queue@webkit.org31d2ef02014-09-05 21:08:14 +0000224 DebuggerEvalEnabler evalEnabler(callFrame);
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000225 VM& vm = callFrame->vm();
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000226
gskachkov@gmail.coma3f0cdf2016-04-03 07:59:19 +0000227 EvalContextType evalContextType;
228
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000229 if (isFunctionParseMode(codeBlock->unlinkedCodeBlock()->parseMode()))
gskachkov@gmail.coma3f0cdf2016-04-03 07:59:19 +0000230 evalContextType = EvalContextType::FunctionEvalContext;
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000231 else if (codeBlock->unlinkedCodeBlock()->codeType() == EvalCode)
232 evalContextType = codeBlock->unlinkedCodeBlock()->evalContextType();
gskachkov@gmail.coma3f0cdf2016-04-03 07:59:19 +0000233 else
234 evalContextType = EvalContextType::None;
235
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000236 VariableEnvironment variablesUnderTDZ;
237 JSScope::collectVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ);
238
utatane.tea@gmail.comc2029072016-05-24 12:04:35 +0000239 EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock->isStrictMode(), codeBlock->unlinkedCodeBlock()->derivedContextType(), codeBlock->unlinkedCodeBlock()->isArrowFunction(), evalContextType, &variablesUnderTDZ);
commit-queue@webkit.org3f922f92013-08-29 00:28:42 +0000240 if (vm.exception()) {
241 exception = vm.exception();
242 vm.clearException();
mark.lam@apple.com8f98b6b2014-01-25 03:15:13 +0000243 return jsUndefined();
oliver@apple.comba10bec2011-03-08 23:17:32 +0000244 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000245
joepeck@webkit.org70d6a302016-05-10 19:16:19 +0000246 JSGlobalObject* globalObject = callFrame->vmEntryGlobalObject();
247 if (scopeExtensionObject) {
248 JSScope* ignoredPreviousScope = globalObject->globalScope();
249 globalObject->setGlobalScopeExtension(JSWithScope::create(vm, globalObject, scopeExtensionObject, ignoredPreviousScope));
250 }
251
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000252 JSValue thisValue = this->thisValue();
mark.lam@apple.com268dda72014-08-29 00:48:59 +0000253 JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope());
commit-queue@webkit.org3f922f92013-08-29 00:28:42 +0000254 if (vm.exception()) {
255 exception = vm.exception();
256 vm.clearException();
barraclough@apple.com2607dd02010-10-27 20:46:09 +0000257 }
joepeck@webkit.org70d6a302016-05-10 19:16:19 +0000258
259 if (scopeExtensionObject)
260 globalObject->clearGlobalScopeExtension();
261
barraclough@apple.com2607dd02010-10-27 20:46:09 +0000262 ASSERT(result);
263 return result;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000264}
265
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000266void DebuggerCallFrame::invalidate()
mark.lam@apple.com649480f2013-09-12 16:27:55 +0000267{
mark.lam@apple.com51d13152014-09-23 22:29:35 +0000268 RefPtr<DebuggerCallFrame> frame = this;
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000269 while (frame) {
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000270 frame->m_validMachineFrame = nullptr;
mark.lam@apple.com51d13152014-09-23 22:29:35 +0000271 if (frame->m_scope) {
272 frame->m_scope->invalidateChain();
273 frame->m_scope.clear();
274 }
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000275 frame = frame->m_caller.release();
276 }
277}
278
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000279TextPosition DebuggerCallFrame::currentPosition()
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000280{
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000281 if (!m_validMachineFrame)
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000282 return TextPosition();
283
sbarati@apple.comce5b05e2016-05-16 23:31:39 +0000284 if (isTailDeleted()) {
285 CodeBlock* codeBlock = m_shadowChickenFrame.codeBlock;
286 if (Optional<unsigned> bytecodeOffset = codeBlock->bytecodeOffsetFromCallSiteIndex(m_shadowChickenFrame.callSiteIndex)) {
287 return TextPosition(OrdinalNumber::fromOneBasedInt(codeBlock->lineNumberForBytecodeOffset(*bytecodeOffset)),
288 OrdinalNumber::fromOneBasedInt(codeBlock->columnNumberForBytecodeOffset(*bytecodeOffset)));
289 }
290 }
291
292 return positionForCallFrame(m_validMachineFrame);
293}
294
295TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame)
296{
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000297 LineAndColumnFunctor functor;
298 callFrame->iterate(functor);
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000299 return TextPosition(OrdinalNumber::fromOneBasedInt(functor.line()), OrdinalNumber::fromOneBasedInt(functor.column()));
300}
301
mark.lam@apple.com26c53402013-11-08 20:03:50 +0000302SourceID DebuggerCallFrame::sourceIDForCallFrame(CallFrame* callFrame)
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000303{
304 ASSERT(callFrame);
305 CodeBlock* codeBlock = callFrame->codeBlock();
306 if (!codeBlock)
mark.lam@apple.com26c53402013-11-08 20:03:50 +0000307 return noSourceID;
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000308 return codeBlock->ownerScriptExecutable()->sourceID();
mark.lam@apple.comaf032dd2013-10-05 00:51:31 +0000309}
310
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000311} // namespace JSC