Changeset 34842 in webkit


Ignore:
Timestamp:
Jun 27, 2008 9:02:03 PM (16 years ago)
Author:
oliver@apple.com
Message:

Bug 18626: SQUIRRELFISH: support the "slow script" dialog <https://bugs.webkit.org/show_bug.cgi?id=18626>
<rdar://problem/5973931> Slow script dialog needs to be reimplemented for squirrelfish

Reviewed by Sam

Adds support for the slow script dialog in squirrelfish. This requires the addition
of three new op codes, op_loop, op_loop_if_true, and op_loop_if_less which have the
same behaviour as their simple jump equivalents but have an additional time out check.

Additional assertions were added to other jump instructions to prevent accidentally
creating loops with jump types that do not support time out checks.

Sunspider does not report a regression, however this appears very sensitive to code
layout and hardware, so i would expect up to a 1% regression on other systems.

Part of this required moving the old timeout logic from JSGlobalObject and into Machine
which is the cause of a number of the larger diff blocks.

Location:
trunk/JavaScriptCore
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r34840 r34842  
     12008-06-27  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Sam.
     4
     5        Bug 18626: SQUIRRELFISH: support the "slow script" dialog <https://bugs.webkit.org/show_bug.cgi?id=18626>
     6        <rdar://problem/5973931> Slow script dialog needs to be reimplemented for squirrelfish
     7
     8        Adds support for the slow script dialog in squirrelfish.  This requires the addition
     9        of three new op codes, op_loop, op_loop_if_true, and op_loop_if_less which have the
     10        same behaviour as their simple jump equivalents but have an additional time out check.
     11
     12        Additional assertions were added to other jump instructions to prevent accidentally
     13        creating loops with jump types that do not support time out checks.
     14
     15        Sunspider does not report a regression, however this appears very sensitive to code
     16        layout and hardware, so i would expect up to a 1% regression on other systems.
     17
     18        Part of this required moving the old timeout logic from JSGlobalObject and into Machine
     19        which is the cause of a number of the larger diff blocks.
     20
     21        * JavaScriptCore.exp:
     22        * VM/CodeBlock.cpp:
     23        (KJS::CodeBlock::dump):
     24        * VM/CodeGenerator.cpp:
     25        (KJS::CodeGenerator::emitJumpIfTrue):
     26        (KJS::CodeGenerator::emitJumpScopes):
     27        * VM/ExceptionHelpers.cpp:
     28        (KJS::InterruptedExecutionError::isWatchdogException):
     29        (KJS::createInterruptedExecutionException):
     30        * VM/ExceptionHelpers.h:
     31        * VM/LabelID.h:
     32        * VM/Machine.cpp:
     33        (KJS::Machine::Machine):
     34        (KJS::Machine::throwException):
     35        (KJS::Machine::resetTimeoutCheck):
     36        (KJS::getCurrentTime):
     37        (KJS::Machine::checkTimeout):
     38        (KJS::Machine::privateExecute):
     39        * VM/Machine.h:
     40        (KJS::Machine::setTimeoutTime):
     41        (KJS::Machine::startTimeoutCheck):
     42        (KJS::Machine::stopTimeoutCheck):
     43        (KJS::Machine::initTimeout):
     44        * VM/Opcode.cpp:
     45        (KJS::):
     46        * VM/Opcode.h:
     47        * kjs/JSGlobalObject.cpp:
     48        (KJS::JSGlobalObject::init):
     49        (KJS::JSGlobalObject::setTimeoutTime):
     50        (KJS::JSGlobalObject::startTimeoutCheck):
     51        * kjs/JSGlobalObject.h:
     52        * kjs/JSObject.h:
     53        * kjs/interpreter.cpp:
     54        (KJS::Interpreter::evaluate):
     55
    1562008-06-27  Jan Michael Alonzo  <jmalonzo@webkit.org>
    257
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r34838 r34842  
    116116__ZN3KJS14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
    117117__ZN3KJS14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
     118__ZN3KJS14JSGlobalObject14setTimeoutTimeEj
    118119__ZN3KJS14JSGlobalObject16stopTimeoutCheckEv
    119120__ZN3KJS14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEj
  • trunk/JavaScriptCore/VM/CodeBlock.cpp

    r34684 r34842  
    463463            break;
    464464        }
     465        case op_loop: {
     466            int offset = (++it)->u.operand;
     467            printf("[%4d] loop\t\t %d(->%d)\n", location, offset, jumpTarget(begin, it, offset));
     468            break;
     469        }
    465470        case op_jtrue: {
    466471            printConditionalJump(begin, it, location, "jtrue");
    467472            break;
    468473        }
     474        case op_loop_if_true: {
     475            printConditionalJump(begin, it, location, "loop_if_true");
     476            break;
     477        }
    469478        case op_jfalse: {
    470479            printConditionalJump(begin, it, location, "jfalse");
     
    476485            int offset = (++it)->u.operand;
    477486            printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, jumpTarget(begin, it, offset));
     487            break;
     488        }
     489        case op_loop_if_less: {
     490            int r0 = (++it)->u.operand;
     491            int r1 = (++it)->u.operand;
     492            int offset = (++it)->u.operand;
     493            printf("[%4d] loop_if_less %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, jumpTarget(begin, it, offset));
    478494            break;
    479495        }
  • trunk/JavaScriptCore/VM/CodeGenerator.cpp

    r34838 r34842  
    438438PassRefPtr<LabelID> CodeGenerator::emitJump(LabelID* target)
    439439{
    440     emitOpcode(op_jmp);
     440    emitOpcode(target->isForwardLabel() ? op_jmp : op_loop);
    441441    instructions().append(target->offsetFrom(instructions().size()));
    442442    return target;
     
    454454        if (cond->index() == dstIndex && !cond->refCount()) {
    455455            rewindBinaryOp();
    456             emitOpcode(op_jless);
     456            emitOpcode(target->isForwardLabel() ? op_jless : op_loop_if_less);
    457457            instructions().append(src1Index);
    458458            instructions().append(src2Index);
     
    462462    }
    463463   
    464     emitOpcode(op_jtrue);
     464    emitOpcode(target->isForwardLabel() ? op_jtrue : op_loop_if_true);
    465465    instructions().append(cond->index());
    466466    instructions().append(target->offsetFrom(instructions().size()));
     
    470470PassRefPtr<LabelID> CodeGenerator::emitJumpIfFalse(RegisterID* cond, LabelID* target)
    471471{
     472    ASSERT(target->isForwardLabel());
    472473    emitOpcode(op_jfalse);
    473474    instructions().append(cond->index());
     
    10441045{
    10451046    ASSERT(scopeDepth() - targetScopeDepth >= 0);
     1047    ASSERT(target->isForwardLabel());
    10461048
    10471049    size_t scopeDelta = scopeDepth() - targetScopeDepth;
  • trunk/JavaScriptCore/VM/ExceptionHelpers.cpp

    r34581 r34842  
    4444    newString.append(string.substr(position + 2));
    4545    string = newString;
     46}
     47
     48class InterruptedExecutionError : public JSObject {
     49public:
     50    virtual bool isWatchdogException() const { return true; }
     51};
     52
     53JSValue* createInterruptedExecutionException(ExecState* exec)
     54{
     55    return new (exec) InterruptedExecutionError;
    4656}
    4757
  • trunk/JavaScriptCore/VM/ExceptionHelpers.h

    r34581 r34842  
    3636    class Node;
    3737
     38    JSValue* createInterruptedExecutionException(ExecState* exec);
    3839    JSValue* createStackOverflowError(ExecState*);
    3940    JSValue* createUndefinedVariableError(ExecState*, const Identifier&);
  • trunk/JavaScriptCore/VM/LabelID.h

    r34781 r34842  
    9999        }
    100100
     101        bool isForwardLabel() const { return m_location == invalidLocation; }
     102
    101103    private:
    102104        typedef Vector<int, 8> JumpVector;
  • trunk/JavaScriptCore/VM/Machine.cpp

    r34838 r34842  
    5050#include "RegExpObject.h"
    5151
     52#if HAVE(SYS_TIME_H)
     53#include <sys/time.h>
     54#endif
     55
     56#if PLATFORM(WIN_OS)
     57#include <windows.h>
     58#endif
     59
     60#if PLATFORM(QT)
     61#include <QDateTime>
     62#endif
     63
    5264using namespace std;
    5365
    5466namespace KJS {
     67
     68// Default number of ticks before a timeout check should be done.
     69static const int initialTickCountThreshold = 255;
     70
     71// Preferred number of milliseconds between each timeout check
     72static const int preferredScriptCheckTimeInterval = 1000;
    5573
    5674#if HAVE(COMPUTED_GOTO)
     
    453471Machine::Machine()
    454472    : m_reentryDepth(0)
     473    , m_timeoutTime(0)
     474    , m_timeAtLastCheckTimeout(0)
     475    , m_timeExecuting(0)
     476    , m_timeoutCheckCount(0)
     477    , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
    455478{
    456479    privateExecute(InitializeAndReturn);
     
    592615            exception->put(exec, Identifier(exec, "sourceURL"), jsOwnedString(exec, codeBlock->ownerNode->sourceURL()));
    593616        }
     617
     618        if (exception->isWatchdogException()) {
     619            while (unwindCallFrame(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r)) {
     620                 // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
     621            }
     622            return 0;
     623        }
    594624    }
    595625
     
    848878}
    849879
     880void Machine::resetTimeoutCheck()
     881{
     882    m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
     883    m_timeAtLastCheckTimeout = 0;
     884    m_timeExecuting = 0;
     885}
     886
     887// Returns the current time in milliseconds
     888// It doesn't matter what "current time" is here, just as long as
     889// it's possible to measure the time difference correctly.
     890// In an ideal world this would be in DateMath or some such, but unfortunately
     891// that's a regression.
     892static inline unsigned getCurrentTime()
     893{
     894#if HAVE(SYS_TIME_H)
     895    struct timeval tv;
     896    gettimeofday(&tv, 0);
     897    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
     898#elif PLATFORM(QT)
     899    QDateTime t = QDateTime::currentDateTime();
     900    return t.toTime_t() * 1000 + t.time().msec();
     901#elif PLATFORM(WIN_OS)
     902    return timeGetTime();
     903#else
     904#error Platform does not have getCurrentTime function
     905#endif
     906}
     907
     908// We have to return a JSValue here, gcc seems to produce worse code if
     909// we attempt to return a bool
     910ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject)
     911{
     912    unsigned currentTime = getCurrentTime();
     913   
     914    if (!m_timeAtLastCheckTimeout) {
     915        // Suspicious amount of looping in a script -- start timing it
     916        m_timeAtLastCheckTimeout = currentTime;
     917        return 0;
     918    }
     919   
     920    unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
     921   
     922    if (timeDiff == 0)
     923        timeDiff = 1;
     924   
     925    m_timeExecuting += timeDiff;
     926    m_timeAtLastCheckTimeout = currentTime;
     927   
     928    // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
     929    // preferredScriptCheckTimeInterval
     930    m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
     931    // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
     932    // preferred script check time interval.
     933    if (m_ticksUntilNextTimeoutCheck == 0)
     934        m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
     935   
     936    if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
     937        if (globalObject->shouldInterruptScript())
     938            return jsNull(); // Appeasing GCC, all we need is a non-null js value.
     939       
     940        resetTimeoutCheck();
     941    }
     942   
     943    return 0;
     944}
     945   
    850946JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
    851947{
     
    875971    JSValue** k = codeBlock->jsValues.data();
    876972    Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
    877    
     973    unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
     974
    878975#define VM_CHECK_EXCEPTION() \
    879976     do { \
     
    888985#endif
    889986
     987#define CHECK_FOR_TIMEOUT() \
     988    if (!--tickCount) { \
     989        if ((exceptionValue = checkTimeout(exec->dynamicGlobalObject()))) \
     990            goto vm_throw; \
     991        tickCount = m_ticksUntilNextTimeoutCheck; \
     992    }
     993   
    890994#if HAVE(COMPUTED_GOTO)
    891995    #define NEXT_OPCODE goto *vPC->u.opcode
     
    18441948        NEXT_OPCODE;
    18451949    }
    1846     BEGIN_OPCODE(op_jmp) {
    1847         /* jmp target(offset)
    1848 
     1950    BEGIN_OPCODE(op_loop) {
     1951        /* loop target(offset)
     1952         
    18491953           Jumps unconditionally to offset target from the current
    18501954           instruction.
    1851         */
     1955
     1956           Additionally this loop instruction may terminate JS execution is
     1957           the JS timeout is reached.
     1958         */
    18521959#if DUMP_OPCODE_STATS
    18531960        OpcodeStats::resetLastInstruction();
    18541961#endif
    18551962        int target = (++vPC)->u.operand;
    1856 
     1963        CHECK_FOR_TIMEOUT();
    18571964        vPC += target;
     1965        NEXT_OPCODE;
     1966    }
     1967    BEGIN_OPCODE(op_jmp) {
     1968        /* jmp target(offset)
     1969
     1970           Jumps unconditionally to offset target from the current
     1971           instruction.
     1972        */
     1973#if DUMP_OPCODE_STATS
     1974        OpcodeStats::resetLastInstruction();
     1975#endif
     1976        int target = (++vPC)->u.operand;
     1977
     1978        vPC += target;
     1979        NEXT_OPCODE;
     1980    }
     1981    BEGIN_OPCODE(op_loop_if_true) {
     1982        /* loop_if_true cond(r) target(offset)
     1983         
     1984           Jumps to offset target from the current instruction, if and
     1985           only if register cond converts to boolean as true.
     1986
     1987           Additionally this loop instruction may terminate JS execution is
     1988           the JS timeout is reached.
     1989         */
     1990        int cond = (++vPC)->u.operand;
     1991        int target = (++vPC)->u.operand;
     1992        if (r[cond].u.jsValue->toBoolean(exec)) {
     1993            vPC += target;
     1994            CHECK_FOR_TIMEOUT();
     1995            NEXT_OPCODE;
     1996        }
     1997       
     1998        ++vPC;
    18581999        NEXT_OPCODE;
    18592000    }
     
    18872028        }
    18882029
     2030        ++vPC;
     2031        NEXT_OPCODE;
     2032    }
     2033    BEGIN_OPCODE(op_loop_if_less) {
     2034        /* loop_if_less src1(r) src2(r) target(offset)
     2035
     2036           Checks whether register src1 is less than register src2, as
     2037           with the ECMAScript '<' operator, and then jumps to offset
     2038           target from the current instruction, if and only if the
     2039           result of the comparison is true.
     2040
     2041           Additionally this loop instruction may terminate JS execution is
     2042           the JS timeout is reached.
     2043         */
     2044        JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
     2045        JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
     2046        int target = (++vPC)->u.operand;
     2047       
     2048        bool result = jsLess(exec, src1, src2);
     2049        VM_CHECK_EXCEPTION();
     2050       
     2051        if (result) {
     2052            vPC += target;
     2053            CHECK_FOR_TIMEOUT();
     2054            NEXT_OPCODE;
     2055        }
     2056       
    18892057        ++vPC;
    18902058        NEXT_OPCODE;
     
    22852453        JSPropertyNameIterator* it = r[iter].u.jsPropertyNameIterator;
    22862454        if (JSValue* temp = it->next(exec)) {
     2455            CHECK_FOR_TIMEOUT();
    22872456            r[dst].u.jsValue = temp;
    22882457            vPC += target;
     
    24762645    vm_throw: {
    24772646        exec->clearException();
     2647        if (!tickCount) {
     2648            // The exceptionValue is a lie! (GCC produces bad code for reasons I
     2649            // cannot fathom if we don't assign to the exceptionValue before branching)
     2650            exceptionValue = createInterruptedExecutionException(exec);
     2651        }
    24782652        handlerVPC = throwException(exec, exceptionValue, &registerBase, vPC, codeBlock, k, scopeChain, r);
    24792653        if (!handlerVPC) {
  • trunk/JavaScriptCore/VM/Machine.h

    r34838 r34842  
    4343    class Instruction;
    4444    class JSFunction;
     45    class JSGlobalObject;
    4546    class ProgramNode;
    4647    class Register;
     
    9798
    9899        void getFunctionAndArguments(Register** registerBase, Register* callFrame, JSFunction*&, Register*& argv, int& argc);
     100        void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; }
     101       
     102        void startTimeoutCheck()
     103        {
     104            if (!m_timeoutCheckCount)
     105                resetTimeoutCheck();
     106           
     107            ++m_timeoutCheckCount;
     108        }
     109       
     110        void stopTimeoutCheck()
     111        {
     112            --m_timeoutCheckCount;
     113        }
    99114
     115        inline void initTimeout()
     116        {
     117            resetTimeoutCheck();
     118            m_timeoutTime = 0;
     119            m_timeoutCheckCount = 0;
     120        }
    100121        void mark(Heap* heap) { m_registerFile.mark(heap); }
    101122
     
    119140        void dumpRegisters(const CodeBlock*, RegisterFile*, const Register*);
    120141
     142        JSValue* checkTimeout(JSGlobalObject*);
     143        void resetTimeoutCheck();
     144
    121145        int m_reentryDepth;
     146        unsigned m_timeoutTime;
     147        unsigned m_timeAtLastCheckTimeout;
     148        unsigned m_timeExecuting;
     149        unsigned m_timeoutCheckCount;
     150        unsigned m_ticksUntilNextTimeoutCheck;
     151
    122152        RegisterFile m_registerFile;
    123153
  • trunk/JavaScriptCore/VM/Opcode.cpp

    r34527 r34842  
    106106    "jless       ",
    107107    "jmp_scopes  ",
     108    "loop        ",
     109    "loop_if_true",
     110    "loop_if_less",
    108111
    109112    "new_func    ",
  • trunk/JavaScriptCore/VM/Opcode.h

    r34781 r34842  
    9898        macro(op_jless) \
    9999        macro(op_jmp_scopes) \
     100        macro(op_loop) \
     101        macro(op_loop_if_true) \
     102        macro(op_loop_if_less) \
    100103        \
    101104        macro(op_new_func) \
  • trunk/JavaScriptCore/kjs/JSGlobalObject.cpp

    r34839 r34842  
    4646#include "string_object.h"
    4747
    48 #if HAVE(SYS_TIME_H)
    49 #include <sys/time.h>
    50 #endif
    51 
    52 #if PLATFORM(WIN_OS)
    53 #include <windows.h>
    54 #endif
    55 
    56 #if PLATFORM(QT)
    57 #include <QDateTime>
    58 #endif
    59 
    6048namespace KJS {
    6149
     
    7058    if (v && !v->marked())
    7159        v->mark();
    72 }
    73    
    74 // Returns the current time in milliseconds
    75 // It doesn't matter what "current time" is here, just as long as
    76 // it's possible to measure the time difference correctly.
    77 static inline unsigned getCurrentTime()
    78 {
    79 #if HAVE(SYS_TIME_H)
    80     struct timeval tv;
    81     gettimeofday(&tv, 0);
    82     return tv.tv_sec * 1000 + tv.tv_usec / 1000;
    83 #elif PLATFORM(QT)
    84     QDateTime t = QDateTime::currentDateTime();
    85     return t.toTime_t() * 1000 + t.time().msec();
    86 #elif PLATFORM(WIN_OS)
    87     return timeGetTime();
    88 #else
    89 #error Platform does not have getCurrentTime function
    90 #endif
    9160}
    9261
     
    132101        headObject = d()->next = d()->prev = this;
    133102
    134     resetTimeoutCheck();
    135     d()->timeoutTime = 0;
    136     d()->timeoutCheckCount = 0;
    137 
    138103    d()->recursion = 0;
    139104    d()->debugger = 0;
    140    
     105    globalData()->machine->initTimeout();
     106
    141107    d()->globalExec.set(new ExecState(this, thisValue, d()->globalScopeChain.node()));
    142108
     
    347313}
    348314
     315void JSGlobalObject::setTimeoutTime(unsigned timeoutTime)
     316{
     317    globalData()->machine->setTimeoutTime(timeoutTime);
     318}
     319
    349320void JSGlobalObject::startTimeoutCheck()
    350321{
    351     if (!d()->timeoutCheckCount)
    352         resetTimeoutCheck();
    353    
    354     ++d()->timeoutCheckCount;
     322    globalData()->machine->startTimeoutCheck();
    355323}
    356324
    357325void JSGlobalObject::stopTimeoutCheck()
    358326{
    359     --d()->timeoutCheckCount;
    360 }
    361 
    362 void JSGlobalObject::resetTimeoutCheck()
    363 {
    364     d()->tickCount = 0;
    365     d()->ticksUntilNextTimeoutCheck = initialTickCountThreshold;
    366     d()->timeAtLastCheckTimeout = 0;
    367     d()->timeExecuting = 0;
    368 }
    369 
    370 bool JSGlobalObject::checkTimeout()
    371 {   
    372     d()->tickCount = 0;
    373    
    374     unsigned currentTime = getCurrentTime();
    375 
    376     if (!d()->timeAtLastCheckTimeout) {
    377         // Suspicious amount of looping in a script -- start timing it
    378         d()->timeAtLastCheckTimeout = currentTime;
    379         return false;
    380     }
    381 
    382     unsigned timeDiff = currentTime - d()->timeAtLastCheckTimeout;
    383 
    384     if (timeDiff == 0)
    385         timeDiff = 1;
    386    
    387     d()->timeExecuting += timeDiff;
    388     d()->timeAtLastCheckTimeout = currentTime;
    389    
    390     // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
    391     // preferredScriptCheckTimeInterval
    392     d()->ticksUntilNextTimeoutCheck = (unsigned)((float)preferredScriptCheckTimeInterval / timeDiff) * d()->ticksUntilNextTimeoutCheck;
    393 
    394     // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
    395     // preferred script check time interval.
    396     if (d()->ticksUntilNextTimeoutCheck == 0)
    397         d()->ticksUntilNextTimeoutCheck = initialTickCountThreshold;
    398 
    399     if (d()->timeoutTime && d()->timeExecuting > d()->timeoutTime) {
    400         if (shouldInterruptScript())
    401             return true;
    402        
    403         resetTimeoutCheck();
    404     }
    405    
    406     return false;
     327    globalData()->machine->stopTimeoutCheck();
    407328}
    408329
  • trunk/JavaScriptCore/kjs/JSGlobalObject.h

    r34838 r34842  
    9090            int recursion;
    9191
    92             unsigned timeoutTime;
    93             unsigned timeAtLastCheckTimeout;
    94             unsigned timeExecuting;
    95             unsigned timeoutCheckCount;
    96             unsigned tickCount;
    97             unsigned ticksUntilNextTimeoutCheck;
    98 
    9992            RegExpConstructor* regExpConstructor;
    10093            ErrorConstructor* errorConstructor;
     
    203196        unsigned pageGroupIdentifier() const { return d()->pageGroupIdentifier; }
    204197
    205         void setTimeoutTime(unsigned timeoutTime) { d()->timeoutTime = timeoutTime; }
     198        void setTimeoutTime(unsigned timeoutTime);
    206199        void startTimeoutCheck();
    207200        void stopTimeoutCheck();
    208         bool timedOut();
    209201
    210202        Debugger* debugger() const { return d()->debugger; }
     
    263255        void addStaticGlobals(GlobalPropertyInfo*, int count);
    264256
    265     private:
    266         bool checkTimeout();
    267         void resetTimeoutCheck();
    268257    };
    269258
     
    299288    }
    300289
    301     inline bool JSGlobalObject::timedOut()
    302     {
    303         d()->tickCount++;
    304 
    305         if (d()->tickCount != d()->ticksUntilNextTimeoutCheck)
    306             return false;
    307 
    308         return checkTimeout();
    309     }
    310 
    311290    inline JSGlobalObject* ScopeChainNode::globalObject() const
    312291    {
  • trunk/JavaScriptCore/kjs/JSObject.h

    r34821 r34842  
    379379    virtual bool isVariableObject() const { return false; }
    380380
     381    virtual bool isWatchdogException() const { return false; }
     382
    381383  protected:
    382384    PropertyMap _prop;
  • trunk/JavaScriptCore/kjs/interpreter.cpp

    r34838 r34842  
    8282    JSValue* result = exec->machine()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception);
    8383
    84     return exception ? Completion(Throw, exception) : Completion(Normal, result);
     84    if (exception) {
     85        if (exception->isObject() && static_cast<JSObject*>(exception)->isWatchdogException())
     86            return Completion(Interrupted, result);
     87        return Completion(Throw, exception);
     88    }
     89    return Completion(Normal, result);
    8590}
    8691
Note: See TracChangeset for help on using the changeset viewer.