Skip to content

Commit 9478176

Browse files
committed
Make WebAssembly globals to be readonly, this forces to use the module environment to read the globals after they've been resolved.
This allows to instantiate the same module more than once whe it has imported/referenced globals
1 parent a148a9a commit 9478176

12 files changed

Lines changed: 284 additions & 231 deletions

lib/Runtime/Library/WebAssemblyInstance.cpp

Lines changed: 176 additions & 124 deletions
Large diffs are not rendered by default.

lib/Runtime/Library/WebAssemblyInstance.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,24 @@ namespace Js
2525
private:
2626
WebAssemblyInstance(WebAssemblyModule * wasmModule, DynamicType * type);
2727

28-
static void LoadDataSegs(WebAssemblyModule * wasmModule, Var* memory, ScriptContext* ctx);
29-
static void LoadFunctions(WebAssemblyModule * wasmModule, ScriptContext* ctx, Var* moduleMemoryPtr, Var* localModuleFunctions);
30-
static void BuildObject(WebAssemblyModule * wasmModule, ScriptContext* ctx, Var exportsNamespace, Var* memory, WebAssemblyTable** table, Var exportObj, Var* localModuleFunctions, Var* importFunctions);
31-
static void LoadImports(WebAssemblyModule * wasmModule, ScriptContext* ctx, Var* importFunctions, Var* localModuleFunctions, Var ffi, Var* memoryObject, WebAssemblyTable ** tableObject);
32-
static void LoadGlobals(WebAssemblyModule * wasmModule, ScriptContext* ctx, Var moduleEnv);
33-
static void LoadIndirectFunctionTable(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyTable** indirectFunctionTables, Var* localModuleFunctions, Var* importFunctions);
34-
static Var GetFunctionObjFromFunctionIndex(WebAssemblyModule * wasmModule, ScriptContext* ctx, uint32 funcIndex, Var* localModuleFunctions, Var* importFunctions);
28+
struct WebAssemblyEnvironment
29+
{
30+
WebAssemblyEnvironment(WebAssemblyModule* module);
31+
Var* ptr;
32+
Var* memory;
33+
Var* imports;
34+
Var* functions;
35+
Var* table;
36+
Var* globals;
37+
};
38+
39+
static void LoadDataSegs(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment env);
40+
static void LoadFunctions(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment env);
41+
static Var BuildObject(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment env);
42+
static void LoadImports(WebAssemblyModule * wasmModule, ScriptContext* ctx, Var ffi, WebAssemblyEnvironment env);
43+
static void LoadGlobals(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment env);
44+
static void LoadIndirectFunctionTable(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment env);
45+
static Var GetFunctionObjFromFunctionIndex(WebAssemblyModule * wasmModule, ScriptContext* ctx, uint32 funcIndex, WebAssemblyEnvironment env);
3546

3647

3748
WebAssemblyModule * m_module;

lib/Runtime/Library/WebAssemblyModule.cpp

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ WebAssemblyModule::EntryImports(RecyclableObject* function, CallInfo callInfo, .
144144
Wasm::WasmImport * import = module->GetImport(i);
145145
Js::JavascriptString * kind = GetExternalKindString(scriptContext, import->kind);
146146
Js::JavascriptString * moduleName = JavascriptString::NewCopySz(import->modName, scriptContext);
147-
Js::JavascriptString * name = JavascriptString::NewCopySz(import->fnName, scriptContext);
147+
Js::JavascriptString * name = JavascriptString::NewCopySz(import->importName, scriptContext);
148148

149149
Var pair = JavascriptOperators::NewJavascriptObjectNoArg(scriptContext);
150150
JavascriptOperators::OP_SetProperty(pair, PropertyIds::kind, kind, scriptContext);
@@ -479,8 +479,8 @@ WebAssemblyModule::AddFunctionImport(uint32 sigId, const char16* modName, uint32
479479
importInfo->kind = Wasm::ExternalKinds::Function;
480480
importInfo->modNameLen = modNameLen;
481481
importInfo->modName = modName;
482-
importInfo->fnNameLen = fnNameLen;
483-
importInfo->fnName = fnName;
482+
importInfo->importNameLen = fnNameLen;
483+
importInfo->importName = fnName;
484484
m_imports->Add(importInfo);
485485

486486
Wasm::WasmSignature* signature = GetSignature(sigId);
@@ -533,26 +533,24 @@ WebAssemblyModule::GetImport(uint32 i) const
533533
}
534534

535535
void
536-
WebAssemblyModule::AddGlobalImport(const char16* modName, uint32 modNameLen, const char16* fnName, uint32 fnNameLen, Wasm::WasmGlobal* importedGlobal)
536+
WebAssemblyModule::AddGlobalImport(const char16* modName, uint32 modNameLen, const char16* importName, uint32 importNameLen)
537537
{
538538
Wasm::WasmImport* wi = Anew(&m_alloc, Wasm::WasmImport);
539539
wi->kind = Wasm::ExternalKinds::Global;
540-
wi->fnName = fnName;
541-
wi->fnNameLen = fnNameLen;
540+
wi->importName = importName;
541+
wi->importNameLen = importNameLen;
542542
wi->modName = modName;
543543
wi->modNameLen = modNameLen;
544544
m_imports->Add(wi);
545-
546-
importedGlobal->SetReferenceType(Wasm::WasmGlobal::ImportedReference);
547545
}
548546

549547
void
550548
WebAssemblyModule::AddMemoryImport(const char16* modName, uint32 modNameLen, const char16* importName, uint32 importNameLen)
551549
{
552550
Wasm::WasmImport* wi = Anew(&m_alloc, Wasm::WasmImport);
553551
wi->kind = Wasm::ExternalKinds::Memory;
554-
wi->fnName = importName;
555-
wi->fnNameLen = importNameLen;
552+
wi->importName = importName;
553+
wi->importNameLen = importNameLen;
556554
wi->modName = modName;
557555
wi->modNameLen = modNameLen;
558556
m_imports->Add(wi);
@@ -564,16 +562,16 @@ WebAssemblyModule::AddTableImport(const char16* modName, uint32 modNameLen, cons
564562
{
565563
Wasm::WasmImport* wi = Anew(&m_alloc, Wasm::WasmImport);
566564
wi->kind = Wasm::ExternalKinds::Table;
567-
wi->fnName = importName;
568-
wi->fnNameLen = importNameLen;
565+
wi->importName = importName;
566+
wi->importNameLen = importNameLen;
569567
wi->modName = modName;
570568
wi->modNameLen = modNameLen;
571569
m_imports->Add(wi);
572570
m_tableImport = wi;
573571
}
574572

575573
uint
576-
WebAssemblyModule::GetOffsetFromInit(const Wasm::WasmNode& initExpr) const
574+
WebAssemblyModule::GetOffsetFromInit(const Wasm::WasmNode& initExpr, Var* moduleEnv) const
577575
{
578576
if (initExpr.op != Wasm::wbI32Const && initExpr.op != Wasm::wbGetGlobal)
579577
{
@@ -591,22 +589,21 @@ WebAssemblyModule::GetOffsetFromInit(const Wasm::WasmNode& initExpr) const
591589
throw Wasm::WasmCompilationException(_u("global %d doesn't exist"), initExpr.var.num);
592590
}
593591
Wasm::WasmGlobal* global = m_globals->Item(initExpr.var.num);
594-
595-
if (global->GetReferenceType() != Wasm::WasmGlobal::Const || global->GetType() != Wasm::WasmTypes::I32)
592+
if (global->GetType() != Wasm::WasmTypes::I32)
596593
{
597594
throw Wasm::WasmCompilationException(_u("global %d must be i32"), initExpr.var.num);
598595
}
599-
offset = global->cnst.i32;
596+
uint32 globalOffset = GetOffsetForGlobal(global);
597+
offset = *((int*)moduleEnv + globalOffset);
600598
}
601599
return offset;
602600
}
603601

604-
Wasm::WasmGlobal*
605-
WebAssemblyModule::AddGlobal(Wasm::WasmTypes::WasmType type, bool isMutable)
602+
void
603+
WebAssemblyModule::AddGlobal(Wasm::ReferenceTypes::Type refType, Wasm::WasmTypes::WasmType type, bool isMutable, Wasm::WasmNode init)
606604
{
607-
Wasm::WasmGlobal* global = Anew(&m_alloc, Wasm::WasmGlobal, m_globalCounts[type]++, type, isMutable);
605+
Wasm::WasmGlobal* global = Anew(&m_alloc, Wasm::WasmGlobal, refType, m_globalCounts[type]++, type, isMutable, init);
608606
m_globals->Add(global);
609-
return global;
610607
}
611608

612609
uint32
@@ -723,7 +720,7 @@ void WebAssemblyModule::Dispose(bool isShutdown)
723720
void WebAssemblyModule::Mark(Recycler * recycler)
724721
{
725722
}
726-
uint WebAssemblyModule::GetOffsetForGlobal(Wasm::WasmGlobal* global)
723+
uint WebAssemblyModule::GetOffsetForGlobal(Wasm::WasmGlobal* global) const
727724
{
728725
Wasm::WasmTypes::WasmType type = global->GetType();
729726
if (type >= Wasm::WasmTypes::Limit)

lib/Runtime/Library/WebAssemblyModule.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ namespace Wasm
1717
class WasmGlobal;
1818
struct WasmImport;
1919
struct WasmExport;
20-
20+
namespace ReferenceTypes
21+
{
22+
enum Type;
23+
}
2124
namespace WasmTypes
2225
{
2326
enum WasmType;
@@ -102,16 +105,16 @@ class WebAssemblyModule : public DynamicObject
102105
uint32 GetImportCount() const;
103106
Wasm::WasmImport* GetImport(uint32 i) const;
104107
void AddFunctionImport(uint32 sigId, const char16* modName, uint32 modNameLen, const char16* fnName, uint32 fnNameLen);
105-
void AddGlobalImport(const char16* modName, uint32 modNameLen, const char16* fnName, uint32 fnNameLen, Wasm::WasmGlobal* importedGlobal);
108+
void AddGlobalImport(const char16* modName, uint32 modNameLen, const char16* importName, uint32 importNameLen);
106109
void AddMemoryImport(const char16* modName, uint32 modNameLen, const char16* importName, uint32 importNameLen);
107110
void AddTableImport(const char16* modName, uint32 modNameLen, const char16* importName, uint32 importNameLen);
108111
Wasm::WasmImport * GetMemoryImport() const { return m_memImport; }
109112
Wasm::WasmImport * GetTableImport() const { return m_tableImport; }
110113
uint32 GetImportedFunctionCount() const { return m_importedFunctionCount; }
111114

112-
uint GetOffsetFromInit(const Wasm::WasmNode& initexpr) const;
115+
uint GetOffsetFromInit(const Wasm::WasmNode& initexpr, Var* moduleEnv) const;
113116

114-
Wasm::WasmGlobal* AddGlobal(Wasm::WasmTypes::WasmType type, bool isMutable);
117+
void AddGlobal(Wasm::ReferenceTypes::Type refType, Wasm::WasmTypes::WasmType type, bool isMutable, Wasm::WasmNode init);
115118
uint32 GetGlobalCount() const;
116119
Wasm::WasmGlobal* GetGlobal(uint32 index) const;
117120

@@ -138,7 +141,7 @@ class WebAssemblyModule : public DynamicObject
138141
uint GetFuncOffset() const { return GetImportFuncOffset() + GetImportedFunctionCount(); }
139142
uint GetTableEnvironmentOffset() const { return GetFuncOffset() + GetWasmFunctionCount(); }
140143
uint GetGlobalOffset() const { return GetTableEnvironmentOffset() + 1; }
141-
uint GetOffsetForGlobal(Wasm::WasmGlobal* global);
144+
uint GetOffsetForGlobal(Wasm::WasmGlobal* global) const;
142145
uint AddGlobalByteSizeToOffset(Wasm::WasmTypes::WasmType type, uint32 offset) const;
143146
uint GetGlobalsByteSize() const;
144147

lib/WasmReader/WasmBinaryReader.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ void WasmBinaryReader::ReadExportTable()
727727
if (type == FunctionIndexTypes::ImportThunk)
728728
{
729729
WasmImport* import = m_module->GetWasmFunctionInfo(index)->importedFunctionReference;
730-
TRACE_WASM_DECODER(_u("Export #%u: Import(%s.%s)(%u) => %s"), iExport, import->modName, import->fnName, index, exportName);
730+
TRACE_WASM_DECODER(_u("Export #%u: Import(%s.%s)(%u) => %s"), iExport, import->modName, import->importName, index, exportName);
731731
}
732732
else
733733
{
@@ -891,24 +891,20 @@ WasmBinaryReader::ReadGlobalsSection()
891891
{
892892
WasmTypes::WasmType type = ReadWasmType(len);
893893
bool isMutable = ReadConst<UINT8>() == 1;
894-
WasmGlobal* global = m_module->AddGlobal(type, isMutable);
895-
896894
WasmNode globalNode = ReadInitExpr();
897895
switch (globalNode.op) {
898896
case wbI32Const:
899897
case wbF32Const:
900898
case wbF64Const:
901899
case wbI64Const:
902-
global->SetReferenceType(WasmGlobal::Const);
903-
global->cnst = globalNode.cnst;
900+
m_module->AddGlobal(ReferenceTypes::Const, type, isMutable, globalNode);
904901
break;
905902
case wbGetGlobal:
906-
if (m_module->GetGlobal(globalNode.var.num)->GetReferenceType() != WasmGlobal::ImportedReference)
903+
if (m_module->GetGlobal(globalNode.var.num)->GetReferenceType() != ReferenceTypes::ImportedReference)
907904
{
908905
ThrowDecodingError(_u("Global can only be initialized with a const or an imported global"));
909906
}
910-
global->SetReferenceType(WasmGlobal::LocalReference);
911-
global->importIndex = globalNode.var.num;
907+
m_module->AddGlobal(ReferenceTypes::LocalReference, type, isMutable, globalNode);
912908
break;
913909
default:
914910
Assert(UNREACHED);
@@ -967,8 +963,8 @@ WasmBinaryReader::ReadImportEntries()
967963
{
968964
WasmTypes::WasmType type = ReadWasmType(len);
969965
bool isMutable = ReadConst<UINT8>() == 1;
970-
WasmGlobal* importedGlobal = m_module->AddGlobal(type, isMutable);
971-
m_module->AddGlobalImport(modName, modNameLen, fnName, fnNameLen, importedGlobal);
966+
m_module->AddGlobal(ReferenceTypes::ImportedReference, type, isMutable, {});
967+
m_module->AddGlobalImport(modName, modNameLen, fnName, fnNameLen);
972968
break;
973969
}
974970
case ExternalKinds::Table:
@@ -1113,7 +1109,7 @@ WasmBinaryReader::ReadInitExpr()
11131109
{
11141110
uint32 globalIndex = node.var.num;
11151111
WasmGlobal* global = m_module->GetGlobal(globalIndex);
1116-
if (global->GetMutability())
1112+
if (global->IsMutable())
11171113
{
11181114
ThrowDecodingError(_u("initializer expression cannot reference a mutable global"));
11191115
}

lib/WasmReader/WasmDataSegment.cpp

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,22 @@ namespace Wasm
1212

1313
WasmDataSegment::WasmDataSegment(ArenaAllocator * alloc, WasmNode ie, uint32 _source_size, const byte* _data) :
1414
m_alloc(alloc),
15-
initExpr(ie),
16-
source_size(_source_size),
17-
data(_data)
15+
m_initExpr(ie),
16+
m_sourceSize(_source_size),
17+
m_data(_data)
1818
{
1919
}
2020

2121
uint32
22-
WasmDataSegment::getDestAddr(Js::WebAssemblyModule* module) const
22+
WasmDataSegment::GetSourceSize() const
2323
{
24-
return module->GetOffsetFromInit(initExpr);
25-
}
26-
27-
uint32
28-
WasmDataSegment::getSourceSize() const
29-
{
30-
return source_size;
24+
return m_sourceSize;
3125
}
3226

3327
const byte*
34-
WasmDataSegment::getData() const
28+
WasmDataSegment::GetData() const
3529
{
36-
return data;
30+
return m_data;
3731
}
3832

3933
} // namespace Wasm

lib/WasmReader/WasmDataSegment.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ class WasmDataSegment
1212
{
1313
public:
1414
WasmDataSegment(ArenaAllocator * alloc, WasmNode initExpr, uint32 _source_size, const byte* _data);
15-
uint32 getDestAddr(Js::WebAssemblyModule* module) const;
16-
uint32 getSourceSize() const;
17-
const byte* getData() const;
15+
WasmNode GetOffsetExpr() const { return m_initExpr; }
16+
uint32 GetSourceSize() const;
17+
const byte* GetData() const;
1818

1919
private:
2020
ArenaAllocator * m_alloc;
21-
WasmNode initExpr;
22-
uint32 source_size;
23-
const byte* data;
21+
WasmNode m_initExpr;
22+
uint32 m_sourceSize;
23+
const byte* m_data;
2424
};
2525

2626
} // namespace Wasm

lib/WasmReader/WasmElementSegment.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,6 @@ namespace Wasm
4444
Assert(m_elems != nullptr);
4545
return m_elems[tableIndex];
4646
}
47-
48-
uint32 WasmElementSegment::GetDestAddr(Js::WebAssemblyModule* module) const
49-
{
50-
return module->GetOffsetFromInit(m_offsetExpr);
51-
}
52-
5347
} // namespace Wasm
5448

5549
#endif // ENABLE_WASM

lib/WasmReader/WasmElementSegment.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ namespace Wasm
1515
void AddElement(const UINT32 funcIndex, const Js::WebAssemblyModule& module);
1616
UINT32 GetElement(const UINT32 tableIndex) const;
1717
UINT32 GetNumElements() const { return m_numElem; }
18-
19-
uint32 GetDestAddr(Js::WebAssemblyModule* module) const;
20-
18+
WasmNode GetOffsetExpr() const { return m_offsetExpr; }
2119
private:
2220
ArenaAllocator* m_alloc;
2321
UINT32 m_index;

lib/WasmReader/WasmGlobal.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,23 @@
1010
namespace Wasm
1111
{
1212

13-
WasmTypes::WasmType
14-
WasmGlobal::GetType() const
15-
{
16-
return m_type;
17-
}
13+
Wasm::WasmConstLitNode WasmGlobal::GetConstInit() const
14+
{
15+
if (GetReferenceType() != ReferenceTypes::Const)
16+
{
17+
throw WasmCompilationException(_u("Global must be initialized from a const to retrieve the const value"));
18+
}
19+
return m_init.cnst;
20+
}
21+
22+
uint32 WasmGlobal::GetGlobalIndexInit() const
23+
{
24+
if (GetReferenceType() != ReferenceTypes::LocalReference)
25+
{
26+
throw WasmCompilationException(_u("Global must be initialized from another global to retrieve its index"));
27+
}
28+
return m_init.var.num;
29+
}
1830

19-
bool
20-
WasmGlobal::GetMutability() const
21-
{
22-
return m_mutability;
23-
}
2431
} // namespace Wasm
2532
#endif // ENABLE_WASM

0 commit comments

Comments
 (0)