Diff
Modified: trunk/JSTests/ChangeLog (214288 => 214289)
--- trunk/JSTests/ChangeLog 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/JSTests/ChangeLog 2017-03-23 01:14:06 UTC (rev 214289)
@@ -1,3 +1,12 @@
+2017-03-22 Mark Lam <[email protected]>
+
+ Add support for Error.stackTraceLimit.
+ https://bugs.webkit.org/show_bug.cgi?id=169904
+
+ Reviewed by Saam Barati.
+
+ * stress/error-stack-trace-limit.js: Added.
+
2017-03-22 Yusuke Suzuki <[email protected]>
[JSC] Use jsNontrivialString for Number toString operations
Added: trunk/JSTests/stress/error-stack-trace-limit.js (0 => 214289)
--- trunk/JSTests/stress/error-stack-trace-limit.js (rev 0)
+++ trunk/JSTests/stress/error-stack-trace-limit.js 2017-03-23 01:14:06 UTC (rev 214289)
@@ -0,0 +1,94 @@
+function assert(testID, b) {
+ if (!b)
+ throw new Error("FAILED test " + testID);
+}
+
+function assertEquals(testID, a, b) {
+ assert(testID, a == b);
+}
+
+var desc = Object.getOwnPropertyDescriptor(Error, "stackTraceLimit");
+
+assertEquals(100, typeof desc.value, "number");
+assertEquals(200, desc.writable, true);
+assertEquals(300, desc.enumerable, true);
+assertEquals(400, desc.configurable, true);
+assertEquals(500, desc.get, undefined);
+assertEquals(600, desc.set, undefined);
+
+function recurse(x) {
+ if (x)
+ recurse(x - 1);
+ else
+ throw Error();
+}
+
+function numberOfFrames(str) {
+ if (str == "")
+ return 0;
+ var lines = str.split(/\r\n|\r|\n/);
+ // note: Chrome always prints a header line. So, for Chrome, use lines.length - 1.
+ return lines.length;
+}
+
+var exception = undefined;
+
+function testLimit(testID, updateLimit, reentryCount, expectedLimit, expectedNumberOfFrames) {
+ exception = undefined;
+ updateLimit();
+ assertEquals(testID, Error.stackTraceLimit, expectedLimit);
+
+ try {
+ recurse(reentryCount);
+ } catch (e) {
+ exception = e;
+ }
+
+ assertEquals(testID + 1, exception, "Error");
+ if (typeof expectedNumberOfFrames == "undefined")
+ assertEquals(testID + 2, exception.stack, undefined);
+ else
+ assertEquals(testID + 3, numberOfFrames(exception.stack), expectedNumberOfFrames);
+}
+
+testLimit(1000, () => { Error.stackTraceLimit = 0 }, 1000, 0, 0);
+// note: Chrome always prints a header line. So, Chrome expects "Error" here.
+assertEquals(1100, exception.stack, "");
+
+testLimit(2000, () => { Error.stackTraceLimit = 10 }, 1000, 10, 10);
+testLimit(3000, () => { Error.stackTraceLimit = 100 }, 1000, 100, 100);
+testLimit(4000, () => { Error.stackTraceLimit = 1000 }, 1000, 1000, 1000);
+
+// expectedNumberOfFrames includes (1) global + (2) testLimit + (3) 1000 recursion of
+// recurse() + (4) recurse() which discovered x == 0 i.e. expectedNumberOfFrames == 1003.
+testLimit(5000, () => { Error.stackTraceLimit = 2000 }, 1000, 2000, 1003);
+
+var value = { };
+testLimit(6000, () => { Error.stackTraceLimit = value }, 1000, value, undefined);
+
+var value = { valueOf() { return 5 } };
+testLimit(7000, () => { Error.stackTraceLimit = value }, 1000, value, undefined);
+
+var value = [ 1, 2, 3 ];
+testLimit(8000, () => { Error.stackTraceLimit = value }, 1000, value, undefined);
+
+var value = "hello";
+testLimit(9000, () => { Error.stackTraceLimit = value }, 1000, value, undefined);
+
+var value = Symbol("hello");
+testLimit(10000, () => { Error.stackTraceLimit = value }, 1000, value, undefined);
+
+var value = true;
+testLimit(11000, () => { Error.stackTraceLimit = value }, 1000, value, undefined);
+
+var value = false;
+testLimit(12000, () => { Error.stackTraceLimit = value }, 1000, value, undefined);
+
+var value = undefined;
+testLimit(13000, () => { Error.stackTraceLimit = value }, 1000, value, undefined);
+
+testLimit(14000, () => { Error.stackTraceLimit = 10 }, 1000, 10, 10);
+
+testLimit(15000, () => { delete Error.stackTraceLimit; }, 1000, undefined, undefined);
+
+testLimit(16000, () => { Error.stackTraceLimit = 10 }, 1000, 10, 10);
Modified: trunk/LayoutTests/ChangeLog (214288 => 214289)
--- trunk/LayoutTests/ChangeLog 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/LayoutTests/ChangeLog 2017-03-23 01:14:06 UTC (rev 214289)
@@ -1,3 +1,15 @@
+2017-03-22 Mark Lam <[email protected]>
+
+ Add support for Error.stackTraceLimit.
+ https://bugs.webkit.org/show_bug.cgi?id=169904
+
+ Reviewed by Saam Barati.
+
+ Rebased test.
+
+ * js/Object-getOwnPropertyNames-expected.txt:
+ * js/script-tests/Object-getOwnPropertyNames.js:
+
2017-03-22 Carlos Alberto Lopez Perez <[email protected]>
[GTK] Update layout test expectations file.
Modified: trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt (214288 => 214289)
--- trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt 2017-03-23 01:14:06 UTC (rev 214289)
@@ -57,7 +57,7 @@
PASS getSortedOwnPropertyNames(Date.prototype) is ['constructor', 'getDate', 'getDay', 'getFullYear', 'getHours', 'getMilliseconds', 'getMinutes', 'getMonth', 'getSeconds', 'getTime', 'getTimezoneOffset', 'getUTCDate', 'getUTCDay', 'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds', 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', 'setYear', 'toDateString', 'toGMTString', 'toISOString', 'toJSON', 'toLocaleDateString', 'toLocaleString', 'toLocaleTimeString', 'toString', 'toTimeString', 'toUTCString', 'valueOf']
PASS getSortedOwnPropertyNames(RegExp) is ['$&', "$'", '$*', '$+', '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9', '$_', '$`', 'input', 'lastMatch', 'lastParen', 'leftContext', 'length', 'multiline', 'name', 'prototype', 'rightContext']
PASS getSortedOwnPropertyNames(RegExp.prototype) is ['compile', 'constructor', 'exec', 'flags', 'global', 'ignoreCase', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode']
-PASS getSortedOwnPropertyNames(Error) is ['length', 'name', 'prototype']
+PASS getSortedOwnPropertyNames(Error) is ['length', 'name', 'prototype', 'stackTraceLimit']
PASS getSortedOwnPropertyNames(Error.prototype) is ['constructor', 'message', 'name', 'toString']
PASS getSortedOwnPropertyNames(Math) is ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']
PASS getSortedOwnPropertyNames(JSON) is ['parse', 'stringify']
Modified: trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js (214288 => 214289)
--- trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js 2017-03-23 01:14:06 UTC (rev 214289)
@@ -66,7 +66,7 @@
"Date.prototype": "['constructor', 'getDate', 'getDay', 'getFullYear', 'getHours', 'getMilliseconds', 'getMinutes', 'getMonth', 'getSeconds', 'getTime', 'getTimezoneOffset', 'getUTCDate', 'getUTCDay', 'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds', 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', 'setYear', 'toDateString', 'toGMTString', 'toISOString', 'toJSON', 'toLocaleDateString', 'toLocaleString', 'toLocaleTimeString', 'toString', 'toTimeString', 'toUTCString', 'valueOf']",
"RegExp": "['$&', \"$'\", '$*', '$+', '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9', '$_', '$`', 'input', 'lastMatch', 'lastParen', 'leftContext', 'length', 'multiline', 'name', 'prototype', 'rightContext']",
"RegExp.prototype": "['compile', 'constructor', 'exec', 'flags', 'global', 'ignoreCase', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode']",
- "Error": "['length', 'name', 'prototype']",
+ "Error": "['length', 'name', 'prototype', 'stackTraceLimit']",
"Error.prototype": "['constructor', 'message', 'name', 'toString']",
"Math": "['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']",
"JSON": "['parse', 'stringify']",
Modified: trunk/Source/_javascript_Core/ChangeLog (214288 => 214289)
--- trunk/Source/_javascript_Core/ChangeLog 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-03-23 01:14:06 UTC (rev 214289)
@@ -1,3 +1,56 @@
+2017-03-22 Mark Lam <[email protected]>
+
+ Add support for Error.stackTraceLimit.
+ https://bugs.webkit.org/show_bug.cgi?id=169904
+
+ Reviewed by Saam Barati.
+
+ Since there's no standard for this yet, we'll implement Error.stackTraceLimit
+ based on how Chrome does it. This includes some idiosyncrasies like:
+ 1. If we set Error.stackTraceLimit = 0, then new Error().stack yields an empty
+ stack trace (Chrome has a title with no stack frame entries).
+ 2. If we set Error.stackTraceLimit = {] (i.e. to a non-number value), then
+ new Error().stack is undefined.
+
+ Chrome and IE defaults their Error.stackTraceLimit to 10. We'll default ours to
+ 100 because 10 may be a bit too skimpy and it is not that costly to allow up to
+ 100 frames instead of 10.
+
+ The default value for Error.stackTraceLimit is specified by
+ Options::defaultErrorStackTraceLimit().
+
+ Also, the Exception object now limits the number of stack trace frames it captures
+ to the limit specified by Options::exceptionStackTraceLimit().
+
+ Note: the Exception object captures a stack trace that is not necessarily the
+ same as the one in an Error object being thrown:
+
+ - The Error object captures the stack trace at the point of object creation.
+
+ - The Exception object captures the stack trace at the point that the exception
+ is thrown. This stack trace is captured even when throwing a value that is not
+ an Error object e.g. a primitive value. The Exception object stack trace is
+ only used by WebInspector to identify where a value is thrown from. Hence,
+ it does not necessary make sense the Exception object stack trace limited by
+ Error.stackTraceLimit. Instead, we have it use own Options::exceptionStackTraceLimit().
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::unwind):
+ * jsc.cpp:
+ (dumpException):
+ * runtime/CommonIdentifiers.h:
+ * runtime/Error.cpp:
+ (JSC::addErrorInfoAndGetBytecodeOffset):
+ * runtime/ErrorConstructor.cpp:
+ (JSC::ErrorConstructor::finishCreation):
+ (JSC::ErrorConstructor::put):
+ (JSC::ErrorConstructor::deleteProperty):
+ * runtime/ErrorConstructor.h:
+ (JSC::ErrorConstructor::stackTraceLimit):
+ * runtime/Exception.cpp:
+ (JSC::Exception::finishCreation):
+ * runtime/Options.h:
+
2017-03-22 Yusuke Suzuki <[email protected]>
[JSC] Use jsNontrivialString for Number toString operations
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (214288 => 214289)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2017-03-23 01:14:06 UTC (rev 214289)
@@ -682,7 +682,7 @@
if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
exceptionValue = jsNull();
- ASSERT_UNUSED(scope, scope.exception() && scope.exception()->stack().size());
+ ASSERT_UNUSED(scope, scope.exception() && (!Options::exceptionStackTraceLimit() || scope.exception()->stack().size()));
// Calculate an exception handler vPC, unwinding call frames as necessary.
HandlerInfo* handler = nullptr;
Modified: trunk/Source/_javascript_Core/jsc.cpp (214288 => 214289)
--- trunk/Source/_javascript_Core/jsc.cpp 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/Source/_javascript_Core/jsc.cpp 2017-03-23 01:14:06 UTC (rev 214289)
@@ -3350,8 +3350,11 @@
lineNumberValue.toWTFString(globalObject->globalExec()).utf8().data());
}
- if (!stackValue.isUndefinedOrNull())
- printf("%s\n", stackValue.toWTFString(globalObject->globalExec()).utf8().data());
+ if (!stackValue.isUndefinedOrNull()) {
+ auto stackString = stackValue.toWTFString(globalObject->globalExec());
+ if (stackString.length())
+ printf("%s\n", stackString.utf8().data());
+ }
#undef CHECK_EXCEPTION
}
Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (214288 => 214289)
--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2017-03-23 01:14:06 UTC (rev 214289)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2007, 2009, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -281,6 +281,7 @@
macro(sourceCode) \
macro(sourceURL) \
macro(stack) \
+ macro(stackTraceLimit) \
macro(sticky) \
macro(subarray) \
macro(summary) \
Modified: trunk/Source/_javascript_Core/runtime/Error.cpp (214288 => 214289)
--- trunk/Source/_javascript_Core/runtime/Error.cpp 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/Source/_javascript_Core/runtime/Error.cpp 2017-03-23 01:14:06 UTC (rev 214289)
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999-2001 Harri Porten ([email protected])
* Copyright (C) 2001 Peter Kelly ([email protected])
- * Copyright (C) 2003-2006, 2008, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
* Copyright (C) 2007 Eric Seidel ([email protected])
*
* This library is free software; you can redistribute it and/or
@@ -157,10 +157,14 @@
bool addErrorInfoAndGetBytecodeOffset(ExecState* exec, VM& vm, JSObject* obj, bool useCurrentFrame, CallFrame*& callFrame, unsigned* bytecodeOffset)
{
+ JSGlobalObject* globalObject = obj->globalObject();
+ ErrorConstructor* errorConstructor = globalObject->errorConstructor();
+ if (!errorConstructor->stackTraceLimit())
+ return false;
+
Vector<StackFrame> stackTrace = Vector<StackFrame>();
-
size_t framesToSkip = useCurrentFrame ? 0 : 1;
- vm.interpreter->getStackTrace(stackTrace, framesToSkip);
+ vm.interpreter->getStackTrace(stackTrace, framesToSkip, errorConstructor->stackTraceLimit().value());
if (!stackTrace.isEmpty()) {
ASSERT(exec == vm.topCallFrame || exec == exec->lexicalGlobalObject()->globalExec() || exec == exec->vmEntryGlobalObject()->globalExec());
@@ -196,6 +200,8 @@
return true;
}
+
+ obj->putDirect(vm, vm.propertyNames->stack, vm.smallStrings.emptyString(), DontEnum);
return false;
}
Modified: trunk/Source/_javascript_Core/runtime/ErrorConstructor.cpp (214288 => 214289)
--- trunk/Source/_javascript_Core/runtime/ErrorConstructor.cpp 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/Source/_javascript_Core/runtime/ErrorConstructor.cpp 2017-03-23 01:14:06 UTC (rev 214289)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten ([email protected])
- * Copyright (C) 2003, 2008, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -44,6 +44,10 @@
// ECMA 15.11.3.1 Error.prototype
putDirectWithoutTransition(vm, vm.propertyNames->prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontEnum | ReadOnly);
+
+ unsigned defaultStackTraceLimit = Options::defaultErrorStackTraceLimit();
+ m_stackTraceLimit = defaultStackTraceLimit;
+ putDirectWithoutTransition(vm, vm.propertyNames->stackTraceLimit, jsNumber(defaultStackTraceLimit), None);
}
// ECMA 15.9.3
@@ -78,4 +82,33 @@
return CallType::Host;
}
+bool ErrorConstructor::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+{
+ VM& vm = exec->vm();
+ ErrorConstructor* thisObject = jsCast<ErrorConstructor*>(cell);
+
+ if (propertyName == vm.propertyNames->stackTraceLimit) {
+ if (value.isNumber()) {
+ double effectiveLimit = value.asNumber();
+ effectiveLimit = std::max(0., effectiveLimit);
+ effectiveLimit = std::min(effectiveLimit, static_cast<double>(std::numeric_limits<unsigned>::max()));
+ thisObject->m_stackTraceLimit = static_cast<unsigned>(effectiveLimit);
+ } else
+ thisObject->m_stackTraceLimit = { };
+ }
+
+ return Base::put(thisObject, exec, propertyName, value, slot);
+}
+
+bool ErrorConstructor::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
+{
+ VM& vm = exec->vm();
+ ErrorConstructor* thisObject = jsCast<ErrorConstructor*>(cell);
+
+ if (propertyName == vm.propertyNames->stackTraceLimit)
+ thisObject->m_stackTraceLimit = { };
+
+ return Base::deleteProperty(thisObject, exec, propertyName);
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/ErrorConstructor.h (214288 => 214289)
--- trunk/Source/_javascript_Core/runtime/ErrorConstructor.h 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/Source/_javascript_Core/runtime/ErrorConstructor.h 2017-03-23 01:14:06 UTC (rev 214289)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten ([email protected])
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -46,13 +46,20 @@
return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}
+ std::optional<unsigned> stackTraceLimit() const { return m_stackTraceLimit; }
+
protected:
void finishCreation(VM&, ErrorPrototype*);
-
+
+ static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
+ static bool deleteProperty(JSCell*, ExecState*, PropertyName);
+
private:
ErrorConstructor(VM&, Structure*);
static ConstructType getConstructData(JSCell*, ConstructData&);
static CallType getCallData(JSCell*, CallData&);
+
+ std::optional<unsigned> m_stackTraceLimit;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/Exception.cpp (214288 => 214289)
--- trunk/Source/_javascript_Core/runtime/Exception.cpp 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/Source/_javascript_Core/runtime/Exception.cpp 2017-03-23 01:14:06 UTC (rev 214289)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -77,7 +77,7 @@
Vector<StackFrame> stackTrace;
if (action == StackCaptureAction::CaptureStack)
- vm.interpreter->getStackTrace(stackTrace);
+ vm.interpreter->getStackTrace(stackTrace, 0, Options::exceptionStackTraceLimit());
m_stack = WTFMove(stackTrace);
}
Modified: trunk/Source/_javascript_Core/runtime/Options.h (214288 => 214289)
--- trunk/Source/_javascript_Core/runtime/Options.h 2017-03-23 00:57:27 UTC (rev 214288)
+++ trunk/Source/_javascript_Core/runtime/Options.h 2017-03-23 01:14:06 UTC (rev 214289)
@@ -376,6 +376,8 @@
v(bool, verifyHeap, false, Normal, nullptr) \
v(unsigned, numberOfGCCyclesToRecordForVerification, 3, Normal, nullptr) \
\
+ v(unsigned, exceptionStackTraceLimit, 100, Normal, "Stack trace limit for internal Exception object") \
+ v(unsigned, defaultErrorStackTraceLimit, 100, Normal, "The default value for Error.stackTraceLimit") \
v(bool, useExceptionFuzz, false, Normal, nullptr) \
v(unsigned, fireExceptionFuzzAt, 0, Normal, nullptr) \
v(bool, validateDFGExceptionHandling, false, Normal, "Causes the DFG to emit code validating exception handling for each node that can exit") /* This is true by default on Debug builds */\