Oolite 1.91.0.7645-241119-222d325
Loading...
Searching...
No Matches
OOJSEngineTimeManagement.m File Reference
#include <jsdbgapi.h>
import "OOJSEngineTimeManagement.h"
import "OOProfilingStopwatch.h"
import "OOJSScript.h"
import "OOCollectionExtractors.h"
import "OOLoggingExtended.h"
#include <unistd.h>
+ Include dependency graph for OOJSEngineTimeManagement.m:

Go to the source code of this file.

Classes

category  OOTimeProfile(Private)
 
category  OOTimeProfileEntry(Private)
 

Macros

#define OOJS_DEBUG_LIMITER   0
 
#define OOJS_TIME_LIMIT   (1)
 

Functions

void OOJSStartTimeLimiterWithTimeLimit_ (OOTimeDelta limit, const char *file, unsigned line)
 
void OOJSStopTimeLimiter_ (const char *file, unsigned line)
 
void OOJSPauseTimeLimiter (void)
 
void OOJSResumeTimeLimiter (void)
 
OOHighResTimeValue OOJSCopyTimeLimiterNominalStartTime (void)
 
void OOJSResetTimeLimiter (void)
 
OOTimeDelta OOJSGetTimeLimiterLimit (void)
 
void OOJSSetTimeLimiterLimit (OOTimeDelta limit)
 
static JSBool OperationCallback (JSContext *context)
 
static JSBool ContextCallback (JSContext *context, uintN contextOp)
 
void OOJSTimeManagementInit (OOJavaScriptEngine *engine, JSRuntime *runtime)
 
void OOJSBeginProfiling (BOOL trace)
 
OOTimeProfileOOJSEndProfiling (void)
 
BOOL OOJSIsProfiling (void)
 
void OOJSBeginTracing (void)
 
void OOJSEndTracing (void)
 
BOOL OOJSIsTracing (void)
 
static void UpdateProfileForFrame (OOHighResTimeValue now, OOJSProfileStackFrame *frame)
 
void OOJSProfileEnter (OOJSProfileStackFrame *frame, const char *function)
 
void OOJSProfileExit (OOJSProfileStackFrame *frame)
 

Variables

static unsigned sLimiterStartDepth
 
static int sLimiterPauseDepth
 
static OOHighResTimeValue sLimiterStart
 
static OOHighResTimeValue sLimiterPauseStart
 
static double sLimiterTimeLimit
 
static BOOL sStop
 
static const char * sLastStartedFile
 
static unsigned sLastStartedLine
 
static const char * sLastStoppedFile
 
static unsigned sLastStoppedLine
 
static BOOL sProfiling = NO
 
static BOOL sTracing = NO
 
static OOJSProfileStackFrame * sProfileStack = NULL
 
static NSMapTable * sProfileInfo
 
static double sProfilerOverhead
 
static double sProfilerTotalNativeTime
 
static double sProfilerTotalJavaScriptTime
 
static double sProfilerEntryTimeLimit
 
static OOHighResTimeValue sProfilerStartTime
 

Macro Definition Documentation

◆ OOJS_DEBUG_LIMITER

#define OOJS_DEBUG_LIMITER   0

Definition at line 49 of file OOJSEngineTimeManagement.m.

◆ OOJS_TIME_LIMIT

#define OOJS_TIME_LIMIT   (1)

Definition at line 63 of file OOJSEngineTimeManagement.m.

Referenced by OOJSStartTimeLimiterWithTimeLimit_().

Function Documentation

◆ ContextCallback()

static JSBool ContextCallback ( JSContext * context,
uintN contextOp )
static

Definition at line 240 of file OOJSEngineTimeManagement.m.

241{
242 if (contextOp == JSCONTEXT_NEW)
243 {
244 JS_SetOperationCallback(context, OperationCallback);
245
246#if OOJS_PROFILE && defined(MOZ_TRACE_JSCALLS)
247 JS_SetFunctionCallback(context, (JSFunctionCallback)FunctionCallback); // Naughtily casts away consts, because const JSContexts and JSFunctions are useless.
248#endif
249 }
250 return YES;
251}
static JSBool OperationCallback(JSContext *context)

References OperationCallback().

Referenced by OOJSTimeManagementInit().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ OOJSBeginProfiling()

void OOJSBeginProfiling ( BOOL trace)

Definition at line 311 of file OOJSEngineTimeManagement.m.

312{
313 assert(sProfiling == NO);
314 sProfiling = YES;
315 sTracing = trace;
316 sProfileInfo = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSObjectMapValueCallBacks, 100);
317 sProfilerOverhead = 0.0;
321
322 // This should be last for precision.
324
325 if (trace)
326 {
327 OOLog(@"script.javaScript.trace", @"%@", @">>>> Beginning trace.");
328 OOLogIndent();
329 }
330}
static BOOL sTracing
static double sProfilerTotalNativeTime
static OOHighResTimeValue sProfilerStartTime
static double sProfilerOverhead
OOTimeDelta OOJSGetTimeLimiterLimit(void)
static double sProfilerTotalJavaScriptTime
static double sProfilerEntryTimeLimit
static BOOL sProfiling
static NSMapTable * sProfileInfo
#define OOLog(class, format,...)
Definition OOLogging.h:88
void OOLogIndent(void)
Definition OOLogging.m:366
#define OOGetHighResTime

References OOGetHighResTime, OOJSGetTimeLimiterLimit(), OOLog, OOLogIndent(), sProfileInfo, sProfilerEntryTimeLimit, sProfilerOverhead, sProfilerStartTime, sProfilerTotalJavaScriptTime, sProfilerTotalNativeTime, sProfiling, and sTracing.

Referenced by Entity(OODebugInspector)::inspect.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ OOJSBeginTracing()

void OOJSBeginTracing ( void )

◆ OOJSCopyTimeLimiterNominalStartTime()

OOHighResTimeValue OOJSCopyTimeLimiterNominalStartTime ( void )

Definition at line 158 of file OOJSEngineTimeManagement.m.

159{
160 return sLimiterStart;
161}
static OOHighResTimeValue sLimiterStart

References sLimiterStart.

◆ OOJSEndProfiling()

OOTimeProfile * OOJSEndProfiling ( void )

Definition at line 333 of file OOJSEngineTimeManagement.m.

334{
335 // This should be at the top for precision.
337 // Time limiter should be as close to outermost as practical.
339
340 assert(sProfiling && sProfileStack == NULL);
341
342 sProfiling = NO;
343
344 OOTimeProfile *result = [[OOTimeProfile alloc] init];
345
346 [result setTotalTime:OOHighResTimeDeltaInSeconds(sProfilerStartTime, now)];
347 [result setNativeTime:sProfilerTotalNativeTime];
348#ifdef MOZ_TRACE_JSCALLS
349 [result setJavaScriptTime:sProfilerTotalJavaScriptTime];
350#endif
351 [result setProfilerOverhead:sProfilerOverhead];
352
353 double currentTimeLimit = OOJSGetTimeLimiterLimit();
354 [result setExtensionTime:currentTimeLimit - sProfilerEntryTimeLimit];
355
356 [result setProfileEntries:[NSAllMapTableValues(sProfileInfo) sortedArrayUsingSelector:@selector(compareBySelfTimeReverse:)]];
357
358 if (sTracing)
359 {
360 OOLogOutdent();
361 OOLog(@"script.javaScript.trace", @"%@", @"<<<< End of trace.");
362 sTracing = NO;
363 }
364
365 // Clean up.
366 NSFreeMapTable(sProfileInfo);
368
370
372 return result;
373}
void OOJSPauseTimeLimiter(void)
static OOJSProfileStackFrame * sProfileStack
void OOJSResumeTimeLimiter(void)
void OOLogOutdent(void)
Definition OOLogging.m:376
OOTimeDelta OOHighResTimeDeltaInSeconds(OOHighResTimeValue startTime, OOHighResTimeValue endTime)
uint64_t OOHighResTimeValue
#define OODisposeHighResTime(time)

References OODisposeHighResTime, OOGetHighResTime, OOJSGetTimeLimiterLimit(), OOJSPauseTimeLimiter(), OOJSResumeTimeLimiter(), OOLog, OOLogOutdent(), OOTimeProfile::setExtensionTime:, OOTimeProfile::setNativeTime:, OOTimeProfile::setProfileEntries:, OOTimeProfile::setProfilerOverhead:, OOTimeProfile::setTotalTime:, sProfileInfo, sProfilerStartTime, sProfileStack, sProfiling, and sTracing.

Referenced by Entity(OODebugInspector)::inspect.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ OOJSEndTracing()

void OOJSEndTracing ( void )

◆ OOJSGetTimeLimiterLimit()

OOTimeDelta OOJSGetTimeLimiterLimit ( void )

Definition at line 173 of file OOJSEngineTimeManagement.m.

174{
175 return sLimiterTimeLimit;
176}
static double sLimiterTimeLimit

References sLimiterTimeLimit.

Referenced by Entity(OODebugInspector)::inspect, OOJSBeginProfiling(), and OOJSEndProfiling().

+ Here is the caller graph for this function:

◆ OOJSIsProfiling()

BOOL OOJSIsProfiling ( void )

Definition at line 376 of file OOJSEngineTimeManagement.m.

377{
378 return sProfiling;
379}

References sProfiling.

Referenced by ConsoleGetProfile(), ConsoleProfile(), and ConsoleTrace().

+ Here is the caller graph for this function:

◆ OOJSIsTracing()

BOOL OOJSIsTracing ( void )

◆ OOJSPauseTimeLimiter()

◆ OOJSProfileEnter()

void OOJSProfileEnter ( OOJSProfileStackFrame * frame,
const char * function )

Definition at line 527 of file OOJSEngineTimeManagement.m.

528{
529 if (EXPECT(!sProfiling)) return;
530 if (EXPECT_NOT(sTracing))
531 {
532 // We use EXPECT_NOT here because profiles are time-critical and traces are not.
533 OOLog(@"script.javaScript.trace.ON", @">> %s [ON]", function);
534 OOLogIndent();
535 }
536
537 *frame = (OOJSProfileStackFrame)
538 {
539 .back = sProfileStack,
540 .key = function,
541 .function = function,
542 .startTime = OOGetHighResTime(),
544 };
545 sProfileStack = frame;
546}
#define EXPECT_NOT(x)
#define EXPECT(x)

References EXPECT, EXPECT_NOT, OOGetHighResTime, OOLog, OOLogIndent(), sProfilerTotalNativeTime, sProfileStack, sProfiling, and sTracing.

+ Here is the call graph for this function:

◆ OOJSProfileExit()

void OOJSProfileExit ( OOJSProfileStackFrame * frame)

Definition at line 549 of file OOJSEngineTimeManagement.m.

550{
551 if (EXPECT(!sProfiling)) return;
552
554 NSAutoreleasePool *pool = [NSAutoreleasePool new];
555 BOOL done = NO;
556
557 /*
558 It's possible there could be JavaScript frames on top of this frame if
559 a JS native returned false. Or possibly not. The semantics of
560 JS_SetFunctionCallback() aren't specified in detail.
561 -- Ahruman 2011-01-16
562 */
563 for (;;)
564 {
565 assert(sProfileStack != NULL);
566
567 done = (sProfileStack == frame);
569 if (EXPECT(done)) break;
570 }
571
572 [pool release];
573
574 OODisposeHighResTime(frame->startTime);
575
577 double currentOverhead = OOHighResTimeDeltaInSeconds(now, end);
578 sProfilerOverhead += currentOverhead;
579
580 /* Equivalent of pausing/resuming time limiter, except that it guarantees
581 excluded time will match profiler overhead if there are no other
582 pauses happening.
583 */
584 if (sLimiterPauseDepth == 0) sLimiterTimeLimit += currentOverhead;
585
588}
static void UpdateProfileForFrame(OOHighResTimeValue now, OOJSProfileStackFrame *frame)

References EXPECT, OODisposeHighResTime, OOGetHighResTime, OOHighResTimeDeltaInSeconds(), sLimiterPauseDepth, sLimiterTimeLimit, sProfilerOverhead, sProfileStack, sProfiling, and UpdateProfileForFrame().

+ Here is the call graph for this function:

◆ OOJSResetTimeLimiter()

void OOJSResetTimeLimiter ( void )

Definition at line 164 of file OOJSEngineTimeManagement.m.

165{
168
169 sStop = NO;
170}
static BOOL sStop

References OODisposeHighResTime, OOGetHighResTime, sLimiterStart, and sStop.

Referenced by Entity(OODebugInspector)::inspect.

+ Here is the caller graph for this function:

◆ OOJSResumeTimeLimiter()

void OOJSResumeTimeLimiter ( void )

Definition at line 143 of file OOJSEngineTimeManagement.m.

144{
145 if (--sLimiterPauseDepth == 0)
146
147 {
151
152 sLimiterTimeLimit += elapsed;
153 }
154}
double OOTimeDelta
Definition OOTypes.h:224

References OODisposeHighResTime, OOGetHighResTime, OOHighResTimeDeltaInSeconds(), sLimiterPauseDepth, sLimiterPauseStart, and sLimiterTimeLimit.

Referenced by NSString(OOJavaScriptExtensions)::concatenationOfStringsFromJavaScriptValues:count:separator:inContext:, ConsoleConsoleMessage(), ConsoleIsExecutableJavaScript(), ConsoleSettingsSetProperty(), OOPlanetEntity(OOJavaScriptExtensions)::getJSClass:andPrototype:, JSFunctionPredicate(), MissionRunScreen(), OOJSEndProfiling(), ReportJSError(), SoundFromJSValue(), SystemFilteredEntities(), and SystemInfoStaticFilteredSystems().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ OOJSSetTimeLimiterLimit()

void OOJSSetTimeLimiterLimit ( OOTimeDelta limit)

Definition at line 179 of file OOJSEngineTimeManagement.m.

180{
181 sLimiterTimeLimit = limit;
182}

References sLimiterTimeLimit.

Referenced by Entity(OODebugInspector)::inspect.

+ Here is the caller graph for this function:

◆ OOJSStartTimeLimiterWithTimeLimit_()

void OOJSStartTimeLimiterWithTimeLimit_ ( OOTimeDelta limit,
const char * file,
unsigned line )

Definition at line 82 of file OOJSEngineTimeManagement.m.

86{
87#if OOJS_DEBUG_LIMITER
88 OOLog(@"script.javaScript.timeLimit.debug",@"Limiter starting: %u => %u",sLimiterStartDepth,sLimiterStartDepth+1);
89#endif
90 if (sLimiterStartDepth++ == 0)
91 {
92 if (limit <= 0.0) limit = OOJS_TIME_LIMIT;
93 sLimiterTimeLimit = limit;
95
98 }
99
100#ifndef NDEBUG
101 sLastStartedFile = file;
102 sLastStartedLine = line;
103#endif
104}
#define OOJS_TIME_LIMIT
static const char * sLastStartedFile
static unsigned sLimiterStartDepth
static unsigned sLastStartedLine

References OODisposeHighResTime, OOGetHighResTime, OOJS_TIME_LIMIT, OOLog, sLastStartedFile, sLastStartedLine, sLimiterPauseDepth, sLimiterStart, sLimiterStartDepth, and sLimiterTimeLimit.

◆ OOJSStopTimeLimiter_()

void OOJSStopTimeLimiter_ ( const char * file,
unsigned line )

Definition at line 108 of file OOJSEngineTimeManagement.m.

112{
113#ifndef NDEBUG
114 if (sLimiterStartDepth == 0)
115 {
116 OOLog(@"bug.javaScript.limiterDepth", @"Attempt to stop JavaScript time limiter while it is already fully stopped. This is an internal bug, please report it. (Last start: %@:%u, last valid stop: %@:%u, this stop attempt: %@:%u.)", OOLogAbbreviatedFileName(sLastStartedFile), sLastStartedLine, OOLogAbbreviatedFileName(sLastStoppedFile), sLastStoppedLine, OOLogAbbreviatedFileName(file), line);
117 return;
118 }
119
120 sLastStoppedFile = file;
121 sLastStoppedLine = line;
122
123#if OOJS_DEBUG_LIMITER
124 OOLog(@"script.javaScript.timeLimit.debug",@"Limiter ending: %u <= %u",sLimiterStartDepth-1,sLimiterStartDepth);
125#endif
126
127#endif
128
129 if (--sLimiterStartDepth == 0) sLimiterTimeLimit = 0.0;
130}
static unsigned sLastStoppedLine
static const char * sLastStoppedFile
NSString * OOLogAbbreviatedFileName(const char *inName)
Definition OOLogging.m:839

References OOLog, OOLogAbbreviatedFileName(), sLastStartedFile, sLastStartedLine, sLastStoppedFile, sLastStoppedLine, sLimiterStartDepth, and sLimiterTimeLimit.

+ Here is the call graph for this function:

◆ OOJSTimeManagementInit()

void OOJSTimeManagementInit ( OOJavaScriptEngine * engine,
JSRuntime * runtime )

Definition at line 254 of file OOJSEngineTimeManagement.m.

255{
256 [NSThread detachNewThreadSelector:@selector(watchdogTimerThread)
257 toTarget:engine
258 withObject:nil];
259
260 JS_SetContextCallback(runtime, ContextCallback);
261}
static JSBool ContextCallback(JSContext *context, uintN contextOp)
return nil

References ContextCallback().

+ Here is the call graph for this function:

◆ OperationCallback()

static JSBool OperationCallback ( JSContext * context)
static

Definition at line 217 of file OOJSEngineTimeManagement.m.

218{
219 if (!sStop) return YES;
220
221 JS_ClearPendingException(context);
222
226
227 if (elapsed <= sLimiterTimeLimit) return YES;
228
229 OOLogERR(@"script.javaScript.timeLimit", @"Script \"%@\" ran for %g seconds and has been terminated.", [[OOJSScript currentlyRunningScript] name], elapsed);
230#ifndef NDEBUG
231 OOJSDumpStack(context);
232#endif
233
234 // FIXME: we really should put something in the JS log here, but since that's implemented in JS there are complications.
235
236 return NO;
237}
void OOJSDumpStack(JSContext *context)
#define OOLogERR(class, format,...)
Definition OOLogging.h:112

References OODisposeHighResTime, OOGetHighResTime, OOHighResTimeDeltaInSeconds(), OOJSDumpStack(), OOLogERR, sLimiterStart, sLimiterTimeLimit, and sStop.

Referenced by ContextCallback().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ UpdateProfileForFrame()

static void UpdateProfileForFrame ( OOHighResTimeValue now,
OOJSProfileStackFrame * frame )
static

Definition at line 591 of file OOJSEngineTimeManagement.m.

592{
593 sProfileStack = frame->back;
594
595 OOTimeProfileEntry *entry = NSMapGet(sProfileInfo, frame->key);
596 if (entry == nil)
597 {
598 entry = [[OOTimeProfileEntry alloc] initWithCName:frame->function];
599 NSMapInsertKnownAbsent(sProfileInfo, frame->key, entry);
600 [entry release];
601 }
602
603 OOTimeDelta time = OOHighResTimeDeltaInSeconds(frame->startTime, now);
604 OOTimeDelta selfTime = time - frame->subTime;
605 [entry addSampleWithTotalTime:time selfTime:selfTime];
606
607 *(frame->total) += selfTime;
608 if (sProfileStack != NULL) sProfileStack->subTime += time;
609
610 if (frame->cleanup != NULL) frame->cleanup(frame);
611
613}

Referenced by OOJSProfileExit().

+ Here is the caller graph for this function:

Variable Documentation

◆ sLastStartedFile

const char* sLastStartedFile
static

◆ sLastStartedLine

unsigned sLastStartedLine
static

◆ sLastStoppedFile

const char* sLastStoppedFile
static

Definition at line 71 of file OOJSEngineTimeManagement.m.

Referenced by OOJSStopTimeLimiter_().

◆ sLastStoppedLine

unsigned sLastStoppedLine
static

Definition at line 72 of file OOJSEngineTimeManagement.m.

Referenced by OOJSStopTimeLimiter_().

◆ sLimiterPauseDepth

◆ sLimiterPauseStart

OOHighResTimeValue sLimiterPauseStart
static

Definition at line 56 of file OOJSEngineTimeManagement.m.

Referenced by OOJSPauseTimeLimiter(), and OOJSResumeTimeLimiter().

◆ sLimiterStart

◆ sLimiterStartDepth

unsigned sLimiterStartDepth
static

◆ sLimiterTimeLimit

◆ sProfileInfo

NSMapTable* sProfileInfo
static

◆ sProfilerEntryTimeLimit

double sProfilerEntryTimeLimit
static

Definition at line 277 of file OOJSEngineTimeManagement.m.

Referenced by OOJSBeginProfiling().

◆ sProfilerOverhead

double sProfilerOverhead
static

Definition at line 274 of file OOJSEngineTimeManagement.m.

Referenced by OOJSBeginProfiling(), and OOJSProfileExit().

◆ sProfilerStartTime

OOHighResTimeValue sProfilerStartTime
static

Definition at line 278 of file OOJSEngineTimeManagement.m.

Referenced by OOJSBeginProfiling(), and OOJSEndProfiling().

◆ sProfilerTotalJavaScriptTime

double sProfilerTotalJavaScriptTime
static

Definition at line 276 of file OOJSEngineTimeManagement.m.

Referenced by OOJSBeginProfiling().

◆ sProfilerTotalNativeTime

double sProfilerTotalNativeTime
static

Definition at line 275 of file OOJSEngineTimeManagement.m.

Referenced by OOJSBeginProfiling(), and OOJSProfileEnter().

◆ sProfileStack

OOJSProfileStackFrame* sProfileStack = NULL
static

◆ sProfiling

BOOL sProfiling = NO
static

◆ sStop

BOOL sStop
static

Definition at line 66 of file OOJSEngineTimeManagement.m.

Referenced by OOJSResetTimeLimiter(), and OperationCallback().

◆ sTracing