Changeset 19534 in webkit for trunk/JavaScriptCore/kjs/interpreter.cpp
- Timestamp:
- Feb 9, 2007, 11:28:02 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/interpreter.cpp
r18461 r19534 58 58 #include <stdio.h> 59 59 60 #if PLATFORM(WIN_OS) 61 #include <windows.h> 62 #endif 63 60 64 namespace KJS { 61 65 62 class TimeoutChecker { 63 public: 64 void startTimeoutCheck(Interpreter*); 65 void stopTimeoutCheck(Interpreter*); 66 void pauseTimeoutCheck(Interpreter*); 67 void resumeTimeoutCheck(Interpreter*); 68 69 private: 70 #if HAVE(SYS_TIME_H) 71 static Interpreter* s_executingInterpreter; 72 static void alarmHandler(int); 73 74 Interpreter* m_oldInterpreter; 75 itimerval m_oldtv; 76 itimerval m_pausetv; 77 void (*m_oldAlarmHandler)(int); 78 #endif 79 }; 80 81 #if HAVE(SYS_TIME_H) 82 Interpreter* TimeoutChecker::s_executingInterpreter = 0; 83 #endif 84 85 void TimeoutChecker::startTimeoutCheck(Interpreter *interpreter) 86 { 87 if (!interpreter->m_timeoutTime) 88 return; 89 90 interpreter->m_startTimeoutCheckCount++; 91 92 #if HAVE(SYS_TIME_H) 93 if (s_executingInterpreter == interpreter) 94 return; 95 96 // Block signals 97 m_oldAlarmHandler = signal(SIGALRM, SIG_IGN); 98 99 m_oldInterpreter = s_executingInterpreter; 100 s_executingInterpreter = interpreter; 101 102 itimerval tv = { 103 { interpreter->m_timeoutTime / 1000, (interpreter->m_timeoutTime % 1000) * 1000 }, 104 { interpreter->m_timeoutTime / 1000, (interpreter->m_timeoutTime % 1000) * 1000 } 105 }; 106 setitimer(ITIMER_REAL, &tv, &m_oldtv); 107 108 // Unblock signals 109 signal(SIGALRM, alarmHandler); 110 #endif 111 } 112 113 void TimeoutChecker::stopTimeoutCheck(Interpreter* interpreter) 114 { 115 if (!interpreter->m_timeoutTime) 116 return; 117 118 ASSERT(interpreter->m_startTimeoutCheckCount > 0); 119 120 interpreter->m_startTimeoutCheckCount--; 121 122 if (interpreter->m_startTimeoutCheckCount != 0) 123 return; 124 125 #if HAVE(SYS_TIME_H) 126 signal(SIGALRM, SIG_IGN); 127 128 s_executingInterpreter = m_oldInterpreter; 129 130 setitimer(ITIMER_REAL, &m_oldtv, 0L); 131 signal(SIGALRM, m_oldAlarmHandler); 132 #endif 133 } 134 135 #if HAVE(SYS_TIME_H) 136 void TimeoutChecker::alarmHandler(int) 137 { 138 s_executingInterpreter->m_timedOut = true; 139 } 140 #endif 141 142 void TimeoutChecker::pauseTimeoutCheck(Interpreter* interpreter) 143 { 144 if (interpreter->m_startTimeoutCheckCount == 0) 145 return; 146 147 #if HAVE(SYS_TIME_H) 148 ASSERT(interpreter == s_executingInterpreter); 149 150 void (*currentSignalHandler)(int); 151 152 // Block signal 153 currentSignalHandler = signal(SIGALRM, SIG_IGN); 154 155 if (currentSignalHandler != alarmHandler) { 156 signal(SIGALRM, currentSignalHandler); 157 return; 158 } 159 160 setitimer(ITIMER_REAL, 0L, &m_pausetv); 161 #endif 162 163 interpreter->m_pauseTimeoutCheckCount++; 164 } 165 166 void TimeoutChecker::resumeTimeoutCheck(Interpreter* interpreter) 167 { 168 if (interpreter->m_startTimeoutCheckCount == 0) 169 return; 170 171 #if HAVE(SYS_TIME_H) 172 ASSERT(interpreter == s_executingInterpreter); 173 #endif 174 175 interpreter->m_pauseTimeoutCheckCount--; 176 177 if (interpreter->m_pauseTimeoutCheckCount != 0) 178 return; 179 180 #if HAVE(SYS_TIME_H) 181 void (*currentSignalHandler)(int); 182 183 // Check so we have the right handler 184 currentSignalHandler = signal(SIGALRM, SIG_IGN); 185 186 if (currentSignalHandler != SIG_IGN) { 187 signal(SIGALRM, currentSignalHandler); 188 return; 189 } 190 191 setitimer(ITIMER_REAL, &m_pausetv, 0L); 192 193 // Unblock signal 194 currentSignalHandler = signal(SIGALRM, alarmHandler); 195 #endif 196 } 66 // Default number of ticks before a timeout check should be done. 67 static const int initialTickCountThreshold = 255; 68 69 // Preferred number of milliseconds between each timeout check 70 static const int preferredScriptCheckTimeInterval = 1000; 197 71 198 72 Interpreter* Interpreter::s_hook = 0; … … 228 102 m_debugger= 0; 229 103 m_context = 0; 230 m_timedOut = false; 231 m_timeoutChecker = 0;232 m_ startTimeoutCheckCount = 0;233 m_pauseTimeoutCheckCount = 0;104 105 resetTimeoutCheck(); 106 m_timeoutCheckCount = 0; 107 234 108 m_compatMode = NativeMode; 235 109 m_argumentsPropertyName = &argumentsPropertyName; … … 254 128 { 255 129 JSLock lock; 256 257 ASSERT (m_startTimeoutCheckCount == 0);258 ASSERT (m_pauseTimeoutCheckCount == 0);259 260 delete m_timeoutChecker;261 130 262 131 if (m_debugger) … … 775 644 void Interpreter::startTimeoutCheck() 776 645 { 777 if ( !m_timeoutChecker)778 m_timeoutChecker = new TimeoutChecker;779 780 m_timeoutCheck er->startTimeoutCheck(this);646 if (m_timeoutCheckCount == 0) 647 resetTimeoutCheck(); 648 649 m_timeoutCheckCount++; 781 650 } 782 651 783 652 void Interpreter::stopTimeoutCheck() 784 653 { 785 ASSERT(m_timeoutChecker); 786 787 m_timeoutChecker->stopTimeoutCheck(this); 788 } 789 790 void Interpreter::pauseTimeoutCheck() 791 { 792 ASSERT(m_timeoutChecker); 793 794 m_timeoutChecker->pauseTimeoutCheck(this); 795 } 796 797 void Interpreter::resumeTimeoutCheck() 798 { 799 ASSERT(m_timeoutChecker); 800 801 m_timeoutChecker->resumeTimeoutCheck(this); 802 } 803 804 bool Interpreter::handleTimeout() 805 { 806 m_timedOut = false; 807 808 pauseTimeoutCheck(); 809 bool retval = shouldInterruptScript(); 810 resumeTimeoutCheck(); 811 812 return retval; 654 m_timeoutCheckCount--; 655 } 656 657 void Interpreter::resetTimeoutCheck() 658 { 659 m_tickCount = 0; 660 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold; 661 m_timeAtLastCheckTimeout = 0; 662 m_timeExecuting = 0; 663 } 664 665 // Returns the current time in milliseconds 666 // It doesn't matter what "current time" is here, just as long as 667 // it's possible to measure the time difference correctly. 668 static inline unsigned getCurrentTime() { 669 #if HAVE(SYS_TIME_H) 670 struct timeval tv; 671 gettimeofday(&tv, 0); 672 return tv.tv_sec * 1000 + tv.tv_usec / 1000; 673 #elif PLATFORM(WIN_OS) 674 return timeGetTime(); 675 #else 676 #error Platform does not have getCurrentTime function 677 #endif 678 } 679 680 bool Interpreter::checkTimeout() 681 { 682 m_tickCount = 0; 683 684 unsigned currentTime = getCurrentTime(); 685 686 if (!m_timeAtLastCheckTimeout) { 687 // Suspicious amount of looping in a script -- start timing it 688 m_timeAtLastCheckTimeout = currentTime; 689 return false; 690 } 691 692 unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout; 693 694 if (timeDiff == 0) 695 timeDiff = 1; 696 697 m_timeExecuting += timeDiff; 698 m_timeAtLastCheckTimeout = currentTime; 699 700 // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in 701 // preferredScriptCheckTimeInterval 702 m_ticksUntilNextTimeoutCheck = (unsigned)((float)preferredScriptCheckTimeInterval / timeDiff) * m_ticksUntilNextTimeoutCheck; 703 704 // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the 705 // preferred script check time interval. 706 if (m_ticksUntilNextTimeoutCheck == 0) 707 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold; 708 709 if (m_timeoutTime && m_timeExecuting > m_timeoutTime) { 710 if (shouldInterruptScript()) 711 return true; 712 713 resetTimeoutCheck(); 714 } 715 716 return false; 813 717 } 814 718
Note:
See TracChangeset
for help on using the changeset viewer.