Avoid eagerly creating the JSActivation when the debugger is attached.
<https://webkit.org/b/127910>

Reviewed by Oliver Hunt.

Octane scores for this patch:
    baseline w/o WebInspector: 11621
    patched  w/o WebInspector: 11801
    baseline w/ WebInspector:  3295
    patched  w/ WebInspector:  7070   2.1x improvement

1. Because debugger can potentially create a closure from any call frame,
   we need every function to allocate an activation register and check for
   the need to tear off the activation (if needed) on return.

   However, we do not need to eagerly create the activation object.
   This patch implements the optimization to defer creation of the
   activation object until we actually need it i.e. when:

   1. We encounter a "eval", "with", or "catch" statement.
   2. We've paused in the debugger, and called DebuggerCallFrame::scope().

2. The UnlinkedCodeBlock provides a needsFullScopeChain flag that is used
   to indicate whether the linked CodeBlock will need an activation
   object or not. Under normal circumstances, needsFullScopeChain and
   needsActivation are synonymous. However, with a debugger attached, we
   want the CodeBlock to always allocate an activationRegister even if
   it does not need a "full scope chain".

   Hence, we apply the following definitions to the "flags":

   1. UnlinkedCodeBlock::needsFullScopeChain() - this flag indicates that
      the parser discovered JS artifacts (e.g. use of "eval", "with", etc.)
      that requires an activation.

      BytecodeGenerator's destinationForAssignResult() and leftHandSideNeedsCopy()
      checks needsFullScopeChain().

   2. UnlinkedCodeBlock::hasActivationRegister() - this flag indicates that
      an activation register was created for the UnlinkedCodeBlock either
      because it needsFullScopeChain() or because the debugger is attached.

   3. CodeBlock::needsActivation() reflects UnlinkedCodeBlock's
      hasActivationRegister().

3. Introduced BytecodeGenerator::emitPushFunctionNameScope() and
   BytecodeGenerator::emitPushCatchScope() because the JSNameScope
   pushed for a function name cannot be popped unlike the JSNameScope
   pushed for a "catch". Hence, we have 2 functions to handle the 2 cases
   differently.

4. Removed DebuggerCallFrame::evaluateWithCallFrame() and require that all
   debugger evaluations go through the DebuggerCallFrame::evaluate(). This
   ensures that debugger evaluations require a DebuggerCallFrame.

   DebuggerCallFrame::evaluateWithCallFrame() was used previously because
   we didn't want to instantiate a DebuggerCallFrame on every debug hook
   callback. However, we now only call the debug hooks when needed, and
   this no longer poses a performance problem.

   In addition, when the debug hook does an eval to test a breakpoint
   condition, it is incorrect to evaluate it without a DebuggerCallFrame
   anyway.

5. Added some utility functions to the CallFrame to make it easier to work
   with the activation register in the frame (if present). These utility
   functions should only be called if the CodeBlock::needsActivation() is
   true (which indicates the presence of the activation register). The
   utlity functions are:

   1. CallFrame::hasActivation()
      - checks if the frame's activation object has been created.

   2. CallFrame::activation()
      - returns the frame's activation object.

   3. CallFrame::uncheckedActivation()
      - returns the JSValue in the frame's activation register. May be null.

   4. CallFrame::setActivation()
      - sets the frame's activation object.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
- added symbollic dumping of ResolveMode and ResolveType values for some
  bytecodes.
(JSC::CodeBlock::CodeBlock):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::activationRegister):
(JSC::CodeBlock::uncheckedActivationRegister):
(JSC::CodeBlock::needsActivation):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::needsFullScopeChain):
(JSC::UnlinkedCodeBlock::hasActivationRegister):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::resolveCallee):
(JSC::BytecodeGenerator::createActivationIfNecessary):
(JSC::BytecodeGenerator::emitCallEval):
(JSC::BytecodeGenerator::emitReturn):
(JSC::BytecodeGenerator::emitPushWithScope):
(JSC::BytecodeGenerator::emitPushFunctionNameScope):
(JSC::BytecodeGenerator::emitPushCatchScope):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::TryNode::emitBytecode):
* debugger/Debugger.cpp:
(JSC::Debugger::hasBreakpoint):
(JSC::Debugger::pauseIfNeeded):
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::scope):
(JSC::DebuggerCallFrame::evaluate):
* debugger/DebuggerCallFrame.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseCodeBlock):
* dfg/DFGGraph.h:
- Removed an unused function DFGGraph::needsActivation().
* interpreter/CallFrame.cpp:
(JSC::CallFrame::activation):
(JSC::CallFrame::setActivation):
* interpreter/CallFrame.h:
(JSC::ExecState::hasActivation):
(JSC::ExecState::registers):
* interpreter/CallFrameInlines.h:
(JSC::CallFrame::uncheckedActivation):
* interpreter/Interpreter.cpp:
(JSC::unwindCallFrame):
(JSC::Interpreter::unwind):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):

* runtime/JSScope.cpp:
* runtime/JSScope.h:
(JSC::resolveModeName):
(JSC::resolveTypeName):
- utility functions for decoding names of the ResolveMode and ResolveType.
  These are used in CodeBlock::dumpBytecode().



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@163223 268f45cc-cd09-0410-ab3c-d52691b4dbfc
21 files changed