Skip to content

Commit 3293ada

Browse files
committed
Fixes entrypoints when 2 functions not sharing the same type are being deferred parsed
1 parent 3087c0c commit 3293ada

4 files changed

Lines changed: 76 additions & 34 deletions

File tree

lib/Runtime/Library/WasmLibrary.cpp

Lines changed: 57 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -106,49 +106,72 @@ Js::JavascriptMethod Js::WasmLibrary::WasmDeferredParseEntryPoint(Js::AsmJsScrip
106106
AsmJsFunctionInfo* info = body->GetAsmJsFunctionInfo();
107107
ScriptContext* scriptContext = func->GetScriptContext();
108108

109-
Js::FunctionEntryPointInfo * entypointInfo = (Js::FunctionEntryPointInfo*)func->GetEntryPointInfo();
109+
Js::FunctionEntryPointInfo * entrypointInfo = (Js::FunctionEntryPointInfo*)func->GetEntryPointInfo();
110110
Wasm::WasmReaderInfo* readerInfo = info->GetWasmReaderInfo();
111-
info->SetWasmReaderInfo(nullptr);
112-
try
111+
if (readerInfo)
113112
{
114-
Wasm::WasmBytecodeGenerator::GenerateFunctionBytecode(scriptContext, readerInfo);
115-
func->GetDynamicType()->SetEntryPoint(Js::AsmJsExternalEntryPoint);
116-
entypointInfo->jsMethod = AsmJsDefaultEntryThunk;
117-
// Do MTJRC/MAIC:0 check
113+
info->SetWasmReaderInfo(nullptr);
114+
try
115+
{
116+
Wasm::WasmBytecodeGenerator::GenerateFunctionBytecode(scriptContext, readerInfo);
117+
func->GetDynamicType()->SetEntryPoint(Js::AsmJsExternalEntryPoint);
118+
entrypointInfo->jsMethod = AsmJsDefaultEntryThunk;
119+
// Do MTJRC/MAIC:0 check
118120
#if ENABLE_DEBUG_CONFIG_OPTIONS
119-
if (CONFIG_FLAG(ForceNative) || CONFIG_FLAG(MaxAsmJsInterpreterRunCount) == 0)
121+
if (CONFIG_FLAG(ForceNative) || CONFIG_FLAG(MaxAsmJsInterpreterRunCount) == 0)
122+
{
123+
GenerateFunction(scriptContext->GetNativeCodeGenerator(), body, func);
124+
body->SetIsAsmJsFullJitScheduled(true);
125+
}
126+
#endif
127+
}
128+
catch (Wasm::WasmCompilationException& ex)
120129
{
121-
GenerateFunction(scriptContext->GetNativeCodeGenerator(), body, func);
122-
body->SetIsAsmJsFullJitScheduled(true);
130+
char16* originalMessage = ex.ReleaseErrorMessage();
131+
intptr_t offset = readerInfo->m_module->GetReader()->GetCurrentOffset();
132+
intptr_t start = readerInfo->m_funcInfo->m_readerInfo.startOffset;
133+
uint32 size = readerInfo->m_funcInfo->m_readerInfo.size;
134+
135+
Wasm::WasmCompilationException newEx = Wasm::WasmCompilationException(
136+
_u("function %s at offset %d/%d: %s"),
137+
body->GetDisplayName(),
138+
offset - start,
139+
size,
140+
originalMessage
141+
);
142+
SysFreeString(originalMessage);
143+
char16* msg = newEx.ReleaseErrorMessage();
144+
JavascriptLibrary *library = scriptContext->GetLibrary();
145+
JavascriptError *pError = library->CreateWebAssemblyCompileError();
146+
JavascriptError::SetErrorMessage(pError, WASMERR_WasmCompileError, msg, scriptContext);
147+
148+
func->GetDynamicType()->SetEntryPoint(WasmLazyTrapCallback);
149+
entrypointInfo->jsMethod = WasmLazyTrapCallback;
150+
info->SetLazyError(pError);
123151
}
124-
#endif
125152
}
126-
catch (Wasm::WasmCompilationException& ex)
153+
else
127154
{
128-
char16* originalMessage = ex.ReleaseErrorMessage();
129-
intptr_t offset = readerInfo->m_module->GetReader()->GetCurrentOffset();
130-
intptr_t start = readerInfo->m_funcInfo->m_readerInfo.startOffset;
131-
uint32 size = readerInfo->m_funcInfo->m_readerInfo.size;
132-
133-
Wasm::WasmCompilationException newEx = Wasm::WasmCompilationException(
134-
_u("function %s at offset %d/%d: %s"),
135-
body->GetDisplayName(),
136-
offset - start,
137-
size,
138-
originalMessage
139-
);
140-
SysFreeString(originalMessage);
141-
char16* msg = newEx.ReleaseErrorMessage();
142-
JavascriptLibrary *library = scriptContext->GetLibrary();
143-
JavascriptError *pError = library->CreateWebAssemblyCompileError();
144-
JavascriptError::SetErrorMessage(pError, WASMERR_WasmCompileError, msg, scriptContext);
145-
146-
func->GetDynamicType()->SetEntryPoint(WasmLazyTrapCallback);
147-
entypointInfo->jsMethod = WasmLazyTrapCallback;
148-
info->SetLazyError(pError);
155+
// This can happen if another function had its type changed and then was parsed
156+
// They still share the function body, so just change the entry point
157+
Assert(body->GetByteCodeCount() > 0);
158+
Js::JavascriptMethod externalEntryPoint = info->GetLazyError() ? WasmLazyTrapCallback : Js::AsmJsExternalEntryPoint;
159+
func->GetDynamicType()->SetEntryPoint(externalEntryPoint);
160+
if (body->GetIsAsmJsFullJitScheduled())
161+
{
162+
Js::FunctionEntryPointInfo* defaultEntryPoint = (Js::FunctionEntryPointInfo*)body->GetDefaultEntryPointInfo();
163+
func->ChangeEntryPoint(defaultEntryPoint, defaultEntryPoint->jsMethod);
164+
}
165+
else if (entrypointInfo->jsMethod == WasmLibrary::WasmDeferredParseInternalThunk)
166+
{
167+
// The entrypointInfo is still shared even if the type has been changed
168+
// However, no sibling functions changed this entry point yet, so fix it
169+
entrypointInfo->jsMethod = info->GetLazyError() ? WasmLazyTrapCallback : AsmJsDefaultEntryThunk;
170+
}
149171
}
172+
150173
Assert(body->HasValidEntryPoint());
151-
Js::JavascriptMethod entryPoint = internalCall ? entypointInfo->jsMethod : func->GetDynamicType()->GetEntryPoint();
174+
Js::JavascriptMethod entryPoint = internalCall ? entrypointInfo->jsMethod : func->GetDynamicType()->GetEntryPoint();
152175
return entryPoint;
153176
#else
154177
Js::Throw::InternalError();
36 Bytes
Binary file not shown.

test/wasm/bugs.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ async function main() {
3131
throw e;
3232
}
3333
}
34+
35+
{
36+
const mod = new WebAssembly.Module(readbuffer("binaries/bugDeferred.wasm"));
37+
const instance1 = new WebAssembly.Instance(mod);
38+
const instance2 = new WebAssembly.Instance(mod);
39+
40+
// Change the type of the function on the first instance
41+
instance1.exports.foo.asdf = 5;
42+
instance1.exports.foo();
43+
// Make sure the entrypoint has been correctly updated on the second instance
44+
instance2.exports.foo();
45+
}
3446
}
3547

3648
main().then(() => console.log("PASSED"), console.log);

test/wasm/wasts/bugDeferred.wast

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
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+
(module
6+
(func (export "foo") (result i32) (i32.const 0))
7+
)

0 commit comments

Comments
 (0)