Skip to content

Commit 0950f53

Browse files
committed
Merge remote-tracking branch 'remotes/origin/WebAssembly' into users/micfer/integrate
2 parents dd3a34c + 7a9c878 commit 0950f53

11 files changed

Lines changed: 145 additions & 106 deletions

lib/Runtime/Base/ScriptContext.cpp

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,48 +1873,15 @@ namespace Js
18731873
// TODO, refactor this function into smaller functions
18741874
for (uint i = 0; i < wasmModule->functions->Count(); ++i)
18751875
{
1876-
if (functionArray[i]->wasmInfo->Imported())
1877-
{
1878-
PropertyRecord const * propertyRecord = nullptr;
1879-
LPCUTF8 name = functionArray[i]->wasmInfo->GetName();
1880-
1881-
utf8::DecodeOptions decodeOptions = utf8::doAllowInvalidWCHARs;
1882-
1883-
UINT utf16Len = utf8::ByteIndexIntoCharacterIndex(name, strlen((const char*)name), decodeOptions);
1884-
LPCWSTR contents = HeapNewArray(WCHAR, (utf16Len + 1));
1885-
if (contents == nullptr)
1886-
{
1887-
Js::Throw::OutOfMemory();
1888-
}
1889-
utf8::DecodeIntoAndNullTerminate((char16*)contents, name, utf16Len, decodeOptions);
1890-
1891-
GetOrAddPropertyRecord(contents, utf16Len, &propertyRecord);
1892-
HeapDeleteArray(utf16Len + 1, contents);
1893-
if (!ffi)
1894-
{
1895-
// TODO: michhol give error message
1896-
Js::Throw::InternalError();
1897-
}
1898-
Var prop = JavascriptOperators::OP_GetProperty(ffi, propertyRecord->GetPropertyId(), this);
1899-
if (!JavascriptFunction::Is(prop))
1900-
{
1901-
Assert(UNREACHED);
1902-
// TODO: michhol figure out correct error path
1903-
}
1904-
localModuleFunctions[i] = prop;
1905-
}
1906-
else
1907-
{
1908-
AsmJsScriptFunction * funcObj = javascriptLibrary->CreateAsmJsScriptFunction(functionArray[i]->body);
1909-
funcObj->GetDynamicType()->SetEntryPoint(AsmJsExternalEntryPoint);
1910-
funcObj->SetModuleMemory(moduleMemoryPtr);
1911-
FunctionEntryPointInfo * entypointInfo = (FunctionEntryPointInfo*)funcObj->GetEntryPointInfo();
1912-
entypointInfo->SetIsAsmJSFunction(true);
1913-
entypointInfo->address = AsmJsDefaultEntryThunk;
1914-
entypointInfo->SetModuleAddress((uintptr_t)moduleMemoryPtr);
1915-
funcObj->SetEnvironment(frameDisplay);
1916-
localModuleFunctions[i] = funcObj;
1917-
}
1876+
AsmJsScriptFunction * funcObj = javascriptLibrary->CreateAsmJsScriptFunction(functionArray[i]->body);
1877+
funcObj->GetDynamicType()->SetEntryPoint(AsmJsExternalEntryPoint);
1878+
funcObj->SetModuleMemory(moduleMemoryPtr);
1879+
FunctionEntryPointInfo * entypointInfo = (FunctionEntryPointInfo*)funcObj->GetEntryPointInfo();
1880+
entypointInfo->SetIsAsmJSFunction(true);
1881+
entypointInfo->address = AsmJsDefaultEntryThunk;
1882+
entypointInfo->SetModuleAddress((uintptr_t)moduleMemoryPtr);
1883+
funcObj->SetEnvironment(frameDisplay);
1884+
localModuleFunctions[i] = funcObj;
19181885
}
19191886

19201887
for (uint32 iExport = 0; iExport < wasmModule->info->GetExportCount(); ++iExport)
@@ -1939,6 +1906,35 @@ namespace Js
19391906
}
19401907
}
19411908

1909+
UINT32 localFuncCount = wasmModule->functions->Count();
1910+
for (uint32 i = 0; i < wasmModule->info->GetImportCount(); ++i)
1911+
{
1912+
PropertyRecord const * modPropertyRecord = nullptr;
1913+
PropertyRecord const * propertyRecord = nullptr;
1914+
1915+
char16* modName = wasmModule->info->GetFunctionImport(i)->modName;
1916+
uint32 modNameLen = wasmModule->info->GetFunctionImport(i)->modNameLen;
1917+
GetOrAddPropertyRecord(modName, modNameLen, &modPropertyRecord);
1918+
1919+
char16* name = wasmModule->info->GetFunctionImport(i)->fnName;
1920+
uint32 nameLen = wasmModule->info->GetFunctionImport(i)->fnNameLen;
1921+
GetOrAddPropertyRecord(name, nameLen, &propertyRecord);
1922+
1923+
if (!ffi)
1924+
{
1925+
// TODO: michhol give error message
1926+
Js::Throw::InternalError();
1927+
}
1928+
Var modProp = JavascriptOperators::OP_GetProperty(ffi, modPropertyRecord->GetPropertyId(), this);
1929+
if (!JavascriptFunction::Is(modProp))
1930+
{
1931+
Assert(UNREACHED);
1932+
// TODO: michhol figure out correct error path
1933+
}
1934+
Var prop = JavascriptOperators::OP_GetProperty(modProp, propertyRecord->GetPropertyId(), this);
1935+
localModuleFunctions[i+localFuncCount] = prop;
1936+
}
1937+
19421938
Var** indirectFunctionTables = (Var**)(moduleMemoryPtr + wasmModule->indirFuncTableOffset);
19431939
for (uint i = 0; i < wasmModule->info->GetIndirectFunctionCount(); ++i)
19441940
{

lib/WasmReader/ModuleInfo.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,32 @@ Wasm::WasmExport* ModuleInfo::GetFunctionExport(uint32 iExport) const
175175
return &m_exports[iExport];
176176
}
177177

178+
void
179+
ModuleInfo::AllocateFunctionImports(uint32 entries)
180+
{
181+
m_imports = AnewArrayZ(m_alloc, WasmImport, entries);
182+
m_importCount = entries;
183+
}
184+
185+
void
186+
ModuleInfo::SetFunctionImport(uint32 i, uint32 sigId, wchar_t* modName, uint32 modNameLen, wchar_t* fnName, uint32 fnNameLen)
187+
{
188+
m_imports[i].sigId = sigId;
189+
m_imports[i].modNameLen = modNameLen;
190+
m_imports[i].modName = modName;
191+
m_imports[i].fnNameLen = fnNameLen;
192+
m_imports[i].fnName = fnName;
193+
}
194+
195+
Wasm::WasmImport* ModuleInfo::GetFunctionImport(uint32 i) const
196+
{
197+
if (i >= m_importCount)
198+
{
199+
return nullptr;
200+
}
201+
return &m_imports[i];
202+
}
203+
178204
} // namespace Wasm
179205

180206
#endif // ENABLE_WASM

lib/WasmReader/ModuleInfo.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,26 @@ class ModuleInfo
4747
uint GetExportCount() const { return m_exportCount; }
4848
void SetFunctionExport(uint32 iExport, uint32 funcIndex, char16* exportName, uint32 nameLength);
4949
WasmExport* GetFunctionExport(uint32 iExport) const;
50+
51+
void AllocateFunctionImports(uint32 entries);
52+
uint32 GetImportCount() const { return m_importCount; }
53+
void SetFunctionImport(uint32 i, uint32 sigId, wchar_t* modName, uint32 modNameLen, wchar_t* fnName, uint32 fnNameLen);
54+
WasmImport* GetFunctionImport(uint32 i) const;
55+
5056
private:
5157
typedef JsUtil::GrowingArray<WasmSignature*, ArenaAllocator> WasmSignatureArray;
5258

5359
WasmSignatureArray * m_signatures;
5460
uint32* m_indirectfuncs;
5561
WasmFunctionInfo** m_funsigs;
5662
WasmExport* m_exports;
63+
WasmImport* m_imports;
5764

5865
uint m_funcCount;
5966
uint m_indirectFuncCount;
6067
uint m_exportCount;
68+
uint32 m_importCount;
69+
6170
ArenaAllocator * m_alloc;
6271
};
6372

lib/WasmReader/SExprParser.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,6 @@ SExprParser::ParseFunctionHeader()
269269

270270
m_funcInfo = Anew(&m_alloc, WasmFunctionInfo, &m_alloc);
271271

272-
if (type == funcImport)
273-
{
274-
m_funcInfo->SetImported(true);
275-
}
276-
277272
if (tok == wtkSTRINGLIT)
278273
{
279274
if (type == funcImport)

lib/WasmReader/WasmBinaryReader.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@ WasmBinaryReader::ProcessSection(SectionCode sectionId, bool isEntry /*= true*/)
197197
case bSectIndirectFunctionTable:
198198
ReadIndirectFunctionTable();
199199
break;
200+
case bSectImportTable:
201+
m_moduleState.size = LEB128(length);
202+
m_moduleInfo->AllocateFunctionImports(m_moduleState.size);
203+
for (m_moduleState.count = 0; m_moduleState.count < m_moduleState.size; m_moduleState.count++)
204+
{
205+
ImportEntry();
206+
}
207+
break;
200208
default:
201209
Assert(false);
202210
return psrInvalid;
@@ -638,7 +646,7 @@ char16* WasmBinaryReader::ReadInlineName(uint32& length, uint32& nameLength)
638646
nameLength = LEB128(length);
639647
CheckBytesLeft(nameLength);
640648
LPCUTF8 rawName = (LPCUTF8)(m_pc);
641-
649+
642650
m_pc += nameLength;
643651
length += nameLength;
644652

@@ -654,6 +662,23 @@ char16* WasmBinaryReader::ReadInlineName(uint32& length, uint32& nameLength)
654662
return contents;
655663
}
656664

665+
void
666+
WasmBinaryReader::ImportEntry()
667+
{
668+
UINT len = 0;
669+
UINT sigId = LEB128(len);
670+
UINT modNameLen = 0, fnNameLen = 0;
671+
672+
if (sigId >= m_moduleInfo->GetSignatureCount())
673+
{
674+
ThrowDecodingError(L"Function signature is out of bound");
675+
}
676+
677+
wchar_t* modName = ReadInlineName(len, modNameLen);
678+
wchar_t* fnName = ReadInlineName(len, fnNameLen);
679+
m_moduleInfo->SetFunctionImport(m_moduleState.count, sigId, modName, modNameLen, fnName, fnNameLen);
680+
}
681+
657682
const char *
658683
WasmBinaryReader::Name(UINT32 offset, UINT &length)
659684
{
@@ -674,8 +699,8 @@ WasmBinaryReader::Name(UINT32 offset, UINT &length)
674699
} while (*str++);
675700

676701
return (const char*)(m_start + offset);
677-
678702
}
703+
679704
UINT
680705
WasmBinaryReader::Offset()
681706
{

lib/WasmReader/WasmBinaryReader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ namespace Wasm
122122
void FunctionBodyHeader();
123123

124124
char16* ReadInlineName(uint32& length, uint32& nameLength);
125+
void ImportEntry();
126+
125127
const char* Name(UINT32 offset, UINT &length);
126128
UINT32 Offset();
127129
UINT LEB128(UINT &length, bool sgn = false);

lib/WasmReader/WasmByteCodeGenerator.cpp

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ WasmBytecodeGenerator::GenerateModule()
7070
sectionProcess[bSectImportTable] = [](WasmBytecodeGenerator* gen, SectionCode code) {
7171
Assert(code == bSectImportTable);
7272
// todo::
73-
return psrInvalid;
73+
if (gen->m_reader->ProcessSection(code) != psrEnd)
74+
{
75+
return psrInvalid;
76+
}
77+
return psrEnd;
7478
};
7579

7680
sectionProcess[bSectFunctionBodies] = [](WasmBytecodeGenerator* gen, SectionCode code) {
@@ -540,7 +544,6 @@ WasmBytecodeGenerator::EmitCall()
540544

541545
uint funcNum = Js::Constants::UninitializedValue;
542546
uint signatureId = Js::Constants::UninitializedValue;
543-
bool imported;
544547
WasmSignature * calleeSignature;
545548
if (wasmOp == wnCALL)
546549
{
@@ -550,13 +553,11 @@ WasmBytecodeGenerator::EmitCall()
550553
throw WasmCompilationException(_u("Call is to unknown function"));
551554
}
552555
calleeSignature = m_module->info->GetFunSig(funcNum)->GetSignature();
553-
imported = m_module->info->GetFunSig(funcNum)->Imported();
554556
}
555557
else
556558
{
557559
signatureId = m_reader->m_currentNode.var.num;
558560
calleeSignature = m_module->info->GetSignature(signatureId);
559-
imported = false;
560561
}
561562

562563
EmitInfo indirectIndexInfo;
@@ -573,22 +574,14 @@ WasmBytecodeGenerator::EmitCall()
573574
// emit start call
574575
Js::ArgSlot argSize;
575576
Js::OpCodeAsmJs startCallOp;
576-
if (imported)
577+
578+
if (calleeSignature->GetParamSize() >= UINT16_MAX)
577579
{
578-
// TODO: michhol set upper limit on param count to prevent overflow
579-
argSize = (Js::ArgSlot)(calleeSignature->GetParamCount() * sizeof(Js::Var));
580-
startCallOp = Js::OpCodeAsmJs::StartCall;
580+
throw WasmCompilationException(_u("Argument size too big"));
581581
}
582-
else
583-
{
584-
if (calleeSignature->GetParamSize() >= UINT16_MAX)
585-
{
586-
throw WasmCompilationException(_u("Argument size too big"));
587-
}
588-
argSize = (Js::ArgSlot)calleeSignature->GetParamSize();
582+
argSize = (Js::ArgSlot)calleeSignature->GetParamSize();
589583

590-
startCallOp = Js::OpCodeAsmJs::I_StartCall;
591-
}
584+
startCallOp = Js::OpCodeAsmJs::I_StartCall;
592585

593586
m_writer.AsmStartCall(startCallOp, argSize + sizeof(void*));
594587

@@ -612,25 +605,16 @@ WasmBytecodeGenerator::EmitCall()
612605
{
613606
case WasmTypes::F32:
614607
// REVIEW: support FFI call with f32 params?
615-
Assert(!imported);
616608
argOp = Js::OpCodeAsmJs::I_ArgOut_Flt;
617609
++nextLoc;
618610
break;
619611
case WasmTypes::F64:
620-
if (imported)
621-
{
622-
argOp = Js::OpCodeAsmJs::ArgOut_Db;
623-
++nextLoc;
624-
}
625-
else
626-
{
627-
argOp = Js::OpCodeAsmJs::I_ArgOut_Db;
628-
// this indexes into physical stack, so on x86 we need double width
629-
nextLoc += sizeof(double) / sizeof(Js::Var);
630-
}
612+
argOp = Js::OpCodeAsmJs::I_ArgOut_Db;
613+
// this indexes into physical stack, so on x86 we need double width
614+
nextLoc += sizeof(double) / sizeof(Js::Var);
631615
break;
632616
case WasmTypes::I32:
633-
argOp = imported ? Js::OpCodeAsmJs::ArgOut_Int : Js::OpCodeAsmJs::I_ArgOut_Int;
617+
argOp = Js::OpCodeAsmJs::I_ArgOut_Int;
634618
++nextLoc;
635619
break;
636620
default:
@@ -680,15 +664,9 @@ WasmBytecodeGenerator::EmitCall()
680664

681665
// calculate number of RegSlots the arguments consume
682666
Js::ArgSlot args;
683-
if (imported)
684-
{
685-
args = (Js::ArgSlot)(calleeSignature->GetParamCount() + 1);
686-
}
687-
else
688-
{
689-
args = (Js::ArgSlot)(::ceil((double)(argSize / sizeof(Js::Var)))) + 1;
690-
}
691-
Js::OpCodeAsmJs callOp = imported ? Js::OpCodeAsmJs::Call : Js::OpCodeAsmJs::I_Call;
667+
668+
args = (Js::ArgSlot)(::ceil((double)(argSize / sizeof(Js::Var)))) + 1;
669+
Js::OpCodeAsmJs callOp = Js::OpCodeAsmJs::I_Call;
692670
m_writer.AsmCall(callOp, 0, 0, args, GetAsmJsReturnType(calleeSignature->GetResultType()));
693671

694672
// emit result coercion
@@ -700,17 +678,16 @@ WasmBytecodeGenerator::EmitCall()
700678
switch (retInfo.type)
701679
{
702680
case WasmTypes::F32:
703-
Assert(!imported);
704681
retInfo.location = m_f32RegSlots->AcquireTmpRegister();
705682
convertOp = Js::OpCodeAsmJs::I_Conv_VTF;
706683
break;
707684
case WasmTypes::F64:
708685
retInfo.location = m_f64RegSlots->AcquireTmpRegister();
709-
convertOp = imported ? Js::OpCodeAsmJs::Conv_VTF : Js::OpCodeAsmJs::I_Conv_VTF;
686+
convertOp = Js::OpCodeAsmJs::I_Conv_VTF;
710687
break;
711688
case WasmTypes::I32:
712689
retInfo.location = m_i32RegSlots->AcquireTmpRegister();
713-
convertOp = imported ? Js::OpCodeAsmJs::Conv_VTI : Js::OpCodeAsmJs::I_Conv_VTI;
690+
convertOp = Js::OpCodeAsmJs::I_Conv_VTI;
714691
break;
715692
case WasmTypes::I64:
716693
Assert(UNREACHED);

0 commit comments

Comments
 (0)