@@ -199,12 +199,24 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
199199 EvallingModuleInstance* instance;
200200 std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances;
201201
202+ // A representation of the contents of wasm memory as we execute.
203+ std::vector<char > memory;
204+
202205 CtorEvalExternalInterface (
203206 std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances_ =
204207 {}) {
205208 linkedInstances.swap (linkedInstances_);
206209 }
207210
211+ // Called when we want to apply the current state of execution to the Module.
212+ // Until this is called the Module is never changed.
213+ void applyToModule () {
214+ // If nothing was ever written to memory then there is nothing to update.
215+ if (!memory.empty ()) {
216+ applyMemoryToModule ();
217+ }
218+ }
219+
208220 void init (Module& wasm_, EvallingModuleInstance& instance_) override {
209221 wasm = &wasm_;
210222 instance = &instance_;
@@ -365,22 +377,12 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
365377 // TODO: handle unaligned too, see shell-interface
366378
367379 template <typename T> T* getMemory (Address address) {
368- // this must be in the singleton segment. resize as needed
369- if (wasm->memory .segments .size () == 0 ) {
370- std::vector<char > temp;
371- Builder builder (*wasm);
372- wasm->memory .segments .push_back (
373- Memory::Segment (builder.makeConst (int32_t (0 )), temp));
374- }
375- // memory should already have been flattened
376- assert (wasm->memory .segments [0 ].offset ->cast <Const>()->value .getInteger () ==
377- 0 );
380+ // resize the memory buffer as needed.
378381 auto max = address + sizeof (T);
379- auto & data = wasm->memory .segments [0 ].data ;
380- if (max > data.size ()) {
381- data.resize (max);
382+ if (max > memory.size ()) {
383+ memory.resize (max);
382384 }
383- return (T*)(&data [address]);
385+ return (T*)(&memory [address]);
384386 }
385387
386388 template <typename T> void doStore (Address address, T value) {
@@ -394,6 +396,23 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
394396 memcpy (&ret, getMemory<T>(address), sizeof (T));
395397 return ret;
396398 }
399+
400+ void applyMemoryToModule () {
401+ // Memory must have already been flattened into the standard form: one
402+ // segment at offset 0, or none.
403+ if (wasm->memory .segments .empty ()) {
404+ Builder builder (*wasm);
405+ std::vector<char > empty;
406+ wasm->memory .segments .push_back (
407+ Memory::Segment (builder.makeConst (int32_t (0 )), empty));
408+ }
409+ auto & segment = wasm->memory .segments [0 ];
410+ assert (segment.offset ->cast <Const>()->value .getInteger () == 0 );
411+
412+ // Copy the current memory contents after execution into the Module's
413+ // memory.
414+ segment.data = memory;
415+ }
397416};
398417
399418void evalCtors (Module& wasm, std::vector<std::string> ctors) {
@@ -422,8 +441,6 @@ void evalCtors(Module& wasm, std::vector<std::string> ctors) {
422441 // TODO: if we knew priorities, we could reorder?
423442 for (auto & ctor : ctors) {
424443 std::cerr << " trying to eval " << ctor << ' \n ' ;
425- // snapshot memory, as either the entire function is done, or none
426- auto memoryBefore = wasm.memory ;
427444 // snapshot globals (note that STACKTOP might be modified, but should
428445 // be returned, so that works out)
429446 auto globalsBefore = instance.globals ;
@@ -437,16 +454,18 @@ void evalCtors(Module& wasm, std::vector<std::string> ctors) {
437454 // that's it, we failed, so stop here, cleaning up partial
438455 // memory changes first
439456 std::cerr << " ...stopping since could not eval: " << fail.why << " \n " ;
440- wasm.memory = memoryBefore;
441457 return ;
442458 }
443459 if (instance.globals != globalsBefore) {
444460 std::cerr << " ...stopping since globals modified\n " ;
445- wasm.memory = memoryBefore;
446461 return ;
447462 }
448463 std::cerr << " ...success on " << ctor << " .\n " ;
449- // success, the entire function was evalled!
464+
465+ // Success, the entire function was evalled! Apply the results of
466+ // execution to the module.
467+ interface.applyToModule ();
468+
450469 // we can nop the function (which may be used elsewhere)
451470 // and remove the export
452471 auto * exp = wasm.getExport (ctor);
0 commit comments