diff --git a/src/parser/WASMComponentParser.cpp b/src/parser/WASMComponentParser.cpp index 55e8906ac..4aaf86e5b 100644 --- a/src/parser/WASMComponentParser.cpp +++ b/src/parser/WASMComponentParser.cpp @@ -44,6 +44,32 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate uint32_t index; }; + struct CanonLess { + bool operator()(const Walrus::ComponentCanonOptions* first, const Walrus::ComponentCanonOptions* second) const + { + ASSERT(first != nullptr && second != nullptr); + + uint8_t firstEncoding = static_cast(first->encoding()); + uint8_t secondEncoding = static_cast(second->encoding()); + if (firstEncoding != secondEncoding) { + return firstEncoding < secondEncoding; + } + if (first->isAsync() != second->isAsync()) { + return second->isAsync(); + } + if (first->memoryIndex() != second->memoryIndex()) { + return first->memoryIndex() < second->memoryIndex(); + } + if (first->reallocIndex() != second->reallocIndex()) { + return first->reallocIndex() < second->reallocIndex(); + } + if (first->postReturnIndex() != second->postReturnIndex()) { + return first->postReturnIndex() < second->postReturnIndex(); + } + return first->callbackIndex() < second->callbackIndex(); + } + }; + // Depth data for each component. struct ComponentTypeInfo { ComponentTypeInfo(ComponentTypeInfo* parent, Walrus::ComponentType* parentComponentType, Walrus::Component* parentComponent) @@ -51,6 +77,7 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate , parentComponentType(parentComponentType) , parentComponent(parentComponent) , coreInstanceCounter(0) + , canonOptionCounter(0) { } @@ -58,12 +85,14 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate Walrus::ComponentType* parentComponentType; Walrus::Component* parentComponent; uint32_t coreInstanceCounter; + uint32_t canonOptionCounter; std::vector coreFuncTypes; std::vector coreMemories; std::vector coreInstanceTypes; std::vector funcTypes; std::vector componentTypes; std::vector instanceTypes; + std::map m_canonOptions; }; Walrus::ComponentTypeRef::Type getValueType(const ComponentType& type) @@ -151,25 +180,25 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate return refType(type); } - Walrus::CanonicalOptions parseCanonOptions(uint32_t optionCount, ComponentCanonOption* options) + uint32_t parseCanonOptions(uint32_t optionCount, ComponentCanonOption* options) { - Walrus::CanonicalOptions::StringEncoding encoding = Walrus::CanonicalOptions::Utf8; + Walrus::ComponentCanonOptions::StringEncoding encoding = Walrus::ComponentCanonOptions::Utf8; bool isAsync = false; - uint32_t memoryIndex = Walrus::CanonicalOptions::NoIndex; - uint32_t reallocIndex = Walrus::CanonicalOptions::NoIndex; - uint32_t postReturnIndex = Walrus::CanonicalOptions::NoIndex; - uint32_t callbackIndex = Walrus::CanonicalOptions::NoIndex; + uint32_t memoryIndex = Walrus::ComponentCanonOptions::NotDefined; + uint32_t reallocIndex = Walrus::ComponentCanonOptions::NotDefined; + uint32_t postReturnIndex = Walrus::ComponentCanonOptions::NotDefined; + uint32_t callbackIndex = Walrus::ComponentCanonOptions::NotDefined; while (optionCount > 0) { switch (options->option) { case ComponentCanonOption::StrEncUtf8: - encoding = Walrus::CanonicalOptions::Utf8; + encoding = Walrus::ComponentCanonOptions::Utf8; break; case ComponentCanonOption::StrEncUtf16: - encoding = Walrus::CanonicalOptions::Utf16; + encoding = Walrus::ComponentCanonOptions::Utf16; break; case ComponentCanonOption::StrEncLatin1Utf16: - encoding = Walrus::CanonicalOptions::Latin1Utf16; + encoding = Walrus::ComponentCanonOptions::Latin1Utf16; break; case ComponentCanonOption::Memory: memoryIndex = options->index; @@ -190,7 +219,17 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate optionCount--; options++; } - return Walrus::CanonicalOptions(encoding, isAsync, memoryIndex, reallocIndex, postReturnIndex, callbackIndex); + + Walrus::ComponentCanonOptions* canonOptions = new Walrus::ComponentCanonOptions(encoding, isAsync, memoryIndex, reallocIndex, postReturnIndex, callbackIndex); + + auto it = m_currentInfo->m_canonOptions.insert(std::pair(canonOptions, m_currentInfo->canonOptionCounter)); + if (it.second) { + m_currentComponent->pushDeclaration(canonOptions); + return m_currentInfo->canonOptionCounter++; + } + + delete canonOptions; + return it.first->second; } Walrus::ComponentRefCounted* getTypeRef(ComponentSort sort, uint32_t index) @@ -739,7 +778,7 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate ComponentCanonOption* options, Index typeIndex) { - Walrus::CanonicalOptions canonOptions = parseCanonOptions(optionCount, options); + uint32_t canonOptions = parseCanonOptions(optionCount, options); Walrus::ComponentTypeFunc* funcType = m_current->getType(typeIndex)->asTypeFunc(); m_currentComponent->pushDeclaration(new Walrus::ComponentCanonLift(coreFuncIndex, canonOptions, funcType)); m_currentInfo->funcTypes.push_back(funcType); @@ -749,7 +788,7 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate uint32_t optionCount, ComponentCanonOption* options) { - Walrus::CanonicalOptions canonOptions = parseCanonOptions(optionCount, options); + uint32_t canonOptions = parseCanonOptions(optionCount, options); m_currentComponent->pushDeclaration(new Walrus::ComponentCanonLower(funcIndex, canonOptions)); } diff --git a/src/runtime/Component.h b/src/runtime/Component.h index 5febf19c0..da24e1c0d 100644 --- a/src/runtime/Component.h +++ b/src/runtime/Component.h @@ -543,66 +543,12 @@ class ComponentType : public ComponentRefCounted { std::vector m_imports; }; -class CanonicalOptions { -public: - enum StringEncoding { - Utf8, - Utf16, - Latin1Utf16, - }; - - static constexpr uint32_t NoIndex = ~static_cast(0); - - CanonicalOptions(StringEncoding encoding, bool isAsync, uint32_t memoryIndex, - uint32_t reallocIndex, uint32_t postReturnIndex, uint32_t callbackIndex) - : m_encoding(encoding) - , m_isAsync(isAsync) - , m_memoryIndex(memoryIndex) - , m_reallocIndex(reallocIndex) - , m_postReturnIndex(postReturnIndex) - , m_callbackIndex(callbackIndex) - { - } - - StringEncoding encoding() const - { - return m_encoding; - } - - bool isAsync() const - { - return m_isAsync; - } - - uint32_t memoryIndex() const - { - return m_memoryIndex; - } - - uint32_t reallocIndex() const - { - return m_reallocIndex; - } - - uint32_t postReturnIndex() const - { - return m_postReturnIndex; - } - -private: - StringEncoding m_encoding; - bool m_isAsync; - uint32_t m_memoryIndex; - uint32_t m_reallocIndex; - uint32_t m_postReturnIndex; - uint32_t m_callbackIndex; -}; - class ComponentCoreInstantiate; class ComponentInstantiate; class ComponentInstantiateInline; class ComponentAliasExport; class ComponentAliasInline; +class ComponentCanonOptions; class ComponentCanonLift; class ComponentCanonLower; class ComponentCanonType; @@ -617,6 +563,7 @@ class ComponentDeclaration { AliasExportKind, AliasCoreExportKind, AliasInlineKind, + CanonOptionsKind, CanonLiftKind, CanonLowerKind, CanonResourceNew, @@ -672,6 +619,12 @@ class ComponentDeclaration { return reinterpret_cast(this); } + ComponentCanonOptions* asCanonOptions() + { + ASSERT(kind() == CanonOptionsKind); + return reinterpret_cast(this); + } + ComponentCanonLift* asCanonLift() { ASSERT(kind() == CanonLiftKind); @@ -841,9 +794,70 @@ class ComponentAliasInline : public ComponentDeclaration { uint32_t m_exportIndex; }; +class ComponentCanonOptions : public ComponentDeclaration { +public: + enum StringEncoding : uint8_t { + Utf8, + Utf16, + Latin1Utf16, + }; + + static constexpr uint32_t NotDefined = ~static_cast(0); + + ComponentCanonOptions(StringEncoding encoding, bool isAsync, uint32_t memoryIndex, + uint32_t reallocIndex, uint32_t postReturnIndex, uint32_t callbackIndex) + : ComponentDeclaration(CanonOptionsKind) + , m_encoding(encoding) + , m_isAsync(isAsync) + , m_memoryIndex(memoryIndex) + , m_reallocIndex(reallocIndex) + , m_postReturnIndex(postReturnIndex) + , m_callbackIndex(callbackIndex) + { + } + + StringEncoding encoding() const + { + return m_encoding; + } + + bool isAsync() const + { + return m_isAsync; + } + + uint32_t memoryIndex() const + { + return m_memoryIndex; + } + + uint32_t reallocIndex() const + { + return m_reallocIndex; + } + + uint32_t postReturnIndex() const + { + return m_postReturnIndex; + } + + uint32_t callbackIndex() const + { + return m_callbackIndex; + } + +private: + StringEncoding m_encoding; + bool m_isAsync; + uint32_t m_memoryIndex; + uint32_t m_reallocIndex; + uint32_t m_postReturnIndex; + uint32_t m_callbackIndex; +}; + class ComponentCanonLift : public ComponentDeclaration { public: - ComponentCanonLift(uint32_t coreFuncIndex, const CanonicalOptions& options, ComponentTypeFunc* funcType) + ComponentCanonLift(uint32_t coreFuncIndex, uint32_t options, ComponentTypeFunc* funcType) : ComponentDeclaration(CanonLiftKind) , m_options(options) , m_coreFuncIndex(coreFuncIndex) @@ -851,7 +865,7 @@ class ComponentCanonLift : public ComponentDeclaration { { } - const CanonicalOptions& options() const + uint32_t options() const { return m_options; } @@ -867,21 +881,21 @@ class ComponentCanonLift : public ComponentDeclaration { } private: - CanonicalOptions m_options; + uint32_t m_options; uint32_t m_coreFuncIndex; ComponentTypeFunc* m_funcType; }; class ComponentCanonLower : public ComponentDeclaration { public: - ComponentCanonLower(uint32_t funcIndex, const CanonicalOptions& options) + ComponentCanonLower(uint32_t funcIndex, uint32_t options) : ComponentDeclaration(CanonLowerKind) , m_options(options) , m_funcIndex(funcIndex) { } - const CanonicalOptions& options() const + uint32_t options() const { return m_options; } @@ -892,7 +906,7 @@ class ComponentCanonLower : public ComponentDeclaration { } private: - CanonicalOptions m_options; + uint32_t m_options; uint32_t m_funcIndex; }; diff --git a/src/runtime/ComponentInstance.cpp b/src/runtime/ComponentInstance.cpp index 76b3475f2..e09bc8d6f 100644 --- a/src/runtime/ComponentInstance.cpp +++ b/src/runtime/ComponentInstance.cpp @@ -29,9 +29,9 @@ namespace Walrus { DEFINE_GLOBAL_TYPE_INFO(componentInstanceTypeInfo, ComponentInstanceKind); -LoweredFunction* LoweredFunction::createLoweredFunction(Store* store, FunctionType* functionType, LiftedFunction* liftedFunction) +LoweredFunction* LoweredFunction::createLoweredFunction(Store* store, const FunctionType* functionType, LiftedFunction* liftedFunction, CanonOptions* options) { - LoweredFunction* func = new LoweredFunction(functionType, liftedFunction); + LoweredFunction* func = new LoweredFunction(functionType, liftedFunction, options); store->appendExtern(func); return func; } @@ -41,7 +41,7 @@ void LoweredFunction::call(ExecutionState& state, Value* argv, Value* result) ASSERT(0); } -CanonFunction* CanonFunction::createCanonFunction(Store* store, FunctionType* functionType, Type type) +CanonFunction* CanonFunction::createCanonFunction(Store* store, const FunctionType* functionType, Type type) { CanonFunction* func = new CanonFunction(functionType, type); store->appendExtern(func); @@ -322,22 +322,40 @@ void ComponentInstance::aliasInline(ComponentAliasInline* alias) } } -void ComponentInstance::lowerFunction(Store* store, ComponentCanonLower* lower) +void ComponentInstance::liftFunction(Store* store, std::vector& canonOptions, ComponentCanonLift* lift) +{ + CanonOptions* options = canonOptions[lift->options()]; + m_funcs.push_back(new LiftedCoreFunction(m_coreFuncs[lift->coreFuncIndex()], options)); +} + +void ComponentInstance::lowerFunction(Store* store, std::vector& canonOptions, ComponentCanonLower* lower) { -#ifdef ENABLE_WASI LiftedFunction* func = m_funcs[lower->funcIndex()]; - m_coreFuncs.push_back(LoweredFunction::createLoweredFunction(store, func->asLiftedWasiFunction()->functionType(), func)); + CanonOptions* options = canonOptions[lower->options()]; + +#ifdef ENABLE_WASI + if (func->kind() == LiftedFunction::WasiFunctionKind) { + m_coreFuncs.push_back(LoweredFunction::createLoweredFunction(store, func->asLiftedWasiFunction()->functionType(), func, options)); + return; + } #endif /* ENABLE_WASI */ + m_coreFuncs.push_back(LoweredFunction::createLoweredFunction(store, func->asLiftedCoreFunction()->function()->functionType(), func, options)); } -ComponentInstance* ComponentInstance::instantiate(ExecutionState& state, Store* store, DefinedFunctionTypes& functionTypes, Component* component) +ComponentInstance* ComponentInstance::InstantiateContext::instantiate(Component* component, ComponentInstance* parent, ComponentInstantiate* arg) { ComponentInstance* instance = new ComponentInstance(component->type()); + m_store->appendComponentInstance(instance); for (auto it : component->declarations()) { switch (it->kind()) { case ComponentDeclaration::CoreInstantiateKind: { - instance->coreInstantiate(state, store, component, it->asCoreInstantiate()); + instance->coreInstantiate(m_state, m_store, component, it->asCoreInstantiate()); + break; + } + case ComponentDeclaration::InstantiateKind: { + Component* source = component->components()[it->asInstantiate()->componentIndex()]; + instance->m_instances.push_back(instantiate(source, instance, it->asInstantiate())); break; } case ComponentDeclaration::AliasExportKind: { @@ -352,12 +370,25 @@ ComponentInstance* ComponentInstance::instantiate(ExecutionState& state, Store* instance->aliasInline(it->asAliasInline()); break; } + case ComponentDeclaration::CanonOptionsKind: { + ComponentCanonOptions* options = it->asCanonOptions(); + Memory* memory = options->memoryIndex() == ComponentCanonOptions::NotDefined ? nullptr : instance->m_coreMemories[options->memoryIndex()]; + Function* realloc = options->reallocIndex() == ComponentCanonOptions::NotDefined ? nullptr : instance->m_coreFuncs[options->reallocIndex()]; + Function* postReturn = options->postReturnIndex() == ComponentCanonOptions::NotDefined ? nullptr : instance->m_coreFuncs[options->postReturnIndex()]; + Function* callback = options->callbackIndex() == ComponentCanonOptions::NotDefined ? nullptr : instance->m_coreFuncs[options->callbackIndex()]; + instance->m_canonOptions.push_back(new CanonOptions(instance, options->encoding(), options->isAsync(), memory, realloc, postReturn, callback)); + break; + } + case ComponentDeclaration::CanonLiftKind: { + instance->liftFunction(m_store, instance->m_canonOptions, it->asCanonLift()); + break; + } case ComponentDeclaration::CanonLowerKind: { - instance->lowerFunction(store, it->asCanonLower()); + instance->lowerFunction(m_store, instance->m_canonOptions, it->asCanonLower()); break; } case ComponentDeclaration::CanonResourceDrop: { - instance->m_coreFuncs.push_back(CanonFunction::createCanonFunction(store, functionTypes[DefinedFunctionTypes::I32R], CanonFunction::ResourceDrop)); + instance->m_coreFuncs.push_back(CanonFunction::createCanonFunction(m_store, m_functionTypes[DefinedFunctionTypes::I32R], CanonFunction::ResourceDrop)); break; } case ComponentDeclaration::ImportKind: { @@ -365,41 +396,63 @@ ComponentInstance* ComponentInstance::instantiate(ExecutionState& state, Store* ComponentType::External& external = component->type()->imports()[index]; bool success = false; - switch (external.sort) { - case ComponentSort::Instance: { + if (parent != nullptr) { + for (auto& it : arg->arguments()) { + if (it.sort == external.sort && it.name == external.name) { + switch (it.sort) { + case ComponentSort::Func: { + LiftedFunction* func = parent->m_funcs[it.index]; + instance->m_funcs.push_back(func); + func->addRef(); + break; + } + case ComponentSort::Instance: + instance->m_instances.push_back(parent->m_instances[it.index]); + break; + default: + RELEASE_ASSERT_NOT_REACHED(); + break; + } + success = true; + break; + } + } + } + #ifdef ENABLE_WASI - ComponentInstance* importedInstance = wasi02LoadInstance(external, functionTypes); + if (!success && external.sort == ComponentSort::Instance) { + ComponentInstance* importedInstance = wasi02LoadInstance(external, m_functionTypes); if (importedInstance != nullptr) { - store->appendComponentInstance(importedInstance); + m_store->appendComponentInstance(importedInstance); instance->m_instances.push_back(importedInstance); success = true; break; } -#endif /* ENABLE_WASI */ - break; - } - default: - break; } +#endif /* ENABLE_WASI */ if (!success) { std::string message = "Cannot import: "; message.append(external.name); - Trap::throwException(state, message); + Trap::throwException(m_state, message); } break; } default: - // TODO: Implement more declarations. - store->appendComponentInstance(instance); + RELEASE_ASSERT_NOT_REACHED(); return instance; } } - store->appendComponentInstance(instance); return instance; } +ComponentInstance* ComponentInstance::instantiate(ExecutionState& state, Store* store, DefinedFunctionTypes& functionTypes, Component* component) +{ + InstantiateContext context(state, store, functionTypes); + return context.instantiate(component, nullptr, nullptr); +} + ComponentInstance::ComponentInstance(ComponentType* type) : Object(GET_GLOBAL_TYPE_INFO(componentInstanceTypeInfo)) , m_type(type) @@ -413,6 +466,9 @@ ComponentInstance::~ComponentInstance() for (auto it : m_funcs) { it->releaseRef(); } + for (auto it : m_canonOptions) { + delete it; + } } } // namespace Walrus diff --git a/src/runtime/ComponentInstance.h b/src/runtime/ComponentInstance.h index 04b277596..6129d9582 100644 --- a/src/runtime/ComponentInstance.h +++ b/src/runtime/ComponentInstance.h @@ -22,25 +22,84 @@ namespace Walrus { +class ComponentInstance; + +class CanonOptions { +public: + CanonOptions(ComponentInstance* instance, ComponentCanonOptions::StringEncoding encoding, bool isAsync, + Memory* memory, Function* realloc, Function* postReturn, Function* callback) + : m_instance(instance) + , m_encoding(encoding) + , m_isAsync(isAsync) + , m_memory(memory) + , m_realloc(realloc) + , m_postReturn(postReturn) + , m_callback(callback) + { + } + + ComponentInstance* instance() const + { + return m_instance; + } + + ComponentCanonOptions::StringEncoding encoding() const + { + return m_encoding; + } + + bool isAsync() const + { + return m_isAsync; + } + + Memory* memory() const + { + return m_memory; + } + + Function* realloc() const + { + return m_realloc; + } + + Function* postReturn() const + { + return m_postReturn; + } + + Function* callback() const + { + return m_callback; + } + +private: + ComponentInstance* m_instance; + ComponentCanonOptions::StringEncoding m_encoding; + bool m_isAsync; + Memory* m_memory; + Function* m_realloc; + Function* m_postReturn; + Function* m_callback; +}; + +class LiftedCoreFunction; #ifdef ENABLE_WASI class LiftedWasiFunction; #endif /* ENABLE_WASI */ class LiftedFunction { public: - enum Type { - CoreFunction, + enum Kind { + CoreFunctionKind, #ifdef ENABLE_WASI - WasiFunction, + WasiFunctionKind, #endif /* ENABLE_WASI */ }; virtual ~LiftedFunction() {} - Type type() const - { - return m_type; - } + virtual Kind kind() const = 0; void addRef() { @@ -55,26 +114,59 @@ class LiftedFunction { } } + LiftedCoreFunction* asLiftedCoreFunction() + { + ASSERT(kind() == CoreFunctionKind); + return reinterpret_cast(this); + } + #ifdef ENABLE_WASI LiftedWasiFunction* asLiftedWasiFunction() { - ASSERT(type() == WasiFunction); + ASSERT(kind() == WasiFunctionKind); return reinterpret_cast(this); } #endif /* ENABLE_WASI */ protected: - LiftedFunction(Type type) - : m_type(type) - , m_refCount(1) + LiftedFunction() + : m_refCount(1) { } private: - Type m_type; size_t m_refCount; }; +class LiftedCoreFunction : public LiftedFunction { +public: + LiftedCoreFunction(Function* function, CanonOptions* options) + : LiftedFunction() + , m_function(function) + , m_options(options) + { + } + + virtual Kind kind() const override + { + return CoreFunctionKind; + } + + Function* function() const + { + return m_function; + } + + CanonOptions* options() const + { + return m_options; + } + +private: + Function* m_function; + CanonOptions* m_options; +}; + #ifdef ENABLE_WASI class LiftedWasiFunction : public LiftedFunction { @@ -96,12 +188,17 @@ class LiftedWasiFunction : public LiftedFunction { }; LiftedWasiFunction(Type type, FunctionType* functionType) - : LiftedFunction(WasiFunction) + : LiftedFunction() , m_type(type) , m_functionType(functionType) { } + virtual Kind kind() const override + { + return WasiFunctionKind; + } + FunctionType* functionType() const { return m_functionType; @@ -116,18 +213,30 @@ class LiftedWasiFunction : public LiftedFunction { class LoweredFunction : public NativeFunction { public: - static LoweredFunction* createLoweredFunction(Store* store, FunctionType* functionType, LiftedFunction* liftedFunction); + static LoweredFunction* createLoweredFunction(Store* store, const FunctionType* functionType, LiftedFunction* liftedFunction, CanonOptions* options); + + virtual Kind kind() const override + { + return LoweredFunctionKind; + } + + CanonOptions* options() + { + return m_options; + } virtual void call(ExecutionState& state, Value* argv, Value* result) override; private: - LoweredFunction(FunctionType* functionType, LiftedFunction* liftedFunction) + LoweredFunction(const FunctionType* functionType, LiftedFunction* liftedFunction, CanonOptions* options) : NativeFunction(functionType) , m_liftedFunction(liftedFunction) + , m_options(options) { } LiftedFunction* m_liftedFunction; + CanonOptions* m_options; }; class CanonFunction : public NativeFunction { @@ -138,17 +247,22 @@ class CanonFunction : public NativeFunction { ResourceRep, }; - static CanonFunction* createCanonFunction(Store* store, FunctionType* functionType, Type type); + static CanonFunction* createCanonFunction(Store* store, const FunctionType* functionType, Type type); Type type() const { return m_type; } + virtual Kind kind() const override + { + return CanonFunctionKind; + } + virtual void call(ExecutionState& state, Value* argv, Value* result) override; private: - CanonFunction(FunctionType* functionType, Type type) + CanonFunction(const FunctionType* functionType, Type type) : NativeFunction(functionType) , m_type(type) { @@ -174,14 +288,42 @@ class ComponentInstance : public Object { return m_type; } + LiftedFunction* getFunction(uint32_t index) + { + return m_funcs[index]; + } + + ComponentInstance* getInstance(uint32_t index) + { + return m_instances[index]; + } + private: ComponentInstance(ComponentType* type); + class InstantiateContext { + public: + InstantiateContext(ExecutionState& state, Store* store, DefinedFunctionTypes& functionTypes) + : m_state(state) + , m_store(store) + , m_functionTypes(functionTypes) + { + } + + ComponentInstance* instantiate(Component* component, ComponentInstance* parent, ComponentInstantiate* arg); + + private: + ExecutionState& m_state; + Store* m_store; + DefinedFunctionTypes& m_functionTypes; + }; + void coreInstantiate(ExecutionState& state, Store* store, Component* component, ComponentCoreInstantiate* instantiate); void aliasExport(ComponentAliasExport* alias); void aliasCoreExport(ComponentAliasExport* alias); void aliasInline(ComponentAliasInline* alias); - void lowerFunction(Store* store, ComponentCanonLower* lower); + void liftFunction(Store* store, std::vector& canonOptions, ComponentCanonLift* lift); + void lowerFunction(Store* store, std::vector& canonOptions, ComponentCanonLower* lower); ComponentType* m_type; std::vector m_coreFuncs; @@ -192,6 +334,7 @@ class ComponentInstance : public Object { std::vector m_coreInstances; std::vector m_funcs; std::vector m_instances; + std::vector m_canonOptions; }; } // namespace Walrus diff --git a/src/runtime/Function.cpp b/src/runtime/Function.cpp index 0460da1e6..6ce4812bf 100644 --- a/src/runtime/Function.cpp +++ b/src/runtime/Function.cpp @@ -28,7 +28,7 @@ namespace Walrus { DEFINE_GLOBAL_TYPE_INFO(functionTypeInfo, FunctionKind); -Function::Function(FunctionType* functionType) +Function::Function(const FunctionType* functionType) : Extern(functionType->subTypeList() != nullptr ? functionType->subTypeList() : GET_GLOBAL_TYPE_INFO(functionTypeInfo)) , m_functionType(functionType) { diff --git a/src/runtime/Function.h b/src/runtime/Function.h index 95592e134..ac34fb491 100644 --- a/src/runtime/Function.h +++ b/src/runtime/Function.h @@ -48,42 +48,42 @@ class WasiFunction; class Function : public Extern { public: + enum Kind { + DefinedFunctionKind, + ImportedFunctionKind, + WasiFunctionKind, + LoweredFunctionKind, + CanonFunctionKind, + }; + const FunctionType* functionType() const { return m_functionType; } + virtual Kind kind() const = 0; virtual void call(ExecutionState& state, Value* argv, Value* result) = 0; virtual void interpreterCall(ExecutionState& state, uint8_t* bp, ByteCodeStackOffset* offsets, uint16_t parameterOffsetCount, uint16_t resultOffsetCount) = 0; - virtual bool isDefinedFunction() const - { - return false; - } - - virtual bool isImportedFunction() const - { - return false; - } - - virtual bool isWasiFunction() const + DefinedFunction* asDefinedFunction() { - return false; + ASSERT(kind() == DefinedFunctionKind); + return reinterpret_cast(this); } - DefinedFunction* asDefinedFunction() + LoweredFunction* asLoweredFunction() { - ASSERT(isDefinedFunction()); - return reinterpret_cast(this); + ASSERT(kind() == LoweredFunctionKind); + return reinterpret_cast(this); } WasiFunction* asWasiFunction() { - ASSERT(isWasiFunction()); + ASSERT(kind() == WasiFunctionKind); return reinterpret_cast(this); } protected: - Function(FunctionType* functionType); + Function(const FunctionType* functionType); const FunctionType* m_functionType; }; @@ -99,10 +99,11 @@ class DefinedFunction : public Function { ModuleFunction* moduleFunction() const { return m_moduleFunction; } Instance* instance() const { return m_instance; } - virtual bool isDefinedFunction() const override + virtual Kind kind() const override { - return true; + return DefinedFunctionKind; } + virtual void call(ExecutionState& state, Value* argv, Value* result) override; virtual void interpreterCall(ExecutionState& state, uint8_t* bp, ByteCodeStackOffset* offsets, uint16_t parameterOffsetCount, uint16_t resultOffsetCount) override; @@ -138,7 +139,7 @@ class NativeFunction : public Function { uint16_t parameterOffsetCount, uint16_t resultOffsetCount) override; protected: - NativeFunction(FunctionType* functionType) + NativeFunction(const FunctionType* functionType) : Function(functionType) { } @@ -153,6 +154,11 @@ class ImportedFunction : public NativeFunction { ImportedFunctionCallback callback, void* data); + virtual Kind kind() const override + { + return ImportedFunctionKind; + } + virtual void call(ExecutionState& state, Value* argv, Value* result) override; protected: @@ -177,9 +183,9 @@ class WasiFunction : public NativeFunction { FunctionType* functionType, WasiFunctionCallback callback); - virtual bool isWasiFunction() const override + virtual Kind kind() const override { - return true; + return WasiFunctionKind; } void setRunningInstance(Instance* instance) diff --git a/src/runtime/Module.cpp b/src/runtime/Module.cpp index 9fb9fae5b..dbfb67078 100644 --- a/src/runtime/Module.cpp +++ b/src/runtime/Module.cpp @@ -180,7 +180,7 @@ Instance* Module::instantiate(ExecutionState& state, const ExternVector& imports } instance->m_functions[funcIndex] = imports[i]->asFunction(); - if (imports[i]->asFunction()->isWasiFunction()) { + if (imports[i]->asFunction()->kind() == Function::WasiFunctionKind) { instance->m_functions[funcIndex]->asWasiFunction()->setRunningInstance(instance); } funcIndex++; diff --git a/src/shell/Shell.cpp b/src/shell/Shell.cpp index 16e2e09f2..ff6b31faa 100644 --- a/src/shell/Shell.cpp +++ b/src/shell/Shell.cpp @@ -389,6 +389,32 @@ static Trap::TrapResult executeWASMComponent(Store* store, DefinedFunctionTypes& return trap.run([](ExecutionState& state, void* d) { RunData* data = reinterpret_cast(d); ComponentInstance* instance = ComponentInstance::instantiate(state, data->store, data->functionTypes, data->component); + for (auto& it : instance->type()->exports()) { + if (it.sort == ComponentSort::Instance && it.name == "wasi:cli/run@0.2.6") { + instance = instance->getInstance(it.exportIndex); + break; + } + } + + Function* run = nullptr; + if (instance != nullptr) { + for (auto& it : instance->type()->exports()) { + if (it.sort == ComponentSort::Func && it.name == "run") { + LiftedFunction* func = instance->getFunction(it.exportIndex); + if (func->kind() == LiftedFunction::CoreFunctionKind) { + run = func->asLiftedCoreFunction()->function(); + } + break; + } + } + } + + if (run != nullptr) { + Value resultValue[1]; + run->call(state, nullptr, resultValue); + } else { + printf("Note: Cannot execute component, missing run()\n"); + } }, &data); }