diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pass.h | 8 | ||||
-rw-r--r-- | src/passes/AbstractTypeRefining.cpp | 10 | ||||
-rw-r--r-- | src/passes/GlobalTypeOptimization.cpp | 14 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 51 |
4 files changed, 25 insertions, 58 deletions
diff --git a/src/pass.h b/src/pass.h index 8d81fce8e..daed8b6ab 100644 --- a/src/pass.h +++ b/src/pass.h @@ -212,14 +212,6 @@ struct PassOptions { // but we also want to keep types of things on the boundary unchanged. For // example, we should not change an exported function's signature, as the // outside may need that type to properly call the export. - // - // * Since the goal of closedWorld is to optimize types aggressively but - // types on the module boundary cannot be changed, we assume the producer - // has made a mistake and we consider it a validation error if any user - // defined types besides the types of imported or exported functions - // themselves appear on the module boundary. For example, no user defined - // struct type may be a parameter or result of an exported function. This - // error may be relaxed or made more configurable in the future. bool closedWorld = false; // Whether to try to preserve debug info through, which are special calls. bool debugInfo = false; diff --git a/src/passes/AbstractTypeRefining.cpp b/src/passes/AbstractTypeRefining.cpp index 313ad5f4d..509448851 100644 --- a/src/passes/AbstractTypeRefining.cpp +++ b/src/passes/AbstractTypeRefining.cpp @@ -106,6 +106,16 @@ struct AbstractTypeRefining : public Pass { } } + // Assume all public types are created, which makes them non-abstract and + // hence ignored below. + // TODO: In principle we could assume such types are not created outside the + // module, given closed world, but we'd also need to make sure that + // we don't need to make any changes to public types that refer to + // them. + for (auto type : ModuleUtils::getPublicHeapTypes(*module)) { + createdTypes.insert(type); + } + SubTypes subTypes(*module); // Compute createdTypesOrSubTypes by starting with the created types and diff --git a/src/passes/GlobalTypeOptimization.cpp b/src/passes/GlobalTypeOptimization.cpp index 1f0da2595..74107f9cd 100644 --- a/src/passes/GlobalTypeOptimization.cpp +++ b/src/passes/GlobalTypeOptimization.cpp @@ -198,6 +198,20 @@ struct GlobalTypeOptimization : public Pass { continue; } + // The propagation analysis ensures we update immutability in all + // supers and subs in concert, but it does not take into account + // visibility, so do that here: we can only become immutable if the + // parent can as well. + auto super = type.getDeclaredSuperType(); + if (super && !canBecomeImmutable.count(*super)) { + // No entry in canBecomeImmutable means nothing in the parent can + // become immutable. We don't need to check the specific field index, + // because visibility affects them all equally (i.e., if it is public + // then no field can be changed, and if it is private then this field + // can be changed, and perhaps more). + continue; + } + // No set exists. Mark it as something we can make immutable. auto& vec = canBecomeImmutable[type]; vec.resize(i + 1); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 0184e3284..d1ca5220c 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -63,7 +63,6 @@ struct ValidationInfo { bool validateWeb; bool validateGlobally; bool quiet; - bool closedWorld; std::atomic<bool> valid; @@ -4135,46 +4134,6 @@ static void validateFeatures(Module& module, ValidationInfo& info) { } } -static void validateClosedWorldInterface(Module& module, ValidationInfo& info) { - // Error if there are any publicly exposed heap types beyond the types of - // publicly exposed functions. Note that we must include all types in the rec - // groups that are used, as if a type if public then all types in its rec - // group are as well. - std::unordered_set<RecGroup> publicRecGroups; - ModuleUtils::iterImportedFunctions(module, [&](Function* func) { - publicRecGroups.insert(func->type.getRecGroup()); - }); - for (auto& ex : module.exports) { - if (ex->kind == ExternalKind::Function) { - publicRecGroups.insert(module.getFunction(ex->value)->type.getRecGroup()); - } - } - - std::unordered_set<HeapType> publicTypes; - for (auto& group : publicRecGroups) { - for (auto type : group) { - publicTypes.insert(type); - } - } - - // Ignorable public types are public, but we can ignore them for purposes of - // erroring here: It is always ok that they are public. - auto ignorable = getIgnorablePublicTypes(); - - for (auto type : ModuleUtils::getPublicHeapTypes(module)) { - if (!publicTypes.count(type) && !ignorable.count(type)) { - auto name = type.toString(); - if (auto it = module.typeNames.find(type); it != module.typeNames.end()) { - name = it->second.name.toString(); - } - info.fail("publicly exposed type disallowed with a closed world: $" + - name, - type, - nullptr); - } - } -} - // TODO: If we want the validator to be part of libwasm rather than libpasses, // then Using PassRunner::getPassDebug causes a circular dependence. We should // fix that, perhaps by moving some of the pass infrastructure into libsupport. @@ -4183,7 +4142,6 @@ bool WasmValidator::validate(Module& module, Flags flags) { info.validateWeb = (flags & Web) != 0; info.validateGlobally = (flags & Globally) != 0; info.quiet = (flags & Quiet) != 0; - info.closedWorld = (flags & ClosedWorld) != 0; // Parallel function validation. PassRunner runner(&module); @@ -4210,9 +4168,6 @@ bool WasmValidator::validate(Module& module, Flags flags) { validateStart(module, info); validateModuleMaps(module, info); validateFeatures(module, info); - if (info.closedWorld) { - validateClosedWorldInterface(module, info); - } } // Validate additional internal IR details when in pass-debug mode. @@ -4231,11 +4186,7 @@ bool WasmValidator::validate(Module& module, Flags flags) { } bool WasmValidator::validate(Module& module, const PassOptions& options) { - Flags flags = options.validateGlobally ? Globally : Minimal; - if (options.closedWorld) { - flags |= ClosedWorld; - } - return validate(module, flags); + return validate(module, options.validateGlobally ? Globally : Minimal); } bool WasmValidator::validate(Function* func, Module& module, Flags flags) { |