[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

barraclough at apple.com barraclough at apple.com
Wed Dec 22 15:57:01 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 4334c30444b410f67b64e55d232639d232913a79
Author: barraclough at apple.com <barraclough at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Nov 17 03:03:34 2010 +0000

    Bug 49635 - Profiler implementation is fragile
    
    Reviewed by Sam Weinig.
    
    The profile presently requires the exception handling mechanism to explicitly
    remove all stack frames that are exited during the exception unwind mechanism.
    This is fragile in a number of ways:
      * We have to change bytecode register allocation when compiling code to run
        when profiling, to preserve the callee function (this is also required to
        call did_call after the call has returned).
      * In the JIT we have to maintain additional data structures
        (CodeBlock::RareData::m_functionRegisterInfos) to map back to the register
        containing the callee.
      * In the interpreter we use 'magic values' to offset into the instruction
        stream to rediscover the register containing the function.
    
    Instead, move profiling into the head and tail of functions.
      * This correctly accounts the cost of the call itself to the caller.
      * This allows us to access the callee function object from the callframe.
      * This means that at the point a call is made we can track the stack depth
        on the ProfileNode.
      * When unwinding we can simply report the depth at which the exception is
        being handled - all call frames above this level are freed.
    
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::dump):
    (JSC::CodeBlock::shrinkToFit):
    * bytecode/CodeBlock.h:
    (JSC::CodeBlock::bytecodeOffset):
    (JSC::CodeBlock::methodCallLinkInfo):
    * bytecode/Opcode.h:
    * bytecompiler/BytecodeGenerator.cpp:
    (JSC::BytecodeGenerator::BytecodeGenerator):
    (JSC::BytecodeGenerator::emitCall):
    (JSC::BytecodeGenerator::emitCallVarargs):
    (JSC::BytecodeGenerator::emitReturn):
    (JSC::BytecodeGenerator::emitConstruct):
    * bytecompiler/BytecodeGenerator.h:
    (JSC::CallArguments::count):
    * bytecompiler/NodesCodegen.cpp:
    (JSC::CallArguments::CallArguments):
    * interpreter/Interpreter.cpp:
    (JSC::ProfileHostCall::ProfileHostCall):
    (JSC::ProfileHostCall::~ProfileHostCall):
    (JSC::Interpreter::unwindCallFrame):
    (JSC::Interpreter::throwException):
    (JSC::Interpreter::execute):
    (JSC::Interpreter::executeCall):
    (JSC::Interpreter::executeConstruct):
    (JSC::Interpreter::privateExecute):
    * jit/JIT.cpp:
    (JSC::JIT::privateCompileMainPass):
    * jit/JIT.h:
    * jit/JITOpcodes.cpp:
    (JSC::JIT::emit_op_profile_has_called):
    (JSC::JIT::emit_op_profile_will_return):
    * jit/JITOpcodes32_64.cpp:
    (JSC::JIT::emit_op_profile_has_called):
    (JSC::JIT::emit_op_profile_will_return):
    * jit/JITStubs.cpp:
    (JSC::DEFINE_STUB_FUNCTION):
    * jit/JITStubs.h:
    * profiler/Profile.cpp:
    (JSC::Profile::Profile):
    * profiler/ProfileGenerator.cpp:
    (JSC::ProfileGenerator::addParentForConsoleStart):
    (JSC::ProfileGenerator::willExecute):
    (JSC::ProfileGenerator::didExecute):
    (JSC::ProfileGenerator::exceptionUnwind):
    (JSC::ProfileGenerator::stopProfiling):
    * profiler/ProfileGenerator.h:
    * profiler/ProfileNode.cpp:
    (JSC::ProfileNode::ProfileNode):
    (JSC::ProfileNode::willExecute):
    * profiler/ProfileNode.h:
    (JSC::ProfileNode::create):
    (JSC::ProfileNode::operator==):
    (JSC::ProfileNode::exec):
    * profiler/Profiler.cpp:
    (JSC::dispatchFunctionToProfiles):
    (JSC::Profiler::hasCalled):
    (JSC::Profiler::willEvaluate):
    (JSC::Profiler::willReturn):
    (JSC::Profiler::didEvaluate):
    (JSC::Profiler::exceptionUnwind):
    * profiler/Profiler.h:
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@72160 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 49856f0..3402408 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,93 @@
+2010-11-16  Gavin Barraclough  <barraclough at apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Bug 49635 - Profiler implementation is fragile
+
+        The profile presently requires the exception handling mechanism to explicitly
+        remove all stack frames that are exited during the exception unwind mechanism.
+        This is fragile in a number of ways:
+          * We have to change bytecode register allocation when compiling code to run
+            when profiling, to preserve the callee function (this is also required to
+            call did_call after the call has returned).
+          * In the JIT we have to maintain additional data structures
+            (CodeBlock::RareData::m_functionRegisterInfos) to map back to the register
+            containing the callee.
+          * In the interpreter we use 'magic values' to offset into the instruction
+            stream to rediscover the register containing the function.
+
+        Instead, move profiling into the head and tail of functions.
+          * This correctly accounts the cost of the call itself to the caller.
+          * This allows us to access the callee function object from the callframe.
+          * This means that at the point a call is made we can track the stack depth
+            on the ProfileNode.
+          * When unwinding we can simply report the depth at which the exception is
+            being handled - all call frames above this level are freed.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dump):
+        (JSC::CodeBlock::shrinkToFit):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::bytecodeOffset):
+        (JSC::CodeBlock::methodCallLinkInfo):
+        * bytecode/Opcode.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitCall):
+        (JSC::BytecodeGenerator::emitCallVarargs):
+        (JSC::BytecodeGenerator::emitReturn):
+        (JSC::BytecodeGenerator::emitConstruct):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::CallArguments::count):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::CallArguments::CallArguments):
+        * interpreter/Interpreter.cpp:
+        (JSC::ProfileHostCall::ProfileHostCall):
+        (JSC::ProfileHostCall::~ProfileHostCall):
+        (JSC::Interpreter::unwindCallFrame):
+        (JSC::Interpreter::throwException):
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::privateExecute):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_profile_has_called):
+        (JSC::JIT::emit_op_profile_will_return):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_profile_has_called):
+        (JSC::JIT::emit_op_profile_will_return):
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        * jit/JITStubs.h:
+        * profiler/Profile.cpp:
+        (JSC::Profile::Profile):
+        * profiler/ProfileGenerator.cpp:
+        (JSC::ProfileGenerator::addParentForConsoleStart):
+        (JSC::ProfileGenerator::willExecute):
+        (JSC::ProfileGenerator::didExecute):
+        (JSC::ProfileGenerator::exceptionUnwind):
+        (JSC::ProfileGenerator::stopProfiling):
+        * profiler/ProfileGenerator.h:
+        * profiler/ProfileNode.cpp:
+        (JSC::ProfileNode::ProfileNode):
+        (JSC::ProfileNode::willExecute):
+        * profiler/ProfileNode.h:
+        (JSC::ProfileNode::create):
+        (JSC::ProfileNode::operator==):
+        (JSC::ProfileNode::exec):
+        * profiler/Profiler.cpp:
+        (JSC::dispatchFunctionToProfiles):
+        (JSC::Profiler::hasCalled):
+        (JSC::Profiler::willEvaluate):
+        (JSC::Profiler::willReturn):
+        (JSC::Profiler::didEvaluate):
+        (JSC::Profiler::exceptionUnwind):
+        * profiler/Profiler.h:
+
 2010-11-16  Brian Weinstein  <bweinstein at apple.com>
 
         Reviewed by Adam Roben and Steve Falkenburg.
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index bcd2af3..e2477ef 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1220,14 +1220,12 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);
             break;
         }
-        case op_profile_will_call: {
-            int function = (++it)->u.operand;
-            printf("[%4d] profile_will_call %s\n", location, registerName(exec, function).data());
+        case op_profile_has_called: {
+            printf("[%4d] op_profile_has_called\n", location);
             break;
         }
-        case op_profile_did_call: {
-            int function = (++it)->u.operand;
-            printf("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).data());
+        case op_profile_will_return: {
+            printf("[%4d] op_profile_will_return\n", location);
             break;
         }
         case op_end: {
@@ -1662,32 +1660,6 @@ void CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned
     return;
 }
 
-#if ENABLE(JIT)
-bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
-{
-    ASSERT(bytecodeOffset < m_instructionCount);
-
-    if (!m_rareData || !m_rareData->m_functionRegisterInfos.size())
-        return false;
-
-    int low = 0;
-    int high = m_rareData->m_functionRegisterInfos.size();
-    while (low < high) {
-        int mid = low + (high - low) / 2;
-        if (m_rareData->m_functionRegisterInfos[mid].bytecodeOffset <= bytecodeOffset)
-            low = mid + 1;
-        else
-            high = mid;
-    }
-
-    if (!low || m_rareData->m_functionRegisterInfos[low - 1].bytecodeOffset != bytecodeOffset)
-        return false;
-
-    functionRegisterIndex = m_rareData->m_functionRegisterInfos[low - 1].functionRegisterIndex;
-    return true;
-}
-#endif
-
 #if ENABLE(INTERPRETER)
 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
 {
@@ -1762,9 +1734,6 @@ void CodeBlock::shrinkToFit()
         m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
         m_rareData->m_characterSwitchJumpTables.shrinkToFit();
         m_rareData->m_stringSwitchJumpTables.shrinkToFit();
-#if ENABLE(JIT)
-        m_rareData->m_functionRegisterInfos.shrinkToFit();
-#endif
     }
 }
 
diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h
index 54acd50..5298327 100644
--- a/JavaScriptCore/bytecode/CodeBlock.h
+++ b/JavaScriptCore/bytecode/CodeBlock.h
@@ -351,8 +351,6 @@ namespace JSC {
                 return 1;
             return binaryChop<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callReturnIndexVector().begin(), callReturnIndexVector().size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset;
         }
-        
-        bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
 #endif
 #if ENABLE(INTERPRETER)
         unsigned bytecodeOffset(CallFrame*, Instruction* returnAddress)
@@ -443,8 +441,6 @@ namespace JSC {
 
         void addMethodCallLinkInfos(unsigned n) { m_methodCallLinkInfos.grow(n); }
         MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
-
-        void addFunctionRegisterInfo(unsigned bytecodeOffset, int functionIndex) { createRareDataIfNecessary(); m_rareData->m_functionRegisterInfos.append(FunctionRegisterInfo(bytecodeOffset, functionIndex)); }
 #endif
 
         // Exception handling support
@@ -598,10 +594,6 @@ namespace JSC {
             Vector<StringJumpTable> m_stringSwitchJumpTables;
 
             EvalCodeCache m_evalCodeCache;
-
-#if ENABLE(JIT)
-            Vector<FunctionRegisterInfo> m_functionRegisterInfos;
-#endif
         };
         OwnPtr<RareData> m_rareData;
     };
diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h
index 6c1c6b2..2bfe58d 100644
--- a/JavaScriptCore/bytecode/Opcode.h
+++ b/JavaScriptCore/bytecode/Opcode.h
@@ -191,8 +191,8 @@ namespace JSC {
         macro(op_sret, 2) \
         \
         macro(op_debug, 4) \
-        macro(op_profile_will_call, 2) \
-        macro(op_profile_did_call, 2) \
+        macro(op_profile_has_called, 1) \
+        macro(op_profile_will_return, 1) \
         \
         macro(op_end, 2) // end must be the last opcode in the list
 
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 1fa5aa4..00673d8 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -324,7 +324,11 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
         m_codeBlock->setNeedsFullScopeChain(true);
 
     codeBlock->setGlobalData(m_globalData);
-    
+
+
+    if (m_shouldEmitProfileHooks)
+        emitOpcode(op_profile_has_called);
+   
     emitOpcode(op_enter);
     if (m_codeBlock->needsFullScopeChain()) {
         m_activationRegister = addVar();
@@ -1633,9 +1637,6 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
     ASSERT(func->refCount());
 
-    if (m_shouldEmitProfileHooks)
-        emitMove(callArguments.profileHookRegister(), func);
-
     // Generate code for arguments.
     unsigned argumentIndex = 0;
     for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next)
@@ -1646,15 +1647,6 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
         callFrame.append(newTemporary());
 
-    if (m_shouldEmitProfileHooks) {
-        emitOpcode(op_profile_will_call);
-        instructions().append(callArguments.profileHookRegister()->index());
-
-#if ENABLE(JIT)
-        m_codeBlock->addFunctionRegisterInfo(instructions().size(), callArguments.profileHookRegister()->index());
-#endif
-    }
-
     emitExpressionInfo(divot, startOffset, endOffset);
 
 #if ENABLE(JIT)
@@ -1671,11 +1663,6 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
         instructions().append(dst->index()); // dst
     }
 
-    if (m_shouldEmitProfileHooks) {
-        emitOpcode(op_profile_did_call);
-        instructions().append(callArguments.profileHookRegister()->index());
-    }
-
     return dst;
 }
 
@@ -1694,14 +1681,6 @@ RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func
     ASSERT(func->refCount());
     ASSERT(thisRegister->refCount());
     ASSERT(dst != func);
-    if (m_shouldEmitProfileHooks) {
-        emitOpcode(op_profile_will_call);
-        instructions().append(func->index());
-        
-#if ENABLE(JIT)
-        m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index());
-#endif
-    }
     
     emitExpressionInfo(divot, startOffset, endOffset);
     
@@ -1714,10 +1693,6 @@ RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func
         emitOpcode(op_call_put_result);
         instructions().append(dst->index()); // dst
     }
-    if (m_shouldEmitProfileHooks) {
-        emitOpcode(op_profile_did_call);
-        instructions().append(func->index());
-    }
     return dst;
 }
 
@@ -1733,6 +1708,9 @@ RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
         instructions().append(m_codeBlock->argumentsRegister());
     }
 
+    if (m_shouldEmitProfileHooks)
+        emitOpcode(op_profile_will_return);
+
     // Constructors use op_ret_object_or_this to check the result is an
     // object, unless we can trivially determine the check is not
     // necessary (currently, if the return value is 'this').
@@ -1756,9 +1734,6 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
 {
     ASSERT(func->refCount());
 
-    if (m_shouldEmitProfileHooks)
-        emitMove(callArguments.profileHookRegister(), func);
-
     // Generate code for arguments.
     unsigned argumentIndex = 0;
     if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
@@ -1766,11 +1741,6 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
             emitNode(callArguments.argumentRegister(argumentIndex++), n);
     }
 
-    if (m_shouldEmitProfileHooks) {
-        emitOpcode(op_profile_will_call);
-        instructions().append(callArguments.profileHookRegister()->index());
-    }
-
     // Reserve space for call frame.
     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
     for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
@@ -1791,11 +1761,6 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
         instructions().append(dst->index()); // dst
     }
 
-    if (m_shouldEmitProfileHooks) {
-        emitOpcode(op_profile_did_call);
-        instructions().append(callArguments.profileHookRegister()->index());
-    }
-
     return dst;
 }
 
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 499d232..7acc00b 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -59,11 +59,9 @@ namespace JSC {
         RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
         unsigned callFrame() { return thisRegister()->index() + count() + RegisterFile::CallFrameHeaderSize; }
         unsigned count() { return m_argv.size(); }
-        RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
         ArgumentsNode* argumentsNode() { return m_argumentsNode; }
 
     private:
-        RefPtr<RegisterID> m_profileHookRegister;
         ArgumentsNode* m_argumentsNode;
         Vector<RefPtr<RegisterID>, 16> m_argv;
     };
diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index a850c96..2a7eacd 100644
--- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -326,8 +326,6 @@ RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
 CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
     : m_argumentsNode(argumentsNode)
 {
-    if (generator.shouldEmitProfileHooks())
-        m_profileHookRegister = generator.newTemporary();
     m_argv.append(generator.newTemporary());
     if (argumentsNode) {
         for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) {
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 0a1be48..59426d9 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -76,6 +76,27 @@ using namespace std;
 
 namespace JSC {
 
+class ProfileHostCall {
+public:
+    ProfileHostCall(ExecState* exec)
+        : m_profiler(Profiler::enabledProfilerReference())
+        , m_exec(exec)
+    {
+        if (*m_profiler)
+            (*m_profiler)->hasCalled(exec);
+    }
+
+    ~ProfileHostCall()
+    {
+        if (*m_profiler)
+            (*m_profiler)->willReturn(m_exec);
+    }
+
+private:
+    Profiler** m_profiler;
+    ExecState* m_exec;
+};
+
 // Returns the depth of the scope chain within a given call frame.
 static int depth(CodeBlock* codeBlock, ScopeChain& sc)
 {
@@ -558,13 +579,6 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
     }
 
-    if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
-        if (callFrame->callee())
-            profiler->didExecute(callFrame, callFrame->callee());
-        else
-            profiler->didExecute(callFrame, codeBlock->ownerExecutable()->sourceURL(), codeBlock->ownerExecutable()->lineNo());
-    }
-
     // If this call frame created an activation or an 'arguments' object, tear it off.
     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
         if (!callFrame->r(oldCodeBlock->activationRegister()).jsValue()) {
@@ -657,9 +671,10 @@ static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception,
 
 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
 {
-    // Set up the exception object
-
     CodeBlock* codeBlock = callFrame->codeBlock();
+    bool isInterrupt = false;
+
+    // Set up the exception object
     if (exceptionValue.isObject()) {
         JSObject* exception = asObject(exceptionValue);
         if (!explicitThrow && exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
@@ -671,12 +686,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
             addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset), codeBlock->ownerExecutable()->source());
 
         ComplType exceptionType = exception->exceptionType();
-        if (exceptionType == Interrupted || exceptionType == Terminated) {
-            while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
-                // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
-            }
-            return 0;
-        }
+        isInterrupt = exceptionType == Interrupted || exceptionType == Terminated;
     }
 
     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
@@ -685,39 +695,19 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
         debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset), hasHandler);
     }
 
-    // If we throw in the middle of a call instruction, we need to notify
-    // the profiler manually that the call instruction has returned, since
-    // we'll never reach the relevant op_profile_did_call.
-    if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
-#if ENABLE(INTERPRETER)
-        if (!callFrame->globalData().canUseJIT()) {
-            // FIXME: Why 8? - work out what this magic value is, replace the constant with something more helpful.
-            if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
-                profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 1].u.operand).jsValue());
-            else if (codeBlock->instructions().size() > (bytecodeOffset + 8) && codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
-                profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 9].u.operand).jsValue());
-        }
-#if ENABLE(JIT)
-        else
-#endif
-#endif
-#if ENABLE(JIT)
-        {
-            int functionRegisterIndex;
-            if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
-                profiler->didExecute(callFrame, callFrame->r(functionRegisterIndex).jsValue());
-        }
-#endif
-    }
-
     // Calculate an exception handler vPC, unwinding call frames as necessary.
-
     HandlerInfo* handler = 0;
-    while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
-        if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock))
+    while (isInterrupt || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
+        if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
+            if (Profiler* profiler = *Profiler::enabledProfilerReference())
+                profiler->exceptionUnwind(callFrame);
             return 0;
+        }
     }
 
+    if (Profiler* profiler = *Profiler::enabledProfilerReference())
+        profiler->exceptionUnwind(callFrame);
+
     // Shrink the JS stack, in case stack overflow made it huge.
     Register* highWaterMark = 0;
     for (CallFrame* callerFrame = callFrame; callerFrame; callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag()) {
@@ -789,7 +779,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, program->sourceURL(), program->lineNo());
+        (*profiler)->willEvaluate(newCallFrame, program->sourceURL(), program->lineNo());
 
     JSValue result;
     {
@@ -807,7 +797,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
     }
 
     if (*profiler)
-        (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
+        (*profiler)->didEvaluate(callFrame, program->sourceURL(), program->lineNo());
 
     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
         lastGlobalObject->copyGlobalsTo(m_registerFile);
@@ -858,10 +848,6 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
 
         DynamicGlobalObjectScope globalObjectScope(newCallFrame, callDataScopeChain->globalObject);
 
-        Profiler** profiler = Profiler::enabledProfilerReference();
-        if (*profiler)
-            (*profiler)->willExecute(newCallFrame, function);
-
         JSValue result;
         {
             SamplingTool::CallRecord callRecord(m_sampler.get());
@@ -876,9 +862,6 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
             m_reentryDepth--;
         }
 
-        if (*profiler)
-            (*profiler)->didExecute(newCallFrame, function);
-
         m_registerFile.shrink(oldEnd);
         return checkedReturn(result);
     }
@@ -890,19 +873,13 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
 
     DynamicGlobalObjectScope globalObjectScope(newCallFrame, scopeChain->globalObject);
 
-    Profiler** profiler = Profiler::enabledProfilerReference();
-    if (*profiler)
-        (*profiler)->willExecute(newCallFrame, function);
-
     JSValue result;
     {
+        ProfileHostCall profileHostCall(newCallFrame);
         SamplingTool::HostCallRecord callRecord(m_sampler.get());
         result = JSValue::decode(callData.native.function(newCallFrame));
     }
 
-    if (*profiler)
-        (*profiler)->didExecute(newCallFrame, function);
-
     m_registerFile.shrink(oldEnd);
     return checkedReturn(result);
 }
@@ -947,10 +924,6 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
 
         DynamicGlobalObjectScope globalObjectScope(newCallFrame, constructDataScopeChain->globalObject);
 
-        Profiler** profiler = Profiler::enabledProfilerReference();
-        if (*profiler)
-            (*profiler)->willExecute(newCallFrame, constructor);
-
         JSValue result;
         {
             SamplingTool::CallRecord callRecord(m_sampler.get());
@@ -965,9 +938,6 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
             m_reentryDepth--;
         }
 
-        if (*profiler)
-            (*profiler)->didExecute(newCallFrame, constructor);
-
         m_registerFile.shrink(oldEnd);
         if (callFrame->hadException())
             return 0;
@@ -982,19 +952,13 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
 
     DynamicGlobalObjectScope globalObjectScope(newCallFrame, scopeChain->globalObject);
 
-    Profiler** profiler = Profiler::enabledProfilerReference();
-    if (*profiler)
-        (*profiler)->willExecute(newCallFrame, constructor);
-
     JSValue result;
     {
+        ProfileHostCall profileHostCall(newCallFrame);
         SamplingTool::HostCallRecord callRecord(m_sampler.get());
         result = JSValue::decode(constructData.native.function(newCallFrame));
     }
 
-    if (*profiler)
-        (*profiler)->didExecute(newCallFrame, constructor);
-
     m_registerFile.shrink(oldEnd);
     if (callFrame->hadException())
         return 0;
@@ -1048,9 +1012,6 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE
 JSValue Interpreter::execute(CallFrameClosure& closure) 
 {
     closure.resetCallFrame();
-    Profiler** profiler = Profiler::enabledProfilerReference();
-    if (*profiler)
-        (*profiler)->willExecute(closure.oldCallFrame, closure.function);
     
     JSValue result;
     {
@@ -1072,8 +1033,6 @@ JSValue Interpreter::execute(CallFrameClosure& closure)
         m_reentryDepth--;
     }
     
-    if (*profiler)
-        (*profiler)->didExecute(closure.oldCallFrame, closure.function);
     return checkedReturn(result);
 }
 
@@ -1159,7 +1118,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, eval->sourceURL(), eval->lineNo());
+        (*profiler)->willEvaluate(newCallFrame, eval->sourceURL(), eval->lineNo());
 
     JSValue result;
     {
@@ -1183,7 +1142,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
     }
 
     if (*profiler)
-        (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
+        (*profiler)->didEvaluate(callFrame, eval->sourceURL(), eval->lineNo());
 
     m_registerFile.shrink(oldEnd);
     if (pushedScope)
@@ -3930,6 +3889,7 @@ skip_id_custom_self:
 
             JSValue returnValue;
             {
+                ProfileHostCall profileHostCall(newCallFrame);
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
             }
@@ -4088,6 +4048,7 @@ skip_id_custom_self:
             
             JSValue returnValue;
             {
+                ProfileHostCall profileHostCall(newCallFrame);
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
             }
@@ -4433,6 +4394,7 @@ skip_id_custom_self:
 
             JSValue returnValue;
             {
+                ProfileHostCall profileHostCall(newCallFrame);
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = JSValue::decode(constructData.native.function(newCallFrame));
             }
@@ -4770,32 +4732,28 @@ skip_id_custom_self:
         vPC += OPCODE_LENGTH(op_debug);
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_profile_will_call) {
-        /* op_profile_will_call function(r)
+    DEFINE_OPCODE(op_profile_has_called) {
+        /* op_profile_has_called
 
          Notifies the profiler of the beginning of a function call. This opcode
          is only generated if developer tools are enabled.
         */
-        int function = vPC[1].u.operand;
-
         if (*enabledProfilerReference)
-            (*enabledProfilerReference)->willExecute(callFrame, callFrame->r(function).jsValue());
+            (*enabledProfilerReference)->hasCalled(callFrame);
 
-        vPC += OPCODE_LENGTH(op_profile_will_call);
+        vPC += OPCODE_LENGTH(op_profile_has_called);
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_profile_did_call) {
-        /* op_profile_did_call function(r)
+    DEFINE_OPCODE(op_profile_will_return) {
+        /* op_profile_will_return
 
          Notifies the profiler of the end of a function call. This opcode
          is only generated if developer tools are enabled.
         */
-        int function = vPC[1].u.operand;
-
         if (*enabledProfilerReference)
-            (*enabledProfilerReference)->didExecute(callFrame, callFrame->r(function).jsValue());
+            (*enabledProfilerReference)->willReturn(callFrame);
 
-        vPC += OPCODE_LENGTH(op_profile_did_call);
+        vPC += OPCODE_LENGTH(op_profile_will_return);
         NEXT_INSTRUCTION();
     }
     vm_throw: {
diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp
index 3f2ec59..999797b 100644
--- a/JavaScriptCore/jit/JIT.cpp
+++ b/JavaScriptCore/jit/JIT.cpp
@@ -284,8 +284,8 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_post_inc)
         DEFINE_OP(op_pre_dec)
         DEFINE_OP(op_pre_inc)
-        DEFINE_OP(op_profile_did_call)
-        DEFINE_OP(op_profile_will_call)
+        DEFINE_OP(op_profile_has_called)
+        DEFINE_OP(op_profile_will_return)
         DEFINE_OP(op_push_new_scope)
         DEFINE_OP(op_push_scope)
         DEFINE_OP(op_put_by_id)
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index 907a774..fd193e5 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -797,8 +797,8 @@ namespace JSC {
         void emit_op_post_inc(Instruction*);
         void emit_op_pre_dec(Instruction*);
         void emit_op_pre_inc(Instruction*);
-        void emit_op_profile_did_call(Instruction*);
-        void emit_op_profile_will_call(Instruction*);
+        void emit_op_profile_has_called(Instruction*);
+        void emit_op_profile_will_return(Instruction*);
         void emit_op_push_new_scope(Instruction*);
         void emit_op_push_scope(Instruction*);
         void emit_op_put_by_id(Instruction*);
diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp
index d783581..c9993a1 100644
--- a/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/JavaScriptCore/jit/JITOpcodes.cpp
@@ -1306,25 +1306,23 @@ void JIT::emit_op_create_this(Instruction* currentInstruction)
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
+void JIT::emit_op_profile_has_called(Instruction*)
 {
     peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
     Jump noProfiler = branchTestPtr(Zero, Address(regT1));
 
-    JITStubCall stubCall(this, cti_op_profile_will_call);
-    stubCall.addArgument(currentInstruction[1].u.operand, regT1);
+    JITStubCall stubCall(this, cti_op_profile_has_called);
     stubCall.call();
     noProfiler.link(this);
 
 }
 
-void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
+void JIT::emit_op_profile_will_return(Instruction*)
 {
     peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
     Jump noProfiler = branchTestPtr(Zero, Address(regT1));
 
-    JITStubCall stubCall(this, cti_op_profile_did_call);
-    stubCall.addArgument(currentInstruction[1].u.operand, regT1);
+    JITStubCall stubCall(this, cti_op_profile_will_return);
     stubCall.call();
     noProfiler.link(this);
 }
diff --git a/JavaScriptCore/jit/JITOpcodes32_64.cpp b/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 076649d..25c53b7 100644
--- a/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -1635,24 +1635,22 @@ void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vecto
     stubCall.call(thisRegister);
 }
 
-void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
+void JIT::emit_op_profile_has_called(Instruction*)
 {
     peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
     Jump noProfiler = branchTestPtr(Zero, Address(regT2));
 
-    JITStubCall stubCall(this, cti_op_profile_will_call);
-    stubCall.addArgument(currentInstruction[1].u.operand);
+    JITStubCall stubCall(this, cti_op_profile_has_called);
     stubCall.call();
     noProfiler.link(this);
 }
 
-void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
+void JIT::emit_op_profile_will_return(Instruction*)
 {
     peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
     Jump noProfiler = branchTestPtr(Zero, Address(regT2));
 
-    JITStubCall stubCall(this, cti_op_profile_did_call);
-    stubCall.addArgument(currentInstruction[1].u.operand);
+    JITStubCall stubCall(this, cti_op_profile_will_return);
     stubCall.call();
     noProfiler.link(this);
 }
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index 36d36a2..ab2f9e3 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -2264,20 +2264,20 @@ DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
     asArguments(stackFrame.args[0].jsValue())->copyRegisters();
 }
 
-DEFINE_STUB_FUNCTION(void, op_profile_will_call)
+DEFINE_STUB_FUNCTION(void, op_profile_has_called)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     ASSERT(*stackFrame.enabledProfilerReference);
-    (*stackFrame.enabledProfilerReference)->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
+    (*stackFrame.enabledProfilerReference)->hasCalled(stackFrame.callFrame);
 }
 
-DEFINE_STUB_FUNCTION(void, op_profile_did_call)
+DEFINE_STUB_FUNCTION(void, op_profile_will_return)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     ASSERT(*stackFrame.enabledProfilerReference);
-    (*stackFrame.enabledProfilerReference)->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
+    (*stackFrame.enabledProfilerReference)->willReturn(stackFrame.callFrame);
 }
 
 DEFINE_STUB_FUNCTION(void, op_ret_scopeChain)
diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h
index 937134b..f6703ea 100644
--- a/JavaScriptCore/jit/JITStubs.h
+++ b/JavaScriptCore/jit/JITStubs.h
@@ -377,8 +377,8 @@ extern "C" {
     void JIT_STUB cti_op_end(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_jmp_scopes(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_pop_scope(STUB_ARGS_DECLARATION);
-    void JIT_STUB cti_op_profile_did_call(STUB_ARGS_DECLARATION);
-    void JIT_STUB cti_op_profile_will_call(STUB_ARGS_DECLARATION);
+    void JIT_STUB cti_op_profile_has_called(STUB_ARGS_DECLARATION);
+    void JIT_STUB cti_op_profile_will_return(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_id(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION);
diff --git a/JavaScriptCore/profiler/Profile.cpp b/JavaScriptCore/profiler/Profile.cpp
index bc239b3..1a84518 100644
--- a/JavaScriptCore/profiler/Profile.cpp
+++ b/JavaScriptCore/profiler/Profile.cpp
@@ -42,7 +42,7 @@ Profile::Profile(const UString& title, unsigned uid)
 {
     // FIXME: When multi-threading is supported this will be a vector and calls
     // into the profiler will need to know which thread it is executing on.
-    m_head = ProfileNode::create(CallIdentifier("Thread_1", UString(), 0), 0, 0);
+    m_head = ProfileNode::create(0, CallIdentifier("Thread_1", UString(), 0), 0, 0);
 }
 
 Profile::~Profile()
diff --git a/JavaScriptCore/profiler/ProfileGenerator.cpp b/JavaScriptCore/profiler/ProfileGenerator.cpp
index 1d916ea..78d85e5 100644
--- a/JavaScriptCore/profiler/ProfileGenerator.cpp
+++ b/JavaScriptCore/profiler/ProfileGenerator.cpp
@@ -63,7 +63,7 @@ void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
     JSValue function;
 
     exec->interpreter()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function);
-    m_currentNode = ProfileNode::create(Profiler::createCallIdentifier(exec, function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get());
+    m_currentNode = ProfileNode::create(exec, Profiler::createCallIdentifier(exec, function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get());
     m_head->insertNode(m_currentNode.get());
 }
 
@@ -72,7 +72,7 @@ const UString& ProfileGenerator::title() const
     return m_profile->title();
 }
 
-void ProfileGenerator::willExecute(const CallIdentifier& callIdentifier)
+void ProfileGenerator::willExecute(ExecState* exec, const CallIdentifier& callIdentifier)
 {
     if (JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED()) {
         CString name = callIdentifier.m_name.utf8();
@@ -83,11 +83,11 @@ void ProfileGenerator::willExecute(const CallIdentifier& callIdentifier)
     if (!m_originatingGlobalExec)
         return;
 
-    ASSERT_ARG(m_currentNode, m_currentNode);
-    m_currentNode = m_currentNode->willExecute(callIdentifier);
+    ASSERT(m_currentNode);
+    m_currentNode = m_currentNode->willExecute(exec, callIdentifier);
 }
 
-void ProfileGenerator::didExecute(const CallIdentifier& callIdentifier)
+void ProfileGenerator::didExecute(ExecState* exec, const CallIdentifier& callIdentifier)
 {
     if (JAVASCRIPTCORE_PROFILE_DID_EXECUTE_ENABLED()) {
         CString name = callIdentifier.m_name.utf8();
@@ -98,9 +98,9 @@ void ProfileGenerator::didExecute(const CallIdentifier& callIdentifier)
     if (!m_originatingGlobalExec)
         return;
 
-    ASSERT_ARG(m_currentNode, m_currentNode);
+    ASSERT(m_currentNode);
     if (m_currentNode->callIdentifier() != callIdentifier) {
-        RefPtr<ProfileNode> returningNode = ProfileNode::create(callIdentifier, m_head.get(), m_currentNode.get());
+        RefPtr<ProfileNode> returningNode = ProfileNode::create(exec, callIdentifier, m_head.get(), m_currentNode.get());
         returningNode->setStartTime(m_currentNode->startTime());
         returningNode->didExecute();
         m_currentNode->insertNode(returningNode.release());
@@ -110,6 +110,15 @@ void ProfileGenerator::didExecute(const CallIdentifier& callIdentifier)
     m_currentNode = m_currentNode->didExecute();
 }
 
+void ProfileGenerator::exceptionUnwind(ExecState* exec, const CallIdentifier&)
+{
+    ASSERT(m_currentNode);
+    while (m_currentNode->exec() > exec) {
+        didExecute(exec, m_currentNode->callIdentifier());
+        ASSERT(m_currentNode);
+    }
+}
+
 void ProfileGenerator::stopProfiling()
 {
     m_profile->forEach(&ProfileNode::stopProfiling);
@@ -117,14 +126,14 @@ void ProfileGenerator::stopProfiling()
     removeProfileStart();
     removeProfileEnd();
 
-    ASSERT_ARG(m_currentNode, m_currentNode);
+    ASSERT(m_currentNode);
 
     // Set the current node to the parent, because we are in a call that
     // will not get didExecute call.
     m_currentNode = m_currentNode->parent();
 
    if (double headSelfTime = m_head->selfTime()) {
-        RefPtr<ProfileNode> idleNode = ProfileNode::create(CallIdentifier(NonJSExecution, UString(), 0), m_head.get(), m_head.get());
+        RefPtr<ProfileNode> idleNode = ProfileNode::create(0, CallIdentifier(NonJSExecution, UString(), 0), m_head.get(), m_head.get());
 
         idleNode->setTotalTime(headSelfTime);
         idleNode->setSelfTime(headSelfTime);
diff --git a/JavaScriptCore/profiler/ProfileGenerator.h b/JavaScriptCore/profiler/ProfileGenerator.h
index 82149b3..71a8f7a 100644
--- a/JavaScriptCore/profiler/ProfileGenerator.h
+++ b/JavaScriptCore/profiler/ProfileGenerator.h
@@ -50,13 +50,15 @@ namespace JSC {
         unsigned profileGroup() const { return m_profileGroup; }
 
         // Collecting
-        void willExecute(const CallIdentifier&);
-        void didExecute(const CallIdentifier&);
+        void willExecute(ExecState* exec, const CallIdentifier&);
+        void didExecute(ExecState* exec, const CallIdentifier&);
+
+        void exceptionUnwind(ExecState* exec, const CallIdentifier&);
 
         // Stopping Profiling
         void stopProfiling();
 
-        typedef void (ProfileGenerator::*ProfileFunction)(const CallIdentifier& callIdentifier);
+        typedef void (ProfileGenerator::*ProfileFunction)(ExecState* exec, const CallIdentifier& callIdentifier);
 
     private:
         ProfileGenerator(const UString& title, ExecState* originatingExec, unsigned uid);
diff --git a/JavaScriptCore/profiler/ProfileNode.cpp b/JavaScriptCore/profiler/ProfileNode.cpp
index bfcfcbe..dc3b88d 100644
--- a/JavaScriptCore/profiler/ProfileNode.cpp
+++ b/JavaScriptCore/profiler/ProfileNode.cpp
@@ -56,8 +56,9 @@ static double getCount()
 #endif
 }
 
-ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
-    : m_callIdentifier(callIdentifier)
+ProfileNode::ProfileNode(ExecState* exec, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
+    : m_exec(exec)
+    , m_callIdentifier(callIdentifier)
     , m_head(headNode)
     , m_parent(parentNode)
     , m_nextSibling(0)
@@ -72,8 +73,9 @@ ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* head
     startTimer();
 }
 
-ProfileNode::ProfileNode(ProfileNode* headNode, ProfileNode* nodeToCopy)
-    : m_callIdentifier(nodeToCopy->callIdentifier())
+ProfileNode::ProfileNode(ExecState* exec, ProfileNode* headNode, ProfileNode* nodeToCopy)
+    : m_exec(exec)
+    , m_callIdentifier(nodeToCopy->callIdentifier())
     , m_head(headNode)
     , m_parent(nodeToCopy->parent())
     , m_nextSibling(0)
@@ -87,7 +89,7 @@ ProfileNode::ProfileNode(ProfileNode* headNode, ProfileNode* nodeToCopy)
 {
 }
 
-ProfileNode* ProfileNode::willExecute(const CallIdentifier& callIdentifier)
+ProfileNode* ProfileNode::willExecute(ExecState* exec, const CallIdentifier& callIdentifier)
 {
     for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
         if ((*currentChild)->callIdentifier() == callIdentifier) {
@@ -96,7 +98,7 @@ ProfileNode* ProfileNode::willExecute(const CallIdentifier& callIdentifier)
         }
     }
 
-    RefPtr<ProfileNode> newChild = ProfileNode::create(callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
+    RefPtr<ProfileNode> newChild = ProfileNode::create(exec, callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
     if (m_children.size())
         m_children.last()->setNextSibling(newChild.get());
     m_children.append(newChild.release());
diff --git a/JavaScriptCore/profiler/ProfileNode.h b/JavaScriptCore/profiler/ProfileNode.h
index eafeea6..d46adee 100644
--- a/JavaScriptCore/profiler/ProfileNode.h
+++ b/JavaScriptCore/profiler/ProfileNode.h
@@ -37,6 +37,7 @@
 
 namespace JSC {
 
+    class ExecState;
     class ProfileNode;
 
     typedef Vector<RefPtr<ProfileNode> >::const_iterator StackIterator;
@@ -44,23 +45,24 @@ namespace JSC {
 
     class ProfileNode : public RefCounted<ProfileNode> {
     public:
-        static PassRefPtr<ProfileNode> create(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
+        static PassRefPtr<ProfileNode> create(ExecState* exec, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
         {
-            return adoptRef(new ProfileNode(callIdentifier, headNode, parentNode));
+            return adoptRef(new ProfileNode(exec, callIdentifier, headNode, parentNode));
         }
-        static PassRefPtr<ProfileNode> create(ProfileNode* headNode, ProfileNode* node)
+        static PassRefPtr<ProfileNode> create(ExecState* exec, ProfileNode* headNode, ProfileNode* node)
         {
-            return adoptRef(new ProfileNode(headNode, node));
+            return adoptRef(new ProfileNode(exec, headNode, node));
         }
 
-        bool operator==(ProfileNode* node) { return m_callIdentifier == node->callIdentifier(); }
+        bool operator==(ProfileNode* node) { return m_exec == node->m_exec && m_callIdentifier == node->callIdentifier(); }
 
-        ProfileNode* willExecute(const CallIdentifier&);
+        ProfileNode* willExecute(ExecState* exec, const CallIdentifier&);
         ProfileNode* didExecute();
 
         void stopProfiling();
 
         // CallIdentifier members
+        const ExecState* exec() const { return m_exec; }
         const CallIdentifier& callIdentifier() const { return m_callIdentifier; }
         const UString& functionName() const { return m_callIdentifier.m_name; }
         const UString& url() const { return m_callIdentifier.m_url; }
@@ -128,8 +130,8 @@ namespace JSC {
 #endif
 
     private:
-        ProfileNode(const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode);
-        ProfileNode(ProfileNode* headNode, ProfileNode* nodeToCopy);
+        ProfileNode(ExecState* exec, const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode);
+        ProfileNode(ExecState* exec, ProfileNode* headNode, ProfileNode* nodeToCopy);
 
         void startTimer();
         void resetChildrensSiblings();
@@ -147,6 +149,7 @@ namespace JSC {
         static inline bool functionNameDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->functionName() > b->functionName(); }
         static inline bool functionNameAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->functionName() < b->functionName(); }
 
+        ExecState* m_exec;
         CallIdentifier m_callIdentifier;
         ProfileNode* m_head;
         ProfileNode* m_parent;
diff --git a/JavaScriptCore/profiler/Profiler.cpp b/JavaScriptCore/profiler/Profiler.cpp
index 78fe2f5..08f67cb 100644
--- a/JavaScriptCore/profiler/Profiler.cpp
+++ b/JavaScriptCore/profiler/Profiler.cpp
@@ -99,42 +99,51 @@ PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& titl
     return 0;
 }
 
-static inline void dispatchFunctionToProfiles(const Vector<RefPtr<ProfileGenerator> >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup)
+static inline void dispatchFunctionToProfiles(ExecState* exec, const Vector<RefPtr<ProfileGenerator> >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup)
 {
     for (size_t i = 0; i < profiles.size(); ++i) {
         if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->originatingGlobalExec())
-            (profiles[i].get()->*function)(callIdentifier);
+            (profiles[i].get()->*function)(exec, callIdentifier);
     }
 }
 
-void Profiler::willExecute(ExecState* exec, JSValue function)
+void Profiler::hasCalled(ExecState* exec)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+    JSValue function = exec->callee();
+    dispatchFunctionToProfiles(exec, m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
 }
 
-void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
+void Profiler::willEvaluate(ExecState* exec, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
     CallIdentifier callIdentifier = createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber);
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(exec, m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup());
 }
 
-void Profiler::didExecute(ExecState* exec, JSValue function)
+void Profiler::willReturn(ExecState* exec)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+    JSValue function = exec->callee();
+    dispatchFunctionToProfiles(exec, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
 }
 
-void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
+void Profiler::didEvaluate(ExecState* exec, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(exec, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
+}
+
+void Profiler::exceptionUnwind(ExecState* exec)
+{
+    ASSERT(!m_currentProfiles.isEmpty());
+
+    dispatchFunctionToProfiles(exec, m_currentProfiles, &ProfileGenerator::exceptionUnwind, createCallIdentifier(exec, JSValue(), "", 0), exec->lexicalGlobalObject()->profileGroup());
 }
 
 CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber)
diff --git a/JavaScriptCore/profiler/Profiler.h b/JavaScriptCore/profiler/Profiler.h
index 4b8b4a0..a592aa1 100644
--- a/JavaScriptCore/profiler/Profiler.h
+++ b/JavaScriptCore/profiler/Profiler.h
@@ -57,10 +57,14 @@ namespace JSC {
         void startProfiling(ExecState*, const UString& title);
         PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title);
 
-        void willExecute(ExecState*, JSValue function);
-        void willExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
-        void didExecute(ExecState*, JSValue function);
-        void didExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
+        // Called for program code and eval.
+        void willEvaluate(ExecState*, const UString& sourceURL, int startingLineNumber);
+        void didEvaluate(ExecState*, const UString& sourceURL, int startingLineNumber);
+
+        void hasCalled(ExecState*);
+        void willReturn(ExecState*);
+
+        void exceptionUnwind(ExecState*);
 
         const Vector<RefPtr<ProfileGenerator> >& currentProfiles() { return m_currentProfiles; };
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list