Changeset 33480

Show
Ignore:
Timestamp:
05/14/08 23:50:33 (6 months ago)
Author:
ggaren@apple.com
Message:

2008-05-14 Geoffrey Garen <ggaren@apple.com>

Reviewed by Oliver Hunt.

A little more debugger action: filled in op_debug. All debugger control
flow works now, but variable inspection and backtraces still don't.


SunSpider reports no change.

  • VM/CodeGenerator.cpp: Changed op_debug to accept line number parameters.
  • VM/Machine.cpp: (KJS::Machine::getFunctionAndArguments): Moved op_debug into a NEVER_INLINE function to avoid a stunning 10% performance regression. Also factored out a common function for retrieving the function and arguments from a call frame.
  • kjs/JSActivation.cpp: (KJS::JSActivation::createArgumentsObject): Use the new factored out function mentioned above.
  • kjs/Parser.cpp: (KJS::Parser::parse): Increment m_sourceId before assigning it, so the sourceId we send to the debugger matches the sourceId recorded in the node.
  • kjs/nodes.cpp: Emit debugging hooks.
Location:
branches/squirrelfish/JavaScriptCore
Files:
10 modified

Legend:

Unmodified
Added
Removed
  • branches/squirrelfish/JavaScriptCore/ChangeLog

    r33438 r33480  
     12008-05-14  Geoffrey Garen  <ggaren@apple.com> 
     2 
     3        Reviewed by Oliver Hunt. 
     4 
     5        A little more debugger action: filled in op_debug. All debugger control 
     6        flow works now, but variable inspection and backtraces still don't. 
     7         
     8        SunSpider reports no change. 
     9 
     10        * VM/CodeGenerator.cpp: Changed op_debug to accept line number parameters. 
     11 
     12        * VM/Machine.cpp: 
     13        (KJS::Machine::getFunctionAndArguments): Moved op_debug into a 
     14        NEVER_INLINE function to avoid a stunning 10% performance regression. 
     15        Also factored out a common function for retrieving the function and  
     16        arguments from a  call frame.  
     17 
     18        * kjs/JSActivation.cpp: 
     19        (KJS::JSActivation::createArgumentsObject): Use the new factored out 
     20        function mentioned above. 
     21 
     22        * kjs/Parser.cpp: 
     23        (KJS::Parser::parse): Increment m_sourceId before assigning it, so the 
     24        sourceId we send to the debugger matches the sourceId recorded in the 
     25        node. 
     26 
     27        * kjs/nodes.cpp: Emit debugging hooks. 
     28 
    1292008-05-14  Oliver Hunt  <oliver@apple.com> 
    230 
  • branches/squirrelfish/JavaScriptCore/VM/CodeBlock.cpp

    r33437 r33480  
    9898{ 
    9999    if (debugHookID == DidEnterCallFrame) 
    100         return "DidEnterCallFrame"; 
     100        return "didEnterCallFrame"; 
    101101    else if (debugHookID == WillLeaveCallFrame) 
    102         return "WillLeaveCallFrame"; 
     102        return "willLeaveCallFrame"; 
    103103    else { 
    104104        ASSERT(debugHookID == WillExecuteStatement); 
    105         return "WillExecuteStatement"; 
     105        return "willExecuteStatement"; 
    106106    } 
    107107} 
     
    530530            break; 
    531531        } 
    532         case op_dbg: { 
     532        case op_debug: { 
    533533            int debugHookID = (++it)->u.operand; 
    534             printf("[%4d] dbg\t\t %s\n", location, debugHookName(debugHookID)); 
     534            int firstLine = (++it)->u.operand; 
     535            int lastLine = (++it)->u.operand; 
     536            printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine); 
    535537            break; 
    536538        } 
  • branches/squirrelfish/JavaScriptCore/VM/CodeGenerator.cpp

    r33437 r33480  
    984984} 
    985985 
    986 void CodeGenerator::emitDebugHook(DebugHookID debugHookID) 
     986void CodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine) 
    987987{ 
    988988    if (!m_shouldEmitDebugHooks) 
    989989        return; 
    990     instructions().append(machine().getOpcode(op_dbg)); 
     990    instructions().append(machine().getOpcode(op_debug)); 
    991991    instructions().append(debugHookID); 
     992    instructions().append(firstLine); 
     993    instructions().append(lastLine); 
    992994} 
    993995 
  • branches/squirrelfish/JavaScriptCore/VM/CodeGenerator.h

    r33437 r33480  
    134134        // Node::emitCode. They're the only functions that accept a NULL register. 
    135135        RegisterID* emitNode(RegisterID* dst, Node* n) { 
    136             ASSERT(!dst || !dst->isTemporary() || dst->refCount()); // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary. 
     136            // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary. 
     137            ASSERT(!dst || !dst->isTemporary() || dst->refCount()); 
    137138            if (!m_codeBlock->lineInfo.size() || m_codeBlock->lineInfo.last().lineNumber != n->lineNo()) { 
    138139                LineInfo info = { instructions().size(), n->lineNo() }; 
     
    237238        void emitPopScope(); 
    238239         
    239         void emitDebugHook(DebugHookID); 
     240        void emitDebugHook(DebugHookID, int firstLine, int lastLine); 
    240241 
    241242        int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; } 
  • branches/squirrelfish/JavaScriptCore/VM/Machine.cpp

    r33438 r33480  
    738738} 
    739739 
     740NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, const ScopeChainNode*, Register** registerBase, Register* r) 
     741{ 
     742    int debugHookID = (++vPC)->u.operand; 
     743    int firstLine = (++vPC)->u.operand; 
     744    int lastLine = (++vPC)->u.operand; 
     745 
     746    Debugger* debugger = exec->dynamicGlobalObject()->debugger(); 
     747    if (!debugger) 
     748        return; 
     749 
     750    if (debugHookID == DidEnterCallFrame) { 
     751        Register* callFrame = r - codeBlock->numLocals - CallFrameHeaderSize; 
     752        FunctionImp* function; 
     753        Register* argv; 
     754        int argc; 
     755        getFunctionAndArguments(registerBase, callFrame, function, argv, argc); 
     756        List args(&argv->u.jsValue, argc); 
     757        debugger->callEvent(exec, codeBlock->ownerNode->sourceId(), firstLine, function, args); 
     758    } else if (debugHookID == WillLeaveCallFrame) { 
     759        Register* callFrame = r - codeBlock->numLocals - CallFrameHeaderSize; 
     760        FunctionImp* function = static_cast<FunctionImp*>(callFrame[Callee].u.jsValue); 
     761        ASSERT(function->inherits(&FunctionImp::info)); 
     762        debugger->returnEvent(exec, codeBlock->ownerNode->sourceId(), lastLine, function); 
     763    } else { 
     764        ASSERT(debugHookID == WillExecuteStatement); 
     765        debugger->atStatement(exec, codeBlock->ownerNode->sourceId(), firstLine, lastLine); 
     766    } 
     767} 
     768 
    740769JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception) 
    741770{ 
     
    13611390 
    13621391        vPC += 3; 
    1363          
    13641392        NEXT_OPCODE; 
    13651393    } 
     
    13731401        */ 
    13741402        resolveBase(exec, vPC, r, scopeChain, codeBlock); 
     1403 
    13751404        vPC += 3; 
    1376  
    13771405        NEXT_OPCODE; 
    13781406    } 
     
    13931421 
    13941422        vPC += 4; 
    1395          
    13961423        NEXT_OPCODE; 
    13971424    } 
     
    14131440        if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue))) 
    14141441            goto vm_throw; 
     1442 
    14151443        vPC += 4; 
    1416  
    14171444        NEXT_OPCODE; 
    14181445    } 
     
    16051632        */ 
    16061633        int target = (++vPC)->u.operand; 
     1634 
    16071635        vPC += target; 
    1608  
    16091636        NEXT_OPCODE; 
    16101637    } 
     
    20942121        NEXT_OPCODE; 
    20952122    } 
    2096     BEGIN_OPCODE(op_dbg) { 
    2097         /* dbg debugHookID(n) 
     2123    BEGIN_OPCODE(op_debug) { 
     2124        /* debug debugHookID(n) firstLine(n) lastLine(n) 
    20982125          
    20992126         Notifies the debugger of the current state of execution: 
     
    21032130        */ 
    21042131 
    2105         int debugHookID = (++vPC)->u.operand; 
    2106  
    2107         Debugger* debugger = exec->dynamicGlobalObject()->debugger(); 
    2108         if (!debugger) { 
    2109             ++vPC; 
    2110             NEXT_OPCODE; 
    2111         } 
    2112  
    2113         if (debugHookID == DidEnterCallFrame) { 
    2114             // callEvent 
    2115         } else if (debugHookID == WillLeaveCallFrame) { 
    2116             // returnEvent 
    2117         } else { 
    2118             // atStatement 
    2119             ASSERT(debugHookID == WillExecuteStatement); 
    2120         } 
    2121  
    2122         ++vPC; 
     2132        debug(exec, vPC, codeBlock, scopeChain, registerBase, r); 
     2133 
     2134        vPC += 3; 
    21232135        NEXT_OPCODE; 
    21242136    } 
     
    21972209} 
    21982210 
     2211void Machine::getFunctionAndArguments(Register** registerBase, Register* callFrame, FunctionImp*& function, Register*& argv, int& argc) 
     2212{ 
     2213    function = static_cast<FunctionImp*>(callFrame[Callee].u.jsValue); 
     2214    ASSERT(function->inherits(&FunctionImp::info)); 
     2215 
     2216    argv = (*registerBase) + callFrame[CallerRegisterOffset].u.i + callFrame[ArgumentStartRegister].u.i + 1; // skip "this" 
     2217    argc = callFrame[ArgumentCount].u.i - 1; // skip "this" 
     2218} 
     2219 
    21992220} // namespace KJS 
  • branches/squirrelfish/JavaScriptCore/VM/Machine.h

    r33370 r33480  
    9292        JSValue* retrieveCaller(ExecState*, FunctionImp*) const; 
    9393         
     94        void getFunctionAndArguments(Register** registerBase, Register* callFrame, FunctionImp*&, Register*& argv, int& argc); 
     95         
    9496    private: 
    9597        enum { MaxReentryDepth = 128 }; 
     
    9799 
    98100        ALWAYS_INLINE void setScopeChain(ExecState* exec, ScopeChainNode*&, ScopeChainNode*); 
     101        NEVER_INLINE void debug(ExecState*, const Instruction*, const CodeBlock*, const ScopeChainNode*, Register**, Register*); 
    99102 
    100103        NEVER_INLINE bool unwindCallFrame(ExecState*, Register**, const Instruction*&, CodeBlock*&, JSValue**&, ScopeChainNode*&, Register*&); 
  • branches/squirrelfish/JavaScriptCore/VM/Opcode.h

    r33437 r33480  
    116116        macro(op_sret) \ 
    117117        \ 
    118         macro(op_dbg) \ 
     118        macro(op_debug) \ 
    119119        \ 
    120120        macro(op_end) // end must be the last opcode in the list 
  • branches/squirrelfish/JavaScriptCore/kjs/JSActivation.cpp

    r33339 r33480  
    179179JSObject* JSActivation::createArgumentsObject(ExecState* exec) 
    180180{ 
    181     CodeBlock* codeBlock = &d()->functionBody->generatedCode(); 
    182     Register* callFrame = registers() - codeBlock->numLocals - Machine::CallFrameHeaderSize; 
     181    Register* callFrame = registers() - d()->functionBody->generatedCode().numLocals - Machine::CallFrameHeaderSize; 
    183182 
    184     FunctionImp* function = static_cast<FunctionImp*>(callFrame[Machine::Callee].u.jsValue); 
    185     int argv = callFrame[Machine::ArgumentStartRegister].u.i; 
    186     int argc = callFrame[Machine::ArgumentCount].u.i; 
    187  
    188     List args(&(*registerBase() + callFrame[Machine::CallerRegisterOffset].u.i + argv + 1)->u.jsValue, argc - 1); 
     183    FunctionImp* function; 
     184    Register* argv; 
     185    int argc; 
     186    exec->machine()->getFunctionAndArguments(registerBase(), callFrame, function, argv, argc); 
     187    List args(&argv->u.jsValue, argc); 
    189188    return new Arguments(exec, function, args, this); 
    190189} 
  • branches/squirrelfish/JavaScriptCore/kjs/Parser.cpp

    r33386 r33480  
    6868 
    6969    lexer.setCode(startingLineNumber, source); 
    70     *sourceId = m_sourceId++; 
     70    *sourceId = ++m_sourceId; 
    7171 
    7272    int parseError = kjsyyparse(&lexer); 
  • branches/squirrelfish/JavaScriptCore/kjs/nodes.cpp

    r33437 r33480  
    46784678    StatementVector::iterator end = statements.end(); 
    46794679    for (StatementVector::iterator it = statements.begin(); it != end; ++it) { 
    4680         generator.emitDebugHook(WillExecuteStatement); 
    4681         if (RegisterID* r1 = generator.emitNode(dst, it->get())) 
     4680        StatementNode* n = it->get(); 
     4681        generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine()); 
     4682        if (RegisterID* r1 = generator.emitNode(dst, n)) 
    46824683            r0 = r1; 
    46834684    } 
     
    53355336        generator.emitLabel(l0.get()); 
    53365337    } 
    5337     generator.emitDebugHook(WillLeaveCallFrame); 
     5338    generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); 
    53385339    return generator.emitReturn(r0); 
    53395340} 
     
    58095810RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*) 
    58105811{ 
    5811     generator.emitDebugHook(DidEnterCallFrame); 
     5812    generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); 
    58125813    statementListEmitCode(m_children, generator); 
    58135814    if (!m_children.size() || !m_children.last()->isReturnNode()) { 
    58145815        RegisterID* r0 = generator.emitLoad(generator.newTemporary(), jsUndefined()); 
    5815         generator.emitDebugHook(WillLeaveCallFrame); 
     5816        generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); 
    58165817        generator.emitReturn(r0); 
    58175818    }