<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[200981] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/200981">200981</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-05-16 16:31:39 -0700 (Mon, 16 May 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Hook up ShadowChicken to the debugger to show tail deleted frames
https://bugs.webkit.org/show_bug.cgi?id=156685
&lt;rdar://problem/25770521&gt;

Reviewed by Filip Pizlo and Mark Lam and Joseph Pecoraro.

Source/JavaScriptCore:

The heart of this patch hooks up ShadowChicken to DebuggerCallFrame to
allow the Web Inspector to display the ShadowChicken's shadow stack.
This means the Web Inspector can now display tail deleted frames.
To make this work, I made the necessary changes to ShadowChicken and
DebuggerCallFrame to allow DebuggerCallFrame to keep the same API
when representing both machine frames and tail deleted frames.

- ShadowChicken prologue packets now log the current scope. Tail packets
  log the current scope, the 'this' value, the CodeBlock, and the
  CallSiteIndex. This allows the inspector to not only show the
  tail deleted frame, but also show exactly where the tail call happened (line and column numbers),
  with which scope it executed, and with which 'this' value. This
  patch also allows DebuggerCallFrame to execute console statements
  in a tail deleted frame.

- I changed ShadowChicken's stack resizing algorithm. ShadowChicken
  now only keeps a maximum number of tail deleted frames in its shadow stack.
  It will happily represent all machine frames without limit. Right now, the
  maximum number of tail deleted frames I chose to keep alive is 128.
  We will keep frames alive starting from the top of the stack. This
  allows us to have a strong defense against runaway memory usage. We will only
  keep around at most 128 &quot;shadow&quot; frames that wouldn't have naturally been kept
  alive by the executing program. We can play around with this number
  if we find that 128 is either too many or too few frames.

- DebuggerCallFrame is no longer a cheap class to create. When it is created,
  we will eagerly create the entire virtual debugger stack. So I modified the
  existing code to lazily create DebuggerCallFrames only when necessary. We
  used to eagerly create them at each op_debug statement even though we would
  just throw them away if we didn't hit a breakpoint.

- A valid DebuggerCallFrame will always have a valid CallFrame* pointer
  into the stack. This pointer won't always refer to the logical frame
  that the DebuggerCallFrame represents because a DebuggerCallFrame can
  now represent a tail deleted frame. To do this, DebuggerCallFrame now
  has a ShadowChicken::Frame member variable. This allows DebuggerCallFrame
  to know when it represents a tail deleted frame and gives DebuggerCallFrame
  a mechanism to ask the tail deleted frame for interesting information
  (like its 'this' value, scope, CodeBlock, etc). A tail deleted frame's
  machine frame pointer will be the machine caller of the tail deleted frame
  (or the machine caller of the first of a series of consecutive tail calls).

- I added a new flag to UnlinkedCodeBlock to indicate when it is compiled
  with debugging opcodes. I did this because ShadowChicken may read a JSScope
  from the machine stack. This is only safe if the machine CodeBlock was
  compiled with debugging opcodes. This is safer than asking if the
  CodeBlock's global object has an interactive debugger enabled because
  it's theoretically possible for the debugger to be enabled while code
  compiled without a debugger is still live on the stack. This field is
  also now used to indicate to the DFGGraph that the interactive debugger
  is enabled.

- Finally, this patch adds a new field to the Inspector's CallFrame protocol
  object called 'isTailDeleted' to allow the Inspector to know when a
  CallFrame represents a tail deleted frame.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::findPC):
(JSC::CodeBlock::bytecodeOffsetFromCallSiteIndex):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::clearDebuggerRequests):
(JSC::CodeBlock::wasCompiledWithDebuggingOpcodes):
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::wasCompiledWithDebuggingOpcodes):
(JSC::UnlinkedCodeBlock::finishCreation):
(JSC::UnlinkedGlobalCodeBlock::UnlinkedGlobalCodeBlock):
* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::generateUnlinkedFunctionCodeBlock):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitEnter):
(JSC::BytecodeGenerator::emitLogShadowChickenPrologueIfNecessary):
(JSC::BytecodeGenerator::emitLogShadowChickenTailIfNecessary):
(JSC::BytecodeGenerator::emitCallDefineProperty):
* debugger/Debugger.cpp:
(JSC::DebuggerPausedScope::DebuggerPausedScope):
(JSC::DebuggerPausedScope::~DebuggerPausedScope):
(JSC::Debugger::didReachBreakpoint):
(JSC::Debugger::currentDebuggerCallFrame):
* debugger/Debugger.h:
* debugger/DebuggerCallFrame.cpp:
(JSC::LineAndColumnFunctor::operator()):
(JSC::DebuggerCallFrame::create):
(JSC::DebuggerCallFrame::DebuggerCallFrame):
(JSC::DebuggerCallFrame::callerFrame):
(JSC::DebuggerCallFrame::globalExec):
(JSC::DebuggerCallFrame::vmEntryGlobalObject):
(JSC::DebuggerCallFrame::sourceID):
(JSC::DebuggerCallFrame::functionName):
(JSC::DebuggerCallFrame::scope):
(JSC::DebuggerCallFrame::type):
(JSC::DebuggerCallFrame::thisValue):
(JSC::DebuggerCallFrame::evaluateWithScopeExtension):
(JSC::DebuggerCallFrame::invalidate):
(JSC::DebuggerCallFrame::currentPosition):
(JSC::DebuggerCallFrame::positionForCallFrame):
(JSC::DebuggerCallFrame::sourceIDForCallFrame):
(JSC::FindCallerMidStackFunctor::FindCallerMidStackFunctor): Deleted.
(JSC::FindCallerMidStackFunctor::operator()): Deleted.
(JSC::FindCallerMidStackFunctor::getCallerFrame): Deleted.
(JSC::DebuggerCallFrame::thisValueForCallFrame): Deleted.
* debugger/DebuggerCallFrame.h:
(JSC::DebuggerCallFrame::isValid):
(JSC::DebuggerCallFrame::isTailDeleted):
(JSC::DebuggerCallFrame::create): Deleted.
(JSC::DebuggerCallFrame::exec): Deleted.
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
(JSC::DFG::Graph::~Graph):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::addCallSite):
(JSC::DFG::JITCompiler::emitStoreCodeOrigin):
(JSC::DFG::JITCompiler::emitStoreCallSiteIndex):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileLogShadowChickenPrologue):
(JSC::FTL::DFG::LowerDFGToB3::compileLogShadowChickenTail):
(JSC::FTL::DFG::LowerDFGToB3::compileRecordRegExpCachedResult):
(JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
(JSC::FTL::DFG::LowerDFGToB3::ensureShadowChickenPacket):
(JSC::FTL::DFG::LowerDFGToB3::setupShadowChickenPacket): Deleted.
* inspector/InjectedScriptSource.js:
(InjectedScript.CallFrameProxy):
* inspector/JSJavaScriptCallFrame.cpp:
(Inspector::JSJavaScriptCallFrame::thisObject):
(Inspector::JSJavaScriptCallFrame::isTailDeleted):
(Inspector::JSJavaScriptCallFrame::type):
* inspector/JSJavaScriptCallFrame.h:
* inspector/JSJavaScriptCallFramePrototype.cpp:
(Inspector::JSJavaScriptCallFramePrototype::finishCreation):
(Inspector::jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension):
(Inspector::jsJavaScriptCallFrameAttributeType):
(Inspector::jsJavaScriptCallFrameIsTailDeleted):
* inspector/JavaScriptCallFrame.h:
(Inspector::JavaScriptCallFrame::type):
(Inspector::JavaScriptCallFrame::scopeChain):
(Inspector::JavaScriptCallFrame::vmEntryGlobalObject):
(Inspector::JavaScriptCallFrame::isTailDeleted):
(Inspector::JavaScriptCallFrame::thisValue):
(Inspector::JavaScriptCallFrame::evaluateWithScopeExtension):
* inspector/ScriptDebugServer.cpp:
(Inspector::ScriptDebugServer::evaluateBreakpointAction):
* inspector/protocol/Debugger.json:
* interpreter/ShadowChicken.cpp:
(JSC::ShadowChicken::update):
(JSC::ShadowChicken::visitChildren):
(JSC::ShadowChicken::reset):
* interpreter/ShadowChicken.h:
(JSC::ShadowChicken::Packet::throwMarker):
(JSC::ShadowChicken::Packet::prologue):
(JSC::ShadowChicken::Packet::tail):
(JSC::ShadowChicken::Frame::Frame):
(JSC::ShadowChicken::Frame::operator==):
* jit/CCallHelpers.cpp:
(JSC::CCallHelpers::logShadowChickenProloguePacket):
(JSC::CCallHelpers::logShadowChickenTailPacket):
(JSC::CCallHelpers::ensureShadowChickenPacket):
(JSC::CCallHelpers::setupShadowChickenPacket): Deleted.
* jit/CCallHelpers.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_profile_type):
(JSC::JIT::emit_op_log_shadow_chicken_prologue):
(JSC::JIT::emit_op_log_shadow_chicken_tail):
(JSC::JIT::emit_op_get_enumerable_length):
(JSC::JIT::emit_op_resume):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_profile_type):
(JSC::JIT::emit_op_log_shadow_chicken_prologue):
(JSC::JIT::emit_op_log_shadow_chicken_tail):
* jit/RegisterSet.cpp:
(JSC::RegisterSet::webAssemblyCalleeSaveRegisters):
(JSC::RegisterSet::argumentGPRS):
(JSC::RegisterSet::registersToNotSaveForJSCall):
* jit/RegisterSet.h:
* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CodeCache.cpp:
(JSC::CodeCache::getGlobalCodeBlock):
* runtime/Options.h:
* tests/stress/shadow-chicken-enabled.js:
(test5a.foo):
(test5a):
(test5b.foo):
(test5b):
(test6.foo):
(test6):

Source/WebCore:

Tests: inspector/debugger/tail-deleted-frames-this-value.html
       inspector/debugger/tail-deleted-frames.html
       inspector/debugger/tail-recursion.html

* ForwardingHeaders/interpreter/ShadowChicken.h: Added.

Source/WebInspectorUI:

This patch makes the WebInspector display tail deleted frames.
We show tail deleted frames with a gray [f] instead of a green
[f]. We also put text in the tooltip to indicate that the frame
is tail deleted. Other than that, tail deleted frames behave like
normal frames. You can evaluate in them, inspect their scope, etc.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Images/TailDeletedFunction.svg: Added.
* UserInterface/Images/gtk/TailDeletedFunction.svg: Added.
* UserInterface/Models/CallFrame.js:
* UserInterface/Views/CallFrameIcons.css:
* UserInterface/Views/CallFrameTreeElement.js:
* UserInterface/Views/CallFrameView.js:

LayoutTests:

* inspector/debugger/resources/tail-deleted-frames-this-value.js: Added.
(a):
(b):
* inspector/debugger/resources/tail-deleted-frames.js: Added.
(a):
(b):
(c):
(startABC):
* inspector/debugger/resources/tail-recursion.js: Added.
(recurse):
(startRecurse):
* inspector/debugger/tail-deleted-frames-expected.txt: Added.
* inspector/debugger/tail-deleted-frames-this-value-expected.txt: Added.
* inspector/debugger/tail-deleted-frames-this-value.html: Added.
* inspector/debugger/tail-deleted-frames.html: Added.
* inspector/debugger/tail-recursion-expected.txt: Added.
* inspector/debugger/tail-recursion.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeListjson">trunk/Source/JavaScriptCore/bytecode/BytecodeList.json</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeUseDefh">trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedFunctionExecutablecpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggercpp">trunk/Source/JavaScriptCore/debugger/Debugger.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerh">trunk/Source/JavaScriptCore/debugger/Debugger.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerCallFramecpp">trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerCallFrameh">trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphcpp">trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilerh">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs">trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramecpp">trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFrameh">trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramePrototypecpp">trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorJavaScriptCallFrameh">trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorScriptDebugServercpp">trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson">trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterShadowChickencpp">trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterShadowChickenh">trunk/Source/JavaScriptCore/interpreter/ShadowChicken.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCCallHelperscpp">trunk/Source/JavaScriptCore/jit/CCallHelpers.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCCallHelpersh">trunk/Source/JavaScriptCore/jit/CCallHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodes32_64cpp">trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSetcpp">trunk/Source/JavaScriptCore/jit/RegisterSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSeth">trunk/Source/JavaScriptCore/jit/RegisterSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntDatacpp">trunk/Source/JavaScriptCore/llint/LLIntData.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCodeCachecpp">trunk/Source/JavaScriptCore/runtime/CodeCache.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressshadowchickenenabledjs">trunk/Source/JavaScriptCore/tests/stress/shadow-chicken-enabled.js</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsCallFramejs">trunk/Source/WebInspectorUI/UserInterface/Models/CallFrame.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsCallFrameIconscss">trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameIcons.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsCallFrameTreeElementjs">trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsCallFrameViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameView.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsinspectordebuggerresourcestaildeletedframesthisvaluejs">trunk/LayoutTests/inspector/debugger/resources/tail-deleted-frames-this-value.js</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggerresourcestaildeletedframesjs">trunk/LayoutTests/inspector/debugger/resources/tail-deleted-frames.js</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggerresourcestailrecursionjs">trunk/LayoutTests/inspector/debugger/resources/tail-recursion.js</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggertaildeletedframesexpectedtxt">trunk/LayoutTests/inspector/debugger/tail-deleted-frames-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggertaildeletedframesthisvalueexpectedtxt">trunk/LayoutTests/inspector/debugger/tail-deleted-frames-this-value-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggertaildeletedframesthisvaluehtml">trunk/LayoutTests/inspector/debugger/tail-deleted-frames-this-value.html</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggertaildeletedframeshtml">trunk/LayoutTests/inspector/debugger/tail-deleted-frames.html</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggertailrecursionexpectedtxt">trunk/LayoutTests/inspector/debugger/tail-recursion-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggertailrecursionhtml">trunk/LayoutTests/inspector/debugger/tail-recursion.html</a></li>
<li><a href="#trunkSourceWebCoreForwardingHeadersinterpreterShadowChickenh">trunk/Source/WebCore/ForwardingHeaders/interpreter/ShadowChicken.h</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceImagesTailDeletedFunctionsvg">trunk/Source/WebInspectorUI/UserInterface/Images/TailDeletedFunction.svg</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceImagesgtkTailDeletedFunctionsvg">trunk/Source/WebInspectorUI/UserInterface/Images/gtk/TailDeletedFunction.svg</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/LayoutTests/ChangeLog        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1,3 +1,29 @@
</span><ins>+2016-05-16  Saam barati  &lt;sbarati@apple.com&gt;
+
+        Hook up ShadowChicken to the debugger to show tail deleted frames
+        https://bugs.webkit.org/show_bug.cgi?id=156685
+        &lt;rdar://problem/25770521&gt;
+
+        Reviewed by Filip Pizlo and Mark Lam and Joseph Pecoraro.
+
+        * inspector/debugger/resources/tail-deleted-frames-this-value.js: Added.
+        (a):
+        (b):
+        * inspector/debugger/resources/tail-deleted-frames.js: Added.
+        (a):
+        (b):
+        (c):
+        (startABC):
+        * inspector/debugger/resources/tail-recursion.js: Added.
+        (recurse):
+        (startRecurse):
+        * inspector/debugger/tail-deleted-frames-expected.txt: Added.
+        * inspector/debugger/tail-deleted-frames-this-value-expected.txt: Added.
+        * inspector/debugger/tail-deleted-frames-this-value.html: Added.
+        * inspector/debugger/tail-deleted-frames.html: Added.
+        * inspector/debugger/tail-recursion-expected.txt: Added.
+        * inspector/debugger/tail-recursion.html: Added.
+
</ins><span class="cx"> 2016-05-16  Aaron Chu  &lt;aaron_chu@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION (r200441): Yahoo sports, finance and news pages automatically scroll
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggerresourcestaildeletedframesthisvaluejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/resources/tail-deleted-frames-this-value.js (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/resources/tail-deleted-frames-this-value.js                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/resources/tail-deleted-frames-this-value.js        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+&quot;use strict&quot;;
+function a() {
+    let x = 20;
+    x;
+    return x;
+}
+function b() {
+    let y = 40;
+    return a.call({aThis: 2});
+}
+function c() {
+    let z = 60;
+    return b.call({bThis: 1}); 
+}
+function startABC() {
+    c.call({cThis: 0});
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggerresourcestaildeletedframesjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/resources/tail-deleted-frames.js (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/resources/tail-deleted-frames.js                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/resources/tail-deleted-frames.js        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+&quot;use strict&quot;;
+function a() {
+    let x = 20;
+    x;
+    return x;
+}
+function b() {
+    let y = 40;
+    return a();
+}
+function c() {
+    let z = 60;
+    return b(); 
+}
+function startABC() {
+    c();
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggerresourcestailrecursionjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/resources/tail-recursion.js (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/resources/tail-recursion.js                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/resources/tail-recursion.js        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+&quot;use strict&quot;;
+function recurse(i) {
+    if (i &lt;= 0) {
+        i++;
+        i++;
+        return;
+    }
+
+    return recurse(i - 1);
+}
+
+function startRecurse() {
+    recurse(1000);
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggertaildeletedframesexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/tail-deleted-frames-expected.txt (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/tail-deleted-frames-expected.txt                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/tail-deleted-frames-expected.txt        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+Testing that we keep around tail deleted frames in the inspector.
+
+Starting Test
+
+
+------------------------------------
+Hit breakpoint at line: 3, column: 4
+------------------------------------
+Expected frame: {&quot;functionName&quot;:&quot;a&quot;,&quot;scope&quot;:[&quot;x&quot;,20],&quot;isTailDeleted&quot;:false}
+Expected frame: {&quot;functionName&quot;:&quot;b&quot;,&quot;scope&quot;:[&quot;y&quot;,40],&quot;isTailDeleted&quot;:true}
+Expected frame: {&quot;functionName&quot;:&quot;c&quot;,&quot;scope&quot;:[&quot;z&quot;,60],&quot;isTailDeleted&quot;:true}
+Looking at frame number: 0
+    variable 'x': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;20&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:20}
+Looking at frame number: 1
+    variable 'y': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;40&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:40}
+Looking at frame number: 2
+    variable 'z': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;60&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:60}
+Tests done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggertaildeletedframesthisvalueexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/tail-deleted-frames-this-value-expected.txt (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/tail-deleted-frames-this-value-expected.txt                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/tail-deleted-frames-this-value-expected.txt        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+Testing that we keep around tail deleted frames in the inspector and their this values.
+
+Starting Test
+
+
+------------------------------------
+Hit breakpoint at line: 3, column: 4
+------------------------------------
+Expected frame: {&quot;functionName&quot;:&quot;a&quot;,&quot;thisValue&quot;:[&quot;aThis&quot;,2],&quot;isTailDeleted&quot;:false}
+PASS: 'this' value should have expected property: aThis
+PASS: Call Frame 0 'this' value is correct.
+Expected frame: {&quot;functionName&quot;:&quot;b&quot;,&quot;thisValue&quot;:[&quot;bThis&quot;,1],&quot;isTailDeleted&quot;:true}
+PASS: 'this' value should have expected property: bThis
+PASS: Call Frame 1 'this' value is correct.
+Expected frame: {&quot;functionName&quot;:&quot;c&quot;,&quot;thisValue&quot;:[&quot;cThis&quot;,0],&quot;isTailDeleted&quot;:true}
+PASS: 'this' value should have expected property: cThis
+PASS: Call Frame 2 'this' value is correct.
+Tests done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggertaildeletedframesthisvaluehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/tail-deleted-frames-this-value.html (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/tail-deleted-frames-this-value.html                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/tail-deleted-frames-this-value.html        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,86 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;../../http/tests/inspector/debugger/debugger-test.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;./resources/tail-deleted-frames-this-value.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+
+function test()
+{
+    var scriptObject;
+
+    function startTest() {
+        InspectorTest.log(&quot;Starting Test&quot;);
+        // 0 based indices.
+        let testInfo = {line: 3, column: 4};
+        let location = scriptObject.createSourceCodeLocation(testInfo.line, testInfo.column);
+        let breakpoint = new WebInspector.Breakpoint(location);
+        WebInspector.debuggerManager.addBreakpoint(breakpoint);
+        InspectorTest.evaluateInPage(&quot;startABC()&quot;);
+    }
+
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, function(event) {
+        var activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
+
+        if (!activeCallFrame)
+            return;
+
+        var stopLocation = &quot;line: &quot; + activeCallFrame.sourceCodeLocation.lineNumber + &quot;, column: &quot; + activeCallFrame.sourceCodeLocation.columnNumber;
+
+        InspectorTest.log(&quot;\n\n------------------------------------&quot;);
+        InspectorTest.log(&quot;Hit breakpoint at &quot; + stopLocation);
+        InspectorTest.log(&quot;------------------------------------&quot;);
+
+        // top down list
+        let expectedFrames = [
+            {functionName: 'a', thisValue: ['aThis', 2], isTailDeleted: false},
+            {functionName: 'b', thisValue: ['bThis', 1], isTailDeleted: true},
+            {functionName: 'c', thisValue: ['cThis', 0], isTailDeleted: true}
+        ];
+
+        InspectorTest.assert(WebInspector.debuggerManager.callFrames.length &gt;= expectedFrames.length);
+
+        for (let i = 0; i &lt; expectedFrames.length; i++) {
+            let callFrame = WebInspector.debuggerManager.callFrames[i];
+            let expectedFrame = expectedFrames[i];
+            InspectorTest.log(&quot;Expected frame: &quot; + JSON.stringify(expectedFrame));
+            InspectorTest.assert(callFrame.functionName === expectedFrame.functionName);
+            InspectorTest.assert(callFrame.isTailDeleted === expectedFrame.isTailDeleted);
+
+            let thisObject = callFrame.thisObject;
+            let properties = thisObject.preview.propertyPreviews;
+            InspectorTest.assert(properties.length === 1);
+            let prop = properties[0];
+            InspectorTest.expectThat(expectedFrame.thisValue[0] === prop.name, `'this' value should have expected property: ${expectedFrame.thisValue[0]}`);
+            InspectorTest.assert('' + expectedFrame.thisValue[1] === prop.value, `'this' value object should have expected property value: ${expectedFrame.thisValue[1]}`);
+            InspectorTest.pass(`Call Frame ${i} 'this' value is correct.`);
+        }
+
+        WebInspector.debuggerManager.resume();
+    });
+
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Resumed, function(event) {
+        InspectorTest.log(&quot;Tests done&quot;);
+        InspectorTest.completeTest();
+    });
+
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptAdded, function(event) {
+        eventScriptObject = event.data.script;
+        
+        if (/tail-deleted-frames-this-value\.js$/.test(eventScriptObject.url)) {
+            scriptObject = eventScriptObject;
+            startTest();
+            return;
+        }
+
+    });
+
+    InspectorTest.reloadPage();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;p&gt;Testing that we keep around tail deleted frames in the inspector and their this values.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggertaildeletedframeshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/tail-deleted-frames.html (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/tail-deleted-frames.html                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/tail-deleted-frames.html        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;../../http/tests/inspector/debugger/debugger-test.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;./resources/tail-deleted-frames.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+
+function test()
+{
+    var scriptObject;
+
+    function startTest() {
+        InspectorTest.log(&quot;Starting Test&quot;);
+        // 0 based indices.
+        let testInfo = {line: 3, column: 4};
+        let location = scriptObject.createSourceCodeLocation(testInfo.line, testInfo.column);
+        let breakpoint = new WebInspector.Breakpoint(location);
+        WebInspector.debuggerManager.addBreakpoint(breakpoint);
+        InspectorTest.evaluateInPage(&quot;startABC()&quot;);
+    }
+
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, function(event) {
+        var activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
+
+        if (!activeCallFrame)
+            return;
+
+        var stopLocation = &quot;line: &quot; + activeCallFrame.sourceCodeLocation.lineNumber + &quot;, column: &quot; + activeCallFrame.sourceCodeLocation.columnNumber;
+
+        InspectorTest.log(&quot;\n\n------------------------------------&quot;);
+        InspectorTest.log(&quot;Hit breakpoint at &quot; + stopLocation);
+        InspectorTest.log(&quot;------------------------------------&quot;);
+
+        // top down list
+        let expectedFrames = [
+            {functionName: 'a', scope: ['x', 20], isTailDeleted: false},
+            {functionName: 'b', scope: ['y', 40], isTailDeleted: true},
+            {functionName: 'c', scope: ['z', 60], isTailDeleted: true}
+        ];
+
+        InspectorTest.assert(WebInspector.debuggerManager.callFrames.length &gt;= expectedFrames.length);
+
+        for (let i = 0; i &lt; expectedFrames.length; i++) {
+            let callFrame = WebInspector.debuggerManager.callFrames[i];
+            let expectedFrame = expectedFrames[i];
+            InspectorTest.log(&quot;Expected frame: &quot; + JSON.stringify(expectedFrame));
+            InspectorTest.assert(callFrame.functionName === expectedFrame.functionName);
+
+            InspectorTest.assert(callFrame.isTailDeleted === expectedFrame.isTailDeleted);
+            let topScope = callFrame.scopeChain[0];
+
+            topScope.objects[0].getAllPropertyDescriptors(function(properties) {
+                let found = false;
+                let variableName = expectedFrame.scope[0];
+                let variableValue = expectedFrame.scope[1];
+                for (let propertyDescriptor of properties) {
+                    if (propertyDescriptor.name === variableName) {
+                        found = true;
+                        InspectorTest.log(&quot;Looking at frame number: &quot; + i);
+                        InspectorTest.log(`    variable '${variableName}': ${JSON.stringify(propertyDescriptor.value)}`);
+                        InspectorTest.assert(propertyDescriptor.value.type === 'number');
+                        InspectorTest.assert(propertyDescriptor.value.value === variableValue);
+                    }
+                }
+                InspectorTest.assert(found);
+            });
+        }
+
+        WebInspector.debuggerManager.resume();
+    });
+
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Resumed, function(event) {
+        InspectorTest.log(&quot;Tests done&quot;);
+        InspectorTest.completeTest();
+    });
+
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptAdded, function(event) {
+        eventScriptObject = event.data.script;
+        
+        if (/tail-deleted-frames\.js$/.test(eventScriptObject.url)) {
+            scriptObject = eventScriptObject;
+            startTest();
+            return;
+        }
+
+    });
+
+    InspectorTest.reloadPage();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;p&gt;Testing that we keep around tail deleted frames in the inspector. &lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggertailrecursionexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/tail-recursion-expected.txt (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/tail-recursion-expected.txt                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/tail-recursion-expected.txt        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,219 @@
</span><ins>+Testing that we keep around tail deleted frames in the inspector.
+
+Starting Test
+
+
+------------------------------------
+Hit breakpoint at line: 3, column: 8
+numBreakpointHits: 1
+Going to look at the top 50 frames.
+------------------------------------
+Looking at frame number: 0
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;0&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:0}
+Looking at frame number: 1
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;1&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:1}
+Looking at frame number: 2
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;2&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:2}
+Looking at frame number: 3
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;3&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:3}
+Looking at frame number: 4
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;4&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:4}
+Looking at frame number: 5
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;5&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:5}
+Looking at frame number: 6
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;6&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:6}
+Looking at frame number: 7
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;7&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:7}
+Looking at frame number: 8
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;8&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:8}
+Looking at frame number: 9
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;9&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:9}
+Looking at frame number: 10
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;10&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:10}
+Looking at frame number: 11
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;11&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:11}
+Looking at frame number: 12
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;12&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:12}
+Looking at frame number: 13
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;13&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:13}
+Looking at frame number: 14
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;14&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:14}
+Looking at frame number: 15
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;15&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:15}
+Looking at frame number: 16
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;16&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:16}
+Looking at frame number: 17
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;17&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:17}
+Looking at frame number: 18
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;18&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:18}
+Looking at frame number: 19
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;19&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:19}
+Looking at frame number: 20
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;20&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:20}
+Looking at frame number: 21
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;21&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:21}
+Looking at frame number: 22
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;22&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:22}
+Looking at frame number: 23
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;23&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:23}
+Looking at frame number: 24
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;24&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:24}
+Looking at frame number: 25
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;25&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:25}
+Looking at frame number: 26
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;26&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:26}
+Looking at frame number: 27
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;27&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:27}
+Looking at frame number: 28
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;28&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:28}
+Looking at frame number: 29
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;29&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:29}
+Looking at frame number: 30
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;30&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:30}
+Looking at frame number: 31
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;31&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:31}
+Looking at frame number: 32
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;32&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:32}
+Looking at frame number: 33
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;33&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:33}
+Looking at frame number: 34
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;34&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:34}
+Looking at frame number: 35
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;35&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:35}
+Looking at frame number: 36
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;36&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:36}
+Looking at frame number: 37
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;37&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:37}
+Looking at frame number: 38
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;38&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:38}
+Looking at frame number: 39
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;39&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:39}
+Looking at frame number: 40
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;40&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:40}
+Looking at frame number: 41
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;41&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:41}
+Looking at frame number: 42
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;42&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:42}
+Looking at frame number: 43
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;43&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:43}
+Looking at frame number: 44
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;44&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:44}
+Looking at frame number: 45
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;45&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:45}
+Looking at frame number: 46
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;46&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:46}
+Looking at frame number: 47
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;47&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:47}
+Looking at frame number: 48
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;48&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:48}
+Looking at frame number: 49
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;49&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:49}
+
+
+------------------------------------
+Hit breakpoint at line: 4, column: 8
+numBreakpointHits: 2
+Going to look at the top 50 frames.
+------------------------------------
+Looking at frame number: 0
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;1&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:1}
+Looking at frame number: 1
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;1&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:1}
+Looking at frame number: 2
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;2&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:2}
+Looking at frame number: 3
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;3&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:3}
+Looking at frame number: 4
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;4&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:4}
+Looking at frame number: 5
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;5&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:5}
+Looking at frame number: 6
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;6&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:6}
+Looking at frame number: 7
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;7&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:7}
+Looking at frame number: 8
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;8&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:8}
+Looking at frame number: 9
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;9&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:9}
+Looking at frame number: 10
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;10&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:10}
+Looking at frame number: 11
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;11&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:11}
+Looking at frame number: 12
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;12&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:12}
+Looking at frame number: 13
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;13&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:13}
+Looking at frame number: 14
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;14&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:14}
+Looking at frame number: 15
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;15&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:15}
+Looking at frame number: 16
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;16&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:16}
+Looking at frame number: 17
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;17&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:17}
+Looking at frame number: 18
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;18&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:18}
+Looking at frame number: 19
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;19&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:19}
+Looking at frame number: 20
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;20&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:20}
+Looking at frame number: 21
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;21&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:21}
+Looking at frame number: 22
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;22&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:22}
+Looking at frame number: 23
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;23&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:23}
+Looking at frame number: 24
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;24&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:24}
+Looking at frame number: 25
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;25&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:25}
+Looking at frame number: 26
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;26&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:26}
+Looking at frame number: 27
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;27&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:27}
+Looking at frame number: 28
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;28&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:28}
+Looking at frame number: 29
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;29&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:29}
+Looking at frame number: 30
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;30&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:30}
+Looking at frame number: 31
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;31&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:31}
+Looking at frame number: 32
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;32&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:32}
+Looking at frame number: 33
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;33&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:33}
+Looking at frame number: 34
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;34&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:34}
+Looking at frame number: 35
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;35&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:35}
+Looking at frame number: 36
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;36&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:36}
+Looking at frame number: 37
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;37&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:37}
+Looking at frame number: 38
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;38&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:38}
+Looking at frame number: 39
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;39&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:39}
+Looking at frame number: 40
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;40&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:40}
+Looking at frame number: 41
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;41&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:41}
+Looking at frame number: 42
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;42&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:42}
+Looking at frame number: 43
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;43&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:43}
+Looking at frame number: 44
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;44&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:44}
+Looking at frame number: 45
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;45&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:45}
+Looking at frame number: 46
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;46&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:46}
+Looking at frame number: 47
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;47&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:47}
+Looking at frame number: 48
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;48&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:48}
+Looking at frame number: 49
+    variable 'i': {&quot;_type&quot;:&quot;number&quot;,&quot;_description&quot;:&quot;49&quot;,&quot;_hasChildren&quot;:false,&quot;_value&quot;:49}
+Tests done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggertailrecursionhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/debugger/tail-recursion.html (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/tail-recursion.html                                (rev 0)
+++ trunk/LayoutTests/inspector/debugger/tail-recursion.html        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,97 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;../../http/tests/inspector/debugger/debugger-test.js&quot;&gt;&lt;/script&gt;
+&lt;script type=&quot;text/javascript&quot; src=&quot;./resources/tail-recursion.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+
+function test()
+{
+    var scriptObject;
+
+    function startTest() {
+        InspectorTest.log(&quot;Starting Test&quot;);
+        // 0 based indices.
+        var testInfos = [{line : 3, column : 8}, {line : 4, column : 8}];
+        for (let testInfo of testInfos) {
+            let location = scriptObject.createSourceCodeLocation(testInfo.line, testInfo.column);
+            let breakpoint = new WebInspector.Breakpoint(location);
+            WebInspector.debuggerManager.addBreakpoint(breakpoint);
+        }
+        InspectorTest.evaluateInPage(&quot;startRecurse()&quot;);
+    }
+
+    let numBreakpointHits = 0;
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, function(event) {
+        var activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
+
+        if (!activeCallFrame)
+            return;
+
+        numBreakpointHits++;
+        var stopLocation = &quot;line: &quot; + activeCallFrame.sourceCodeLocation.lineNumber + &quot;, column: &quot; + activeCallFrame.sourceCodeLocation.columnNumber;
+
+        InspectorTest.log(&quot;\n\n------------------------------------&quot;);
+        InspectorTest.log(&quot;Hit breakpoint at &quot; + stopLocation);
+        InspectorTest.log(&quot;numBreakpointHits: &quot; + numBreakpointHits);
+        const numFramesToInspect = 50;
+        InspectorTest.log(&quot;Going to look at the top &quot; + numFramesToInspect + &quot; frames.&quot;);
+        InspectorTest.log(&quot;------------------------------------&quot;);
+
+        InspectorTest.assert(WebInspector.debuggerManager.callFrames.length &gt; numFramesToInspect); // We just look at top 50. This isn't a precise number. But it gets at the gist of the debugging experience.
+        for (let i = 0; i &lt; numFramesToInspect; i++) {
+            let callFrame = WebInspector.debuggerManager.callFrames[i];
+            InspectorTest.assert(callFrame.functionName === &quot;recurse&quot;);
+            let topScope = callFrame.scopeChain[0];
+
+            if (i &gt; 0)
+                InspectorTest.assert(callFrame.isTailDeleted);
+            else
+                InspectorTest.assert(!callFrame.isTailDeleted);
+
+            topScope.objects[0].getAllPropertyDescriptors(function(properties) {
+                let found = false;
+                for (let propertyDescriptor of properties) {
+                    if (propertyDescriptor.name === 'i') {
+                        found = true;
+                        InspectorTest.log(&quot;Looking at frame number: &quot; + i);
+                        InspectorTest.log(&quot;    variable 'i': &quot; + JSON.stringify(propertyDescriptor.value));
+                        InspectorTest.assert(propertyDescriptor.value.type === 'number');
+                        if (numBreakpointHits === 2 &amp;&amp; i === 0)
+                            InspectorTest.assert(propertyDescriptor.value.value === i + 1); // this tests the i++ inside tail-recurse.js
+                        else
+                            InspectorTest.assert(propertyDescriptor.value.value === i);
+                    }
+                }
+                InspectorTest.assert(found);
+            });
+        }
+
+        WebInspector.debuggerManager.resume();
+    });
+
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Resumed, function(event) {
+        InspectorTest.log(&quot;Tests done&quot;);
+        InspectorTest.completeTest();
+    });
+
+    WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptAdded, function(event) {
+        eventScriptObject = event.data.script;
+        
+        if (/tail-recursion\.js$/.test(eventScriptObject.url)) {
+            scriptObject = eventScriptObject;
+            startTest();
+            return;
+        }
+
+    });
+
+    InspectorTest.reloadPage();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;p&gt;Testing that we keep around tail deleted frames in the inspector. &lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1,5 +1,221 @@
</span><span class="cx"> 2016-05-16  Saam barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Hook up ShadowChicken to the debugger to show tail deleted frames
+        https://bugs.webkit.org/show_bug.cgi?id=156685
+        &lt;rdar://problem/25770521&gt;
+
+        Reviewed by Filip Pizlo and Mark Lam and Joseph Pecoraro.
+
+        The heart of this patch hooks up ShadowChicken to DebuggerCallFrame to
+        allow the Web Inspector to display the ShadowChicken's shadow stack.
+        This means the Web Inspector can now display tail deleted frames.
+        To make this work, I made the necessary changes to ShadowChicken and
+        DebuggerCallFrame to allow DebuggerCallFrame to keep the same API
+        when representing both machine frames and tail deleted frames.
+
+        - ShadowChicken prologue packets now log the current scope. Tail packets
+          log the current scope, the 'this' value, the CodeBlock, and the
+          CallSiteIndex. This allows the inspector to not only show the
+          tail deleted frame, but also show exactly where the tail call happened (line and column numbers),
+          with which scope it executed, and with which 'this' value. This
+          patch also allows DebuggerCallFrame to execute console statements
+          in a tail deleted frame.
+
+        - I changed ShadowChicken's stack resizing algorithm. ShadowChicken
+          now only keeps a maximum number of tail deleted frames in its shadow stack.
+          It will happily represent all machine frames without limit. Right now, the
+          maximum number of tail deleted frames I chose to keep alive is 128.
+          We will keep frames alive starting from the top of the stack. This
+          allows us to have a strong defense against runaway memory usage. We will only
+          keep around at most 128 &quot;shadow&quot; frames that wouldn't have naturally been kept
+          alive by the executing program. We can play around with this number
+          if we find that 128 is either too many or too few frames.
+
+        - DebuggerCallFrame is no longer a cheap class to create. When it is created,
+          we will eagerly create the entire virtual debugger stack. So I modified the
+          existing code to lazily create DebuggerCallFrames only when necessary. We
+          used to eagerly create them at each op_debug statement even though we would
+          just throw them away if we didn't hit a breakpoint.
+
+        - A valid DebuggerCallFrame will always have a valid CallFrame* pointer
+          into the stack. This pointer won't always refer to the logical frame
+          that the DebuggerCallFrame represents because a DebuggerCallFrame can
+          now represent a tail deleted frame. To do this, DebuggerCallFrame now
+          has a ShadowChicken::Frame member variable. This allows DebuggerCallFrame
+          to know when it represents a tail deleted frame and gives DebuggerCallFrame
+          a mechanism to ask the tail deleted frame for interesting information
+          (like its 'this' value, scope, CodeBlock, etc). A tail deleted frame's
+          machine frame pointer will be the machine caller of the tail deleted frame
+          (or the machine caller of the first of a series of consecutive tail calls).
+
+        - I added a new flag to UnlinkedCodeBlock to indicate when it is compiled
+          with debugging opcodes. I did this because ShadowChicken may read a JSScope
+          from the machine stack. This is only safe if the machine CodeBlock was
+          compiled with debugging opcodes. This is safer than asking if the
+          CodeBlock's global object has an interactive debugger enabled because
+          it's theoretically possible for the debugger to be enabled while code
+          compiled without a debugger is still live on the stack. This field is
+          also now used to indicate to the DFGGraph that the interactive debugger
+          is enabled.
+
+        - Finally, this patch adds a new field to the Inspector's CallFrame protocol
+          object called 'isTailDeleted' to allow the Inspector to know when a
+          CallFrame represents a tail deleted frame.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::findPC):
+        (JSC::CodeBlock::bytecodeOffsetFromCallSiteIndex):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::clearDebuggerRequests):
+        (JSC::CodeBlock::wasCompiledWithDebuggingOpcodes):
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::wasCompiledWithDebuggingOpcodes):
+        (JSC::UnlinkedCodeBlock::finishCreation):
+        (JSC::UnlinkedGlobalCodeBlock::UnlinkedGlobalCodeBlock):
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::generateUnlinkedFunctionCodeBlock):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::generate):
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitEnter):
+        (JSC::BytecodeGenerator::emitLogShadowChickenPrologueIfNecessary):
+        (JSC::BytecodeGenerator::emitLogShadowChickenTailIfNecessary):
+        (JSC::BytecodeGenerator::emitCallDefineProperty):
+        * debugger/Debugger.cpp:
+        (JSC::DebuggerPausedScope::DebuggerPausedScope):
+        (JSC::DebuggerPausedScope::~DebuggerPausedScope):
+        (JSC::Debugger::didReachBreakpoint):
+        (JSC::Debugger::currentDebuggerCallFrame):
+        * debugger/Debugger.h:
+        * debugger/DebuggerCallFrame.cpp:
+        (JSC::LineAndColumnFunctor::operator()):
+        (JSC::DebuggerCallFrame::create):
+        (JSC::DebuggerCallFrame::DebuggerCallFrame):
+        (JSC::DebuggerCallFrame::callerFrame):
+        (JSC::DebuggerCallFrame::globalExec):
+        (JSC::DebuggerCallFrame::vmEntryGlobalObject):
+        (JSC::DebuggerCallFrame::sourceID):
+        (JSC::DebuggerCallFrame::functionName):
+        (JSC::DebuggerCallFrame::scope):
+        (JSC::DebuggerCallFrame::type):
+        (JSC::DebuggerCallFrame::thisValue):
+        (JSC::DebuggerCallFrame::evaluateWithScopeExtension):
+        (JSC::DebuggerCallFrame::invalidate):
+        (JSC::DebuggerCallFrame::currentPosition):
+        (JSC::DebuggerCallFrame::positionForCallFrame):
+        (JSC::DebuggerCallFrame::sourceIDForCallFrame):
+        (JSC::FindCallerMidStackFunctor::FindCallerMidStackFunctor): Deleted.
+        (JSC::FindCallerMidStackFunctor::operator()): Deleted.
+        (JSC::FindCallerMidStackFunctor::getCallerFrame): Deleted.
+        (JSC::DebuggerCallFrame::thisValueForCallFrame): Deleted.
+        * debugger/DebuggerCallFrame.h:
+        (JSC::DebuggerCallFrame::isValid):
+        (JSC::DebuggerCallFrame::isTailDeleted):
+        (JSC::DebuggerCallFrame::create): Deleted.
+        (JSC::DebuggerCallFrame::exec): Deleted.
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::Graph):
+        (JSC::DFG::Graph::~Graph):
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::addCallSite):
+        (JSC::DFG::JITCompiler::emitStoreCodeOrigin):
+        (JSC::DFG::JITCompiler::emitStoreCallSiteIndex):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileLogShadowChickenPrologue):
+        (JSC::FTL::DFG::LowerDFGToB3::compileLogShadowChickenTail):
+        (JSC::FTL::DFG::LowerDFGToB3::compileRecordRegExpCachedResult):
+        (JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
+        (JSC::FTL::DFG::LowerDFGToB3::ensureShadowChickenPacket):
+        (JSC::FTL::DFG::LowerDFGToB3::setupShadowChickenPacket): Deleted.
+        * inspector/InjectedScriptSource.js:
+        (InjectedScript.CallFrameProxy):
+        * inspector/JSJavaScriptCallFrame.cpp:
+        (Inspector::JSJavaScriptCallFrame::thisObject):
+        (Inspector::JSJavaScriptCallFrame::isTailDeleted):
+        (Inspector::JSJavaScriptCallFrame::type):
+        * inspector/JSJavaScriptCallFrame.h:
+        * inspector/JSJavaScriptCallFramePrototype.cpp:
+        (Inspector::JSJavaScriptCallFramePrototype::finishCreation):
+        (Inspector::jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension):
+        (Inspector::jsJavaScriptCallFrameAttributeType):
+        (Inspector::jsJavaScriptCallFrameIsTailDeleted):
+        * inspector/JavaScriptCallFrame.h:
+        (Inspector::JavaScriptCallFrame::type):
+        (Inspector::JavaScriptCallFrame::scopeChain):
+        (Inspector::JavaScriptCallFrame::vmEntryGlobalObject):
+        (Inspector::JavaScriptCallFrame::isTailDeleted):
+        (Inspector::JavaScriptCallFrame::thisValue):
+        (Inspector::JavaScriptCallFrame::evaluateWithScopeExtension):
+        * inspector/ScriptDebugServer.cpp:
+        (Inspector::ScriptDebugServer::evaluateBreakpointAction):
+        * inspector/protocol/Debugger.json:
+        * interpreter/ShadowChicken.cpp:
+        (JSC::ShadowChicken::update):
+        (JSC::ShadowChicken::visitChildren):
+        (JSC::ShadowChicken::reset):
+        * interpreter/ShadowChicken.h:
+        (JSC::ShadowChicken::Packet::throwMarker):
+        (JSC::ShadowChicken::Packet::prologue):
+        (JSC::ShadowChicken::Packet::tail):
+        (JSC::ShadowChicken::Frame::Frame):
+        (JSC::ShadowChicken::Frame::operator==):
+        * jit/CCallHelpers.cpp:
+        (JSC::CCallHelpers::logShadowChickenProloguePacket):
+        (JSC::CCallHelpers::logShadowChickenTailPacket):
+        (JSC::CCallHelpers::ensureShadowChickenPacket):
+        (JSC::CCallHelpers::setupShadowChickenPacket): Deleted.
+        * jit/CCallHelpers.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_profile_type):
+        (JSC::JIT::emit_op_log_shadow_chicken_prologue):
+        (JSC::JIT::emit_op_log_shadow_chicken_tail):
+        (JSC::JIT::emit_op_get_enumerable_length):
+        (JSC::JIT::emit_op_resume):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_profile_type):
+        (JSC::JIT::emit_op_log_shadow_chicken_prologue):
+        (JSC::JIT::emit_op_log_shadow_chicken_tail):
+        * jit/RegisterSet.cpp:
+        (JSC::RegisterSet::webAssemblyCalleeSaveRegisters):
+        (JSC::RegisterSet::argumentGPRS):
+        (JSC::RegisterSet::registersToNotSaveForJSCall):
+        * jit/RegisterSet.h:
+        * llint/LLIntData.cpp:
+        (JSC::LLInt::Data::performAssertions):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::getGlobalCodeBlock):
+        * runtime/Options.h:
+        * tests/stress/shadow-chicken-enabled.js:
+        (test5a.foo):
+        (test5a):
+        (test5b.foo):
+        (test5b):
+        (test6.foo):
+        (test6):
+
+2016-05-16  Saam barati  &lt;sbarati@apple.com&gt;
+
</ins><span class="cx">         TypeSet/StructureShape have a flawed sense of JS prototype chains
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=157760
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1988,8 +1988,8 @@
</span><span class="cx">                 C4F4B6F61A05C984005CAB76 /* objc_generator_templates.py in Headers */ = {isa = PBXBuildFile; fileRef = C4F4B6D81A05C76F005CAB76 /* objc_generator_templates.py */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 DC00039319D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h in Headers */ = {isa = PBXBuildFile; fileRef = DC00039019D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h */; };
</span><span class="cx">                 DC17E8171C9C91D6008A6AB3 /* ShadowChicken.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC17E8131C9C7FD4008A6AB3 /* ShadowChicken.cpp */; };
</span><del>-                DC17E8181C9C91D9008A6AB3 /* ShadowChicken.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17E8141C9C7FD4008A6AB3 /* ShadowChicken.h */; };
-                DC17E8191C9C91DB008A6AB3 /* ShadowChickenInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17E8151C9C7FD4008A6AB3 /* ShadowChickenInlines.h */; };
</del><ins>+                DC17E8181C9C91D9008A6AB3 /* ShadowChicken.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17E8141C9C7FD4008A6AB3 /* ShadowChicken.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                DC17E8191C9C91DB008A6AB3 /* ShadowChickenInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = DC17E8151C9C7FD4008A6AB3 /* ShadowChickenInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 DC17E81A1C9C91E9008A6AB3 /* CCallHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC17E8161C9C802B008A6AB3 /* CCallHelpers.cpp */; };
</span><span class="cx">                 DC2143071CA32E55000A8869 /* ICStats.h in Headers */ = {isa = PBXBuildFile; fileRef = DC2143061CA32E52000A8869 /* ICStats.h */; };
</span><span class="cx">                 DC2143081CA32E58000A8869 /* ICStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC2143051CA32E52000A8869 /* ICStats.cpp */; };
</span><span class="lines">@@ -6972,6 +6972,8 @@
</span><span class="cx">                                 0F4570391BE44C910062A629 /* AirEliminateDeadCode.h in Headers */,
</span><span class="cx">                                 79B00CBD1C6AB07E0088C65D /* ProxyConstructor.h in Headers */,
</span><span class="cx">                                 990DA67F1C8E316A00295159 /* generate_objc_protocol_type_conversions_implementation.py in Headers */,
</span><ins>+                                DC17E8191C9C91DB008A6AB3 /* ShadowChickenInlines.h in Headers */,
+                                DC17E8181C9C91D9008A6AB3 /* ShadowChicken.h in Headers */,
</ins><span class="cx">                                 799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */,
</span><span class="cx">                                 79B00CBF1C6AB07E0088C65D /* ProxyObject.h in Headers */,
</span><span class="cx">                                 79160DBE1C8E3EC8008C085A /* ProxyRevoke.h in Headers */,
</span><span class="lines">@@ -7670,7 +7672,6 @@
</span><span class="cx">                                 BC18C41E0E16F5CD00B34460 /* JSContextRef.h in Headers */,
</span><span class="cx">                                 A5EA70EE19F5B5C40098F5EC /* JSContextRefInspectorSupport.h in Headers */,
</span><span class="cx">                                 A5D2E665195E174000A518E7 /* JSContextRefInternal.h in Headers */,
</span><del>-                                DC17E8191C9C91DB008A6AB3 /* ShadowChickenInlines.h in Headers */,
</del><span class="cx">                                 A5AB49DD1BEC8086007020FB /* PerGlobalObjectWrapperWorld.h in Headers */,
</span><span class="cx">                                 148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */,
</span><span class="cx">                                 A72028B81797601E0098028C /* JSCTestRunnerUtils.h in Headers */,
</span><span class="lines">@@ -8123,7 +8124,6 @@
</span><span class="cx">                                 A7CA3AE617DA41AE006538AF /* WeakMapPrototype.h in Headers */,
</span><span class="cx">                                 0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */,
</span><span class="cx">                                 14E84FA114EE1ACC00D6D5D4 /* WeakSet.h in Headers */,
</span><del>-                                DC17E8181C9C91D9008A6AB3 /* ShadowChicken.h in Headers */,
</del><span class="cx">                                 709FB86A1AE335C60039D069 /* WeakSetConstructor.h in Headers */,
</span><span class="cx">                                 14150133154BB13F005D8C98 /* WeakSetInlines.h in Headers */,
</span><span class="cx">                                 709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -143,8 +143,8 @@
</span><span class="cx">             { &quot;name&quot; : &quot;op_save&quot;, &quot;length&quot; : 4 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_resume&quot;, &quot;length&quot; : 3 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_watchdog&quot;, &quot;length&quot; : 1 },
</span><del>-            { &quot;name&quot; : &quot;op_log_shadow_chicken_prologue&quot;, &quot;length&quot; : 1},
-            { &quot;name&quot; : &quot;op_log_shadow_chicken_tail&quot;, &quot;length&quot; : 1}
</del><ins>+            { &quot;name&quot; : &quot;op_log_shadow_chicken_prologue&quot;, &quot;length&quot; : 2},
+            { &quot;name&quot; : &quot;op_log_shadow_chicken_tail&quot;, &quot;length&quot; : 3}
</ins><span class="cx">         ]
</span><span class="cx">     },
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -55,8 +55,6 @@
</span><span class="cx">     case op_create_cloned_arguments:
</span><span class="cx">     case op_get_rest_length:
</span><span class="cx">     case op_watchdog:
</span><del>-    case op_log_shadow_chicken_prologue:
-    case op_log_shadow_chicken_tail:
</del><span class="cx">         return;
</span><span class="cx">     case op_assert:
</span><span class="cx">     case op_get_scope:
</span><span class="lines">@@ -74,6 +72,7 @@
</span><span class="cx">     case op_jneq_null:
</span><span class="cx">     case op_dec:
</span><span class="cx">     case op_inc:
</span><ins>+    case op_log_shadow_chicken_prologue:
</ins><span class="cx">     case op_resume: {
</span><span class="cx">         ASSERT(opcodeLengths[opcodeID] &gt; 1);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
</span><span class="lines">@@ -88,6 +87,7 @@
</span><span class="cx">     case op_jngreatereq:
</span><span class="cx">     case op_jless:
</span><span class="cx">     case op_set_function_name:
</span><ins>+    case op_log_shadow_chicken_tail:
</ins><span class="cx">     case op_copy_rest: {
</span><span class="cx">         ASSERT(opcodeLengths[opcodeID] &gt; 2);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1360,11 +1360,16 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_log_shadow_chicken_prologue: {
</span><ins>+            int r0 = (++it)-&gt;u.operand;
</ins><span class="cx">             printLocationAndOp(out, exec, location, it, &quot;log_shadow_chicken_prologue&quot;);
</span><ins>+            out.printf(&quot;%s&quot;, registerName(r0).data());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_log_shadow_chicken_tail: {
</span><ins>+            int r0 = (++it)-&gt;u.operand;
+            int r1 = (++it)-&gt;u.operand;
</ins><span class="cx">             printLocationAndOp(out, exec, location, it, &quot;log_shadow_chicken_tail&quot;);
</span><ins>+            out.printf(&quot;%s, %s&quot;, registerName(r0).data(), registerName(r1).data());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_switch_imm: {
</span><span class="lines">@@ -4387,4 +4392,24 @@
</span><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx"> 
</span><ins>+Optional&lt;unsigned&gt; CodeBlock::bytecodeOffsetFromCallSiteIndex(CallSiteIndex callSiteIndex)
+{
+    Optional&lt;unsigned&gt; bytecodeOffset;
+    JITCode::JITType jitType = this-&gt;jitType();
+    if (jitType == JITCode::InterpreterThunk || jitType == JITCode::BaselineJIT) {
+#if USE(JSVALUE64)
+        bytecodeOffset = callSiteIndex.bits();
+#else
+        Instruction* instruction = bitwise_cast&lt;Instruction*&gt;(callSiteIndex.bits());
+        bytecodeOffset = instruction - instructions().begin();
+#endif
+    } else if (jitType == JITCode::DFGJIT || jitType == JITCode::FTLJIT) {
+        RELEASE_ASSERT(canGetCodeOrigin(callSiteIndex));
+        CodeOrigin origin = codeOrigin(callSiteIndex);
+        bytecodeOffset = origin.bytecodeIndex;
+    }
+
+    return bytecodeOffset;
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -231,6 +231,8 @@
</span><span class="cx">     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int&amp; divot,
</span><span class="cx">                                           int&amp; startOffset, int&amp; endOffset, unsigned&amp; line, unsigned&amp; column);
</span><span class="cx"> 
</span><ins>+    Optional&lt;unsigned&gt; bytecodeOffsetFromCallSiteIndex(CallSiteIndex);
+
</ins><span class="cx">     void getStubInfoMap(const ConcurrentJITLocker&amp;, StubInfoMap&amp; result);
</span><span class="cx">     void getStubInfoMap(StubInfoMap&amp; result);
</span><span class="cx">     
</span><span class="lines">@@ -833,6 +835,8 @@
</span><span class="cx">         m_steppingMode = SteppingModeDisabled;
</span><span class="cx">         m_numBreakpoints = 0;
</span><span class="cx">     }
</span><ins>+
+    bool wasCompiledWithDebuggingOpcodes() const { return m_unlinkedCode-&gt;wasCompiledWithDebuggingOpcodes(); }
</ins><span class="cx">     
</span><span class="cx">     // FIXME: Make these remaining members private.
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx"> const ClassInfo UnlinkedEvalCodeBlock::s_info = { &quot;UnlinkedEvalCodeBlock&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) };
</span><span class="cx"> const ClassInfo UnlinkedFunctionCodeBlock::s_info = { &quot;UnlinkedFunctionCodeBlock&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) };
</span><span class="cx"> 
</span><del>-UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo&amp; info)
</del><ins>+UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
</ins><span class="cx">     : Base(*vm, structure)
</span><span class="cx">     , m_numVars(0)
</span><span class="cx">     , m_numCalleeLocals(0)
</span><span class="lines">@@ -68,6 +68,7 @@
</span><span class="cx">     , m_evalContextType(static_cast&lt;unsigned&gt;(info.evalContextType()))
</span><span class="cx">     , m_isArrowFunctionContext(info.isArrowFunctionContext())
</span><span class="cx">     , m_isClassContext(info.isClassContext())
</span><ins>+    , m_wasCompiledWithDebuggingOpcodes(debuggerMode == DebuggerMode::DebuggerOn)
</ins><span class="cx">     , m_firstLine(0)
</span><span class="cx">     , m_lineCount(0)
</span><span class="cx">     , m_endColumn(UINT_MAX)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -368,8 +368,10 @@
</span><span class="cx"> 
</span><span class="cx">     void dumpExpressionRangeInfo(); // For debugging purpose only.
</span><span class="cx"> 
</span><ins>+    bool wasCompiledWithDebuggingOpcodes() const { return m_wasCompiledWithDebuggingOpcodes; }
+
</ins><span class="cx"> protected:
</span><del>-    UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&amp;);
</del><ins>+    UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&amp;, DebuggerMode);
</ins><span class="cx">     ~UnlinkedCodeBlock();
</span><span class="cx"> 
</span><span class="cx">     void finishCreation(VM&amp; vm)
</span><span class="lines">@@ -409,6 +411,7 @@
</span><span class="cx">     unsigned m_evalContextType : 2;
</span><span class="cx">     unsigned m_isArrowFunctionContext : 1;
</span><span class="cx">     unsigned m_isClassContext : 1;
</span><ins>+    unsigned m_wasCompiledWithDebuggingOpcodes : 1;
</ins><span class="cx">     unsigned m_firstLine;
</span><span class="cx">     unsigned m_lineCount;
</span><span class="cx">     unsigned m_endColumn;
</span><span class="lines">@@ -479,8 +482,8 @@
</span><span class="cx">     typedef UnlinkedCodeBlock Base;
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><del>-    UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo&amp; info)
-        : Base(vm, structure, codeType, info)
</del><ins>+    UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
+        : Base(vm, structure, codeType, info, debuggerMode)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -490,9 +493,9 @@
</span><span class="cx"> class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
</span><span class="cx"> private:
</span><span class="cx">     friend class CodeCache;
</span><del>-    static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo&amp; info)
</del><ins>+    static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
</ins><span class="cx">     {
</span><del>-        UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell&lt;UnlinkedProgramCodeBlock&gt;(vm-&gt;heap)) UnlinkedProgramCodeBlock(vm, vm-&gt;unlinkedProgramCodeBlockStructure.get(), info);
</del><ins>+        UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell&lt;UnlinkedProgramCodeBlock&gt;(vm-&gt;heap)) UnlinkedProgramCodeBlock(vm, vm-&gt;unlinkedProgramCodeBlockStructure.get(), info, debuggerMode);
</ins><span class="cx">         instance-&gt;finishCreation(*vm);
</span><span class="cx">         return instance;
</span><span class="cx">     }
</span><span class="lines">@@ -512,8 +515,8 @@
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo&amp; info)
-        : Base(vm, structure, GlobalCode, info)
</del><ins>+    UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
+        : Base(vm, structure, GlobalCode, info, debuggerMode)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -532,9 +535,9 @@
</span><span class="cx"> class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock {
</span><span class="cx"> private:
</span><span class="cx">     friend class CodeCache;
</span><del>-    static UnlinkedModuleProgramCodeBlock* create(VM* vm, const ExecutableInfo&amp; info)
</del><ins>+    static UnlinkedModuleProgramCodeBlock* create(VM* vm, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
</ins><span class="cx">     {
</span><del>-        UnlinkedModuleProgramCodeBlock* instance = new (NotNull, allocateCell&lt;UnlinkedModuleProgramCodeBlock&gt;(vm-&gt;heap)) UnlinkedModuleProgramCodeBlock(vm, vm-&gt;unlinkedModuleProgramCodeBlockStructure.get(), info);
</del><ins>+        UnlinkedModuleProgramCodeBlock* instance = new (NotNull, allocateCell&lt;UnlinkedModuleProgramCodeBlock&gt;(vm-&gt;heap)) UnlinkedModuleProgramCodeBlock(vm, vm-&gt;unlinkedModuleProgramCodeBlockStructure.get(), info, debuggerMode);
</ins><span class="cx">         instance-&gt;finishCreation(*vm);
</span><span class="cx">         return instance;
</span><span class="cx">     }
</span><span class="lines">@@ -578,8 +581,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo&amp; info)
-        : Base(vm, structure, ModuleCode, info)
</del><ins>+    UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
+        : Base(vm, structure, ModuleCode, info, debuggerMode)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -598,9 +601,9 @@
</span><span class="cx"> private:
</span><span class="cx">     friend class CodeCache;
</span><span class="cx"> 
</span><del>-    static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo&amp; info)
</del><ins>+    static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
</ins><span class="cx">     {
</span><del>-        UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell&lt;UnlinkedEvalCodeBlock&gt;(vm-&gt;heap)) UnlinkedEvalCodeBlock(vm, vm-&gt;unlinkedEvalCodeBlockStructure.get(), info);
</del><ins>+        UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell&lt;UnlinkedEvalCodeBlock&gt;(vm-&gt;heap)) UnlinkedEvalCodeBlock(vm, vm-&gt;unlinkedEvalCodeBlockStructure.get(), info, debuggerMode);
</ins><span class="cx">         instance-&gt;finishCreation(*vm);
</span><span class="cx">         return instance;
</span><span class="cx">     }
</span><span class="lines">@@ -620,8 +623,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo&amp; info)
-        : Base(vm, structure, EvalCode, info)
</del><ins>+    UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
+        : Base(vm, structure, EvalCode, info, debuggerMode)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -641,9 +644,9 @@
</span><span class="cx">     typedef UnlinkedCodeBlock Base;
</span><span class="cx">     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
</span><span class="cx"> 
</span><del>-    static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo&amp; info)
</del><ins>+    static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
</ins><span class="cx">     {
</span><del>-        UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell&lt;UnlinkedFunctionCodeBlock&gt;(vm-&gt;heap)) UnlinkedFunctionCodeBlock(vm, vm-&gt;unlinkedFunctionCodeBlockStructure.get(), codeType, info);
</del><ins>+        UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell&lt;UnlinkedFunctionCodeBlock&gt;(vm-&gt;heap)) UnlinkedFunctionCodeBlock(vm, vm-&gt;unlinkedFunctionCodeBlockStructure.get(), codeType, info, debuggerMode);
</ins><span class="cx">         instance-&gt;finishCreation(*vm);
</span><span class="cx">         return instance;
</span><span class="cx">     }
</span><span class="lines">@@ -651,8 +654,8 @@
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo&amp; info)
-        : Base(vm, structure, codeType, info)
</del><ins>+    UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo&amp; info, DebuggerMode debuggerMode)
+        : Base(vm, structure, codeType, info, debuggerMode)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedFunctionExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool isClassContext = executable-&gt;superBinding() == SuperBinding::Needed;
</span><span class="cx"> 
</span><del>-    UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&amp;vm, FunctionCode, ExecutableInfo(function-&gt;usesEval(), function-&gt;isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable-&gt;constructorKind(), executable-&gt;superBinding(), parseMode, executable-&gt;derivedContextType(), false, isClassContext, EvalContextType::FunctionEvalContext));
</del><ins>+    UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&amp;vm, FunctionCode, ExecutableInfo(function-&gt;usesEval(), function-&gt;isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable-&gt;constructorKind(), executable-&gt;superBinding(), parseMode, executable-&gt;derivedContextType(), false, isClassContext, EvalContextType::FunctionEvalContext), debuggerMode);
</ins><span class="cx"> 
</span><span class="cx">     error = BytecodeGenerator::generate(vm, function.get(), result, debuggerMode, profilerMode, executable-&gt;parentScopeTDZVariables());
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -64,6 +64,8 @@
</span><span class="cx"> ParserError BytecodeGenerator::generate()
</span><span class="cx"> {
</span><span class="cx">     m_codeBlock-&gt;setThisRegister(m_thisRegister.virtualRegister());
</span><ins>+
+    emitLogShadowChickenPrologueIfNecessary();
</ins><span class="cx">     
</span><span class="cx">     // If we have declared a variable named &quot;arguments&quot; and we are using arguments then we should
</span><span class="cx">     // perform that assignment now.
</span><span class="lines">@@ -291,7 +293,7 @@
</span><span class="cx">     emitEnter();
</span><span class="cx"> 
</span><span class="cx">     allocateAndEmitScope();
</span><del>-    
</del><ins>+
</ins><span class="cx">     m_calleeRegister.setIndex(JSStack::Callee);
</span><span class="cx"> 
</span><span class="cx">     initializeParameters(parameters);
</span><span class="lines">@@ -1105,7 +1107,6 @@
</span><span class="cx"> void BytecodeGenerator::emitEnter()
</span><span class="cx"> {
</span><span class="cx">     emitOpcode(op_enter);
</span><del>-    emitLogShadowChickenPrologueIfNecessary();
</del><span class="cx">     emitWatchdog();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -3167,6 +3168,7 @@
</span><span class="cx">     if (!m_shouldEmitDebugHooks &amp;&amp; !Options::alwaysUseShadowChicken())
</span><span class="cx">         return;
</span><span class="cx">     emitOpcode(op_log_shadow_chicken_prologue);
</span><ins>+    instructions().append(scopeRegister()-&gt;index());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::emitLogShadowChickenTailIfNecessary()
</span><span class="lines">@@ -3174,6 +3176,8 @@
</span><span class="cx">     if (!m_shouldEmitDebugHooks &amp;&amp; !Options::alwaysUseShadowChicken())
</span><span class="cx">         return;
</span><span class="cx">     emitOpcode(op_log_shadow_chicken_tail);
</span><ins>+    instructions().append(thisRegister()-&gt;index());
+    instructions().append(scopeRegister()-&gt;index());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -77,8 +77,6 @@
</span><span class="cx">         : m_debugger(debugger)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(!m_debugger.m_currentDebuggerCallFrame);
</span><del>-        if (m_debugger.m_currentCallFrame)
-            m_debugger.m_currentDebuggerCallFrame = DebuggerCallFrame::create(debugger.m_currentCallFrame);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ~DebuggerPausedScope()
</span><span class="lines">@@ -770,9 +768,10 @@
</span><span class="cx">     updateCallFrameAndPauseIfNeeded(callFrame);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-DebuggerCallFrame* Debugger::currentDebuggerCallFrame() const
</del><ins>+DebuggerCallFrame* Debugger::currentDebuggerCallFrame()
</ins><span class="cx"> {
</span><del>-    ASSERT(m_currentDebuggerCallFrame);
</del><ins>+    if (!m_currentDebuggerCallFrame)
+        m_currentDebuggerCallFrame = DebuggerCallFrame::create(m_currentCallFrame);
</ins><span class="cx">     return m_currentDebuggerCallFrame.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx"> 
</span><span class="cx">     VM&amp; vm() { return m_vm; }
</span><span class="cx"> 
</span><del>-    JSC::DebuggerCallFrame* currentDebuggerCallFrame() const;
</del><ins>+    JSC::DebuggerCallFrame* currentDebuggerCallFrame();
</ins><span class="cx">     bool hasHandlerForExceptionCallback() const
</span><span class="cx">     {
</span><span class="cx">         ASSERT(m_reasonForPause == PausedForException);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -38,14 +38,12 @@
</span><span class="cx"> #include &quot;JSLexicalEnvironment.h&quot;
</span><span class="cx"> #include &quot;JSWithScope.h&quot;
</span><span class="cx"> #include &quot;Parser.h&quot;
</span><ins>+#include &quot;ShadowChickenInlines.h&quot;
</ins><span class="cx"> #include &quot;StackVisitor.h&quot;
</span><span class="cx"> #include &quot;StrongInlines.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-// FIXME: Make this use ShadowChicken so that it sees tail-deleted frames.
-// https://bugs.webkit.org/show_bug.cgi?id=155690
-
</del><span class="cx"> class LineAndColumnFunctor {
</span><span class="cx"> public:
</span><span class="cx">     StackVisitor::Status operator()(StackVisitor&amp; visitor) const
</span><span class="lines">@@ -62,61 +60,59 @@
</span><span class="cx">     mutable unsigned m_column;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-class FindCallerMidStackFunctor {
-public:
-    FindCallerMidStackFunctor(CallFrame* callFrame)
-        : m_callFrame(callFrame)
-        , m_callerFrame(nullptr)
-    { }
</del><ins>+Ref&lt;DebuggerCallFrame&gt; DebuggerCallFrame::create(CallFrame* callFrame)
+{
+    Vector&lt;ShadowChicken::Frame&gt; frames;
+    callFrame-&gt;vm().shadowChicken().iterate(callFrame-&gt;vm(), callFrame, [&amp;] (const ShadowChicken::Frame&amp; frame) -&gt; bool {
+        frames.append(frame);
+        return true;
+    });
</ins><span class="cx"> 
</span><del>-    StackVisitor::Status operator()(StackVisitor&amp; visitor) const
-    {
-        if (visitor-&gt;callFrame() == m_callFrame) {
-            m_callerFrame = visitor-&gt;callerFrame();
-            return StackVisitor::Done;
-        }
-        return StackVisitor::Continue;
</del><ins>+    RELEASE_ASSERT(frames.size());
+    RELEASE_ASSERT(!frames[0].isTailDeleted); // The top frame should never be tail deleted.
+    RELEASE_ASSERT(!frames[frames.size() - 1].isTailDeleted); // The first frame should never be tail deleted.
+
+    RefPtr&lt;DebuggerCallFrame&gt; currentParent = nullptr;
+    ExecState* exec = nullptr;
+    for (unsigned i = frames.size(); i--; ) {
+        const ShadowChicken::Frame&amp; frame = frames[i];
+        if (!frame.isTailDeleted)
+            exec = frame.frame;
+        ASSERT(exec);
+        Ref&lt;DebuggerCallFrame&gt; currentFrame = adoptRef(*new DebuggerCallFrame(exec, frame));
+        currentFrame-&gt;m_caller = currentParent;
+        currentParent = WTFMove(currentFrame);
</ins><span class="cx">     }
</span><ins>+    return *currentParent;
+}
</ins><span class="cx"> 
</span><del>-    CallFrame* getCallerFrame() const { return m_callerFrame; }
-
-private:
-    CallFrame* m_callFrame;
-    mutable CallFrame* m_callerFrame;
-};
-
-DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame)
-    : m_callFrame(callFrame)
</del><ins>+DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame, const ShadowChicken::Frame&amp; frame)
+    : m_validMachineFrame(callFrame)
+    , m_shadowChickenFrame(frame)
</ins><span class="cx"> {
</span><del>-    m_position = positionForCallFrame(m_callFrame);
</del><ins>+    m_position = currentPosition();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RefPtr&lt;DebuggerCallFrame&gt; DebuggerCallFrame::callerFrame()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isValid());
</span><span class="cx">     if (!isValid())
</span><del>-        return 0;
-
-    if (m_caller)
-        return m_caller;
-
-    FindCallerMidStackFunctor functor(m_callFrame);
-    m_callFrame-&gt;vm().topCallFrame-&gt;iterate(functor);
-
-    CallFrame* callerFrame = functor.getCallerFrame();
-    if (!callerFrame)
</del><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    m_caller = DebuggerCallFrame::create(callerFrame);
</del><span class="cx">     return m_caller;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ExecState* DebuggerCallFrame::globalExec()
+{
+    return scope()-&gt;globalObject()-&gt;globalExec();
+}
+
</ins><span class="cx"> JSC::JSGlobalObject* DebuggerCallFrame::vmEntryGlobalObject() const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isValid());
</span><span class="cx">     if (!isValid())
</span><del>-        return 0;
-    return m_callFrame-&gt;vmEntryGlobalObject();
</del><ins>+        return nullptr;
+    return m_validMachineFrame-&gt;vmEntryGlobalObject();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> SourceID DebuggerCallFrame::sourceID() const
</span><span class="lines">@@ -124,7 +120,9 @@
</span><span class="cx">     ASSERT(isValid());
</span><span class="cx">     if (!isValid())
</span><span class="cx">         return noSourceID;
</span><del>-    return sourceIDForCallFrame(m_callFrame);
</del><ins>+    if (isTailDeleted())
+        return m_shadowChickenFrame.codeBlock-&gt;ownerScriptExecutable()-&gt;sourceID();
+    return sourceIDForCallFrame(m_validMachineFrame);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String DebuggerCallFrame::functionName() const
</span><span class="lines">@@ -132,25 +130,34 @@
</span><span class="cx">     ASSERT(isValid());
</span><span class="cx">     if (!isValid())
</span><span class="cx">         return String();
</span><del>-    return m_callFrame-&gt;friendlyFunctionName();
</del><ins>+
+    if (isTailDeleted()) {
+        if (JSFunction* func = jsDynamicCast&lt;JSFunction*&gt;(m_shadowChickenFrame.callee))
+            return func-&gt;calculatedDisplayName(m_validMachineFrame);
+        return m_shadowChickenFrame.codeBlock-&gt;inferredName().data();
+    }
+
+    return m_validMachineFrame-&gt;friendlyFunctionName();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> DebuggerScope* DebuggerCallFrame::scope()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isValid());
</span><span class="cx">     if (!isValid())
</span><del>-        return 0;
</del><ins>+        return nullptr;
</ins><span class="cx"> 
</span><span class="cx">     if (!m_scope) {
</span><del>-        VM&amp; vm = m_callFrame-&gt;vm();
</del><ins>+        VM&amp; vm = m_validMachineFrame-&gt;vm();
</ins><span class="cx">         JSScope* scope;
</span><del>-        CodeBlock* codeBlock = m_callFrame-&gt;codeBlock();
-        if (codeBlock &amp;&amp; codeBlock-&gt;scopeRegister().isValid())
-            scope = m_callFrame-&gt;scope(codeBlock-&gt;scopeRegister().offset());
-        else if (JSCallee* callee = jsDynamicCast&lt;JSCallee*&gt;(m_callFrame-&gt;callee()))
</del><ins>+        CodeBlock* codeBlock = m_validMachineFrame-&gt;codeBlock();
+        if (isTailDeleted())
+            scope = m_shadowChickenFrame.scope;
+        else if (codeBlock &amp;&amp; codeBlock-&gt;scopeRegister().isValid())
+            scope = m_validMachineFrame-&gt;scope(codeBlock-&gt;scopeRegister().offset());
+        else if (JSCallee* callee = jsDynamicCast&lt;JSCallee*&gt;(m_validMachineFrame-&gt;callee()))
</ins><span class="cx">             scope = callee-&gt;scope();
</span><span class="cx">         else
</span><del>-            scope = m_callFrame-&gt;lexicalGlobalObject();
</del><ins>+            scope = m_validMachineFrame-&gt;lexicalGlobalObject()-&gt;globalLexicalEnvironment();
</ins><span class="cx"> 
</span><span class="cx">         m_scope.set(vm, DebuggerScope::create(vm, scope));
</span><span class="cx">     }
</span><span class="lines">@@ -163,49 +170,75 @@
</span><span class="cx">     if (!isValid())
</span><span class="cx">         return ProgramType;
</span><span class="cx"> 
</span><del>-    if (jsDynamicCast&lt;JSFunction*&gt;(m_callFrame-&gt;callee()))
</del><ins>+    if (isTailDeleted())
</ins><span class="cx">         return FunctionType;
</span><span class="cx"> 
</span><ins>+    if (jsDynamicCast&lt;JSFunction*&gt;(m_validMachineFrame-&gt;callee()))
+        return FunctionType;
+
</ins><span class="cx">     return ProgramType;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSValue DebuggerCallFrame::thisValue() const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isValid());
</span><del>-    return thisValueForCallFrame(m_callFrame);
</del><ins>+    if (!isValid())
+        return jsUndefined();
+
+    CodeBlock* codeBlock = nullptr;
+    JSValue thisValue;
+    if (isTailDeleted()) {
+        thisValue = m_shadowChickenFrame.thisValue;
+        codeBlock = m_shadowChickenFrame.codeBlock;
+    } else {
+        thisValue = m_validMachineFrame-&gt;thisValue();
+        codeBlock = m_validMachineFrame-&gt;codeBlock();
+    }
+
+    if (!thisValue)
+        return jsUndefined();
+
+    ECMAMode ecmaMode = NotStrictMode;
+    if (codeBlock &amp;&amp; codeBlock-&gt;isStrictMode())
+        ecmaMode = StrictMode;
+    return thisValue.toThis(m_validMachineFrame, ecmaMode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Evaluate some JavaScript code in the scope of this frame.
</span><span class="cx"> JSValue DebuggerCallFrame::evaluateWithScopeExtension(const String&amp; script, JSObject* scopeExtensionObject, NakedPtr&lt;Exception&gt;&amp; exception)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isValid());
</span><del>-    CallFrame* callFrame = m_callFrame;
</del><ins>+    CallFrame* callFrame = m_validMachineFrame;
</ins><span class="cx">     if (!callFrame)
</span><span class="cx">         return jsUndefined();
</span><span class="cx"> 
</span><span class="cx">     JSLockHolder lock(callFrame);
</span><span class="cx"> 
</span><del>-    if (!callFrame-&gt;codeBlock())
</del><ins>+    CodeBlock* codeBlock = nullptr;
+    if (isTailDeleted())
+        codeBlock = m_shadowChickenFrame.codeBlock;
+    else
+        codeBlock = callFrame-&gt;codeBlock();
+    if (!codeBlock)
</ins><span class="cx">         return jsUndefined();
</span><span class="cx">     
</span><span class="cx">     DebuggerEvalEnabler evalEnabler(callFrame);
</span><span class="cx">     VM&amp; vm = callFrame-&gt;vm();
</span><del>-    auto&amp; codeBlock = *callFrame-&gt;codeBlock();
-    ThisTDZMode thisTDZMode = codeBlock.unlinkedCodeBlock()-&gt;constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded;
</del><ins>+    ThisTDZMode thisTDZMode = codeBlock-&gt;unlinkedCodeBlock()-&gt;constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded;
</ins><span class="cx"> 
</span><span class="cx">     EvalContextType evalContextType;
</span><span class="cx">     
</span><del>-    if (isFunctionParseMode(codeBlock.unlinkedCodeBlock()-&gt;parseMode()))
</del><ins>+    if (isFunctionParseMode(codeBlock-&gt;unlinkedCodeBlock()-&gt;parseMode()))
</ins><span class="cx">         evalContextType = EvalContextType::FunctionEvalContext;
</span><del>-    else if (codeBlock.unlinkedCodeBlock()-&gt;codeType() == EvalCode)
-        evalContextType = codeBlock.unlinkedCodeBlock()-&gt;evalContextType();
</del><ins>+    else if (codeBlock-&gt;unlinkedCodeBlock()-&gt;codeType() == EvalCode)
+        evalContextType = codeBlock-&gt;unlinkedCodeBlock()-&gt;evalContextType();
</ins><span class="cx">     else 
</span><span class="cx">         evalContextType = EvalContextType::None;
</span><span class="cx"> 
</span><span class="cx">     VariableEnvironment variablesUnderTDZ;
</span><span class="cx">     JSScope::collectVariablesUnderTDZ(scope()-&gt;jsScope(), variablesUnderTDZ);
</span><span class="cx"> 
</span><del>-    EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock.isStrictMode(), thisTDZMode, codeBlock.unlinkedCodeBlock()-&gt;derivedContextType(), codeBlock.unlinkedCodeBlock()-&gt;isArrowFunction(), evalContextType, &amp;variablesUnderTDZ);
</del><ins>+    EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock-&gt;isStrictMode(), thisTDZMode, codeBlock-&gt;unlinkedCodeBlock()-&gt;derivedContextType(), codeBlock-&gt;unlinkedCodeBlock()-&gt;isArrowFunction(), evalContextType, &amp;variablesUnderTDZ);
</ins><span class="cx">     if (vm.exception()) {
</span><span class="cx">         exception = vm.exception();
</span><span class="cx">         vm.clearException();
</span><span class="lines">@@ -218,7 +251,7 @@
</span><span class="cx">         globalObject-&gt;setGlobalScopeExtension(JSWithScope::create(vm, globalObject, scopeExtensionObject, ignoredPreviousScope));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JSValue thisValue = thisValueForCallFrame(callFrame);
</del><ins>+    JSValue thisValue = this-&gt;thisValue();
</ins><span class="cx">     JSValue result = vm.interpreter-&gt;execute(eval, callFrame, thisValue, scope()-&gt;jsScope());
</span><span class="cx">     if (vm.exception()) {
</span><span class="cx">         exception = vm.exception();
</span><span class="lines">@@ -236,7 +269,7 @@
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;DebuggerCallFrame&gt; frame = this;
</span><span class="cx">     while (frame) {
</span><del>-        frame-&gt;m_callFrame = nullptr;
</del><ins>+        frame-&gt;m_validMachineFrame = nullptr;
</ins><span class="cx">         if (frame-&gt;m_scope) {
</span><span class="cx">             frame-&gt;m_scope-&gt;invalidateChain();
</span><span class="cx">             frame-&gt;m_scope.clear();
</span><span class="lines">@@ -245,11 +278,24 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame)
</del><ins>+TextPosition DebuggerCallFrame::currentPosition()
</ins><span class="cx"> {
</span><del>-    if (!callFrame)
</del><ins>+    if (!m_validMachineFrame)
</ins><span class="cx">         return TextPosition();
</span><span class="cx"> 
</span><ins>+    if (isTailDeleted()) {
+        CodeBlock* codeBlock = m_shadowChickenFrame.codeBlock;
+        if (Optional&lt;unsigned&gt; bytecodeOffset = codeBlock-&gt;bytecodeOffsetFromCallSiteIndex(m_shadowChickenFrame.callSiteIndex)) {
+            return TextPosition(OrdinalNumber::fromOneBasedInt(codeBlock-&gt;lineNumberForBytecodeOffset(*bytecodeOffset)),
+                OrdinalNumber::fromOneBasedInt(codeBlock-&gt;columnNumberForBytecodeOffset(*bytecodeOffset)));
+        }
+    }
+
+    return positionForCallFrame(m_validMachineFrame);
+}
+
+TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame)
+{
</ins><span class="cx">     LineAndColumnFunctor functor;
</span><span class="cx">     callFrame-&gt;iterate(functor);
</span><span class="cx">     return TextPosition(OrdinalNumber::fromOneBasedInt(functor.line()), OrdinalNumber::fromOneBasedInt(functor.column()));
</span><span class="lines">@@ -264,20 +310,4 @@
</span><span class="cx">     return codeBlock-&gt;ownerScriptExecutable()-&gt;sourceID();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSValue DebuggerCallFrame::thisValueForCallFrame(CallFrame* callFrame)
-{
-    if (!callFrame)
-        return jsUndefined();
-
-    if (!callFrame-&gt;thisValue())
-        return jsUndefined();
-
-    ECMAMode ecmaMode = NotStrictMode;
-    CodeBlock* codeBlock = callFrame-&gt;codeBlock();
-    if (codeBlock &amp;&amp; codeBlock-&gt;isStrictMode())
-        ecmaMode = StrictMode;
-
-    return callFrame-&gt;thisValue().toThis(callFrame, ecmaMode);
-}
-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -29,7 +29,9 @@
</span><span class="cx"> #ifndef DebuggerCallFrame_h
</span><span class="cx"> #define DebuggerCallFrame_h
</span><span class="cx"> 
</span><ins>+#include &quot;CallFrame.h&quot;
</ins><span class="cx"> #include &quot;DebuggerPrimitives.h&quot;
</span><ins>+#include &quot;ShadowChicken.h&quot;
</ins><span class="cx"> #include &quot;Strong.h&quot;
</span><span class="cx"> #include &lt;wtf/NakedPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/PassRefPtr.h&gt;
</span><span class="lines">@@ -40,22 +42,15 @@
</span><span class="cx"> 
</span><span class="cx"> class DebuggerScope;
</span><span class="cx"> class Exception;
</span><del>-class ExecState;
-typedef ExecState CallFrame;
</del><span class="cx"> 
</span><span class="cx"> class DebuggerCallFrame : public RefCounted&lt;DebuggerCallFrame&gt; {
</span><span class="cx"> public:
</span><span class="cx">     enum Type { ProgramType, FunctionType };
</span><span class="cx"> 
</span><del>-    static Ref&lt;DebuggerCallFrame&gt; create(CallFrame* callFrame)
-    {
-        return adoptRef(*new DebuggerCallFrame(callFrame));
-    }
</del><ins>+    static Ref&lt;DebuggerCallFrame&gt; create(CallFrame*);
</ins><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE explicit DebuggerCallFrame(CallFrame*);
-
</del><span class="cx">     JS_EXPORT_PRIVATE RefPtr&lt;DebuggerCallFrame&gt; callerFrame();
</span><del>-    ExecState* exec() const { return m_callFrame; }
</del><ins>+    ExecState* globalExec();
</ins><span class="cx">     JS_EXPORT_PRIVATE SourceID sourceID() const;
</span><span class="cx"> 
</span><span class="cx">     // line and column are in base 0 e.g. the first line is line 0.
</span><span class="lines">@@ -70,23 +65,28 @@
</span><span class="cx">     JS_EXPORT_PRIVATE JSValue thisValue() const;
</span><span class="cx">     JSValue evaluateWithScopeExtension(const String&amp;, JSObject* scopeExtensionObject, NakedPtr&lt;Exception&gt;&amp;);
</span><span class="cx"> 
</span><del>-    bool isValid() const { return !!m_callFrame; }
</del><ins>+    bool isValid() const { return !!m_validMachineFrame || isTailDeleted(); }
</ins><span class="cx">     JS_EXPORT_PRIVATE void invalidate();
</span><span class="cx"> 
</span><span class="cx">     // The following are only public for the Debugger's use only. They will be
</span><span class="cx">     // made private soon. Other clients should not use these.
</span><span class="cx"> 
</span><ins>+    JS_EXPORT_PRIVATE TextPosition currentPosition();
</ins><span class="cx">     JS_EXPORT_PRIVATE static TextPosition positionForCallFrame(CallFrame*);
</span><span class="cx">     JS_EXPORT_PRIVATE static SourceID sourceIDForCallFrame(CallFrame*);
</span><del>-    static JSValue thisValueForCallFrame(CallFrame*);
</del><span class="cx"> 
</span><ins>+    bool isTailDeleted() const { return m_shadowChickenFrame.isTailDeleted; }
+
</ins><span class="cx"> private:
</span><del>-    CallFrame* m_callFrame;
</del><ins>+    DebuggerCallFrame(CallFrame*, const ShadowChicken::Frame&amp;);
+
+    CallFrame* m_validMachineFrame;
</ins><span class="cx">     RefPtr&lt;DebuggerCallFrame&gt; m_caller;
</span><span class="cx">     TextPosition m_position;
</span><span class="cx">     // The DebuggerPausedScope is responsible for calling invalidate() which,
</span><span class="cx">     // in turn, will clear this strong ref.
</span><span class="cx">     Strong&lt;DebuggerScope&gt; m_scope;
</span><ins>+    ShadowChicken::Frame m_shadowChickenFrame;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -5109,7 +5109,7 @@
</span><span class="cx">             
</span><span class="cx">         case op_log_shadow_chicken_prologue: {
</span><span class="cx">             if (!m_inlineStackTop-&gt;m_inlineCallFrame)
</span><del>-                addToGraph(LogShadowChickenPrologue);
</del><ins>+                addToGraph(LogShadowChickenPrologue, get(VirtualRegister(currentInstruction[1].u.operand)));
</ins><span class="cx">             NEXT_OPCODE(op_log_shadow_chicken_prologue);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -5118,7 +5118,7 @@
</span><span class="cx">                 // FIXME: The right solution for inlining is to elide these whenever the tail call
</span><span class="cx">                 // ends up being inlined.
</span><span class="cx">                 // https://bugs.webkit.org/show_bug.cgi?id=155686
</span><del>-                addToGraph(LogShadowChickenTail);
</del><ins>+                addToGraph(LogShadowChickenTail, get(VirtualRegister(currentInstruction[1].u.operand)), get(VirtualRegister(currentInstruction[2].u.operand)));
</ins><span class="cx">             }
</span><span class="cx">             NEXT_OPCODE(op_log_shadow_chicken_tail);
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1501,6 +1501,16 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case LogShadowChickenPrologue: {
+            fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
+            break;
+        }
+        case LogShadowChickenTail: {
+            fixEdge&lt;UntypedUse&gt;(node-&gt;child1());
+            fixEdge&lt;KnownCellUse&gt;(node-&gt;child2());
+            break;
+        }
+
</ins><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">         // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
</span><span class="cx">         case SetArgument:
</span><span class="lines">@@ -1561,8 +1571,6 @@
</span><span class="cx">         case CheckBadCell:
</span><span class="cx">         case CheckNotEmpty:
</span><span class="cx">         case CheckWatchdogTimer:
</span><del>-        case LogShadowChickenPrologue:
-        case LogShadowChickenTail:
</del><span class="cx">         case Unreachable:
</span><span class="cx">         case ExtractOSREntryLocal:
</span><span class="cx">         case LoopHint:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -79,8 +79,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_profiledBlock);
</span><span class="cx">     
</span><del>-    m_hasDebuggerEnabled = m_profiledBlock-&gt;globalObject()-&gt;hasInteractiveDebugger()
-        || Options::forceDebuggerBytecodeGeneration();
</del><ins>+    m_hasDebuggerEnabled = m_profiledBlock-&gt;wasCompiledWithDebuggingOpcodes() || Options::forceDebuggerBytecodeGeneration();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Graph::~Graph()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -147,10 +147,11 @@
</span><span class="cx">         return m_jitCode-&gt;common.addCodeOrigin(codeOrigin);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void emitStoreCodeOrigin(CodeOrigin codeOrigin)
</del><ins>+    CallSiteIndex emitStoreCodeOrigin(CodeOrigin codeOrigin)
</ins><span class="cx">     {
</span><span class="cx">         CallSiteIndex callSite = addCallSite(codeOrigin);
</span><span class="cx">         emitStoreCallSiteIndex(callSite);
</span><ins>+        return callSite;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void emitStoreCallSiteIndex(CallSiteIndex callSite)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -5152,7 +5152,20 @@
</span><span class="cx">         flushRegisters();
</span><span class="cx">         prepareForExternalCall();
</span><span class="cx">         m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
</span><del>-        m_jit.logShadowChickenProloguePacket();
</del><ins>+
+        GPRTemporary scratch1(this, GPRInfo::nonArgGPR0); // This must be a non-argument GPR.
+        GPRReg scratch1Reg = scratch1.gpr();
+        GPRTemporary shadowPacket(this);
+        GPRReg shadowPacketReg = shadowPacket.gpr();
+        GPRTemporary scratch2(this);
+        GPRReg scratch2Reg = scratch2.gpr();
+
+        m_jit.ensureShadowChickenPacket(shadowPacketReg, scratch1Reg, scratch2Reg);
+
+        SpeculateCellOperand scope(this, node-&gt;child1());
+        GPRReg scopeReg = scope.gpr();
+
+        m_jit.logShadowChickenProloguePacket(shadowPacketReg, scratch1Reg, scopeReg);
</ins><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -5160,8 +5173,23 @@
</span><span class="cx">     case LogShadowChickenTail: {
</span><span class="cx">         flushRegisters();
</span><span class="cx">         prepareForExternalCall();
</span><del>-        m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
-        m_jit.logShadowChickenTailPacket();
</del><ins>+        CallSiteIndex callSiteIndex = m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
+
+        GPRTemporary scratch1(this, GPRInfo::nonArgGPR0); // This must be a non-argument GPR.
+        GPRReg scratch1Reg = scratch1.gpr();
+        GPRTemporary shadowPacket(this);
+        GPRReg shadowPacketReg = shadowPacket.gpr();
+        GPRTemporary scratch2(this);
+        GPRReg scratch2Reg = scratch2.gpr();
+
+        m_jit.ensureShadowChickenPacket(shadowPacketReg, scratch1Reg, scratch2Reg);
+
+        JSValueOperand thisValue(this, node-&gt;child1());
+        JSValueRegs thisRegs = thisValue.jsValueRegs();
+        SpeculateCellOperand scope(this, node-&gt;child2());
+        GPRReg scopeReg = scope.gpr();
+
+        m_jit.logShadowChickenTailPacket(shadowPacketReg, thisRegs, scopeReg, m_jit.codeBlock(), callSiteIndex);
</ins><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -5146,7 +5146,20 @@
</span><span class="cx">         flushRegisters();
</span><span class="cx">         prepareForExternalCall();
</span><span class="cx">         m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
</span><del>-        m_jit.logShadowChickenProloguePacket();
</del><ins>+
+        GPRTemporary scratch1(this, GPRInfo::nonArgGPR0); // This must be a non-argument GPR.
+        GPRReg scratch1Reg = scratch1.gpr();
+        GPRTemporary scratch2(this);
+        GPRReg scratch2Reg = scratch2.gpr();
+        GPRTemporary shadowPacket(this);
+        GPRReg shadowPacketReg = shadowPacket.gpr();
+
+        m_jit.ensureShadowChickenPacket(shadowPacketReg, scratch1Reg, scratch2Reg);
+
+        SpeculateCellOperand scope(this, node-&gt;child1());
+        GPRReg scopeReg = scope.gpr();
+
+        m_jit.logShadowChickenProloguePacket(shadowPacketReg, scratch1Reg, scopeReg);
</ins><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -5154,8 +5167,23 @@
</span><span class="cx">     case LogShadowChickenTail: {
</span><span class="cx">         flushRegisters();
</span><span class="cx">         prepareForExternalCall();
</span><del>-        m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
-        m_jit.logShadowChickenTailPacket();
</del><ins>+        CallSiteIndex callSiteIndex = m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
+
+        GPRTemporary scratch1(this, GPRInfo::nonArgGPR0); // This must be a non-argument GPR.
+        GPRReg scratch1Reg = scratch1.gpr();
+        GPRTemporary scratch2(this);
+        GPRReg scratch2Reg = scratch2.gpr();
+        GPRTemporary shadowPacket(this);
+        GPRReg shadowPacketReg = shadowPacket.gpr();
+
+        m_jit.ensureShadowChickenPacket(shadowPacketReg, scratch1Reg, scratch2Reg);
+
+        JSValueOperand thisValue(this, node-&gt;child1());
+        JSValueRegs thisRegs = JSValueRegs(thisValue.gpr());
+        SpeculateCellOperand scope(this, node-&gt;child2());
+        GPRReg scopeReg = scope.gpr();
+
+        m_jit.logShadowChickenTailPacket(shadowPacketReg, thisRegs, scopeReg, m_jit.codeBlock(), callSiteIndex);
</ins><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -87,6 +87,10 @@
</span><span class="cx">     macro(ShadowChicken_Packet_callee, OBJECT_OFFSETOF(ShadowChicken::Packet, callee)) \
</span><span class="cx">     macro(ShadowChicken_Packet_frame, OBJECT_OFFSETOF(ShadowChicken::Packet, frame)) \
</span><span class="cx">     macro(ShadowChicken_Packet_callerFrame, OBJECT_OFFSETOF(ShadowChicken::Packet, callerFrame)) \
</span><ins>+    macro(ShadowChicken_Packet_thisValue, OBJECT_OFFSETOF(ShadowChicken::Packet, thisValue)) \
+    macro(ShadowChicken_Packet_scope, OBJECT_OFFSETOF(ShadowChicken::Packet, scope)) \
+    macro(ShadowChicken_Packet_codeBlock, OBJECT_OFFSETOF(ShadowChicken::Packet, codeBlock)) \
+    macro(ShadowChicken_Packet_callSiteIndex, OBJECT_OFFSETOF(ShadowChicken::Packet, callSiteIndex)) \
</ins><span class="cx">     macro(ScopedArguments_overrodeThings, ScopedArguments::offsetOfOverrodeThings()) \
</span><span class="cx">     macro(ScopedArguments_scope, ScopedArguments::offsetOfScope()) \
</span><span class="cx">     macro(ScopedArguments_table, ScopedArguments::offsetOfTable()) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -7094,19 +7094,28 @@
</span><span class="cx">     
</span><span class="cx">     void compileLogShadowChickenPrologue()
</span><span class="cx">     {
</span><del>-        LValue packet = setupShadowChickenPacket();
-        
</del><ins>+        LValue packet = ensureShadowChickenPacket();
+        LValue scope = lowCell(m_node-&gt;child1());
+
</ins><span class="cx">         m_out.storePtr(m_callFrame, packet, m_heaps.ShadowChicken_Packet_frame);
</span><span class="cx">         m_out.storePtr(m_out.loadPtr(addressFor(0)), packet, m_heaps.ShadowChicken_Packet_callerFrame);
</span><span class="cx">         m_out.storePtr(m_out.loadPtr(payloadFor(JSStack::Callee)), packet, m_heaps.ShadowChicken_Packet_callee);
</span><ins>+        m_out.storePtr(scope, packet, m_heaps.ShadowChicken_Packet_scope);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void compileLogShadowChickenTail()
</span><span class="cx">     {
</span><del>-        LValue packet = setupShadowChickenPacket();
</del><ins>+        LValue packet = ensureShadowChickenPacket();
+        LValue thisValue = lowJSValue(m_node-&gt;child1());
+        LValue scope = lowCell(m_node-&gt;child2());
+        CallSiteIndex callSiteIndex = m_ftlState.jitCode-&gt;common.addCodeOrigin(m_node-&gt;origin.semantic);
</ins><span class="cx">         
</span><span class="cx">         m_out.storePtr(m_callFrame, packet, m_heaps.ShadowChicken_Packet_frame);
</span><span class="cx">         m_out.storePtr(m_out.constIntPtr(ShadowChicken::Packet::tailMarker()), packet, m_heaps.ShadowChicken_Packet_callee);
</span><ins>+        m_out.store64(thisValue, packet, m_heaps.ShadowChicken_Packet_thisValue);
+        m_out.storePtr(scope, packet, m_heaps.ShadowChicken_Packet_scope);
+        m_out.storePtr(m_out.constIntPtr(codeBlock()), packet, m_heaps.ShadowChicken_Packet_codeBlock);
+        m_out.store32(m_out.constInt32(callSiteIndex.bits()), packet, m_heaps.ShadowChicken_Packet_callSiteIndex);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void compileRecordRegExpCachedResult()
</span><span class="lines">@@ -8380,7 +8389,7 @@
</span><span class="cx">             m_out.phi(m_out.intPtr, fastButterfly, slowButterfly));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    LValue setupShadowChickenPacket()
</del><ins>+    LValue ensureShadowChickenPacket()
</ins><span class="cx">     {
</span><span class="cx">         LBasicBlock slowCase = m_out.newBlock();
</span><span class="cx">         LBasicBlock continuation = m_out.newBlock();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1299,6 +1299,7 @@
</span><span class="cx">     this.location = {scriptId: String(callFrame.sourceID), lineNumber: callFrame.line, columnNumber: callFrame.column};
</span><span class="cx">     this.scopeChain = this._wrapScopeChain(callFrame);
</span><span class="cx">     this.this = injectedScript._wrapObject(callFrame.thisObject, &quot;backtrace&quot;, false, true);
</span><ins>+    this.isTailDeleted = callFrame.isTailDeleted;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> InjectedScript.CallFrameProxy.prototype = {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -184,6 +184,11 @@
</span><span class="cx">     return impl().thisValue();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSValue JSJavaScriptCallFrame::isTailDeleted(JSC::ExecState*) const
+{
+    return jsBoolean(impl().isTailDeleted());
+}
+
</ins><span class="cx"> JSValue JSJavaScriptCallFrame::type(ExecState* exec) const
</span><span class="cx"> {
</span><span class="cx">     switch (impl().type()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -69,6 +69,7 @@
</span><span class="cx">     JSC::JSValue scopeChain(JSC::ExecState*) const;
</span><span class="cx">     JSC::JSValue thisObject(JSC::ExecState*) const;
</span><span class="cx">     JSC::JSValue type(JSC::ExecState*) const;
</span><ins>+    JSC::JSValue isTailDeleted(JSC::ExecState*) const;
</ins><span class="cx"> 
</span><span class="cx">     // Constants.
</span><span class="cx">     static const unsigned short GLOBAL_SCOPE = 0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSJavaScriptCallFramePrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeScopeChain(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeThisObject(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeType(ExecState*);
</span><ins>+static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameIsTailDeleted(ExecState*);
</ins><span class="cx"> 
</span><span class="cx"> const ClassInfo JSJavaScriptCallFramePrototype::s_info = { &quot;JavaScriptCallFrame&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(JSJavaScriptCallFramePrototype) };
</span><span class="cx"> 
</span><span class="lines">@@ -70,6 +71,7 @@
</span><span class="cx">     JSC_NATIVE_GETTER(&quot;scopeChain&quot;, jsJavaScriptCallFrameAttributeScopeChain, DontEnum | Accessor);
</span><span class="cx">     JSC_NATIVE_GETTER(&quot;thisObject&quot;, jsJavaScriptCallFrameAttributeThisObject, DontEnum | Accessor);
</span><span class="cx">     JSC_NATIVE_GETTER(&quot;type&quot;, jsJavaScriptCallFrameAttributeType, DontEnum | Accessor);
</span><ins>+    JSC_NATIVE_GETTER(&quot;isTailDeleted&quot;, jsJavaScriptCallFrameIsTailDeleted, DontEnum | Accessor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension(ExecState* exec)
</span><span class="lines">@@ -172,4 +174,14 @@
</span><span class="cx">     return JSValue::encode(castedThis-&gt;type(exec));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameIsTailDeleted(ExecState* exec)
+{
+    JSValue thisValue = exec-&gt;thisValue();
+    JSJavaScriptCallFrame* castedThis = jsDynamicCast&lt;JSJavaScriptCallFrame*&gt;(thisValue);
+    if (!castedThis)
+        return throwVMTypeError(exec);
+
+    return JSValue::encode(castedThis-&gt;isTailDeleted(exec));
+}
+
</ins><span class="cx"> } // namespace Inspector
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJavaScriptCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">     JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame-&gt;type(); }
</span><span class="cx">     JSC::DebuggerScope* scopeChain() const { return m_debuggerCallFrame-&gt;scope(); }
</span><span class="cx">     JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame-&gt;vmEntryGlobalObject(); }
</span><ins>+    bool isTailDeleted() const { return m_debuggerCallFrame-&gt;isTailDeleted(); }
</ins><span class="cx"> 
</span><span class="cx">     JSC::JSValue thisValue() const { return m_debuggerCallFrame-&gt;thisValue(); }
</span><span class="cx">     JSC::JSValue evaluateWithScopeExtension(const String&amp; script, JSC::JSObject* scopeExtension, NakedPtr&lt;JSC::Exception&gt;&amp; exception) const { return m_debuggerCallFrame-&gt;evaluateWithScopeExtension(script, scopeExtension, exception); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorScriptDebugServercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx"> 
</span><span class="cx">     switch (breakpointAction.type) {
</span><span class="cx">     case ScriptBreakpointActionTypeLog: {
</span><del>-        dispatchBreakpointActionLog(debuggerCallFrame-&gt;exec(), breakpointAction.data);
</del><ins>+        dispatchBreakpointActionLog(debuggerCallFrame-&gt;globalExec(), breakpointAction.data);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     case ScriptBreakpointActionTypeEvaluate: {
</span><span class="lines">@@ -97,21 +97,21 @@
</span><span class="cx">         JSObject* scopeExtensionObject = nullptr;
</span><span class="cx">         debuggerCallFrame-&gt;evaluateWithScopeExtension(breakpointAction.data, scopeExtensionObject, exception);
</span><span class="cx">         if (exception)
</span><del>-            reportException(debuggerCallFrame-&gt;exec(), exception);
</del><ins>+            reportException(debuggerCallFrame-&gt;globalExec(), exception);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     case ScriptBreakpointActionTypeSound:
</span><del>-        dispatchBreakpointActionSound(debuggerCallFrame-&gt;exec(), breakpointAction.identifier);
</del><ins>+        dispatchBreakpointActionSound(debuggerCallFrame-&gt;globalExec(), breakpointAction.identifier);
</ins><span class="cx">         break;
</span><span class="cx">     case ScriptBreakpointActionTypeProbe: {
</span><span class="cx">         NakedPtr&lt;Exception&gt; exception;
</span><span class="cx">         JSObject* scopeExtensionObject = nullptr;
</span><span class="cx">         JSValue result = debuggerCallFrame-&gt;evaluateWithScopeExtension(breakpointAction.data, scopeExtensionObject, exception);
</span><ins>+        JSC::ExecState* exec = debuggerCallFrame-&gt;globalExec();
</ins><span class="cx">         if (exception)
</span><del>-            reportException(debuggerCallFrame-&gt;exec(), exception);
</del><ins>+            reportException(exec, exception);
</ins><span class="cx">         
</span><del>-        JSC::ExecState* state = debuggerCallFrame-&gt;scope()-&gt;globalObject()-&gt;globalExec();
-        dispatchBreakpointActionProbe(state, breakpointAction, exception ? exception-&gt;value() : result);
</del><ins>+        dispatchBreakpointActionProbe(exec, breakpointAction, exception ? exception-&gt;value() : result);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -72,7 +72,8 @@
</span><span class="cx">                 { &quot;name&quot;: &quot;functionName&quot;, &quot;type&quot;: &quot;string&quot;, &quot;description&quot;: &quot;Name of the JavaScript function called on this call frame.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;location&quot;, &quot;$ref&quot;: &quot;Location&quot;, &quot;description&quot;: &quot;Location in the source code.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;scopeChain&quot;, &quot;type&quot;: &quot;array&quot;, &quot;items&quot;: { &quot;$ref&quot;: &quot;Scope&quot; }, &quot;description&quot;: &quot;Scope chain for this call frame.&quot; },
</span><del>-                { &quot;name&quot;: &quot;this&quot;, &quot;$ref&quot;: &quot;Runtime.RemoteObject&quot;, &quot;description&quot;: &quot;&lt;code&gt;this&lt;/code&gt; object for this call frame.&quot; }
</del><ins>+                { &quot;name&quot;: &quot;this&quot;, &quot;$ref&quot;: &quot;Runtime.RemoteObject&quot;, &quot;description&quot;: &quot;&lt;code&gt;this&lt;/code&gt; object for this call frame.&quot; },
+                { &quot;name&quot;: &quot;isTailDeleted&quot;, &quot;type&quot;: &quot;boolean&quot;, &quot;description&quot;: &quot;Is the current frame tail deleted from a tail call.&quot; }
</ins><span class="cx">             ],
</span><span class="cx">             &quot;description&quot;: &quot;JavaScript call frame. Array of call frames form the call stack.&quot;
</span><span class="cx">         },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterShadowChickencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;ShadowChicken.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CodeBlock.h&quot;
</ins><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;ShadowChickenInlines.h&quot;
</span><span class="cx"> #include &lt;wtf/ListDump.h&gt;
</span><span class="lines">@@ -112,7 +113,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (verbose)
</span><del>-        dataLog(&quot;    Highest point since last time: &quot;, RawPointer(highestPointSinceLastTime), &quot;\n&quot;);
</del><ins>+        dataLog(&quot;Highest point since last time: &quot;, RawPointer(highestPointSinceLastTime), &quot;\n&quot;);
</ins><span class="cx">     
</span><span class="cx">     while (!m_stack.isEmpty() &amp;&amp; (m_stack.last().frame &lt; highestPointSinceLastTime || m_stack.last().isTailDeleted))
</span><span class="cx">         m_stack.removeLast();
</span><span class="lines">@@ -128,11 +129,17 @@
</span><span class="cx">         for (unsigned i = 0; i &lt; logCursorIndex; ++i) {
</span><span class="cx">             Packet&amp; packet = m_log[i];
</span><span class="cx">             if (packet.isTail() &amp;&amp; packet.frame == m_stack.last().frame) {
</span><del>-                m_stack.last().isTailDeleted = true;
</del><ins>+                Frame&amp; frame = m_stack.last();
+                frame.thisValue = packet.thisValue;
+                frame.scope = packet.scope;
+                frame.codeBlock = packet.codeBlock;
+                frame.callSiteIndex = packet.callSiteIndex;
+                frame.isTailDeleted = true;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx">     
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;    Revised stack: &quot;, listDump(m_stack), &quot;\n&quot;);
</span><span class="lines">@@ -164,7 +171,13 @@
</span><span class="cx">                 shadowIndex++;
</span><span class="cx">                 continue;
</span><span class="cx">             }
</span><del>-            if (m_stack[shadowIndex] == stackRightNow[rightNowIndex]) {
</del><ins>+
+            // We specifically don't use operator== here because we are using a less
+            // strict filter on equality of frames. For example, the scope pointer
+            // could change, but we wouldn't want to consider the frames different entities
+            // because of that because it's natural for the program to change scopes.
+            if (m_stack[shadowIndex].frame == stackRightNow[rightNowIndex].frame
+                &amp;&amp; m_stack[shadowIndex].callee == stackRightNow[rightNowIndex].callee) {
</ins><span class="cx">                 shadowIndex++;
</span><span class="cx">                 rightNowIndex++;
</span><span class="cx">                 continue;
</span><span class="lines">@@ -193,8 +206,7 @@
</span><span class="cx">     // Set everything up so that we know where the top frame is in the log.
</span><span class="cx">     unsigned indexInLog = logCursorIndex;
</span><span class="cx">     
</span><del>-    auto advanceIndexInLogTo =
-        [&amp;] (CallFrame* frame, JSObject* callee, CallFrame* callerFrame) -&gt; bool {
</del><ins>+    auto advanceIndexInLogTo = [&amp;] (CallFrame* frame, JSObject* callee, CallFrame* callerFrame) -&gt; bool {
</ins><span class="cx">         if (verbose)
</span><span class="cx">             dataLog(&quot;    Advancing to frame = &quot;, RawPointer(frame), &quot; from indexInLog = &quot;, indexInLog, &quot;\n&quot;);
</span><span class="cx">         if (indexInLog &gt; logCursorIndex) {
</span><span class="lines">@@ -278,8 +290,8 @@
</span><span class="cx">                     
</span><span class="cx">                     if (!indexInLog)
</span><span class="cx">                         break;
</span><del>-                    Packet lastPacket = m_log[indexInLog - 1];
-                    if (!lastPacket.isTail()) {
</del><ins>+                    Packet tailPacket = m_log[indexInLog - 1];
+                    if (!tailPacket.isTail()) {
</ins><span class="cx">                         // Last frame that we recorded was not the outcome of a tail call. So, there
</span><span class="cx">                         // will not be any more deleted frames.
</span><span class="cx">                         // FIXME: We might want to have a filter here. Consider that this was a tail
</span><span class="lines">@@ -290,14 +302,19 @@
</span><span class="cx">                     }
</span><span class="cx">                     indexInLog--; // Skip over the tail packet.
</span><span class="cx">                     
</span><del>-                    if (!advanceIndexInLogTo(lastPacket.frame, nullptr, nullptr)) {
-                        // We were unable to locate the prologue packet for this tail packet. That's
-                        // quite suspect, so give up.
</del><ins>+                    if (!advanceIndexInLogTo(tailPacket.frame, nullptr, nullptr)) {
+                        // We were unable to locate the prologue packet for this tail packet.
+                        // This is rare but can happen in a situation like:
+                        // function foo() {
+                        //     ... call some deeply tail-recursive function, causing a random number of log processings.
+                        //     return bar(); // tail call
+                        // }
</ins><span class="cx">                         break;
</span><span class="cx">                     }
</span><span class="cx">                     Packet packet = m_log[indexInLog];
</span><span class="cx">                     bool isTailDeleted = true;
</span><del>-                    toPush.append(Frame(packet.callee, packet.frame, isTailDeleted));
</del><ins>+                    RELEASE_ASSERT(tailPacket.scope-&gt;inherits(JSScope::info()));
+                    toPush.append(Frame(packet.callee, packet.frame, isTailDeleted, tailPacket.thisValue, tailPacket.scope, tailPacket.codeBlock, tailPacket.callSiteIndex));
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">             if (callFrame == highestPointSinceLastTime) {
</span><span class="lines">@@ -305,12 +322,22 @@
</span><span class="cx">                     dataLog(&quot;    Bailing at &quot;, RawPointer(callFrame), &quot; because it's the highest point since last time.\n&quot;);
</span><span class="cx">                 return StackVisitor::Done;
</span><span class="cx">             }
</span><del>-            advanceIndexInLogTo(callFrame, callFrame-&gt;callee(), callFrame-&gt;callerFrame());
</del><ins>+            bool foundFrame = advanceIndexInLogTo(callFrame, callFrame-&gt;callee(), callFrame-&gt;callerFrame());
</ins><span class="cx">             bool isTailDeleted = false;
</span><del>-            toPush.append(Frame(visitor-&gt;callee(), callFrame, isTailDeleted));
</del><ins>+            JSScope* scope = nullptr;
+            CodeBlock* codeBlock = callFrame-&gt;codeBlock();
+            if (codeBlock &amp;&amp; codeBlock-&gt;wasCompiledWithDebuggingOpcodes() &amp;&amp; codeBlock-&gt;scopeRegister().isValid()) {
+                scope = callFrame-&gt;scope(codeBlock-&gt;scopeRegister().offset());
+                RELEASE_ASSERT(scope-&gt;inherits(JSScope::info()));
+            } else if (foundFrame) {
+                scope = m_log[indexInLog].scope;
+                if (scope)
+                    RELEASE_ASSERT(scope-&gt;inherits(JSScope::info()));
+            }
+            toPush.append(Frame(visitor-&gt;callee(), callFrame, isTailDeleted, callFrame-&gt;thisValue(), scope, codeBlock, callFrame-&gt;callSiteIndex()));
</ins><span class="cx">             return StackVisitor::Continue;
</span><span class="cx">         });
</span><del>-    
</del><ins>+
</ins><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;    Pushing: &quot;, listDump(toPush), &quot;\n&quot;);
</span><span class="cx">     
</span><span class="lines">@@ -329,23 +356,28 @@
</span><span class="cx"> 
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;    After pushing: &quot;, *this, &quot;\n&quot;);
</span><del>-    
-    // Remove tail frames until the stack is small enough again.
-    const unsigned stackSizeLimit = Options::shadowChickenStackSizeLimit();
-    if (m_stack.size() &gt; stackSizeLimit) {
-        unsigned dstIndex = 0;
-        unsigned srcIndex = 0;
-        unsigned size = m_stack.size();
-        while (srcIndex &lt; m_stack.size()) {
-            Frame frame = m_stack[srcIndex++];
-            if (size &gt; stackSizeLimit &amp;&amp; frame.isTailDeleted) {
-                size--;
-                continue;
</del><ins>+
+    // Remove tail frames until the number of tail deleted frames is small enough.
+    const unsigned maxTailDeletedFrames = Options::shadowChickenMaxTailDeletedFramesSize();
+    if (m_stack.size() &gt; maxTailDeletedFrames) {
+        unsigned numberOfTailDeletedFrames = 0;
+        for (const Frame&amp; frame : m_stack) {
+            if (frame.isTailDeleted)
+                numberOfTailDeletedFrames++;
+        }
+        if (numberOfTailDeletedFrames &gt; maxTailDeletedFrames) {
+            unsigned dstIndex = 0;
+            unsigned srcIndex = 0;
+            while (srcIndex &lt; m_stack.size()) {
+                Frame frame = m_stack[srcIndex++];
+                if (numberOfTailDeletedFrames &gt; maxTailDeletedFrames &amp;&amp; frame.isTailDeleted) {
+                    numberOfTailDeletedFrames--;
+                    continue;
+                }
+                m_stack[dstIndex++] = frame;
</ins><span class="cx">             }
</span><del>-            m_stack[dstIndex++] = frame;
</del><ins>+            m_stack.resize(dstIndex);
</ins><span class="cx">         }
</span><del>-        RELEASE_ASSERT(dstIndex == size);
-        m_stack.resize(size);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (verbose)
</span><span class="lines">@@ -358,10 +390,23 @@
</span><span class="cx">         JSObject* callee = m_log[i].callee;
</span><span class="cx">         if (callee != Packet::tailMarker() &amp;&amp; callee != Packet::throwMarker())
</span><span class="cx">             visitor.appendUnbarrieredReadOnlyPointer(callee);
</span><ins>+        if (callee != Packet::throwMarker())
+            visitor.appendUnbarrieredReadOnlyPointer(m_log[i].scope);
+        if (callee == Packet::tailMarker()) {
+            visitor.appendUnbarrieredValue(&amp;m_log[i].thisValue);
+            visitor.appendUnbarrieredReadOnlyPointer(m_log[i].codeBlock);
+        }
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    for (Frame&amp; frame : m_stack)
</del><ins>+    for (unsigned i = m_stack.size(); i--; ) {
+        Frame&amp; frame = m_stack[i];
+        visitor.appendUnbarrieredValue(&amp;frame.thisValue);
</ins><span class="cx">         visitor.appendUnbarrieredReadOnlyPointer(frame.callee);
</span><ins>+        if (frame.scope)
+            visitor.appendUnbarrieredReadOnlyPointer(frame.scope);
+        if (frame.codeBlock)
+            visitor.appendUnbarrieredReadOnlyPointer(frame.codeBlock);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ShadowChicken::reset()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterShadowChickenh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/ShadowChicken.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/ShadowChicken.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/interpreter/ShadowChicken.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -25,6 +25,8 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include &quot;CallFrame.h&quot;
+#include &quot;JSCJSValue.h&quot;
</ins><span class="cx"> #include &lt;wtf/FastMalloc.h&gt;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="lines">@@ -33,9 +35,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class CodeBlock;
</ins><span class="cx"> class ExecState;
</span><span class="cx"> class JSArray;
</span><span class="cx"> class JSObject;
</span><ins>+class JSScope;
</ins><span class="cx"> class LLIntOffsetsExtractor;
</span><span class="cx"> class SlotVisitor;
</span><span class="cx"> class VM;
</span><span class="lines">@@ -85,23 +89,25 @@
</span><span class="cx">             return bitwise_cast&lt;JSObject*&gt;(static_cast&lt;intptr_t&gt;(unlikelyValue + 1));
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        static Packet prologue(JSObject* callee, CallFrame* frame, CallFrame* callerFrame)
</del><ins>+        static Packet prologue(JSObject* callee, CallFrame* frame, CallFrame* callerFrame, JSScope* scope)
</ins><span class="cx">         {
</span><span class="cx">             Packet result;
</span><span class="cx">             result.callee = callee;
</span><span class="cx">             result.frame = frame;
</span><span class="cx">             result.callerFrame = callerFrame;
</span><ins>+            result.scope = scope;
</ins><span class="cx">             return result;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        // FIXME: Tail packets should hold currentScope so that the inspector can look at local
-        // variables in tail-deleted frames.
-        // https://bugs.webkit.org/show_bug.cgi?id=155722
-        static Packet tail(CallFrame* frame)
</del><ins>+        static Packet tail(CallFrame* frame, JSValue thisValue, JSScope* scope, CodeBlock* codeBlock, CallSiteIndex callSiteIndex)
</ins><span class="cx">         {
</span><span class="cx">             Packet result;
</span><span class="cx">             result.callee = tailMarker();
</span><span class="cx">             result.frame = frame;
</span><ins>+            result.thisValue = thisValue;
+            result.scope = scope;
+            result.codeBlock = codeBlock;
+            result.callSiteIndex = callSiteIndex;
</ins><span class="cx">             return result;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -120,9 +126,14 @@
</span><span class="cx">         
</span><span class="cx">         void dump(PrintStream&amp;) const;
</span><span class="cx">         
</span><ins>+        // Only tail packets have a valid thisValue, CodeBlock*, and CallSiteIndex. We grab 'this' and CodeBlock* from non tail-deleted frames from the machine frame.
+        JSValue thisValue { JSValue() };
</ins><span class="cx">         JSObject* callee { nullptr };
</span><span class="cx">         CallFrame* frame { nullptr };
</span><span class="cx">         CallFrame* callerFrame { nullptr };
</span><ins>+        JSScope* scope { nullptr };
+        CodeBlock* codeBlock { nullptr };
+        CallSiteIndex callSiteIndex;
</ins><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     struct Frame {
</span><span class="lines">@@ -130,9 +141,13 @@
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        Frame(JSObject* callee, CallFrame* frame, bool isTailDeleted)
</del><ins>+        Frame(JSObject* callee, CallFrame* frame, bool isTailDeleted, JSValue thisValue = JSValue(), JSScope* scope = nullptr, CodeBlock* codeBlock = nullptr, CallSiteIndex callSiteIndex = CallSiteIndex())
</ins><span class="cx">             : callee(callee)
</span><span class="cx">             , frame(frame)
</span><ins>+            , thisValue(thisValue)
+            , scope(scope)
+            , codeBlock(codeBlock)
+            , callSiteIndex(callSiteIndex)
</ins><span class="cx">             , isTailDeleted(isTailDeleted)
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="lines">@@ -141,6 +156,10 @@
</span><span class="cx">         {
</span><span class="cx">             return callee == other.callee
</span><span class="cx">                 &amp;&amp; frame == other.frame
</span><ins>+                &amp;&amp; thisValue == other.thisValue
+                &amp;&amp; scope == other.scope
+                &amp;&amp; codeBlock == other.codeBlock
+                &amp;&amp; callSiteIndex.bits() == other.callSiteIndex.bits()
</ins><span class="cx">                 &amp;&amp; isTailDeleted == other.isTailDeleted;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -156,6 +175,10 @@
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=155686
</span><span class="cx">         JSObject* callee { nullptr };
</span><span class="cx">         CallFrame* frame { nullptr };
</span><ins>+        JSValue thisValue { JSValue() };
+        JSScope* scope { nullptr };
+        CodeBlock* codeBlock { nullptr };
+        CallSiteIndex callSiteIndex;
</ins><span class="cx">         bool isTailDeleted { false };
</span><span class="cx">     };
</span><span class="cx">     
</span><span class="lines">@@ -166,7 +189,7 @@
</span><span class="cx">     
</span><span class="cx">     void update(VM&amp;, ExecState*);
</span><span class="cx">     
</span><del>-    // Expects this signature: (const Frame&amp; frame) -&gt; bool.
</del><ins>+    // Expects this signature: (const Frame&amp; frame) -&gt; bool. Return true to keep iterating. Return false to stop iterating.
</ins><span class="cx">     // Note that this only works right with inlining disabled, but that's OK since for now we
</span><span class="cx">     // disable inlining when the inspector is attached. It would be easy to make this work with
</span><span class="cx">     // inlining, and would mostly require that we can request that StackVisitor doesn't skip tail
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCCallHelperscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CCallHelpers.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CCallHelpers.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/jit/CCallHelpers.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -32,36 +32,40 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-void CCallHelpers::logShadowChickenProloguePacket()
</del><ins>+void CCallHelpers::logShadowChickenProloguePacket(GPRReg shadowPacket, GPRReg scratch1, GPRReg scope)
</ins><span class="cx"> {
</span><del>-    setupShadowChickenPacket();
-    storePtr(GPRInfo::callFrameRegister, Address(GPRInfo::regT1, OBJECT_OFFSETOF(ShadowChicken::Packet, frame)));
-    loadPtr(Address(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame)), GPRInfo::regT0);
-    storePtr(GPRInfo::regT0, Address(GPRInfo::regT1, OBJECT_OFFSETOF(ShadowChicken::Packet, callerFrame)));
-    loadPtr(addressFor(JSStack::Callee), GPRInfo::regT0);
-    storePtr(GPRInfo::regT0, Address(GPRInfo::regT1, OBJECT_OFFSETOF(ShadowChicken::Packet, callee)));
</del><ins>+    storePtr(GPRInfo::callFrameRegister, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, frame)));
+    loadPtr(Address(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame)), scratch1);
+    storePtr(scratch1, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, callerFrame)));
+    loadPtr(addressFor(JSStack::Callee), scratch1);
+    storePtr(scratch1, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, callee)));
+    storePtr(scope, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, scope)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CCallHelpers::logShadowChickenTailPacket()
</del><ins>+void CCallHelpers::logShadowChickenTailPacket(GPRReg shadowPacket, JSValueRegs thisRegs, GPRReg scope, CodeBlock* codeBlock, CallSiteIndex callSiteIndex)
</ins><span class="cx"> {
</span><del>-    setupShadowChickenPacket();
-    storePtr(GPRInfo::callFrameRegister, Address(GPRInfo::regT1, OBJECT_OFFSETOF(ShadowChicken::Packet, frame)));
-    storePtr(TrustedImmPtr(ShadowChicken::Packet::tailMarker()), Address(GPRInfo::regT1, OBJECT_OFFSETOF(ShadowChicken::Packet, callee)));
</del><ins>+    storePtr(GPRInfo::callFrameRegister, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, frame)));
+    storePtr(TrustedImmPtr(ShadowChicken::Packet::tailMarker()), Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, callee)));
+    storeValue(thisRegs, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, thisValue)));
+    storePtr(scope, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, scope)));
+    storePtr(TrustedImmPtr(codeBlock), Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, codeBlock)));
+    store32(TrustedImm32(callSiteIndex.bits()), Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, callSiteIndex)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CCallHelpers::setupShadowChickenPacket()
</del><ins>+void CCallHelpers::ensureShadowChickenPacket(GPRReg shadowPacket, GPRReg scratch1NonArgGPR, GPRReg scratch2)
</ins><span class="cx"> {
</span><del>-    move(TrustedImmPtr(vm()-&gt;shadowChicken().addressOfLogCursor()), GPRInfo::regT0);
-    loadPtr(Address(GPRInfo::regT0), GPRInfo::regT1);
-    Jump ok = branchPtr(Below, GPRInfo::regT1, TrustedImmPtr(vm()-&gt;shadowChicken().logEnd()));
</del><ins>+    ASSERT(!RegisterSet::argumentGPRS().get(scratch1NonArgGPR));
+    move(TrustedImmPtr(vm()-&gt;shadowChicken().addressOfLogCursor()), scratch1NonArgGPR);
+    loadPtr(Address(scratch1NonArgGPR), shadowPacket);
+    Jump ok = branchPtr(Below, shadowPacket, TrustedImmPtr(vm()-&gt;shadowChicken().logEnd()));
</ins><span class="cx">     setupArgumentsExecState();
</span><del>-    move(TrustedImmPtr(bitwise_cast&lt;void*&gt;(operationProcessShadowChickenLog)), GPRInfo::nonArgGPR0);
-    call(GPRInfo::nonArgGPR0);
-    move(TrustedImmPtr(vm()-&gt;shadowChicken().addressOfLogCursor()), GPRInfo::regT0);
-    loadPtr(Address(GPRInfo::regT0), GPRInfo::regT1);
</del><ins>+    move(TrustedImmPtr(bitwise_cast&lt;void*&gt;(operationProcessShadowChickenLog)), scratch1NonArgGPR);
+    call(scratch1NonArgGPR);
+    move(TrustedImmPtr(vm()-&gt;shadowChicken().addressOfLogCursor()), scratch1NonArgGPR);
+    loadPtr(Address(scratch1NonArgGPR), shadowPacket);
</ins><span class="cx">     ok.link(this);
</span><del>-    addPtr(TrustedImm32(sizeof(ShadowChicken::Packet)), GPRInfo::regT1, GPRInfo::regT2);
-    storePtr(GPRInfo::regT2, Address(GPRInfo::regT0));
</del><ins>+    addPtr(TrustedImm32(sizeof(ShadowChicken::Packet)), shadowPacket, scratch2);
+    storePtr(scratch2, Address(scratch1NonArgGPR));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if NUMBER_OF_ARGUMENT_REGISTERS &gt;= 4
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCCallHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CCallHelpers.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -2330,12 +2330,10 @@
</span><span class="cx">     
</span><span class="cx">     // These operations clobber all volatile registers. They assume that there is room on the top of
</span><span class="cx">     // stack to marshall call arguments.
</span><del>-    void logShadowChickenProloguePacket();
-    void logShadowChickenTailPacket();
-
-private:
-    // Leaves behind a pointer to the Packet we should write to in regT1.
-    void setupShadowChickenPacket();
</del><ins>+    void logShadowChickenProloguePacket(GPRReg shadowPacket, GPRReg scratch1, GPRReg scope);
+    void logShadowChickenTailPacket(GPRReg shadowPacket, JSValueRegs thisRegs, GPRReg scope, CodeBlock*, CallSiteIndex);
+    // Leaves behind a pointer to the Packet we should write to in shadowPacket.
+    void ensureShadowChickenPacket(GPRReg shadowPacket, GPRReg scratch1NonArgGPR, GPRReg scratch2);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1352,6 +1352,31 @@
</span><span class="cx">     jumpToEnd.link(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_log_shadow_chicken_prologue(Instruction* currentInstruction)
+{
+    updateTopCallFrame();
+    static_assert(nonArgGPR0 != regT0 &amp;&amp; nonArgGPR0 != regT2, &quot;we will have problems if this is true.&quot;);
+    GPRReg shadowPacketReg = regT0;
+    GPRReg scratch1Reg = nonArgGPR0; // This must be a non-argument register.
+    GPRReg scratch2Reg = regT2;
+    ensureShadowChickenPacket(shadowPacketReg, scratch1Reg, scratch2Reg);
+    emitGetVirtualRegister(currentInstruction[1].u.operand, regT3);
+    logShadowChickenProloguePacket(shadowPacketReg, scratch1Reg, regT3);
+}
+
+void JIT::emit_op_log_shadow_chicken_tail(Instruction* currentInstruction)
+{
+    updateTopCallFrame();
+    static_assert(nonArgGPR0 != regT0 &amp;&amp; nonArgGPR0 != regT2, &quot;we will have problems if this is true.&quot;);
+    GPRReg shadowPacketReg = regT0;
+    GPRReg scratch1Reg = nonArgGPR0; // This must be a non-argument register.
+    GPRReg scratch2Reg = regT2;
+    ensureShadowChickenPacket(shadowPacketReg, scratch1Reg, scratch2Reg);
+    emitGetVirtualRegister(currentInstruction[1].u.operand, regT2);
+    emitGetVirtualRegister(currentInstruction[2].u.operand, regT3);
+    logShadowChickenTailPacket(shadowPacketReg, JSValueRegs(regT2), regT3, m_codeBlock, CallSiteIndex(m_bytecodeOffset));
+}
+
</ins><span class="cx"> #endif // USE(JSVALUE64)
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_get_enumerable_length(Instruction* currentInstruction)
</span><span class="lines">@@ -1462,18 +1487,6 @@
</span><span class="cx">     slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emit_op_log_shadow_chicken_prologue(Instruction*)
-{
-    updateTopCallFrame();
-    logShadowChickenProloguePacket();
-}
-
-void JIT::emit_op_log_shadow_chicken_tail(Instruction*)
-{
-    updateTopCallFrame();
-    logShadowChickenTailPacket();
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1354,6 +1354,36 @@
</span><span class="cx">     jumpToEnd.link(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_log_shadow_chicken_prologue(Instruction* currentInstruction)
+{
+    updateTopCallFrame();
+    static_assert(nonArgGPR0 != regT0 &amp;&amp; nonArgGPR0 != regT2, &quot;we will have problems if this is true.&quot;);
+    GPRReg shadowPacketReg = regT0;
+    GPRReg scratch1Reg = nonArgGPR0; // This must be a non-argument register.
+    GPRReg scratch2Reg = regT2;
+    ensureShadowChickenPacket(shadowPacketReg, scratch1Reg, scratch2Reg);
+
+    scratch1Reg = regT4;
+    emitLoadPayload(currentInstruction[1].u.operand, regT3);
+    logShadowChickenProloguePacket(shadowPacketReg, scratch1Reg, regT3);
+}
+
+void JIT::emit_op_log_shadow_chicken_tail(Instruction* currentInstruction)
+{
+    updateTopCallFrame();
+    static_assert(nonArgGPR0 != regT0 &amp;&amp; nonArgGPR0 != regT2, &quot;we will have problems if this is true.&quot;);
+    GPRReg shadowPacketReg = regT0;
+    GPRReg scratch1Reg = nonArgGPR0; // This must be a non-argument register.
+    GPRReg scratch2Reg = regT2;
+    ensureShadowChickenPacket(shadowPacketReg, scratch1Reg, scratch2Reg);
+
+    emitLoadPayload(currentInstruction[1].u.operand, regT2);
+    emitLoadTag(currentInstruction[1].u.operand, regT1);
+    JSValueRegs thisRegs(regT1, regT2);
+    emitLoadPayload(currentInstruction[2].u.operand, regT3);
+    logShadowChickenTailPacket(shadowPacketReg, thisRegs, regT3, m_codeBlock, CallSiteIndex(currentInstruction));
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // USE(JSVALUE32_64)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -339,6 +339,16 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+RegisterSet RegisterSet::argumentGPRS()
+{
+    RegisterSet result;
+#if NUMBER_OF_ARGUMENT_REGISTERS
+    for (unsigned i = 0; i &lt; GPRInfo::numberOfArgumentRegisters; i++)
+        result.set(GPRInfo::toArgumentRegister(i));
+#endif
+    return result;
+}
+
</ins><span class="cx"> RegisterSet RegisterSet::registersToNotSaveForJSCall()
</span><span class="cx"> {
</span><span class="cx">     return RegisterSet(RegisterSet::vmCalleeSaveRegisters(), RegisterSet::stackRegisters(), RegisterSet::reservedHardwareRegisters());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx">     JS_EXPORT_PRIVATE static RegisterSet allGPRs();
</span><span class="cx">     JS_EXPORT_PRIVATE static RegisterSet allFPRs();
</span><span class="cx">     static RegisterSet allRegisters();
</span><ins>+    static RegisterSet argumentGPRS();
</ins><span class="cx"> 
</span><span class="cx">     static RegisterSet registersToNotSaveForJSCall();
</span><span class="cx">     static RegisterSet registersToNotSaveForCCall();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntData.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntData.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/llint/LLIntData.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;MaxFrameExtentForSlowPathCall.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><span class="cx"> #include &quot;PropertyOffset.h&quot;
</span><ins>+#include &quot;ShadowChicken.h&quot;
</ins><span class="cx"> #include &quot;WriteBarrier.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #define STATIC_ASSERT(cond) static_assert(cond, &quot;LLInt assumes &quot; #cond)
</span><span class="lines">@@ -191,6 +192,8 @@
</span><span class="cx"> 
</span><span class="cx">     STATIC_ASSERT(MarkedBlock::blockMask == ~static_cast&lt;decltype(MarkedBlock::blockMask)&gt;(0x3fff));
</span><span class="cx"> 
</span><ins>+    ASSERT(bitwise_cast&lt;uintptr_t&gt;(ShadowChicken::Packet::tailMarker()) == static_cast&lt;uintptr_t&gt;(0x7a11));
+
</ins><span class="cx">     // FIXME: make these assertions less horrible.
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">     Vector&lt;int&gt; testVector;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1542,8 +1542,8 @@
</span><span class="cx"> {
</span><span class="cx">     LLINT_BEGIN();
</span><span class="cx">     
</span><del>-    vm.shadowChicken().log(
-        vm, exec, ShadowChicken::Packet::prologue(exec-&gt;callee(), exec, exec-&gt;callerFrame()));
</del><ins>+    JSScope* scope = exec-&gt;uncheckedR(pc[1].u.operand).Register::scope();
+    vm.shadowChicken().log(vm, exec, ShadowChicken::Packet::prologue(exec-&gt;callee(), exec, exec-&gt;callerFrame(), scope));
</ins><span class="cx">     
</span><span class="cx">     LLINT_END();
</span><span class="cx"> }
</span><span class="lines">@@ -1551,8 +1551,16 @@
</span><span class="cx"> LLINT_SLOW_PATH_DECL(slow_path_log_shadow_chicken_tail)
</span><span class="cx"> {
</span><span class="cx">     LLINT_BEGIN();
</span><ins>+
+    JSValue thisValue = LLINT_OP(1).jsValue();
+    JSScope* scope = exec-&gt;uncheckedR(pc[2].u.operand).Register::scope();
</ins><span class="cx">     
</span><del>-    vm.shadowChicken().log(vm, exec, ShadowChicken::Packet::tail(exec));
</del><ins>+#if USE(JSVALUE64)
+    CallSiteIndex callSiteIndex(exec-&gt;codeBlock()-&gt;bytecodeOffset(pc));
+#else
+    CallSiteIndex callSiteIndex(pc);
+#endif
+    vm.shadowChicken().log(vm, exec, ShadowChicken::Packet::tail(exec, thisValue, scope, exec-&gt;codeBlock(), callSiteIndex));
</ins><span class="cx">     
</span><span class="cx">     LLINT_END();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -249,6 +249,9 @@
</span><span class="cx"> const IsWatched = 1
</span><span class="cx"> const IsInvalidated = 2
</span><span class="cx"> 
</span><ins>+# ShadowChicken data
+const ShadowChickenTailMarker = 0x7a11
+
</ins><span class="cx"> # Some register conventions.
</span><span class="cx"> if JSVALUE64
</span><span class="cx">     # - Use a pair of registers to represent the PC: one register for the
</span><span class="lines">@@ -1471,31 +1474,7 @@
</span><span class="cx">     storep t1, ShadowChicken::m_logCursor[t2]
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-_llint_op_log_shadow_chicken_prologue:
-    traceExecution()
-    acquireShadowChickenPacket(.opLogShadowChickenPrologueSlow)
-    storep cfr, ShadowChicken::Packet::frame[t0]
-    loadp CallerFrame[cfr], t1
-    storep t1, ShadowChicken::Packet::callerFrame[t0]
-    loadp Callee + PayloadOffset[cfr], t1
-    storep t1, ShadowChicken::Packet::callee[t0]
-    dispatch(1)
-.opLogShadowChickenPrologueSlow:
-    callSlowPath(_llint_slow_path_log_shadow_chicken_prologue)
-    dispatch(1)
</del><span class="cx"> 
</span><del>-
-_llint_op_log_shadow_chicken_tail:
-    traceExecution()
-    acquireShadowChickenPacket(.opLogShadowChickenTailSlow)
-    storep cfr, ShadowChicken::Packet::frame[t0]
-    storep 0x7a11, ShadowChicken::Packet::callee[t0]
-    dispatch(1)
-.opLogShadowChickenTailSlow:
-    callSlowPath(_llint_slow_path_log_shadow_chicken_tail)
-    dispatch(1)
-
-
</del><span class="cx"> _llint_op_switch_string:
</span><span class="cx">     traceExecution()
</span><span class="cx">     callSlowPath(_llint_slow_path_switch_string)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -2444,3 +2444,40 @@
</span><span class="cx">     storei t0, PayloadOffset[cfr, t1, 8]
</span><span class="cx">     storei Int32Tag, TagOffset[cfr, t1, 8]
</span><span class="cx">     dispatch(3)
</span><ins>+
+
+_llint_op_log_shadow_chicken_prologue:
+    traceExecution()
+    acquireShadowChickenPacket(.opLogShadowChickenPrologueSlow)
+    storep cfr, ShadowChicken::Packet::frame[t0]
+    loadp CallerFrame[cfr], t1
+    storep t1, ShadowChicken::Packet::callerFrame[t0]
+    loadp Callee + PayloadOffset[cfr], t1
+    storep t1, ShadowChicken::Packet::callee[t0]
+    loadisFromInstruction(1, t1)
+    loadi PayloadOffset[cfr, t1, 8], t1
+    storep t1, ShadowChicken::Packet::scope[t0]
+    dispatch(2)
+.opLogShadowChickenPrologueSlow:
+    callSlowPath(_llint_slow_path_log_shadow_chicken_prologue)
+    dispatch(2)
+
+
+_llint_op_log_shadow_chicken_tail:
+    traceExecution()
+    acquireShadowChickenPacket(.opLogShadowChickenTailSlow)
+    storep cfr, ShadowChicken::Packet::frame[t0]
+    storep ShadowChickenTailMarker, ShadowChicken::Packet::callee[t0]
+    loadVariable(1, t3, t2, t1)
+    storei t2, TagOffset + ShadowChicken::Packet::thisValue[t0]
+    storei t1, PayloadOffset + ShadowChicken::Packet::thisValue[t0]
+    loadisFromInstruction(2, t1)
+    loadi PayloadOffset[cfr, t1, 8], t1
+    storep t1, ShadowChicken::Packet::scope[t0]
+    loadp CodeBlock[cfr], t1
+    storep t1, ShadowChicken::Packet::codeBlock[t0]
+    storei PC, ShadowChicken::Packet::callSiteIndex[t0]
+    dispatch(3)
+.opLogShadowChickenTailSlow:
+    callSlowPath(_llint_slow_path_log_shadow_chicken_tail)
+    dispatch(3)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -2301,3 +2301,37 @@
</span><span class="cx">     loadisFromInstruction(1, t1)
</span><span class="cx">     storeq t0, [cfr, t1, 8]
</span><span class="cx">     dispatch(3)
</span><ins>+
+
+_llint_op_log_shadow_chicken_prologue:
+    traceExecution()
+    acquireShadowChickenPacket(.opLogShadowChickenPrologueSlow)
+    storep cfr, ShadowChicken::Packet::frame[t0]
+    loadp CallerFrame[cfr], t1
+    storep t1, ShadowChicken::Packet::callerFrame[t0]
+    loadp Callee + PayloadOffset[cfr], t1
+    storep t1, ShadowChicken::Packet::callee[t0]
+    loadVariable(1, t1)
+    storep t1, ShadowChicken::Packet::scope[t0]
+    dispatch(2)
+.opLogShadowChickenPrologueSlow:
+    callSlowPath(_llint_slow_path_log_shadow_chicken_prologue)
+    dispatch(2)
+
+
+_llint_op_log_shadow_chicken_tail:
+    traceExecution()
+    acquireShadowChickenPacket(.opLogShadowChickenTailSlow)
+    storep cfr, ShadowChicken::Packet::frame[t0]
+    storep ShadowChickenTailMarker, ShadowChicken::Packet::callee[t0]
+    loadVariable(1, t1)
+    storep t1, ShadowChicken::Packet::thisValue[t0]
+    loadVariable(2, t1)
+    storep t1, ShadowChicken::Packet::scope[t0]
+    loadp CodeBlock[cfr], t1
+    storep t1, ShadowChicken::Packet::codeBlock[t0]
+    storei PC, ShadowChicken::Packet::callSiteIndex[t0]
+    dispatch(3)
+.opLogShadowChickenTailSlow:
+    callSlowPath(_llint_slow_path_log_shadow_chicken_tail)
+    dispatch(3)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCodeCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CodeCache.cpp (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CodeCache.cpp        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/runtime/CodeCache.cpp        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx">     unsigned arrowContextFeature = executable-&gt;isArrowFunctionContext() ? ArrowFunctionContextFeature : 0;
</span><span class="cx">     executable-&gt;recordParse(rootNode-&gt;features() | arrowContextFeature, rootNode-&gt;hasCapturedVariables(), rootNode-&gt;firstLine(), rootNode-&gt;lastLine(), startColumn, endColumn);
</span><span class="cx"> 
</span><del>-    UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&amp;vm, executable-&gt;executableInfo());
</del><ins>+    UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&amp;vm, executable-&gt;executableInfo(), debuggerMode);
</ins><span class="cx">     unlinkedCodeBlock-&gt;recordParse(rootNode-&gt;features(), rootNode-&gt;hasCapturedVariables(), rootNode-&gt;firstLine() - source.firstLine(), lineCount, unlinkedEndColumn);
</span><span class="cx">     unlinkedCodeBlock-&gt;setSourceURLDirective(source.provider()-&gt;sourceURL());
</span><span class="cx">     unlinkedCodeBlock-&gt;setSourceMappingURLDirective(source.provider()-&gt;sourceMappingURL());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -137,7 +137,7 @@
</span><span class="cx">     v(bool, useTailCalls, true, Normal, nullptr) \
</span><span class="cx">     v(bool, alwaysUseShadowChicken, false, Normal, nullptr) \
</span><span class="cx">     v(unsigned, shadowChickenLogSize, 1000, Normal, nullptr) \
</span><del>-    v(unsigned, shadowChickenStackSizeLimit, 100000, Normal, nullptr) \
</del><ins>+    v(unsigned, shadowChickenMaxTailDeletedFramesSize, 128, Normal, nullptr) \
</ins><span class="cx">     \
</span><span class="cx">     /* dumpDisassembly implies dumpDFGDisassembly. */ \
</span><span class="cx">     v(bool, dumpDisassembly, false, Normal, &quot;dumps disassembly of all JIT compiled code upon compilation&quot;) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressshadowchickenenabledjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/shadow-chicken-enabled.js (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/shadow-chicken-enabled.js        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/JavaScriptCore/tests/stress/shadow-chicken-enabled.js        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -121,7 +121,7 @@
</span><span class="cx"> (function test5a() {
</span><span class="cx">     if (verbose)
</span><span class="cx">         print(&quot;In test5a:&quot;);
</span><del>-    var foos = 990;
</del><ins>+    var foos = 50;
</ins><span class="cx">     
</span><span class="cx">     function foo(ttl) {
</span><span class="cx">         if (ttl &lt;= 1) {
</span><span class="lines">@@ -141,7 +141,7 @@
</span><span class="cx"> (function test5b() {
</span><span class="cx">     if (verbose)
</span><span class="cx">         print(&quot;In test5b:&quot;);
</span><del>-    var foos = 9990;
</del><ins>+    var foos = 100;
</ins><span class="cx">     
</span><span class="cx">     function foo(ttl) {
</span><span class="cx">         if (ttl &lt;= 1) {
</span><span class="lines">@@ -165,7 +165,7 @@
</span><span class="cx">         print(&quot;array.push = &quot; + describe([].push));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    var foos = 99990;
</del><ins>+    var foos = 128;
</ins><span class="cx">     
</span><span class="cx">     function foo(ttl) {
</span><span class="cx">         if (ttl &lt;= 1) {
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/WebCore/ChangeLog        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-05-16  Saam barati  &lt;sbarati@apple.com&gt;
+
+        Hook up ShadowChicken to the debugger to show tail deleted frames
+        https://bugs.webkit.org/show_bug.cgi?id=156685
+        &lt;rdar://problem/25770521&gt;
+
+        Reviewed by Filip Pizlo and Mark Lam and Joseph Pecoraro.
+
+        Tests: inspector/debugger/tail-deleted-frames-this-value.html
+               inspector/debugger/tail-deleted-frames.html
+               inspector/debugger/tail-recursion.html
+
+        * ForwardingHeaders/interpreter/ShadowChicken.h: Added.
+
</ins><span class="cx"> 2016-05-16  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Don't include CSSParser.h from other headers
</span></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersinterpreterShadowChickenh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/interpreter/ShadowChicken.h (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/interpreter/ShadowChicken.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/interpreter/ShadowChicken.h        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+#ifndef WebCore_FWD_ShadowChicken_h
+#define WebCore_FWD_ShadowChicken_h
+#include &lt;JavaScriptCore/ShadowChicken.h&gt;
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2016-05-16  Saam barati  &lt;sbarati@apple.com&gt;
+
+        Hook up ShadowChicken to the debugger to show tail deleted frames
+        https://bugs.webkit.org/show_bug.cgi?id=156685
+        &lt;rdar://problem/25770521&gt;
+
+        Reviewed by Filip Pizlo and Mark Lam and Joseph Pecoraro.
+
+        This patch makes the WebInspector display tail deleted frames.
+        We show tail deleted frames with a gray [f] instead of a green
+        [f]. We also put text in the tooltip to indicate that the frame
+        is tail deleted. Other than that, tail deleted frames behave like
+        normal frames. You can evaluate in them, inspect their scope, etc.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Images/TailDeletedFunction.svg: Added.
+        * UserInterface/Images/gtk/TailDeletedFunction.svg: Added.
+        * UserInterface/Models/CallFrame.js:
+        * UserInterface/Views/CallFrameIcons.css:
+        * UserInterface/Views/CallFrameTreeElement.js:
+        * UserInterface/Views/CallFrameView.js:
+
</ins><span class="cx"> 2016-05-16  Nikita Vasilyev  &lt;nvasilyev@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Contents of Duration column are covered by always on (legacy) scroll bars
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> localizedStrings[&quot;%s delay&quot;] = &quot;%s delay&quot;;
</span><span class="cx"> localizedStrings[&quot;%s interval&quot;] = &quot;%s interval&quot;;
</span><span class="cx"> localizedStrings[&quot;(Index)&quot;] = &quot;(Index)&quot;;
</span><ins>+localizedStrings[&quot;(Tail Call)&quot;] = &quot;(Tail Call)&quot;;
</ins><span class="cx"> localizedStrings[&quot;(anonymous function)&quot;] = &quot;(anonymous function)&quot;;
</span><span class="cx"> localizedStrings[&quot;(many)&quot;] = &quot;(many)&quot;;
</span><span class="cx"> localizedStrings[&quot;(modify the boxes below to add a value)&quot;] = &quot;(modify the boxes below to add a value)&quot;;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceImagesTailDeletedFunctionsvg"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Images/TailDeletedFunction.svg (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Images/TailDeletedFunction.svg                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Images/TailDeletedFunction.svg        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+&lt;!-- Copyright © 2013 Apple Inc. All rights reserved. --&gt;
+&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; id=&quot;root&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot;&gt;
+    &lt;path fill=&quot;rgb(203, 203, 203)&quot; d=&quot;M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 Z&quot;/&gt;
+    &lt;path fill=&quot;rgb(153, 153, 153)&quot; d=&quot;M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 M 13 2 C 13.550781 2 14 2.449219 14 3 L 14 13 C 14 13.550781 13.550781 14 13 14 L 3 14 C 2.449219 14 2 13.550781 2 13 L 2 3 C 2 2.449219 2.449219 2 3 2 L 13 2&quot;/&gt;
+    &lt;path fill=&quot;rgb(166, 166, 166)&quot; d=&quot;M 10.503906 2.558594 C 8.164062 2.558594 6.574219 3.742188 5.882812 5.988281 L 4.445312 6 L 3.449219 6.007812 L 3.449219 9 L 5.15625 9 L 4.21875 12.925781 L 3.921875 14.15625 L 7.964844 14.15625 L 8.148438 13.386719 L 9.191406 9 L 11.300781 9 L 11.300781 6 L 9.902344 6 C 10.070312 5.589844 10.296875 5.589844 10.480469 5.589844 C 10.800781 5.589844 11.191406 5.652344 11.644531 5.769531 L 12.796875 6.074219 L 12.898438 4.890625 L 12.996094 3.757812 L 13.078125 2.828125 L 12.15625 2.683594 C 11.636719 2.597656 11.082031 2.558594 10.503906 2.558594 M 10.503906 3.558594 C 11.03125 3.558594 11.53125 3.59375 12 3.667969 L 11.902344 4.804688 C 11.363281 4.660156 10.890625 4.589844 10.480469 4.589844 C 9.605469 4.589844 9.050781 5.101562 8.820312 6.128906 L 8.625 7 L 10.300781 7 L 10.300781 8 L 8.398438 8 L 7.175781 13.15625 L 5.191406 13.15625 L 6.425781 8 L 4.449219 8 L 4.449219 7 L 6.613281 6.984375 L 6.742188 6.617188 C 7.2
 57812 4.578125 8.507812 3.558594 10.503906 3.558594&quot;/&gt;
+    &lt;path fill=&quot;white&quot; d=&quot;M 5.191406 13.15625 L 6.425781 8 L 4.449219 8 L 4.449219 7 L 6.613281 6.984375 L 6.742188 6.617188 C 7.257812 4.578125 8.507812 3.558594 10.5 3.558594 C 11.03125 3.558594 11.53125 3.59375 12 3.667969 L 11.902344 4.804688 C 11.363281 4.660156 10.890625 4.589844 10.484375 4.589844 C 9.605469 4.589844 9.050781 5.101562 8.820312 6.128906 L 8.625 7 L 10.300781 7 L 10.300781 8 L 8.398438 8 L 7.175781 13.15625 Z&quot;/&gt;
+&lt;/svg&gt;
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceImagesgtkTailDeletedFunctionsvg"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Images/gtk/TailDeletedFunction.svg (0 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Images/gtk/TailDeletedFunction.svg                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Images/gtk/TailDeletedFunction.svg        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;!-- Licensed under the Creative Commons Attribution-Share Alike 3.0 United States License (http://creativecommons.org/licenses/by-sa/3.0/) --&gt;
+&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; id=&quot;root&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot;&gt;
+ &lt;defs&gt;
+  &lt;radialGradient id=&quot;b&quot; cx=&quot;301&quot; cy=&quot;51.5&quot; r=&quot;19.5&quot; gradientUnits=&quot;userSpaceOnUse&quot; gradientTransform=&quot;matrix(.97063 1.9684e-8 0 .28611 -291.16 -14.63)&quot;&gt;
+   &lt;stop stop-color=&quot;#fff&quot; offset=&quot;0&quot;/&gt;
+   &lt;stop stop-color=&quot;#fff&quot; stop-opacity=&quot;0&quot; offset=&quot;1&quot;/&gt;
+  &lt;/radialGradient&gt;
+  &lt;radialGradient id=&quot;a&quot; cx=&quot;24.446&quot; cy=&quot;35.878&quot; r=&quot;20.531&quot; gradientUnits=&quot;userSpaceOnUse&quot; gradientTransform=&quot;matrix(.85696 3.2529e-7 -1.253e-7 .33010 -12.949 .77181)&quot;&gt;
+   &lt;stop stop-color=&quot;#fff&quot; offset=&quot;0&quot;/&gt;
+   &lt;stop stop-color=&quot;#dcdcdc&quot; offset=&quot;1&quot;/&gt;
+  &lt;/radialGradient&gt;
+  &lt;linearGradient id=&quot;c&quot; x1=&quot;321.57&quot; x2=&quot;311.65&quot; y1=&quot;145.52&quot; y2=&quot;118.5&quot; gradientUnits=&quot;userSpaceOnUse&quot; gradientTransform=&quot;matrix(.55569 0 0 .55568 -169.27 -70.906)&quot;&gt;
+   &lt;stop stop-color=&quot;#9b9b9b&quot; offset=&quot;0&quot;/&gt;
+   &lt;stop stop-color=&quot;#d3d7cf&quot; offset=&quot;1&quot;/&gt;
+  &lt;/linearGradient&gt;
+  &lt;linearGradient id=&quot;d&quot; x1=&quot;491.22&quot; x2=&quot;491.22&quot; y1=&quot;506.65&quot; y2=&quot;732.05&quot; gradientUnits=&quot;userSpaceOnUse&quot; gradientTransform=&quot;matrix(.093294 0 0 .093294 -35.871 -43.769)&quot;&gt;
+   &lt;stop stop-color=&quot;#888a85&quot; offset=&quot;0&quot;/&gt;
+   &lt;stop stop-color=&quot;#d3d7cf&quot; offset=&quot;1&quot;/&gt;
+  &lt;/linearGradient&gt;
+ &lt;/defs&gt;
+ &lt;rect width=&quot;15.004&quot; height=&quot;15.003&quot; x=&quot;.49815&quot; y=&quot;.49833&quot; fill=&quot;url(#a)&quot; fill-rule=&quot;evenodd&quot; stroke=&quot;url(#c)&quot; stroke-miterlimit=&quot;10&quot; rx=&quot;1.5143&quot; ry=&quot;1.5143&quot; stroke-linejoin=&quot;bevel&quot;/&gt;
+ &lt;rect width=&quot;12.997&quot; height=&quot;13&quot; x=&quot;1.5014&quot; y=&quot;1.5016&quot; fill=&quot;none&quot; stroke=&quot;#fff&quot; stroke-miterlimit=&quot;10&quot; ry=&quot;.50810&quot; stroke-linejoin=&quot;bevel&quot; rx=&quot;.50812&quot;/&gt;
+ &lt;rect width=&quot;14&quot; height=&quot;14&quot; x=&quot;1.0017&quot; y=&quot;1.0016&quot; fill=&quot;url(#b)&quot; fill-rule=&quot;evenodd&quot; rx=&quot;1.9062&quot; ry=&quot;1.9062&quot;/&gt;
+ &lt;path fill=&quot;#fff&quot; d=&quot;m9.0593 4.8342c-1.0619 0-1.8016 0.3977-2.25 0.875-0.44838 0.4773-0.61719 1.005-0.6875 1.3438l-0.0625 0.25h-0.71875a0.25002 0.25002 0 0 0 -0.0625 0 0.25002 0.25002 0 0 0 -0.09375 0.0625 0.25002 0.25002 0 0 0 -0.03125 0.03125 0.25002 0.25002 0 0 0 -0.03125 0.03125 0.25002 0.25002 0 0 0 -0.03125 0.09375l-0.1875 1.0938a0.25002 0.25002 0 0 0 0 0.03125 0.25002 0.25002 0 0 0 0 0.0625 0.25002 0.25002 0 0 0 0.125 0.15625 0.25002 0.25002 0 0 0 0.125 0.03125h0.59375l-0.84375 4.1563a0.25002 0.25002 0 0 0 0 0.0625 0.25002 0.25002 0 0 0 0 0.0625 0.25002 0.25002 0 0 0 0.09375 0.125 0.25002 0.25002 0 0 0 0.03125 0.03125 0.25002 0.25002 0 0 0 0.09375 0.03125 0.25002 0.25002 0 0 0 0.03125 0h1.4062a0.25002 0.25002 0 0 0 0.03125 0 0.25002 0.25002 0 0 0 0.09375 -0.03125 0.25002 0.25002 0 0 0 0.09375 -0.09375 0.25002 0.25002 0 0 0 0.03125 -0.0625l0.84375-4.2813h1.875a0.25002 0.25002 0 0 0 0.03125 0 0.25002 0.25002 0 0 0 0.09375 -0.03125 0.25002 0.25002 0 0 
 0 0.09375 -0.09375 0.25002 0.25002 0 0 0 0.03125 -0.0625l0.21875-1.0938a0.25002 0.25002 0 0 0 0 -0.0625 0.25002 0.25002 0 0 0 0 -0.0625 0.25002 0.25002 0 0 0 -0.0625 -0.09375 0.25002 0.25002 0 0 0 -0.03125 -0.03125 0.25002 0.25002 0 0 0 -0.0625 -0.03125 0.25002 0.25002 0 0 0 -0.09375 -0.03125h-1.7812l0.03125-0.15625c0.037755-0.19297 0.14732-0.34648 0.34375-0.46875 0.19642-0.12227 0.4762-0.21875 0.8125-0.21875 0.30479 0 0.6559 0.064823 0.78125 0.09375l0.21875 0.0625a0.25002 0.25002 0 0 0 0.0625 0 0.25002 0.25002 0 0 0 0.0625 0 0.25002 0.25002 0 0 0 0.125 -0.09375 0.25002 0.25002 0 0 0 0.03125 -0.03125 0.25002 0.25002 0 0 0 0 -0.03125l0.40625-1a0.25002 0.25002 0 0 0 0.03125 -0.03125 0.25002 0.25002 0 0 0 0 -0.0625 0.25002 0.25002 0 0 0 -0.03125 -0.09375 0.25002 0.25002 0 0 0 -0.03125 -0.0625 0.25002 0.25002 0 0 0 -0.03125 -0.03125 0.25002 0.25002 0 0 0 -0.0625 -0.03125 0.25002 0.25002 0 0 0 -0.03125 -0.03125l-0.1875-0.0625c-0.673-0.2163-1.1307-0.2185-1.4367-0.2185z&quot; displ
 ay=&quot;block&quot;/&gt;
+ &lt;path fill=&quot;url(#d)&quot; d=&quot;m9.1111 3.8039c-1.0619 0-1.8016 0.3977-2.25 0.875-0.44838 0.4773-0.61719 1.005-0.6875 1.3438l-0.0625 0.25h-0.71875a0.25002 0.25002 0 0 0 -0.0625 0 0.25002 0.25002 0 0 0 -0.09375 0.0625 0.25002 0.25002 0 0 0 -0.03125 0.03125 0.25002 0.25002 0 0 0 -0.03125 0.03125 0.25002 0.25002 0 0 0 -0.03125 0.09375l-0.1875 1.0938a0.25002 0.25002 0 0 0 0 0.03125 0.25002 0.25002 0 0 0 0 0.0625 0.25002 0.25002 0 0 0 0.125 0.15625 0.25002 0.25002 0 0 0 0.125 0.03125h0.59375l-0.84375 4.1563a0.25002 0.25002 0 0 0 0 0.0625 0.25002 0.25002 0 0 0 0 0.0625 0.25002 0.25002 0 0 0 0.09375 0.125 0.25002 0.25002 0 0 0 0.03125 0.03125 0.25002 0.25002 0 0 0 0.09375 0.03125 0.25002 0.25002 0 0 0 0.03125 0h1.4062a0.25002 0.25002 0 0 0 0.03125 0 0.25002 0.25002 0 0 0 0.09375 -0.03125 0.25002 0.25002 0 0 0 0.09375 -0.09375 0.25002 0.25002 0 0 0 0.03125 -0.0625l0.84375-4.2813h1.875a0.25002 0.25002 0 0 0 0.03125 0 0.25002 0.25002 0 0 0 0.09375 -0.03125 0.25002 0.25002 0
  0 0 0.09375 -0.09375 0.25002 0.25002 0 0 0 0.03125 -0.0625l0.2191-1.0941a0.25002 0.25002 0 0 0 0 -0.0625 0.25002 0.25002 0 0 0 0 -0.0625 0.25002 0.25002 0 0 0 -0.0625 -0.09375 0.25002 0.25002 0 0 0 -0.03125 -0.03125 0.25002 0.25002 0 0 0 -0.0625 -0.03125 0.25002 0.25002 0 0 0 -0.09375 -0.03125h-1.7812l0.03125-0.15625c0.037755-0.19297 0.14732-0.34648 0.34375-0.46875 0.19642-0.12227 0.4762-0.21875 0.8125-0.21875 0.30479 0 0.6559 0.064823 0.78125 0.09375l0.21875 0.0625a0.25002 0.25002 0 0 0 0.0625 0 0.25002 0.25002 0 0 0 0.0625 0 0.25002 0.25002 0 0 0 0.125 -0.09375 0.25002 0.25002 0 0 0 0.03125 -0.03125 0.25002 0.25002 0 0 0 0 -0.03125l0.40625-1a0.25002 0.25002 0 0 0 0.03125 -0.03125 0.25002 0.25002 0 0 0 0 -0.0625 0.25002 0.25002 0 0 0 -0.03125 -0.09375 0.25002 0.25002 0 0 0 -0.03125 -0.0625 0.25002 0.25002 0 0 0 -0.03125 -0.03125 0.25002 0.25002 0 0 0 -0.0625 -0.03125 0.25002 0.25002 0 0 0 -0.03125 -0.03125l-0.1875-0.0625c-0.6732-0.2164-1.1309-0.2186-1.4369-0.2186z&quot; di
 splay=&quot;block&quot;/&gt;
+&lt;/svg&gt;
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsCallFramejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/CallFrame.js (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/CallFrame.js        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/CallFrame.js        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> WebInspector.CallFrame = class CallFrame extends WebInspector.Object
</span><span class="cx"> {
</span><del>-    constructor(id, sourceCodeLocation, functionName, thisObject, scopeChain, nativeCode, programCode)
</del><ins>+    constructor(id, sourceCodeLocation, functionName, thisObject, scopeChain, nativeCode, programCode, isTailDeleted)
</ins><span class="cx">     {
</span><span class="cx">         super();
</span><span class="cx"> 
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx">         this._scopeChain = scopeChain || [];
</span><span class="cx">         this._nativeCode = nativeCode || false;
</span><span class="cx">         this._programCode = programCode || false;
</span><ins>+        this._isTailDeleted = isTailDeleted || false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="lines">@@ -79,6 +80,11 @@
</span><span class="cx">         return this._scopeChain;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    get isTailDeleted()
+    {
+        return this._isTailDeleted;
+    }
+
</ins><span class="cx">     saveIdentityToCookie()
</span><span class="cx">     {
</span><span class="cx">         // Do nothing. The call frame is torn down when the inspector closes, and
</span><span class="lines">@@ -132,13 +138,14 @@
</span><span class="cx">         let functionName = WebInspector.CallFrame.functionNameFromPayload(payload);
</span><span class="cx">         let nativeCode = false;
</span><span class="cx">         let programCode = WebInspector.CallFrame.programCodeFromPayload(payload);
</span><ins>+        let isTailDeleted = payload.isTailDeleted;
</ins><span class="cx"> 
</span><span class="cx">         if (sourceCodeLocation &amp;&amp; isWebInspectorConsoleEvaluationScript(sourceCodeLocation.sourceCode.sourceURL)) {
</span><span class="cx">             functionName = WebInspector.UIString(&quot;Console Evaluation&quot;);
</span><span class="cx">             programCode = true;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return new WebInspector.CallFrame(id, sourceCodeLocation, functionName, thisObject, scopeChain, nativeCode, programCode);
</del><ins>+        return new WebInspector.CallFrame(id, sourceCodeLocation, functionName, thisObject, scopeChain, nativeCode, programCode, isTailDeleted);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static fromPayload(payload)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsCallFrameIconscss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameIcons.css (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameIcons.css        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameIcons.css        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -38,3 +38,7 @@
</span><span class="cx"> .native-icon .icon {
</span><span class="cx">     content: url(../Images/Native.svg);
</span><span class="cx"> }
</span><ins>+
+.tail-deleted .icon {
+    content: url(../Images/TailDeletedFunction.svg);
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsCallFrameTreeElementjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.js (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.js        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.js        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -29,13 +29,13 @@
</span><span class="cx">     {
</span><span class="cx">         console.assert(callFrame instanceof WebInspector.CallFrame);
</span><span class="cx"> 
</span><del>-        var className = WebInspector.CallFrameView.iconClassNameForCallFrame(callFrame);
-        var title = callFrame.functionName || WebInspector.UIString(&quot;(anonymous function)&quot;);
</del><ins>+        let className = WebInspector.CallFrameView.iconClassNameForCallFrame(callFrame);
+        let title = callFrame.functionName || WebInspector.UIString(&quot;(anonymous function)&quot;);
</ins><span class="cx"> 
</span><span class="cx">         super(className, title, null, callFrame, false);
</span><span class="cx"> 
</span><span class="cx">         if (!callFrame.nativeCode &amp;&amp; callFrame.sourceCodeLocation) {
</span><del>-            var displayScriptURL = callFrame.sourceCodeLocation.displaySourceCode.url;
</del><ins>+            let displayScriptURL = callFrame.sourceCodeLocation.displaySourceCode.url;
</ins><span class="cx">             if (displayScriptURL) {
</span><span class="cx">                 this.subtitle = document.createElement(&quot;span&quot;);
</span><span class="cx">                 callFrame.sourceCodeLocation.populateLiveDisplayLocationString(this.subtitle, &quot;textContent&quot;);
</span><span class="lines">@@ -63,7 +63,10 @@
</span><span class="cx">         console.assert(this.element);
</span><span class="cx"> 
</span><span class="cx">         if (this.tooltipHandledSeparately) {
</span><del>-            var tooltipPrefix = this.mainTitle + &quot;\n&quot;;
</del><ins>+            let tailCallSuffix = &quot;&quot;;
+            if (this._callFrame.isTailDeleted)
+                tailCallSuffix = &quot; &quot; + WebInspector.UIString(&quot;(Tail Call)&quot;);
+            let tooltipPrefix = this.mainTitle + tailCallSuffix + &quot;\n&quot;;
</ins><span class="cx">             this._callFrame.sourceCodeLocation.populateLiveDisplayLocationTooltip(this.element, tooltipPrefix);
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsCallFrameViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameView.js (200980 => 200981)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameView.js        2016-05-16 23:27:27 UTC (rev 200980)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameView.js        2016-05-16 23:31:39 UTC (rev 200981)
</span><span class="lines">@@ -73,6 +73,9 @@
</span><span class="cx"> 
</span><span class="cx">     static iconClassNameForCallFrame(callFrame)
</span><span class="cx">     {
</span><ins>+        if (callFrame.isTailDeleted)
+            return WebInspector.CallFrameView.TailDeletedIcon;
+
</ins><span class="cx">         if (callFrame.programCode)
</span><span class="cx">             return WebInspector.CallFrameView.ProgramIconStyleClassName;
</span><span class="cx"> 
</span><span class="lines">@@ -92,3 +95,4 @@
</span><span class="cx"> WebInspector.CallFrameView.FunctionIconStyleClassName = &quot;function-icon&quot;;
</span><span class="cx"> WebInspector.CallFrameView.EventListenerIconStyleClassName = &quot;event-listener-icon&quot;;
</span><span class="cx"> WebInspector.CallFrameView.NativeIconStyleClassName = &quot;native-icon&quot;;
</span><ins>+WebInspector.CallFrameView.TailDeletedIcon = &quot;tail-deleted&quot;;
</ins></span></pre>
</div>
</div>

</body>
</html>