Changeset 188648 in webkit
- Timestamp:
- Aug 19, 2015 1:41:30 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp
r188329 r188648 27 27 #include "ExecutionTimeLimitTest.h" 28 28 29 #include "InitializeThreading.h" 29 30 #include "JSContextRefPrivate.h" 30 31 #include "JavaScriptCore.h" 32 #include "Options.h" 31 33 #include <chrono> 32 34 #include <wtf/CurrentTime.h> 35 #include <wtf/text/StringBuilder.h> 33 36 34 37 using namespace std::chrono; 38 using JSC::Options; 35 39 36 40 static JSGlobalContextRef context = nullptr; … … 79 83 } 80 84 85 struct TierOptions { 86 const char* tier; 87 unsigned timeLimitAdjustmentMillis; 88 const char* optionsStr; 89 }; 81 90 82 91 int testExecutionTimeLimit() 83 92 { 84 context = JSGlobalContextCreateInGroup(nullptr, nullptr); 85 86 JSContextGroupRef contextGroup = JSContextGetGroup(context); 87 JSObjectRef globalObject = JSContextGetGlobalObject(context); 88 ASSERT(JSValueIsObject(context, globalObject)); 89 90 JSValueRef v = nullptr; 91 JSValueRef exception = nullptr; 93 static const TierOptions tierOptionsList[] = { 94 { "LLINT", 0, "--enableConcurrentJIT=false --useLLInt=true --useJIT=false" }, 95 { "Baseline", 0, "--enableConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=false" }, 96 { "DFG", 0, "--enableConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=false" }, 97 { "FTL", 200, "--enableConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=true" }, 98 }; 99 92 100 bool failed = false; 93 101 94 JSStringRef currentCPUTimeStr = JSStringCreateWithUTF8CString("currentCPUTime"); 95 JSObjectRef currentCPUTimeFunction = JSObjectMakeFunctionWithCallback(context, currentCPUTimeStr, currentCPUTimeAsJSFunctionCallback); 96 JSObjectSetProperty(context, globalObject, currentCPUTimeStr, currentCPUTimeFunction, kJSPropertyAttributeNone, nullptr); 97 JSStringRelease(currentCPUTimeStr); 98 99 /* Test script timeout: */ 100 JSContextGroupSetExecutionTimeLimit(contextGroup, .10f, shouldTerminateCallback, 0); 101 { 102 const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } "; 103 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript); 104 exception = nullptr; 105 shouldTerminateCallbackWasCalled = false; 106 auto startTime = currentCPUTime(); 107 v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); 108 auto endTime = currentCPUTime(); 109 110 if (((endTime - startTime) < milliseconds(150)) && shouldTerminateCallbackWasCalled) 111 printf("PASS: script timed out as expected.\n"); 112 else { 113 if (!((endTime - startTime) < milliseconds(150))) 114 printf("FAIL: script did not time out as expected.\n"); 115 if (!shouldTerminateCallbackWasCalled) 116 printf("FAIL: script timeout callback was not called.\n"); 117 failed = true; 118 } 119 120 if (!exception) { 121 printf("FAIL: TerminatedExecutionException was not thrown.\n"); 122 failed = true; 123 } 102 JSC::initializeThreading(); 103 Options::initialize(); // Ensure options is initialized first. 104 105 for (auto tierOptions : tierOptionsList) { 106 StringBuilder savedOptionsBuilder; 107 Options::dumpAllOptionsInALine(savedOptionsBuilder); 108 109 Options::setOptions(tierOptions.optionsStr); 110 111 unsigned tierAdjustmentMillis = tierOptions.timeLimitAdjustmentMillis; 112 double timeLimit; 113 114 context = JSGlobalContextCreateInGroup(nullptr, nullptr); 115 116 JSContextGroupRef contextGroup = JSContextGetGroup(context); 117 JSObjectRef globalObject = JSContextGetGlobalObject(context); 118 ASSERT(JSValueIsObject(context, globalObject)); 119 120 JSValueRef scriptResult = nullptr; 121 JSValueRef exception = nullptr; 122 123 JSStringRef currentCPUTimeStr = JSStringCreateWithUTF8CString("currentCPUTime"); 124 JSObjectRef currentCPUTimeFunction = JSObjectMakeFunctionWithCallback(context, currentCPUTimeStr, currentCPUTimeAsJSFunctionCallback); 125 JSObjectSetProperty(context, globalObject, currentCPUTimeStr, currentCPUTimeFunction, kJSPropertyAttributeNone, nullptr); 126 JSStringRelease(currentCPUTimeStr); 127 128 /* Test script timeout: */ 129 timeLimit = (100 + tierAdjustmentMillis) / 1000.0; 130 JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0); 131 { 132 unsigned timeAfterWatchdogShouldHaveFired = 150 + tierAdjustmentMillis; 133 134 StringBuilder scriptBuilder; 135 scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); 136 scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); 137 scriptBuilder.append(") break; } } foo();"); 138 139 JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); 140 exception = nullptr; 141 shouldTerminateCallbackWasCalled = false; 142 auto startTime = currentCPUTime(); 143 scriptResult = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); 144 auto endTime = currentCPUTime(); 145 146 if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) && shouldTerminateCallbackWasCalled) 147 printf("PASS: %s script timed out as expected.\n", tierOptions.tier); 148 else { 149 if ((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) 150 printf("FAIL: %s script did not time out as expected.\n", tierOptions.tier); 151 if (!shouldTerminateCallbackWasCalled) 152 printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier); 153 failed = true; 154 } 155 156 if (!exception) { 157 printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier); 158 failed = true; 159 } 160 } 161 162 /* Test the script timeout's TerminatedExecutionException should NOT be catchable: */ 163 timeLimit = (100 + tierAdjustmentMillis) / 1000.0; 164 JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0); 165 { 166 unsigned timeAfterWatchdogShouldHaveFired = 150 + tierAdjustmentMillis; 167 168 StringBuilder scriptBuilder; 169 scriptBuilder.append("function foo() { var startTime = currentCPUTime(); try { while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); 170 scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); 171 scriptBuilder.append(") break; } } catch(e) { } } foo();"); 172 173 JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); 174 exception = nullptr; 175 shouldTerminateCallbackWasCalled = false; 176 177 auto startTime = currentCPUTime(); 178 scriptResult = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); 179 auto endTime = currentCPUTime(); 180 181 if (((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) || !shouldTerminateCallbackWasCalled) { 182 if (!((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired))) 183 printf("FAIL: %s script did not time out as expected.\n", tierOptions.tier); 184 if (!shouldTerminateCallbackWasCalled) 185 printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier); 186 failed = true; 187 } 188 189 if (exception) 190 printf("PASS: %s TerminatedExecutionException was not catchable as expected.\n", tierOptions.tier); 191 else { 192 printf("FAIL: %s TerminatedExecutionException was caught.\n", tierOptions.tier); 193 failed = true; 194 } 195 } 196 197 /* Test script timeout with no callback: */ 198 timeLimit = (100 + tierAdjustmentMillis) / 1000.0; 199 JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, 0, 0); 200 { 201 unsigned timeAfterWatchdogShouldHaveFired = 150 + tierAdjustmentMillis; 202 203 StringBuilder scriptBuilder; 204 scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); 205 scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); 206 scriptBuilder.append(") break; } } foo();"); 207 208 JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); 209 exception = nullptr; 210 shouldTerminateCallbackWasCalled = false; 211 212 auto startTime = currentCPUTime(); 213 scriptResult = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); 214 auto endTime = currentCPUTime(); 215 216 if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) && !shouldTerminateCallbackWasCalled) 217 printf("PASS: %s script timed out as expected when no callback is specified.\n", tierOptions.tier); 218 else { 219 if ((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) 220 printf("FAIL: %s script did not time out as expected when no callback is specified.\n", tierOptions.tier); 221 else 222 printf("FAIL: %s script called stale callback function.\n", tierOptions.tier); 223 failed = true; 224 } 225 226 if (!exception) { 227 printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier); 228 failed = true; 229 } 230 } 231 232 /* Test script timeout cancellation: */ 233 timeLimit = (100 + tierAdjustmentMillis) / 1000.0; 234 JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, cancelTerminateCallback, 0); 235 { 236 unsigned timeAfterWatchdogShouldHaveFired = 150 + tierAdjustmentMillis; 237 238 StringBuilder scriptBuilder; 239 scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); 240 scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); 241 scriptBuilder.append(") break; } } foo();"); 242 243 JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); 244 exception = nullptr; 245 cancelTerminateCallbackWasCalled = false; 246 247 auto startTime = currentCPUTime(); 248 scriptResult = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); 249 auto endTime = currentCPUTime(); 250 251 if (((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) && cancelTerminateCallbackWasCalled && !exception) 252 printf("PASS: %s script timeout was cancelled as expected.\n", tierOptions.tier); 253 else { 254 if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) || exception) 255 printf("FAIL: %s script timeout was not cancelled.\n", tierOptions.tier); 256 if (!cancelTerminateCallbackWasCalled) 257 printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier); 258 failed = true; 259 } 260 261 if (exception) { 262 printf("FAIL: %s Unexpected TerminatedExecutionException thrown.\n", tierOptions.tier); 263 failed = true; 264 } 265 } 266 267 /* Test script timeout extension: */ 268 timeLimit = (100 + tierAdjustmentMillis) / 1000.0; 269 JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, extendTerminateCallback, 0); 270 { 271 unsigned timeBeforeExtendedDeadline = 200 + tierAdjustmentMillis; 272 unsigned timeAfterExtendedDeadline = 350 + tierAdjustmentMillis; 273 unsigned maxBusyLoopTime = 500 + tierAdjustmentMillis; 274 275 StringBuilder scriptBuilder; 276 scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); 277 scriptBuilder.appendNumber(maxBusyLoopTime / 1000.0); // in seconds. 278 scriptBuilder.append(") break; } } foo();"); 279 280 JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); 281 exception = nullptr; 282 extendTerminateCallbackCalled = 0; 283 284 auto startTime = currentCPUTime(); 285 scriptResult = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); 286 auto endTime = currentCPUTime(); 287 auto deltaTime = endTime - startTime; 288 289 if ((deltaTime >= milliseconds(timeBeforeExtendedDeadline)) && (deltaTime < milliseconds(timeAfterExtendedDeadline)) && (extendTerminateCallbackCalled == 2) && exception) 290 printf("PASS: %s script timeout was extended as expected.\n", tierOptions.tier); 291 else { 292 if (deltaTime < milliseconds(timeBeforeExtendedDeadline)) 293 printf("FAIL: %s script timeout was not extended as expected.\n", tierOptions.tier); 294 else if (deltaTime >= milliseconds(timeAfterExtendedDeadline)) 295 printf("FAIL: %s script did not timeout.\n", tierOptions.tier); 296 297 if (extendTerminateCallbackCalled < 1) 298 printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier); 299 if (extendTerminateCallbackCalled < 2) 300 printf("FAIL: %s script timeout callback was not called after timeout extension.\n", tierOptions.tier); 301 302 if (!exception) 303 printf("FAIL: %s TerminatedExecutionException was not thrown during timeout extension test.\n", tierOptions.tier); 304 305 failed = true; 306 } 307 } 308 309 JSGlobalContextRelease(context); 310 311 Options::setOptions(savedOptionsBuilder.toString().ascii().data()); 124 312 } 125 313 126 /* Test the script timeout's TerminatedExecutionException should NOT be catchable: */127 JSContextGroupSetExecutionTimeLimit(contextGroup, 0.10f, shouldTerminateCallback, 0);128 {129 const char* loopForeverScript = "var startTime = currentCPUTime(); try { while (true) { if (currentCPUTime() - startTime > .150) break; } } catch(e) { }";130 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);131 exception = nullptr;132 shouldTerminateCallbackWasCalled = false;133 auto startTime = currentCPUTime();134 v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);135 auto endTime = currentCPUTime();136 137 if (((endTime - startTime) >= milliseconds(150)) || !shouldTerminateCallbackWasCalled) {138 if (!((endTime - startTime) < milliseconds(150)))139 printf("FAIL: script did not time out as expected.\n");140 if (!shouldTerminateCallbackWasCalled)141 printf("FAIL: script timeout callback was not called.\n");142 failed = true;143 }144 145 if (exception)146 printf("PASS: TerminatedExecutionException was not catchable as expected.\n");147 else {148 printf("FAIL: TerminatedExecutionException was caught.\n");149 failed = true;150 }151 }152 153 /* Test script timeout with no callback: */154 JSContextGroupSetExecutionTimeLimit(contextGroup, .10f, 0, 0);155 {156 const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";157 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);158 exception = nullptr;159 auto startTime = currentCPUTime();160 v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);161 auto endTime = currentCPUTime();162 163 if (((endTime - startTime) < milliseconds(150)) && shouldTerminateCallbackWasCalled)164 printf("PASS: script timed out as expected when no callback is specified.\n");165 else {166 if (!((endTime - startTime) < milliseconds(150)))167 printf("FAIL: script did not time out as expected when no callback is specified.\n");168 failed = true;169 }170 171 if (!exception) {172 printf("FAIL: TerminatedExecutionException was not thrown.\n");173 failed = true;174 }175 }176 177 /* Test script timeout cancellation: */178 JSContextGroupSetExecutionTimeLimit(contextGroup, 0.10f, cancelTerminateCallback, 0);179 {180 const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";181 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);182 exception = nullptr;183 auto startTime = currentCPUTime();184 v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);185 auto endTime = currentCPUTime();186 187 if (((endTime - startTime) >= milliseconds(150)) && cancelTerminateCallbackWasCalled && !exception)188 printf("PASS: script timeout was cancelled as expected.\n");189 else {190 if (((endTime - startTime) < milliseconds(150)) || exception)191 printf("FAIL: script timeout was not cancelled.\n");192 if (!cancelTerminateCallbackWasCalled)193 printf("FAIL: script timeout callback was not called.\n");194 failed = true;195 }196 197 if (exception) {198 printf("FAIL: Unexpected TerminatedExecutionException thrown.\n");199 failed = true;200 }201 }202 203 /* Test script timeout extension: */204 JSContextGroupSetExecutionTimeLimit(contextGroup, 0.100f, extendTerminateCallback, 0);205 {206 const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .500) break; } ";207 JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);208 exception = nullptr;209 auto startTime = currentCPUTime();210 v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);211 auto endTime = currentCPUTime();212 auto deltaTime = endTime - startTime;213 214 if ((deltaTime >= milliseconds(300)) && (deltaTime < milliseconds(500)) && (extendTerminateCallbackCalled == 2) && exception)215 printf("PASS: script timeout was extended as expected.\n");216 else {217 if (deltaTime < milliseconds(200))218 printf("FAIL: script timeout was not extended as expected.\n");219 else if (deltaTime >= milliseconds(500))220 printf("FAIL: script did not timeout.\n");221 222 if (extendTerminateCallbackCalled < 1)223 printf("FAIL: script timeout callback was not called.\n");224 if (extendTerminateCallbackCalled < 2)225 printf("FAIL: script timeout callback was not called after timeout extension.\n");226 227 if (!exception)228 printf("FAIL: TerminatedExecutionException was not thrown during timeout extension test.\n");229 230 failed = true;231 }232 }233 234 JSGlobalContextRelease(context);235 314 return failed; 236 315 } -
trunk/Source/JavaScriptCore/ChangeLog
r188642 r188648 1 2015-08-19 Mark Lam <mark.lam@apple.com> 2 3 Add ability to save and restore JSC options. 4 https://bugs.webkit.org/show_bug.cgi?id=148125 5 6 Reviewed by Saam Barati. 7 8 * API/tests/ExecutionTimeLimitTest.cpp: 9 (testExecutionTimeLimit): 10 - Employ the new options getter/setter to run watchdog tests for each of the 11 execution engine tiers. 12 - Also altered the test scripts to be in a function instead of global code. 13 This is one of 2 changes needed to give them an opportunity to be FTL compiled. 14 The other is to add support for compiling CheckWatchdogTimer in the FTL (which 15 will be addressed in a separate patch). 16 17 * jsc.cpp: 18 (CommandLine::parseArguments): 19 * runtime/Options.cpp: 20 (JSC::parse): 21 - Add the ability to clear a string option with a nullptr value. 22 This is needed to restore a default string option value which may be null. 23 24 (JSC::OptionRange::init): 25 - Add the ability to clear a range option with a null value. 26 This is needed to restore a default range option value which may be null. 27 28 (JSC::Options::initialize): 29 (JSC::Options::dumpOptionsIfNeeded): 30 - Factor code to dump options out to dumpOptionsIfNeeded() since we will need 31 that logic elsewhere. 32 33 (JSC::Options::setOptions): 34 - Parse an options string and set each of the specified options. 35 36 (JSC::Options::dumpAllOptions): 37 (JSC::Options::dumpAllOptionsInALine): 38 (JSC::Options::dumpOption): 39 (JSC::Option::dump): 40 - Refactored so that the underlying dumper dumps to a StringBuilder instead of 41 stderr. This lets us reuse this code to serialize all the options into a 42 single string for dumpAllOptionsInALine(). 43 44 * runtime/Options.h: 45 (JSC::OptionRange::rangeString): 46 1 47 2015-08-18 Filip Pizlo <fpizlo@apple.com> 2 48 -
trunk/Source/JavaScriptCore/jsc.cpp
r188549 r188648 1551 1551 1552 1552 if (needToDumpOptions) 1553 JSC::Options::dumpAllOptions( JSC::Options::DumpLevel::Verbose, "All JSC runtime options:", stderr);1553 JSC::Options::dumpAllOptions(stderr, JSC::Options::DumpLevel::Verbose, "All JSC runtime options:"); 1554 1554 JSC::Options::ensureOptionsAreCoherent(); 1555 1555 if (needToExit) -
trunk/Source/JavaScriptCore/runtime/Options.cpp
r187125 r188648 39 39 #include <wtf/StdLibExtras.h> 40 40 #include <wtf/StringExtras.h> 41 #include <wtf/text/StringBuilder.h> 41 42 42 43 #if OS(DARWIN) && ENABLE(PARALLEL_GC) … … 85 86 static bool parse(const char* string, const char*& value) 86 87 { 88 if (!strlen(string)) 89 string = nullptr; 87 90 value = string; 88 91 return true; … … 150 153 } 151 154 155 const char* const OptionRange::s_nullRangeStr = "<null>"; 156 152 157 bool OptionRange::init(const char* rangeString) 153 158 { … … 156 161 157 162 bool invert = false; 158 159 if (m_state > Uninitialized)160 return true;161 163 162 164 if (!rangeString) { … … 165 167 } 166 168 169 if (!strcmp(rangeString, s_nullRangeStr)) { 170 m_state = Uninitialized; 171 return true; 172 } 173 167 174 m_rangeString = rangeString; 168 175 … … 361 368 ASSERT(Options::thresholdForOptimizeAfterWarmUp() >= 0); 362 369 363 if (Options::showOptions()) { 364 DumpLevel level = static_cast<DumpLevel>(Options::showOptions()); 365 if (level > DumpLevel::Verbose) 366 level = DumpLevel::Verbose; 367 368 const char* title = nullptr; 369 switch (level) { 370 case DumpLevel::None: 371 break; 372 case DumpLevel::Overridden: 373 title = "Overridden JSC options:"; 374 break; 375 case DumpLevel::All: 376 title = "All JSC options:"; 377 break; 378 case DumpLevel::Verbose: 379 title = "All JSC options with descriptions:"; 380 break; 381 } 382 dumpAllOptions(level, title); 383 } 384 370 dumpOptionsIfNeeded(); 385 371 ensureOptionsAreCoherent(); 386 372 }); 373 } 374 375 void Options::dumpOptionsIfNeeded() 376 { 377 if (Options::showOptions()) { 378 DumpLevel level = static_cast<DumpLevel>(Options::showOptions()); 379 if (level > DumpLevel::Verbose) 380 level = DumpLevel::Verbose; 381 382 const char* title = nullptr; 383 switch (level) { 384 case DumpLevel::None: 385 break; 386 case DumpLevel::Overridden: 387 title = "Overridden JSC options:"; 388 break; 389 case DumpLevel::All: 390 title = "All JSC options:"; 391 break; 392 case DumpLevel::Verbose: 393 title = "All JSC options with descriptions:"; 394 break; 395 } 396 397 StringBuilder builder; 398 dumpAllOptions(builder, level, title, nullptr, " ", "\n", ShowDefaults); 399 dataLog(builder.toString()); 400 } 401 } 402 403 bool Options::setOptions(const char* optionsStr) 404 { 405 Vector<char*> options; 406 407 size_t length = strlen(optionsStr); 408 char* optionsStrCopy = WTF::fastStrDup(optionsStr); 409 char* end = optionsStrCopy + length; 410 char* p = optionsStrCopy; 411 412 while (p < end) { 413 char* optionStart = p; 414 p = strstr(p, "="); 415 if (!p) { 416 dataLogF("'=' not found in option string: %p\n", optionStart); 417 return false; 418 } 419 p++; 420 421 char* valueBegin = p; 422 bool hasStringValue = false; 423 const int minStringLength = 2; // The min is an empty string i.e. 2 double quotes. 424 if ((p + minStringLength < end) && (*p == '"')) { 425 p = strstr(p + 1, "\""); 426 if (!p) { 427 dataLogF("Missing trailing '\"' in option string: %p\n", optionStart); 428 return false; // End of string not found. 429 } 430 hasStringValue = true; 431 } 432 433 p = strstr(p, " "); 434 if (!p) 435 p = end; // No more " " separator. Hence, this is the last arg. 436 437 // If we have a well-formed string value, strip the quotes. 438 if (hasStringValue) { 439 char* valueEnd = p; 440 ASSERT((*valueBegin == '"') && ((valueEnd - valueBegin) >= minStringLength) && (valueEnd[-1] == '"')); 441 memmove(valueBegin, valueBegin + 1, valueEnd - valueBegin - minStringLength); 442 valueEnd[-minStringLength] = '\0'; 443 } 444 445 // Strip leading -- if present. 446 if ((p - optionStart > 2) && optionStart[0] == '-' && optionStart[1] == '-') 447 optionStart += 2; 448 449 *p++ = '\0'; 450 options.append(optionStart); 451 } 452 453 bool success = true; 454 for (auto& option : options) { 455 bool optionSuccess = setOption(option); 456 if (!optionSuccess) { 457 dataLogF("Failed to set option : %s\n", option); 458 success = false; 459 } 460 } 461 462 dumpOptionsIfNeeded(); 463 return success; 387 464 } 388 465 … … 421 498 } 422 499 423 void Options::dumpAllOptions(DumpLevel level, const char* title, FILE* stream) 424 { 425 if (title) 426 fprintf(stream, "%s\n", title); 427 for (int id = 0; id < numberOfOptions; id++) 428 dumpOption(level, static_cast<OptionID>(id), stream, " ", "\n"); 429 } 430 431 void Options::dumpOption(DumpLevel level, OptionID id, FILE* stream, const char* header, const char* footer) 500 void Options::dumpAllOptions(StringBuilder& builder, DumpLevel level, const char* title, 501 const char* separator, const char* optionHeader, const char* optionFooter, ShowDefaultsOption showDefaultsOption) 502 { 503 if (title) { 504 builder.append(title); 505 builder.append('\n'); 506 } 507 508 for (int id = 0; id < numberOfOptions; id++) { 509 if (separator && id) 510 builder.append(separator); 511 dumpOption(builder, level, static_cast<OptionID>(id), optionHeader, optionFooter, showDefaultsOption); 512 } 513 } 514 515 void Options::dumpAllOptionsInALine(StringBuilder& builder) 516 { 517 dumpAllOptions(builder, DumpLevel::All, nullptr, " ", nullptr, nullptr, DontShowDefaults); 518 } 519 520 void Options::dumpAllOptions(FILE* stream, DumpLevel level, const char* title) 521 { 522 StringBuilder builder; 523 dumpAllOptions(builder, level, title, nullptr, " ", "\n", ShowDefaults); 524 fprintf(stream, "%s", builder.toString().ascii().data()); 525 } 526 527 void Options::dumpOption(StringBuilder& builder, DumpLevel level, OptionID id, 528 const char* header, const char* footer, ShowDefaultsOption showDefaultsOption) 432 529 { 433 530 if (id >= numberOfOptions) … … 441 538 return; 442 539 443 fprintf(stream, "%s%s: ", header, option.name()); 444 option.dump(stream); 445 446 if (wasOverridden) { 447 fprintf(stream, " (default: "); 448 option.defaultOption().dump(stream); 449 fprintf(stream, ")"); 450 } 451 452 if (needsDescription) 453 fprintf(stream, " ... %s", option.description()); 454 455 fprintf(stream, "%s", footer); 540 if (header) 541 builder.append(header); 542 builder.append(option.name()); 543 builder.append('='); 544 option.dump(builder); 545 546 if (wasOverridden && (showDefaultsOption == ShowDefaults)) { 547 builder.append(" (default: "); 548 option.defaultOption().dump(builder); 549 builder.append(")"); 550 } 551 552 if (needsDescription) { 553 builder.append(" ... "); 554 builder.append(option.description()); 555 } 556 557 builder.append(footer); 456 558 } 457 559 … … 467 569 } 468 570 469 void Option::dump( FILE* stream) const571 void Option::dump(StringBuilder& builder) const 470 572 { 471 573 switch (type()) { 472 574 case Options::Type::boolType: 473 fprintf(stream, "%s",m_entry.boolVal ? "true" : "false");575 builder.append(m_entry.boolVal ? "true" : "false"); 474 576 break; 475 577 case Options::Type::unsignedType: 476 fprintf(stream, "%u",m_entry.unsignedVal);578 builder.appendNumber(m_entry.unsignedVal); 477 579 break; 478 580 case Options::Type::doubleType: 479 fprintf(stream, "%lf",m_entry.doubleVal);581 builder.appendNumber(m_entry.doubleVal); 480 582 break; 481 583 case Options::Type::int32Type: 482 fprintf(stream, "%d",m_entry.int32Val);584 builder.appendNumber(m_entry.int32Val); 483 585 break; 484 586 case Options::Type::optionRangeType: 485 fprintf(stream, "%s",m_entry.optionRangeVal.rangeString());587 builder.append(m_entry.optionRangeVal.rangeString()); 486 588 break; 487 589 case Options::Type::optionStringType: { … … 489 591 if (!option) 490 592 option = ""; 491 fprintf(stream, "%s", option); 593 builder.append('"'); 594 builder.append(option); 595 builder.append('"'); 492 596 break; 493 597 } 494 598 case Options::Type::gcLogLevelType: { 495 fprintf(stream, "%s",GCLogging::levelAsString(m_entry.gcLogLevelVal));599 builder.append(GCLogging::levelAsString(m_entry.gcLogLevelVal)); 496 600 break; 497 601 } -
trunk/Source/JavaScriptCore/runtime/Options.h
r188355 r188648 33 33 #include <wtf/PrintStream.h> 34 34 #include <wtf/StdLibExtras.h> 35 36 namespace WTF { 37 class StringBuilder; 38 } 39 using WTF::StringBuilder; 35 40 36 41 namespace JSC { … … 81 86 bool init(const char*); 82 87 bool isInRange(unsigned); 83 const char* rangeString() const { return (m_state > InitError) ? m_rangeString : "<null>"; }88 const char* rangeString() const { return (m_state > InitError) ? m_rangeString : s_nullRangeStr; } 84 89 85 90 void dump(PrintStream& out) const; 86 91 87 92 private: 93 static const char* const s_nullRangeStr; 94 88 95 RangeState m_state; 89 96 const char* m_rangeString; … … 360 367 JS_EXPORT_PRIVATE static void initialize(); 361 368 369 // Parses a string of options where each option is of the format "--<optionName>=<value>" 370 // and are separated by a space. The leading "--" is optional and will be ignored. 371 JS_EXPORT_PRIVATE static bool setOptions(const char* optionsList); 372 362 373 // Parses a single command line option in the format "<optionName>=<value>" 363 374 // (no spaces allowed) and set the specified option if appropriate. 364 375 JS_EXPORT_PRIVATE static bool setOption(const char* arg); 365 JS_EXPORT_PRIVATE static void dumpAllOptions(DumpLevel, const char* title = nullptr, FILE* stream = stdout); 366 static void dumpOption(DumpLevel, OptionID, FILE* stream = stdout, const char* header = "", const char* footer = ""); 376 377 JS_EXPORT_PRIVATE static void dumpAllOptions(FILE*, DumpLevel, const char* title = nullptr); 378 JS_EXPORT_PRIVATE static void dumpAllOptionsInALine(StringBuilder&); 379 367 380 JS_EXPORT_PRIVATE static void ensureOptionsAreCoherent(); 368 381 … … 396 409 Options(); 397 410 411 enum ShowDefaultsOption { 412 DontShowDefaults, 413 ShowDefaults 414 }; 415 static void dumpOptionsIfNeeded(); 416 static void dumpAllOptions(StringBuilder&, DumpLevel, const char* title, 417 const char* separator, const char* optionHeader, const char* optionFooter, ShowDefaultsOption); 418 static void dumpOption(StringBuilder&, DumpLevel, OptionID, 419 const char* optionHeader, const char* optionFooter, ShowDefaultsOption); 420 398 421 // Declare the singleton instance of the options store: 399 422 JS_EXPORTDATA static Entry s_options[numberOfOptions]; … … 412 435 } 413 436 414 void dump(FILE*) const; 437 void dump(StringBuilder&) const; 438 415 439 bool operator==(const Option& other) const; 416 440 bool operator!=(const Option& other) const { return !(*this == other); }
Note: See TracChangeset
for help on using the changeset viewer.