Skip to content

Commit 01215c5

Browse files
wyrichteakroshg
authored andcommitted
Fixes bug where ImplicitCallFlags and DisableImplicitFlags were not restored to previous values held.
1 parent cc87151 commit 01215c5

File tree

6 files changed

+59
-33
lines changed

6 files changed

+59
-33
lines changed

lib/Runtime/Base/ThreadContext.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,25 @@ class ThreadContext sealed :
347347
WorkerThread(HANDLE handle = nullptr) :threadHandle(handle){};
348348
};
349349

350+
struct AutoRestoreImplicitFlags
351+
{
352+
ThreadContext * threadContext;
353+
Js::ImplicitCallFlags savedImplicitCallFlags;
354+
DisableImplicitFlags savedDisableImplicitFlags;
355+
AutoRestoreImplicitFlags(ThreadContext *threadContext, Js::ImplicitCallFlags implicitCallFlags, DisableImplicitFlags disableImplicitFlags) :
356+
threadContext(threadContext),
357+
savedImplicitCallFlags(implicitCallFlags),
358+
savedDisableImplicitFlags(disableImplicitFlags)
359+
{
360+
}
361+
362+
~AutoRestoreImplicitFlags()
363+
{
364+
threadContext->SetImplicitCallFlags((Js::ImplicitCallFlags)(savedImplicitCallFlags));
365+
threadContext->SetDisableImplicitFlags((DisableImplicitFlags)savedDisableImplicitFlags);
366+
}
367+
};
368+
350369
void SetCurrentThreadId(DWORD threadId) { this->currentThreadId = threadId; }
351370
DWORD GetCurrentThreadId() const { return this->currentThreadId; }
352371
void SetIsThreadBound()

lib/Runtime/Language/InlineCache.inl

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,13 @@ namespace Js
183183

184184
bool canSetField; // To verify if we can set a field on the object
185185
Var setterValue = nullptr;
186-
{
187-
// We need to disable implicit call to ensure the check doesn't cause unwanted side effects in debug code
188-
// Save old disableImplicitFlags and implicitCallFlags and disable implicit call and exception
186+
{
187+
// We need to disable implicit call to ensure the check doesn't cause unwanted side effects in debug
188+
// code Save old disableImplicitFlags and implicitCallFlags and disable implicit call and exception.
189189
ThreadContext * threadContext = requestContext->GetThreadContext();
190-
DisableImplicitFlags disableImplicitFlags = *threadContext->GetAddressOfDisableImplicitFlags();
191-
Js::ImplicitCallFlags implicitCallFlags = threadContext->GetImplicitCallFlags();
190+
ThreadContext::AutoRestoreImplicitFlags autoRestoreImplicitFlags(threadContext, threadContext->GetImplicitCallFlags(), threadContext->GetDisableImplicitFlags());
192191
threadContext->ClearImplicitCallFlags();
193-
*threadContext->GetAddressOfDisableImplicitFlags() = DisableImplicitCallAndExceptionFlag;
192+
threadContext->SetDisableImplicitFlags(DisableImplicitCallAndExceptionFlag);
194193

195194
DescriptorFlags flags = DescriptorFlags::None;
196195
canSetField = !JavascriptOperators::CheckPrototypesForAccessorOrNonWritablePropertySlow(object, propertyId, &setterValue, &flags, isRoot, requestContext);
@@ -199,15 +198,12 @@ namespace Js
199198
canSetField = true; // If there was an implicit call, inconclusive. Disable debug check.
200199
setterValue = nullptr;
201200
}
202-
else
203-
if ((flags & Accessor) == Accessor)
201+
else if ((flags & Accessor) == Accessor)
204202
{
205203
Assert(setterValue != nullptr);
206204
}
207205

208-
// Restore old disableImplicitFlags and implicitCallFlags
209-
*threadContext->GetAddressOfDisableImplicitFlags() = disableImplicitFlags;
210-
threadContext->SetImplicitCallFlags(implicitCallFlags);
206+
// ImplicitCallFlags and DisableImplicitFlags restored by AutoRestoreImplicitFlags' destructor.
211207
}
212208
#endif
213209

lib/Runtime/Library/JsBuiltInEngineInterfaceExtensionObject.cpp

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -100,26 +100,6 @@ namespace Js
100100
{
101101
return;
102102
}
103-
104-
struct AutoRestoreFlags
105-
{
106-
ThreadContext * ctx;
107-
ImplicitCallFlags savedImplicitCallFlags;
108-
DisableImplicitFlags savedDisableImplicitFlags;
109-
AutoRestoreFlags(ThreadContext *ctx, Js::ImplicitCallFlags implFlags, DisableImplicitFlags disableImplFlags) :
110-
ctx(ctx),
111-
savedImplicitCallFlags(implFlags),
112-
savedDisableImplicitFlags(disableImplFlags)
113-
{
114-
ctx->ClearDisableImplicitFlags();
115-
}
116-
117-
~AutoRestoreFlags()
118-
{
119-
ctx->SetImplicitCallFlags((Js::ImplicitCallFlags)(savedImplicitCallFlags));
120-
ctx->SetDisableImplicitFlags((DisableImplicitFlags)savedDisableImplicitFlags);
121-
}
122-
};
123103

124104
try {
125105
EnsureJsBuiltInByteCode(scriptContext);
@@ -159,7 +139,8 @@ namespace Js
159139
#endif
160140
// Clear disable implicit call bit as initialization code doesn't have any side effect
161141
{
162-
AutoRestoreFlags autoRestoreFlags(scriptContext->GetThreadContext(), scriptContext->GetThreadContext()->GetImplicitCallFlags(), scriptContext->GetThreadContext()->GetDisableImplicitFlags());
142+
ThreadContext::AutoRestoreImplicitFlags autoRestoreImplicitFlags(scriptContext->GetThreadContext(), scriptContext->GetThreadContext()->GetImplicitCallFlags(), scriptContext->GetThreadContext()->GetDisableImplicitFlags());
143+
scriptContext->GetThreadContext()->ClearDisableImplicitFlags();
163144
JavascriptFunction::CallRootFunctionInScript(functionGlobal, Js::Arguments(callInfo, args));
164145
}
165146

@@ -168,7 +149,8 @@ namespace Js
168149

169150
// Clear disable implicit call bit as initialization code doesn't have any side effect
170151
{
171-
AutoRestoreFlags autoRestoreFlags(scriptContext->GetThreadContext(), scriptContext->GetThreadContext()->GetImplicitCallFlags(), scriptContext->GetThreadContext()->GetDisableImplicitFlags());
152+
ThreadContext::AutoRestoreImplicitFlags autoRestoreImplicitFlags(scriptContext->GetThreadContext(), scriptContext->GetThreadContext()->GetImplicitCallFlags(), scriptContext->GetThreadContext()->GetDisableImplicitFlags());
153+
scriptContext->GetThreadContext()->ClearDisableImplicitFlags();
172154
JavascriptFunction::CallRootFunctionInScript(functionBuiltins, Js::Arguments(callInfo, args));
173155
}
174156

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
var a = [];
7+
function f() {
8+
try {
9+
f();
10+
} catch (e) {
11+
a.foo = 100;
12+
}
13+
}
14+
f();
15+
16+
print("pass");

test/TryCatch/rlexe.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<regress-exe>
3+
<test>
4+
<default>
5+
<files>TryCatchStackOverflow.js</files>
6+
</default>
7+
</test>
8+
</regress-exe>

test/rlexedirs.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@
118118
<files>TaggedFloats</files>
119119
</default>
120120
</dir>
121+
<dir>
122+
<default>
123+
<files>TryCatch</files>
124+
</default>
125+
</dir>
121126
<dir>
122127
<default>
123128
<files>Optimizer</files>

0 commit comments

Comments
 (0)