Skip to content

Commit ae0e6f0

Browse files
LLIntSlowPath's llint_loop_osr and llint_replace should set the topCallFrame.
https://bugs.webkit.org/show_bug.cgi?id=191579 <rdar://problem/45942472> Reviewed by Saam Barati. JSTests: * stress/regress-191579.js: Added. Source/JavaScriptCore: Both of these functions do a lot of work. It would be good for the topCallFrame to be correct should we need to throw an exception. For example, we've observed the following crash trace: * frame #0: WTFCrash() at Assertions.cpp:253 frame #1: ... frame #2: JSC::StructureIDTable::get(this=0x00006040000162f0, structureID=1874583248) at StructureIDTable.h:129 frame #3: JSC::VM::getStructure(this=0x0000604000016210, id=4022066896) at VM.h:705 frame #4: JSC::JSCell::structure(this=0x00007ffeefbbde30, vm=0x0000604000016210) const at JSCellInlines.h:125 frame #5: JSC::JSCell::classInfo(this=0x00007ffeefbbde30, vm=0x0000604000016210) const at JSCellInlines.h:335 frame #6: JSC::JSCell::inherits(this=0x00007ffeefbbde30, vm=0x0000604000016210, info=0x0000000105eaf020) const at JSCellInlines.h:302 frame #7: JSC::JSObject* JSC::jsCast<JSC::JSObject*, JSC::JSCell>(from=0x00007ffeefbbde30) at JSCast.h:36 frame #8: JSC::asObject(cell=0x00007ffeefbbde30) at JSObject.h:1299 frame #9: JSC::asObject(value=JSValue @ 0x00007ffeefbba380) at JSObject.h:1304 frame #10: JSC::Register::object(this=0x00007ffeefbbdd58) const at JSObject.h:1514 frame #11: JSC::ExecState::jsCallee(this=0x00007ffeefbbdd40) const at CallFrame.h:107 frame #12: JSC::ExecState::isStackOverflowFrame(this=0x00007ffeefbbdd40) const at CallFrameInlines.h:36 frame #13: JSC::StackVisitor::StackVisitor(this=0x00007ffeefbba860, startFrame=0x00007ffeefbbdd40, vm=0x0000631000000800) at StackVisitor.cpp:52 frame #14: JSC::StackVisitor::StackVisitor(this=0x00007ffeefbba860, startFrame=0x00007ffeefbbdd40, vm=0x0000631000000800) at StackVisitor.cpp:41 frame #15: void JSC::StackVisitor::visit<(JSC::StackVisitor::EmptyEntryFrameAction)0, JSC::Interpreter::getStackTrace(JSC::JSCell*, WTF::Vector<JSC::StackFrame, 0ul, WTF::CrashOnOverflow, 16ul>&, unsigned long, unsigned long)::$_3>(startFrame=0x00007ffeefbbdd40, vm=0x0000631000000800, functor=0x00007ffeefbbaa60)::$_3 const&) at StackVisitor.h:147 frame #16: JSC::Interpreter::getStackTrace(this=0x0000602000005db0, owner=0x000062d00020cbe0, results=0x00006020000249d0, framesToSkip=0, maxStackSize=1) at Interpreter.cpp:437 frame #17: JSC::getStackTrace(exec=0x000062d00002c048, vm=0x0000631000000800, obj=0x000062d00020cbe0, useCurrentFrame=true) at Error.cpp:170 frame #18: JSC::ErrorInstance::finishCreation(this=0x000062d00020cbe0, exec=0x000062d00002c048, vm=0x0000631000000800, message=0x00007ffeefbbb800, useCurrentFrame=true) at ErrorInstance.cpp:119 frame #19: JSC::ErrorInstance::create(exec=0x000062d00002c048, vm=0x0000631000000800, structure=0x000062d0000f5730, message=0x00007ffeefbbb800, appender=0x0000000000000000, type=TypeNothing, useCurrentFrame=true)(WTF::String const&, WTF::String const&, JSC::RuntimeType, JSC::ErrorInstance::SourceTextWhereErrorOccurred), JSC::RuntimeType, bool) at ErrorInstance.h:49 frame #20: JSC::createRangeError(exec=0x000062d00002c048, globalObject=0x000062d00002c000, message=0x00007ffeefbbb800, appender=0x0000000000000000)(WTF::String const&, WTF::String const&, JSC::RuntimeType, JSC::ErrorInstance::SourceTextWhereErrorOccurred)) at Error.cpp:68 frame #21: JSC::createRangeError(exec=0x000062d00002c048, globalObject=0x000062d00002c000, message=0x00007ffeefbbb800) at Error.cpp:316 frame #22: JSC::createStackOverflowError(exec=0x000062d00002c048, globalObject=0x000062d00002c000) at ExceptionHelpers.cpp:77 frame #23: JSC::createStackOverflowError(exec=0x000062d00002c048) at ExceptionHelpers.cpp:72 frame #24: JSC::throwStackOverflowError(exec=0x000062d00002c048, scope=0x00007ffeefbbbaa0) at ExceptionHelpers.cpp:335 frame #25: JSC::ProxyObject::getOwnPropertySlotCommon(this=0x000062d000200e40, exec=0x000062d00002c048, propertyName=PropertyName @ 0x00007ffeefbbba80, slot=0x00007ffeefbbc720) at ProxyObject.cpp:372 frame #26: JSC::ProxyObject::getOwnPropertySlot(object=0x000062d000200e40, exec=0x000062d00002c048, propertyName=PropertyName @ 0x00007ffeefbbbd40, slot=0x00007ffeefbbc720) at ProxyObject.cpp:395 frame #27: JSC::JSObject::getNonIndexPropertySlot(this=0x000062d000200e40, exec=0x000062d00002c048, propertyName=PropertyName @ 0x00007ffeefbbbea0, slot=0x00007ffeefbbc720) at JSObjectInlines.h:150 frame #28: bool JSC::JSObject::getPropertySlot<false>(this=0x000062d000200e40, exec=0x000062d00002c048, propertyName=PropertyName @ 0x00007ffeefbbc320, slot=0x00007ffeefbbc720) at JSObject.h:1424 frame #29: JSC::JSObject::calculatedClassName(object=0x000062d000200e40) at JSObject.cpp:535 frame #30: JSC::Structure::toStructureShape(this=0x000062d000007410, value=JSValue @ 0x00007ffeefbbcae0, sawPolyProtoStructure=0x00007ffeefbbcf60) at Structure.cpp:1142 frame #31: JSC::TypeProfilerLog::processLogEntries(this=0x000060400000a950, reason=0x00007ffeefbbd5c0) at TypeProfilerLog.cpp:89 frame #32: JSC::JIT::doMainThreadPreparationBeforeCompile(this=0x0000619000034da0) at JIT.cpp:951 frame #33: JSC::JITWorklist::Plan::Plan(this=0x0000619000034d80, codeBlock=0x000062d0001d88c0, loopOSREntryBytecodeOffset=0) at JITWorklist.cpp:43 frame #34: JSC::JITWorklist::Plan::Plan(this=0x0000619000034d80, codeBlock=0x000062d0001d88c0, loopOSREntryBytecodeOffset=0) at JITWorklist.cpp:42 frame #35: JSC::JITWorklist::compileLater(this=0x0000616000001b80, codeBlock=0x000062d0001d88c0, loopOSREntryBytecodeOffset=0) at JITWorklist.cpp:256 frame #36: JSC::LLInt::jitCompileAndSetHeuristics(codeBlock=0x000062d0001d88c0, exec=0x00007ffeefbbde30, loopOSREntryBytecodeOffset=0) at LLIntSlowPaths.cpp:391 frame #37: llint_replace(exec=0x00007ffeefbbde30, pc=0x00006040000161ba) at LLIntSlowPaths.cpp:516 frame #38: llint_entry at LowLevelInterpreter64.asm:98 frame #39: vmEntryToJavaScript at LowLevelInterpreter64.asm:296 ... This crash occurred because StackVisitor was seeing an invalid topCallFrame while trying to capture the Error stack while throwing a StackOverflowError below llint_replace. While in this specific example, it is questionable whether we should be executing JS code below TypeProfilerLog::processLogEntries(), it is correct to have set the topCallFrame in llint_replace. We do this by calling LLINT_BEGIN_NO_SET_PC() at the top of llint_replace. We also do the same for llint_osr. Note: both of these LLInt slow path functions are called with a fully initialized CallFrame. Hence, there's no issue with setting topCallFrame to their CallFrames for these functions. * llint/LLIntSlowPaths.cpp: (JSC::LLInt::LLINT_SLOW_PATH_DECL): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@238141 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 41508a5 commit ae0e6f0

File tree

4 files changed

+111
-0
lines changed

4 files changed

+111
-0
lines changed

JSTests/ChangeLog

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
2018-11-13 Mark Lam <[email protected]>
2+
3+
LLIntSlowPath's llint_loop_osr and llint_replace should set the topCallFrame.
4+
https://bugs.webkit.org/show_bug.cgi?id=191579
5+
<rdar://problem/45942472>
6+
7+
Reviewed by Saam Barati.
8+
9+
* stress/regress-191579.js: Added.
10+
111
2018-11-13 Caio Lima <[email protected]>
212

313
[BigInt] JSBigInt::createWithLength should throw when length is greater than JSBigInt::maxLength

JSTests/stress/regress-191579.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//@ requireOptions("--maxPerThreadStackUsage=400000", "--useTypeProfiler=true", "--exceptionStackTraceLimit=1", "--defaultErrorStackTraceLimit=1")
2+
3+
// This test passes if it does not crash.
4+
5+
var count = 0;
6+
7+
function bar() {
8+
new foo();
9+
};
10+
11+
function foo() {
12+
if (count++ > 2000)
13+
return;
14+
let proxy = new Proxy({}, {
15+
set: function() {
16+
bar();
17+
}
18+
});
19+
try {
20+
Reflect.set(proxy);
21+
foo();
22+
} catch (e) {
23+
}
24+
}
25+
26+
bar();

Source/JavaScriptCore/ChangeLog

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,74 @@
1+
2018-11-13 Mark Lam <[email protected]>
2+
3+
LLIntSlowPath's llint_loop_osr and llint_replace should set the topCallFrame.
4+
https://bugs.webkit.org/show_bug.cgi?id=191579
5+
<rdar://problem/45942472>
6+
7+
Reviewed by Saam Barati.
8+
9+
Both of these functions do a lot of work. It would be good for the topCallFrame
10+
to be correct should we need to throw an exception.
11+
12+
For example, we've observed the following crash trace:
13+
14+
* frame #0: WTFCrash() at Assertions.cpp:253
15+
frame #1: ...
16+
frame #2: JSC::StructureIDTable::get(this=0x00006040000162f0, structureID=1874583248) at StructureIDTable.h:129
17+
frame #3: JSC::VM::getStructure(this=0x0000604000016210, id=4022066896) at VM.h:705
18+
frame #4: JSC::JSCell::structure(this=0x00007ffeefbbde30, vm=0x0000604000016210) const at JSCellInlines.h:125
19+
frame #5: JSC::JSCell::classInfo(this=0x00007ffeefbbde30, vm=0x0000604000016210) const at JSCellInlines.h:335
20+
frame #6: JSC::JSCell::inherits(this=0x00007ffeefbbde30, vm=0x0000604000016210, info=0x0000000105eaf020) const at JSCellInlines.h:302
21+
frame #7: JSC::JSObject* JSC::jsCast<JSC::JSObject*, JSC::JSCell>(from=0x00007ffeefbbde30) at JSCast.h:36
22+
frame #8: JSC::asObject(cell=0x00007ffeefbbde30) at JSObject.h:1299
23+
frame #9: JSC::asObject(value=JSValue @ 0x00007ffeefbba380) at JSObject.h:1304
24+
frame #10: JSC::Register::object(this=0x00007ffeefbbdd58) const at JSObject.h:1514
25+
frame #11: JSC::ExecState::jsCallee(this=0x00007ffeefbbdd40) const at CallFrame.h:107
26+
frame #12: JSC::ExecState::isStackOverflowFrame(this=0x00007ffeefbbdd40) const at CallFrameInlines.h:36
27+
frame #13: JSC::StackVisitor::StackVisitor(this=0x00007ffeefbba860, startFrame=0x00007ffeefbbdd40, vm=0x0000631000000800) at StackVisitor.cpp:52
28+
frame #14: JSC::StackVisitor::StackVisitor(this=0x00007ffeefbba860, startFrame=0x00007ffeefbbdd40, vm=0x0000631000000800) at StackVisitor.cpp:41
29+
frame #15: void JSC::StackVisitor::visit<(JSC::StackVisitor::EmptyEntryFrameAction)0, JSC::Interpreter::getStackTrace(JSC::JSCell*, WTF::Vector<JSC::StackFrame, 0ul, WTF::CrashOnOverflow, 16ul>&, unsigned long, unsigned long)::$_3>(startFrame=0x00007ffeefbbdd40, vm=0x0000631000000800, functor=0x00007ffeefbbaa60)::$_3 const&) at StackVisitor.h:147
30+
frame #16: JSC::Interpreter::getStackTrace(this=0x0000602000005db0, owner=0x000062d00020cbe0, results=0x00006020000249d0, framesToSkip=0, maxStackSize=1) at Interpreter.cpp:437
31+
frame #17: JSC::getStackTrace(exec=0x000062d00002c048, vm=0x0000631000000800, obj=0x000062d00020cbe0, useCurrentFrame=true) at Error.cpp:170
32+
frame #18: JSC::ErrorInstance::finishCreation(this=0x000062d00020cbe0, exec=0x000062d00002c048, vm=0x0000631000000800, message=0x00007ffeefbbb800, useCurrentFrame=true) at ErrorInstance.cpp:119
33+
frame #19: JSC::ErrorInstance::create(exec=0x000062d00002c048, vm=0x0000631000000800, structure=0x000062d0000f5730, message=0x00007ffeefbbb800, appender=0x0000000000000000, type=TypeNothing, useCurrentFrame=true)(WTF::String const&, WTF::String const&, JSC::RuntimeType, JSC::ErrorInstance::SourceTextWhereErrorOccurred), JSC::RuntimeType, bool) at ErrorInstance.h:49
34+
frame #20: JSC::createRangeError(exec=0x000062d00002c048, globalObject=0x000062d00002c000, message=0x00007ffeefbbb800, appender=0x0000000000000000)(WTF::String const&, WTF::String const&, JSC::RuntimeType, JSC::ErrorInstance::SourceTextWhereErrorOccurred)) at Error.cpp:68
35+
frame #21: JSC::createRangeError(exec=0x000062d00002c048, globalObject=0x000062d00002c000, message=0x00007ffeefbbb800) at Error.cpp:316
36+
frame #22: JSC::createStackOverflowError(exec=0x000062d00002c048, globalObject=0x000062d00002c000) at ExceptionHelpers.cpp:77
37+
frame #23: JSC::createStackOverflowError(exec=0x000062d00002c048) at ExceptionHelpers.cpp:72
38+
frame #24: JSC::throwStackOverflowError(exec=0x000062d00002c048, scope=0x00007ffeefbbbaa0) at ExceptionHelpers.cpp:335
39+
frame #25: JSC::ProxyObject::getOwnPropertySlotCommon(this=0x000062d000200e40, exec=0x000062d00002c048, propertyName=PropertyName @ 0x00007ffeefbbba80, slot=0x00007ffeefbbc720) at ProxyObject.cpp:372
40+
frame #26: JSC::ProxyObject::getOwnPropertySlot(object=0x000062d000200e40, exec=0x000062d00002c048, propertyName=PropertyName @ 0x00007ffeefbbbd40, slot=0x00007ffeefbbc720) at ProxyObject.cpp:395
41+
frame #27: JSC::JSObject::getNonIndexPropertySlot(this=0x000062d000200e40, exec=0x000062d00002c048, propertyName=PropertyName @ 0x00007ffeefbbbea0, slot=0x00007ffeefbbc720) at JSObjectInlines.h:150
42+
frame #28: bool JSC::JSObject::getPropertySlot<false>(this=0x000062d000200e40, exec=0x000062d00002c048, propertyName=PropertyName @ 0x00007ffeefbbc320, slot=0x00007ffeefbbc720) at JSObject.h:1424
43+
frame #29: JSC::JSObject::calculatedClassName(object=0x000062d000200e40) at JSObject.cpp:535
44+
frame #30: JSC::Structure::toStructureShape(this=0x000062d000007410, value=JSValue @ 0x00007ffeefbbcae0, sawPolyProtoStructure=0x00007ffeefbbcf60) at Structure.cpp:1142
45+
frame #31: JSC::TypeProfilerLog::processLogEntries(this=0x000060400000a950, reason=0x00007ffeefbbd5c0) at TypeProfilerLog.cpp:89
46+
frame #32: JSC::JIT::doMainThreadPreparationBeforeCompile(this=0x0000619000034da0) at JIT.cpp:951
47+
frame #33: JSC::JITWorklist::Plan::Plan(this=0x0000619000034d80, codeBlock=0x000062d0001d88c0, loopOSREntryBytecodeOffset=0) at JITWorklist.cpp:43
48+
frame #34: JSC::JITWorklist::Plan::Plan(this=0x0000619000034d80, codeBlock=0x000062d0001d88c0, loopOSREntryBytecodeOffset=0) at JITWorklist.cpp:42
49+
frame #35: JSC::JITWorklist::compileLater(this=0x0000616000001b80, codeBlock=0x000062d0001d88c0, loopOSREntryBytecodeOffset=0) at JITWorklist.cpp:256
50+
frame #36: JSC::LLInt::jitCompileAndSetHeuristics(codeBlock=0x000062d0001d88c0, exec=0x00007ffeefbbde30, loopOSREntryBytecodeOffset=0) at LLIntSlowPaths.cpp:391
51+
frame #37: llint_replace(exec=0x00007ffeefbbde30, pc=0x00006040000161ba) at LLIntSlowPaths.cpp:516
52+
frame #38: llint_entry at LowLevelInterpreter64.asm:98
53+
frame #39: vmEntryToJavaScript at LowLevelInterpreter64.asm:296
54+
...
55+
56+
This crash occurred because StackVisitor was seeing an invalid topCallFrame while
57+
trying to capture the Error stack while throwing a StackOverflowError below
58+
llint_replace. While in this specific example, it is questionable whether we
59+
should be executing JS code below TypeProfilerLog::processLogEntries(), it is
60+
correct to have set the topCallFrame in llint_replace. We do this by calling
61+
LLINT_BEGIN_NO_SET_PC() at the top of llint_replace.
62+
63+
We also do the same for llint_osr.
64+
65+
Note: both of these LLInt slow path functions are called with a fully initialized
66+
CallFrame. Hence, there's no issue with setting topCallFrame to their CallFrames
67+
for these functions.
68+
69+
* llint/LLIntSlowPaths.cpp:
70+
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
71+
172
2018-11-13 Caio Lima <[email protected]>
273

374
[BigInt] JSBigInt::createWithLength should throw when length is greater than JSBigInt::maxLength

Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,8 @@ LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck)
455455

456456
LLINT_SLOW_PATH_DECL(loop_osr)
457457
{
458+
LLINT_BEGIN_NO_SET_PC();
459+
UNUSED_PARAM(throwScope);
458460
CodeBlock* codeBlock = exec->codeBlock();
459461

460462
#if ENABLE(JIT)
@@ -495,6 +497,8 @@ LLINT_SLOW_PATH_DECL(loop_osr)
495497

496498
LLINT_SLOW_PATH_DECL(replace)
497499
{
500+
LLINT_BEGIN_NO_SET_PC();
501+
UNUSED_PARAM(throwScope);
498502
CodeBlock* codeBlock = exec->codeBlock();
499503

500504
#if ENABLE(JIT)

0 commit comments

Comments
 (0)