From e25b0a62754e9f223784dc3b41aae4dc0dca501f Mon Sep 17 00:00:00 2001 From: Andy Friesen Date: Fri, 18 Aug 2023 11:15:41 -0700 Subject: [PATCH 1/5] Sync to upstream/release/591 (#1012) * Fix a use-after-free bug in the new type cloning algorithm * Tighten up the type of `coroutine.wrap`. It is now `(f: (A...) -> R...) -> ((A...) -> R...)` * Break `.luaurc` out into a separate library target `Luau.Config`. This makes it easier for applications to reason about config files without also depending on the type inference engine. * Move typechecking limits into `FrontendOptions`. This allows embedders more finely-grained control over autocomplete's internal time limits. * Fix stability issue with debugger onprotectederror callback allowing break in non-yieldable contexts New solver: * Initial work toward [Local Type Inference](https://github.com/Roblox/luau/blob/0e1082108fd6fb3a32dfdf5f1766ea3fc1391328/rfcs/local-type-inference.md) * Introduce a new subtyping test. This will be much nicer than the old test because it is completely separate both from actual type inference and from error reporting. Native code generation: * Added function to compute iterated dominance frontier * Optimize barriers in SET_UPVALUE when tag is known * Cache lua_State::global in a register on A64 * Optimize constant stores in A64 lowering * Track table array size state to optimize array size checks * Add split tag/value store into a VM register * Check that spills can outlive the block only in specific conditions --------- Co-authored-by: Arseny Kapoulkine Co-authored-by: Vyacheslav Egorov --- Analysis/include/Luau/ConstraintSolver.h | 2 - Analysis/include/Luau/Frontend.h | 6 + Analysis/include/Luau/Module.h | 1 + Analysis/include/Luau/Subtyping.h | 63 ++++ Analysis/include/Luau/Type.h | 9 + Analysis/include/Luau/TypeUtils.h | 24 ++ Analysis/src/Autocomplete.cpp | 3 +- Analysis/src/Clone.cpp | 37 +- Analysis/src/ConstraintSolver.cpp | 35 -- Analysis/src/EmbeddedBuiltinDefinitions.cpp | 3 +- Analysis/src/Frontend.cpp | 119 ++++-- Analysis/src/Simplify.cpp | 12 +- Analysis/src/Subtyping.cpp | 344 +++++++++++++++++ Analysis/src/Type.cpp | 17 +- CMakeLists.txt | 7 +- CodeGen/include/Luau/IrAnalysis.h | 41 ++ CodeGen/include/Luau/IrData.h | 17 +- CodeGen/include/Luau/IrUtils.h | 1 - CodeGen/src/CodeGenA64.cpp | 5 +- CodeGen/src/CodeGenLower.h | 2 +- CodeGen/src/EmitCommonA64.h | 19 +- CodeGen/src/EmitCommonX64.h | 5 - CodeGen/src/IrAnalysis.cpp | 74 ++++ CodeGen/src/IrBuilder.cpp | 2 + CodeGen/src/IrDump.cpp | 6 +- CodeGen/src/IrLoweringA64.cpp | 155 +++++--- CodeGen/src/IrLoweringA64.h | 2 +- CodeGen/src/IrLoweringX64.cpp | 75 +++- CodeGen/src/IrLoweringX64.h | 2 +- CodeGen/src/IrRegAllocA64.cpp | 5 - CodeGen/src/IrRegAllocA64.h | 2 - CodeGen/src/IrRegAllocX64.cpp | 7 +- CodeGen/src/IrTranslation.cpp | 15 +- CodeGen/src/IrTranslation.h | 35 -- CodeGen/src/IrUtils.cpp | 14 +- CodeGen/src/IrValueLocationTracking.cpp | 1 + CodeGen/src/OptimizeConstProp.cpp | 204 +++++++--- Common/include/Luau/BytecodeUtils.h | 42 +++ Compiler/include/Luau/BytecodeBuilder.h | 1 + Compiler/src/BytecodeBuilder.cpp | 72 ++-- Compiler/src/Compiler.cpp | 15 +- Compiler/src/CostModel.cpp | 10 +- {Analysis => Config}/include/Luau/Config.h | 0 .../include/Luau/LinterConfig.h | 2 + {Analysis => Config}/src/Config.cpp | 0 {Analysis => Config}/src/LinterConfig.cpp | 0 Makefile | 20 +- Sources.cmake | 39 +- VM/src/ldo.cpp | 6 +- VM/src/lmathlib.cpp | 6 +- tests/Autocomplete.test.cpp | 2 - tests/Compiler.test.cpp | 2 - tests/Conformance.test.cpp | 94 ++++- tests/CostModel.test.cpp | 4 - tests/Error.test.cpp | 21 ++ tests/IrBuilder.test.cpp | 189 +++++++++- tests/Module.test.cpp | 38 +- tests/Subtyping.test.cpp | 352 ++++++++++++++++++ tests/TypeInfer.functions.test.cpp | 65 ++++ tests/TypeInfer.oop.test.cpp | 2 +- tests/conformance/native.lua | 18 + tests/conformance/tmerror.lua | 26 ++ tools/faillist.txt | 3 + 63 files changed, 1976 insertions(+), 424 deletions(-) create mode 100644 Analysis/include/Luau/Subtyping.h create mode 100644 Analysis/src/Subtyping.cpp create mode 100644 Common/include/Luau/BytecodeUtils.h rename {Analysis => Config}/include/Luau/Config.h (100%) rename {Analysis => Config}/include/Luau/LinterConfig.h (99%) rename {Analysis => Config}/src/Config.cpp (100%) rename {Analysis => Config}/src/LinterConfig.cpp (100%) create mode 100644 tests/Subtyping.test.cpp diff --git a/Analysis/include/Luau/ConstraintSolver.h b/Analysis/include/Luau/ConstraintSolver.h index 47effcea..76520b2c 100644 --- a/Analysis/include/Luau/ConstraintSolver.h +++ b/Analysis/include/Luau/ConstraintSolver.h @@ -279,8 +279,6 @@ private: TypeId errorRecoveryType() const; TypePackId errorRecoveryTypePack() const; - TypeId unionOfTypes(TypeId a, TypeId b, NotNull scope, bool unifyFreeTypes); - TypePackId anyifyModuleReturnTypePackGenerics(TypePackId tp); void throwTimeLimitError(); diff --git a/Analysis/include/Luau/Frontend.h b/Analysis/include/Luau/Frontend.h index 5853eb32..3404c6a2 100644 --- a/Analysis/include/Luau/Frontend.h +++ b/Analysis/include/Luau/Frontend.h @@ -100,6 +100,12 @@ struct FrontendOptions std::optional enabledLintWarnings; std::shared_ptr cancellationToken; + + // Time limit for typechecking a single module + std::optional moduleTimeLimitSec; + + // When true, some internal complexity limits will be scaled down for modules that miss the limit set by moduleTimeLimitSec + bool applyInternalLimitScaling = false; }; struct CheckResult diff --git a/Analysis/include/Luau/Module.h b/Analysis/include/Luau/Module.h index cb761714..d647750f 100644 --- a/Analysis/include/Luau/Module.h +++ b/Analysis/include/Luau/Module.h @@ -111,6 +111,7 @@ struct Module LintResult lintResult; Mode mode; SourceCode::Type type; + double checkDurationSec = 0.0; bool timeout = false; bool cancelled = false; diff --git a/Analysis/include/Luau/Subtyping.h b/Analysis/include/Luau/Subtyping.h new file mode 100644 index 00000000..9ebdfc16 --- /dev/null +++ b/Analysis/include/Luau/Subtyping.h @@ -0,0 +1,63 @@ +// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details +#pragma once + +#include "Luau/Type.h" + +#include +#include + +namespace Luau +{ + +template +struct TryPair; + +class Normalizer; +struct NormalizedType; + +struct SubtypingGraph +{ + // Did the test succeed? + bool isSubtype = false; + bool isErrorSuppressing = false; + bool normalizationTooComplex = false; + + // If so, what constraints are implied by this relation? + // If not, what happened? + + SubtypingGraph and_(const SubtypingGraph& other); + SubtypingGraph or_(const SubtypingGraph& other); + + static SubtypingGraph and_(const std::vector& results); + static SubtypingGraph or_(const std::vector& results); +}; + +struct Subtyping +{ + NotNull builtinTypes; + NotNull normalizer; + + // TODO cache + // TODO cyclic types + // TODO recursion limits + + SubtypingGraph isSubtype(TypeId subTy, TypeId superTy); + SubtypingGraph isSubtype(TypePackId subTy, TypePackId superTy); + +private: + template + SubtypingGraph isSubtype(const TryPair& pair); + + SubtypingGraph isSubtype(TypeId subTy, const UnionType* superUnion); + SubtypingGraph isSubtype(const UnionType* subUnion, TypeId superTy); + SubtypingGraph isSubtype(TypeId subTy, const IntersectionType* superIntersection); + SubtypingGraph isSubtype(const IntersectionType* subIntersection, TypeId superTy); + SubtypingGraph isSubtype(const PrimitiveType* subPrim, const PrimitiveType* superPrim); + SubtypingGraph isSubtype(const SingletonType* subSingleton, const PrimitiveType* superPrim); + SubtypingGraph isSubtype(const SingletonType* subSingleton, const SingletonType* superSingleton); + SubtypingGraph isSubtype(const FunctionType* subFunction, const FunctionType* superFunction); + + SubtypingGraph isSubtype(const NormalizedType* subNorm, const NormalizedType* superNorm); +}; + +} // namespace Luau diff --git a/Analysis/include/Luau/Type.h b/Analysis/include/Luau/Type.h index c152fc02..cc88d54b 100644 --- a/Analysis/include/Luau/Type.h +++ b/Analysis/include/Luau/Type.h @@ -733,9 +733,17 @@ struct Type final using SeenSet = std::set>; bool areEqual(SeenSet& seen, const Type& lhs, const Type& rhs); +enum class FollowOption +{ + Normal, + DisableLazyTypeThunks, +}; + // Follow BoundTypes until we get to something real TypeId follow(TypeId t); +TypeId follow(TypeId t, FollowOption followOption); TypeId follow(TypeId t, const void* context, TypeId (*mapper)(const void*, TypeId)); +TypeId follow(TypeId t, FollowOption followOption, const void* context, TypeId (*mapper)(const void*, TypeId)); std::vector flattenIntersection(TypeId ty); @@ -818,6 +826,7 @@ public: const TypeId optionalNumberType; const TypeId optionalStringType; + const TypePackId emptyTypePack; const TypePackId anyTypePack; const TypePackId neverTypePack; const TypePackId uninhabitableTypePack; diff --git a/Analysis/include/Luau/TypeUtils.h b/Analysis/include/Luau/TypeUtils.h index 793415ee..c360e4bc 100644 --- a/Analysis/include/Luau/TypeUtils.h +++ b/Analysis/include/Luau/TypeUtils.h @@ -101,6 +101,30 @@ ErrorSuppression shouldSuppressErrors(NotNull normalizer, TypeId ty1 */ ErrorSuppression shouldSuppressErrors(NotNull normalizer, TypePackId tp1, TypePackId tp2); +// Similar to `std::optional>`, but whose `sizeof()` is the same as `std::pair` +// and cooperates with C++'s `if (auto p = ...)` syntax without the extra fatness of `std::optional`. +template +struct TryPair { + A first; + B second; + + operator bool() const + { + return bool(first) && bool(second); + } +}; + +template +TryPair get2(Ty one, Ty two) +{ + const A* a = get(one); + const B* b = get(two); + if (a && b) + return {a, b}; + else + return {nullptr, nullptr}; +} + template const T* get(std::optional ty) { diff --git a/Analysis/src/Autocomplete.cpp b/Analysis/src/Autocomplete.cpp index eaf47b77..9b6f4db7 100644 --- a/Analysis/src/Autocomplete.cpp +++ b/Analysis/src/Autocomplete.cpp @@ -13,7 +13,6 @@ #include LUAU_FASTFLAG(DebugLuauReadWriteProperties) -LUAU_FASTFLAGVARIABLE(LuauDisableCompletionOutsideQuotes, false) LUAU_FASTFLAGVARIABLE(LuauAnonymousAutofilled1, false); LUAU_FASTFLAGVARIABLE(LuauAutocompleteLastTypecheck, false) LUAU_FASTFLAGVARIABLE(LuauAutocompleteHideSelfArg, false) @@ -1345,7 +1344,7 @@ static std::optional autocompleteStringParams(const Source return std::nullopt; } - if (FFlag::LuauDisableCompletionOutsideQuotes && !nodes.back()->is()) + if (!nodes.back()->is()) { if (nodes.back()->location.end == position || nodes.back()->location.begin == position) { diff --git a/Analysis/src/Clone.cpp b/Analysis/src/Clone.cpp index 66bd5e8e..ad96527e 100644 --- a/Analysis/src/Clone.cpp +++ b/Analysis/src/Clone.cpp @@ -4,6 +4,7 @@ #include "Luau/NotNull.h" #include "Luau/RecursionCounter.h" #include "Luau/TxnLog.h" +#include "Luau/Type.h" #include "Luau/TypePack.h" #include "Luau/Unifiable.h" @@ -14,7 +15,7 @@ LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution) LUAU_FASTINTVARIABLE(LuauTypeCloneRecursionLimit, 300) LUAU_FASTFLAGVARIABLE(LuauCloneCyclicUnions, false) -LUAU_FASTFLAGVARIABLE(LuauStacklessTypeClone, false) +LUAU_FASTFLAGVARIABLE(LuauStacklessTypeClone2, false) LUAU_FASTINTVARIABLE(LuauTypeCloneIterationLimit, 100'000) namespace Luau @@ -115,6 +116,7 @@ private: std::optional find(TypeId ty) const { + ty = follow(ty, FollowOption::DisableLazyTypeThunks); if (auto it = types->find(ty); it != types->end()) return it->second; return std::nullopt; @@ -122,6 +124,7 @@ private: std::optional find(TypePackId tp) const { + tp = follow(tp); if (auto it = packs->find(tp); it != packs->end()) return it->second; return std::nullopt; @@ -143,24 +146,17 @@ private: private: TypeId shallowClone(TypeId ty) { + // We want to [`Luau::follow`] but without forcing the expansion of [`LazyType`]s. + ty = follow(ty, FollowOption::DisableLazyTypeThunks); + if (auto clone = find(ty)) return *clone; else if (ty->persistent) return ty; - // We want to [`Luau::follow`] but without forcing the expansion of [`LazyType`]s. - TypeId target = nullptr; - if (auto bt = get(ty)) - target = bt->boundTo; - else if (auto tt = get(ty); tt && tt->boundTo) - target = *tt->boundTo; - else - { - target = arena->addType(ty->ty); - asMutable(target)->documentationSymbol = ty->documentationSymbol; - } + TypeId target = arena->addType(ty->ty); + asMutable(target)->documentationSymbol = ty->documentationSymbol; - LUAU_ASSERT(target); (*types)[ty] = target; queue.push_back(target); return target; @@ -168,18 +164,15 @@ private: TypePackId shallowClone(TypePackId tp) { + tp = follow(tp); + if (auto clone = find(tp)) return *clone; else if (tp->persistent) return tp; - TypePackId target; - if (auto btp = get(tp)) - target = btp->boundTo; - else - target = arena->addTypePack(tp->ty); + TypePackId target = arena->addTypePack(tp->ty); - LUAU_ASSERT(target); (*packs)[tp] = target; queue.push_back(target); return target; @@ -883,7 +876,7 @@ TypePackId clone(TypePackId tp, TypeArena& dest, CloneState& cloneState) if (tp->persistent) return tp; - if (FFlag::LuauStacklessTypeClone) + if (FFlag::LuauStacklessTypeClone2) { TypeCloner2 cloner{NotNull{&dest}, cloneState.builtinTypes, NotNull{&cloneState.seenTypes}, NotNull{&cloneState.seenTypePacks}}; return cloner.clone(tp); @@ -909,7 +902,7 @@ TypeId clone(TypeId typeId, TypeArena& dest, CloneState& cloneState) if (typeId->persistent) return typeId; - if (FFlag::LuauStacklessTypeClone) + if (FFlag::LuauStacklessTypeClone2) { TypeCloner2 cloner{NotNull{&dest}, cloneState.builtinTypes, NotNull{&cloneState.seenTypes}, NotNull{&cloneState.seenTypePacks}}; return cloner.clone(typeId); @@ -938,7 +931,7 @@ TypeId clone(TypeId typeId, TypeArena& dest, CloneState& cloneState) TypeFun clone(const TypeFun& typeFun, TypeArena& dest, CloneState& cloneState) { - if (FFlag::LuauStacklessTypeClone) + if (FFlag::LuauStacklessTypeClone2) { TypeCloner2 cloner{NotNull{&dest}, cloneState.builtinTypes, NotNull{&cloneState.seenTypes}, NotNull{&cloneState.seenTypePacks}}; diff --git a/Analysis/src/ConstraintSolver.cpp b/Analysis/src/ConstraintSolver.cpp index e1291eeb..78dc0d54 100644 --- a/Analysis/src/ConstraintSolver.cpp +++ b/Analysis/src/ConstraintSolver.cpp @@ -2727,41 +2727,6 @@ TypePackId ConstraintSolver::errorRecoveryTypePack() const return builtinTypes->errorRecoveryTypePack(); } -TypeId ConstraintSolver::unionOfTypes(TypeId a, TypeId b, NotNull scope, bool unifyFreeTypes) -{ - a = follow(a); - b = follow(b); - - if (unifyFreeTypes && (get(a) || get(b))) - { - Unifier u{normalizer, scope, Location{}, Covariant}; - u.enableNewSolver(); - u.tryUnify(b, a); - - if (u.errors.empty()) - { - u.log.commit(); - return a; - } - else - { - return builtinTypes->errorRecoveryType(builtinTypes->anyType); - } - } - - if (*a == *b) - return a; - - std::vector types = reduceUnion({a, b}); - if (types.empty()) - return builtinTypes->neverType; - - if (types.size() == 1) - return types[0]; - - return arena->addType(UnionType{types}); -} - TypePackId ConstraintSolver::anyifyModuleReturnTypePackGenerics(TypePackId tp) { tp = follow(tp); diff --git a/Analysis/src/EmbeddedBuiltinDefinitions.cpp b/Analysis/src/EmbeddedBuiltinDefinitions.cpp index dfc6ff07..65b04d62 100644 --- a/Analysis/src/EmbeddedBuiltinDefinitions.cpp +++ b/Analysis/src/EmbeddedBuiltinDefinitions.cpp @@ -148,8 +148,7 @@ declare coroutine: { resume: (co: thread, A...) -> (boolean, R...), running: () -> thread, status: (co: thread) -> "dead" | "running" | "normal" | "suspended", - -- FIXME: This technically returns a function, but we can't represent this yet. - wrap: (f: (A...) -> R...) -> any, + wrap: (f: (A...) -> R...) -> ((A...) -> R...), yield: (A...) -> R..., isyieldable: () -> boolean, close: (co: thread) -> (boolean, any) diff --git a/Analysis/src/Frontend.cpp b/Analysis/src/Frontend.cpp index 4dd815fb..c6c360b8 100644 --- a/Analysis/src/Frontend.cpp +++ b/Analysis/src/Frontend.cpp @@ -31,10 +31,11 @@ LUAU_FASTINT(LuauTypeInferRecursionLimit) LUAU_FASTINT(LuauTarjanChildLimit) LUAU_FASTFLAG(LuauInferInNoCheckMode) LUAU_FASTFLAGVARIABLE(LuauKnowsTheDataModel3, false) -LUAU_FASTINTVARIABLE(LuauAutocompleteCheckTimeoutMs, 100) +LUAU_FASTINTVARIABLE(LuauAutocompleteCheckTimeoutMs, 100) // TODO: Remove with FFlagLuauTypecheckLimitControls LUAU_FASTFLAGVARIABLE(DebugLuauDeferredConstraintResolution, false) LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJson, false) LUAU_FASTFLAGVARIABLE(DebugLuauReadWriteProperties, false) +LUAU_FASTFLAGVARIABLE(LuauTypecheckLimitControls, false) namespace Luau { @@ -873,6 +874,14 @@ void Frontend::addBuildQueueItems(std::vector& items, std::vecto } } +static void applyInternalLimitScaling(SourceNode& sourceNode, const ModulePtr module, double limit) +{ + if (module->timeout) + sourceNode.autocompleteLimitsMult = sourceNode.autocompleteLimitsMult / 2.0; + else if (module->checkDurationSec < limit / 2.0) + sourceNode.autocompleteLimitsMult = std::min(sourceNode.autocompleteLimitsMult * 2.0, 1.0); +} + void Frontend::checkBuildQueueItem(BuildQueueItem& item) { SourceNode& sourceNode = *item.sourceNode; @@ -883,43 +892,85 @@ void Frontend::checkBuildQueueItem(BuildQueueItem& item) double timestamp = getTimestamp(); const std::vector& requireCycles = item.requireCycles; - if (item.options.forAutocomplete) + TypeCheckLimits typeCheckLimits; + + if (FFlag::LuauTypecheckLimitControls) { - double autocompleteTimeLimit = FInt::LuauAutocompleteCheckTimeoutMs / 1000.0; - - // The autocomplete typecheck is always in strict mode with DM awareness - // to provide better type information for IDE features - TypeCheckLimits typeCheckLimits; - - if (autocompleteTimeLimit != 0.0) - typeCheckLimits.finishTime = TimeTrace::getClock() + autocompleteTimeLimit; + if (item.options.moduleTimeLimitSec) + typeCheckLimits.finishTime = TimeTrace::getClock() + *item.options.moduleTimeLimitSec; else typeCheckLimits.finishTime = std::nullopt; // TODO: This is a dirty ad hoc solution for autocomplete timeouts // We are trying to dynamically adjust our existing limits to lower total typechecking time under the limit // so that we'll have type information for the whole file at lower quality instead of a full abort in the middle - if (FInt::LuauTarjanChildLimit > 0) - typeCheckLimits.instantiationChildLimit = std::max(1, int(FInt::LuauTarjanChildLimit * sourceNode.autocompleteLimitsMult)); - else - typeCheckLimits.instantiationChildLimit = std::nullopt; + if (item.options.applyInternalLimitScaling) + { + if (FInt::LuauTarjanChildLimit > 0) + typeCheckLimits.instantiationChildLimit = std::max(1, int(FInt::LuauTarjanChildLimit * sourceNode.autocompleteLimitsMult)); + else + typeCheckLimits.instantiationChildLimit = std::nullopt; - if (FInt::LuauTypeInferIterationLimit > 0) - typeCheckLimits.unifierIterationLimit = std::max(1, int(FInt::LuauTypeInferIterationLimit * sourceNode.autocompleteLimitsMult)); - else - typeCheckLimits.unifierIterationLimit = std::nullopt; + if (FInt::LuauTypeInferIterationLimit > 0) + typeCheckLimits.unifierIterationLimit = std::max(1, int(FInt::LuauTypeInferIterationLimit * sourceNode.autocompleteLimitsMult)); + else + typeCheckLimits.unifierIterationLimit = std::nullopt; + } typeCheckLimits.cancellationToken = item.options.cancellationToken; + } + if (item.options.forAutocomplete) + { + double autocompleteTimeLimit = FInt::LuauAutocompleteCheckTimeoutMs / 1000.0; + + if (!FFlag::LuauTypecheckLimitControls) + { + // The autocomplete typecheck is always in strict mode with DM awareness + // to provide better type information for IDE features + TypeCheckLimits typeCheckLimits; + + if (autocompleteTimeLimit != 0.0) + typeCheckLimits.finishTime = TimeTrace::getClock() + autocompleteTimeLimit; + else + typeCheckLimits.finishTime = std::nullopt; + + // TODO: This is a dirty ad hoc solution for autocomplete timeouts + // We are trying to dynamically adjust our existing limits to lower total typechecking time under the limit + // so that we'll have type information for the whole file at lower quality instead of a full abort in the middle + if (FInt::LuauTarjanChildLimit > 0) + typeCheckLimits.instantiationChildLimit = std::max(1, int(FInt::LuauTarjanChildLimit * sourceNode.autocompleteLimitsMult)); + else + typeCheckLimits.instantiationChildLimit = std::nullopt; + + if (FInt::LuauTypeInferIterationLimit > 0) + typeCheckLimits.unifierIterationLimit = std::max(1, int(FInt::LuauTypeInferIterationLimit * sourceNode.autocompleteLimitsMult)); + else + typeCheckLimits.unifierIterationLimit = std::nullopt; + + typeCheckLimits.cancellationToken = item.options.cancellationToken; + } + + // The autocomplete typecheck is always in strict mode with DM awareness to provide better type information for IDE features ModulePtr moduleForAutocomplete = check(sourceModule, Mode::Strict, requireCycles, environmentScope, /*forAutocomplete*/ true, /*recordJsonLog*/ false, typeCheckLimits); double duration = getTimestamp() - timestamp; - if (moduleForAutocomplete->timeout) - sourceNode.autocompleteLimitsMult = sourceNode.autocompleteLimitsMult / 2.0; - else if (duration < autocompleteTimeLimit / 2.0) - sourceNode.autocompleteLimitsMult = std::min(sourceNode.autocompleteLimitsMult * 2.0, 1.0); + if (FFlag::LuauTypecheckLimitControls) + { + moduleForAutocomplete->checkDurationSec = duration; + + if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling) + applyInternalLimitScaling(sourceNode, moduleForAutocomplete, *item.options.moduleTimeLimitSec); + } + else + { + if (moduleForAutocomplete->timeout) + sourceNode.autocompleteLimitsMult = sourceNode.autocompleteLimitsMult / 2.0; + else if (duration < autocompleteTimeLimit / 2.0) + sourceNode.autocompleteLimitsMult = std::min(sourceNode.autocompleteLimitsMult * 2.0, 1.0); + } item.stats.timeCheck += duration; item.stats.filesStrict += 1; @@ -928,13 +979,29 @@ void Frontend::checkBuildQueueItem(BuildQueueItem& item) return; } - TypeCheckLimits typeCheckLimits; - - typeCheckLimits.cancellationToken = item.options.cancellationToken; + if (!FFlag::LuauTypecheckLimitControls) + { + typeCheckLimits.cancellationToken = item.options.cancellationToken; + } ModulePtr module = check(sourceModule, mode, requireCycles, environmentScope, /*forAutocomplete*/ false, item.recordJsonLog, typeCheckLimits); - item.stats.timeCheck += getTimestamp() - timestamp; + if (FFlag::LuauTypecheckLimitControls) + { + double duration = getTimestamp() - timestamp; + + module->checkDurationSec = duration; + + if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling) + applyInternalLimitScaling(sourceNode, module, *item.options.moduleTimeLimitSec); + + item.stats.timeCheck += duration; + } + else + { + item.stats.timeCheck += getTimestamp() - timestamp; + } + item.stats.filesStrict += mode == Mode::Strict; item.stats.filesNonstrict += mode == Mode::Nonstrict; diff --git a/Analysis/src/Simplify.cpp b/Analysis/src/Simplify.cpp index 15b3b2c6..6519c6ff 100644 --- a/Analysis/src/Simplify.cpp +++ b/Analysis/src/Simplify.cpp @@ -2,10 +2,12 @@ #include "Luau/Simplify.h" +#include "Luau/Normalize.h" // TypeIds #include "Luau/RecursionCounter.h" #include "Luau/ToString.h" #include "Luau/TypeArena.h" -#include "Luau/Normalize.h" // TypeIds +#include "Luau/TypeUtils.h" + #include LUAU_FASTINT(LuauTypeReductionRecursionLimit) @@ -47,14 +49,6 @@ struct TypeSimplifier TypeId simplify(TypeId ty, DenseHashSet& seen); }; -template -static std::pair get2(TID one, TID two) -{ - const A* a = get(one); - const B* b = get(two); - return a && b ? std::make_pair(a, b) : std::make_pair(nullptr, nullptr); -} - // Match the exact type false|nil static bool isFalsyType(TypeId ty) { diff --git a/Analysis/src/Subtyping.cpp b/Analysis/src/Subtyping.cpp new file mode 100644 index 00000000..596890f9 --- /dev/null +++ b/Analysis/src/Subtyping.cpp @@ -0,0 +1,344 @@ +// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details + +#include "Luau/Subtyping.h" + +#include "Luau/Common.h" +#include "Luau/Normalize.h" +#include "Luau/Type.h" +#include "Luau/TypePack.h" +#include "Luau/TypeUtils.h" + +#include + +namespace Luau +{ + +SubtypingGraph SubtypingGraph::and_(const SubtypingGraph& other) +{ + return SubtypingGraph{ + isSubtype && other.isSubtype, + // `||` is intentional here, we want to preserve error-suppressing flag. + isErrorSuppressing || other.isErrorSuppressing, + normalizationTooComplex || other.normalizationTooComplex, + }; +} + +SubtypingGraph SubtypingGraph::or_(const SubtypingGraph& other) +{ + return SubtypingGraph{ + isSubtype || other.isSubtype, + isErrorSuppressing || other.isErrorSuppressing, + normalizationTooComplex || other.normalizationTooComplex, + }; +} + +SubtypingGraph SubtypingGraph::and_(const std::vector& results) +{ + SubtypingGraph acc{true, false}; + for (const SubtypingGraph& current : results) + acc = acc.and_(current); + return acc; +} + +SubtypingGraph SubtypingGraph::or_(const std::vector& results) +{ + SubtypingGraph acc{false, false}; + for (const SubtypingGraph& current : results) + acc = acc.or_(current); + return acc; +} + +SubtypingGraph Subtyping::isSubtype(TypeId subTy, TypeId superTy) +{ + subTy = follow(subTy); + superTy = follow(superTy); + + // TODO: Do we care about returning a proof that this is error-suppressing? + // e.g. given `a | error <: a | error` where both operands are pointer equal, + // then should it also carry the information that it's error-suppressing? + // If it should, then `error <: error` should also do the same. + if (subTy == superTy) + return {true}; + + + if (auto superUnion = get(superTy)) + return isSubtype(subTy, superUnion); + else if (auto subUnion = get(subTy)) + return isSubtype(subUnion, superTy); + else if (auto superIntersection = get(superTy)) + return isSubtype(subTy, superIntersection); + else if (auto subIntersection = get(subTy)) + { + SubtypingGraph result = isSubtype(subIntersection, superTy); + if (result.isSubtype || result.isErrorSuppressing || result.normalizationTooComplex) + return result; + else + return isSubtype(normalizer->normalize(subTy), normalizer->normalize(superTy)); + } + else if (get(superTy)) + return {true}; // This is always true. + else if (get(subTy)) + { + // any = unknown | error, so we rewrite this to match. + // As per TAPL: A | B <: T iff A <: T && B <: T + return isSubtype(builtinTypes->unknownType, superTy).and_(isSubtype(builtinTypes->errorType, superTy)); + } + else if (auto superUnknown = get(superTy)) + { + LUAU_ASSERT(!get(subTy)); // TODO: replace with ice. + LUAU_ASSERT(!get(subTy)); // TODO: replace with ice. + LUAU_ASSERT(!get(subTy)); // TODO: replace with ice. + + bool errorSuppressing = get(subTy); + return {!errorSuppressing, errorSuppressing}; + } + else if (get(subTy)) + return {true}; + else if (get(superTy)) + return {false, true}; + else if (get(subTy)) + return {false, true}; + else if (auto p = get2(subTy, superTy)) + return isSubtype(p); + else if (auto p = get2(subTy, superTy)) + return isSubtype(p); + else if (auto p = get2(subTy, superTy)) + return isSubtype(p); + else if (auto p = get2(subTy, superTy)) + return isSubtype(p); + + return {false}; +} + +SubtypingGraph Subtyping::isSubtype(TypePackId subTp, TypePackId superTp) +{ + subTp = follow(subTp); + superTp = follow(superTp); + + auto [subHead, subTail] = flatten(subTp); + auto [superHead, superTail] = flatten(superTp); + + const size_t headSize = std::min(subHead.size(), superHead.size()); + + std::vector results; + results.reserve(std::max(subHead.size(), superHead.size()) + 1); + + // Match head types pairwise + + for (size_t i = 0; i < headSize; ++i) + { + results.push_back(isSubtype(subHead[i], superHead[i])); + if (!results.back().isSubtype) + return {false}; + } + + // Handle mismatched head sizes + + if (subHead.size() < superHead.size()) + { + if (subTail) + { + if (auto vt = get(*subTail)) + { + for (size_t i = headSize; i < superHead.size(); ++i) + { + results.push_back(isSubtype(vt->ty, superHead[i])); + } + } + else + LUAU_ASSERT(0); // TODO + } + else + return {false}; + } + else if (subHead.size() > superHead.size()) + { + if (superTail) + { + if (auto vt = get(*superTail)) + { + for (size_t i = headSize; i < subHead.size(); ++i) + { + results.push_back(isSubtype(subHead[i], vt->ty)); + } + } + else + LUAU_ASSERT(0); // TODO + } + else + return {false}; + } + else + { + // subHead and superHead are the same size. Nothing more must be done. + } + + // Handle tails + + if (subTail && superTail) + { + if (auto p = get2(*subTail, *superTail)) + { + results.push_back(isSubtype(p.first->ty, p.second->ty)); + } + else + LUAU_ASSERT(0); // TODO + } + else if (subTail) + { + if (get(*subTail)) + { + return {false}; + } + + LUAU_ASSERT(0); // TODO + } + else if (superTail) + { + if (get(*superTail)) + { + /* + * A variadic type pack ...T can be thought of as an infinite union of finite type packs. + * () | (T) | (T, T) | (T, T, T) | ... + * + * And, per TAPL: + * T <: A | B iff T <: A or T <: B + * + * All variadic type packs are therefore supertypes of the empty type pack. + */ + } + else + LUAU_ASSERT(0); // TODO + } + + return SubtypingGraph::and_(results); +} + +template +SubtypingGraph Subtyping::isSubtype(const TryPair& pair) +{ + return isSubtype(pair.first, pair.second); +} + +/* + * This is much simpler than the Unifier implementation because we don't + * actually care about potential "cross-talk" between union parts that match the + * left side. + * + * In fact, we're very limited in what we can do: If multiple choices match, but + * all of them have non-overlapping constraints, then we're stuck with an "or" + * conjunction of constraints. Solving this in the general case is quite + * difficult. + * + * For example, we cannot dispatch anything from this constraint: + * + * {x: number, y: string} <: {x: number, y: 'a} | {x: 'b, y: string} + * + * From this constraint, we can know that either string <: 'a or number <: 'b, + * but we don't know which! + * + * However: + * + * {x: number, y: string} <: {x: number, y: 'a} | {x: number, y: string} + * + * We can dispatch this constraint because there is no 'or' conjunction. One of + * the arms requires 0 matches. + * + * {x: number, y: string, z: boolean} | {x: number, y: 'a, z: 'b} | {x: number, + * y: string, z: 'b} + * + * Here, we have two matches. One asks for string ~ 'a and boolean ~ 'b. The + * other just asks for boolean ~ 'b. We can dispatch this and only commit + * boolean ~ 'b. This constraint does not teach us anything about 'a. + */ +SubtypingGraph Subtyping::isSubtype(TypeId subTy, const UnionType* superUnion) +{ + // As per TAPL: T <: A | B iff T <: A || T <: B + std::vector subtypings; + for (TypeId ty : superUnion) + subtypings.push_back(isSubtype(subTy, ty)); + return SubtypingGraph::or_(subtypings); +} + +SubtypingGraph Subtyping::isSubtype(const UnionType* subUnion, TypeId superTy) +{ + // As per TAPL: A | B <: T iff A <: T && B <: T + std::vector subtypings; + for (TypeId ty : subUnion) + subtypings.push_back(isSubtype(ty, superTy)); + return SubtypingGraph::and_(subtypings); +} + +SubtypingGraph Subtyping::isSubtype(TypeId subTy, const IntersectionType* superIntersection) +{ + // As per TAPL: T <: A & B iff T <: A && T <: B + std::vector subtypings; + for (TypeId ty : superIntersection) + subtypings.push_back(isSubtype(subTy, ty)); + return SubtypingGraph::and_(subtypings); +} + +SubtypingGraph Subtyping::isSubtype(const IntersectionType* subIntersection, TypeId superTy) +{ + // TODO: Semantic subtyping here. + // As per TAPL: A & B <: T iff A <: T || B <: T + std::vector subtypings; + for (TypeId ty : subIntersection) + subtypings.push_back(isSubtype(ty, superTy)); + return SubtypingGraph::or_(subtypings); +} + +SubtypingGraph Subtyping::isSubtype(const PrimitiveType* subPrim, const PrimitiveType* superPrim) +{ + return {subPrim->type == superPrim->type}; +} + +SubtypingGraph Subtyping::isSubtype(const SingletonType* subSingleton, const PrimitiveType* superPrim) +{ + if (get(subSingleton) && superPrim->type == PrimitiveType::String) + return {true}; + else if (get(subSingleton) && superPrim->type == PrimitiveType::Boolean) + return {true}; + else + return {false}; +} + +SubtypingGraph Subtyping::isSubtype(const SingletonType* subSingleton, const SingletonType* superSingleton) +{ + return {*subSingleton == *superSingleton}; +} + +SubtypingGraph Subtyping::isSubtype(const FunctionType* subFunction, const FunctionType* superFunction) +{ + SubtypingGraph argResult = isSubtype(superFunction->argTypes, subFunction->argTypes); + SubtypingGraph retResult = isSubtype(subFunction->retTypes, superFunction->retTypes); + + return argResult.and_(retResult); +} + +SubtypingGraph Subtyping::isSubtype(const NormalizedType* subNorm, const NormalizedType* superNorm) +{ + if (!subNorm || !superNorm) + return {false, true, true}; + + SubtypingGraph result{true}; + result = result.and_(isSubtype(subNorm->tops, superNorm->tops)); + result = result.and_(isSubtype(subNorm->booleans, superNorm->booleans)); + // isSubtype(subNorm->classes, superNorm->classes); + // isSubtype(subNorm->classes, superNorm->tables); + result = result.and_(isSubtype(subNorm->errors, superNorm->errors)); + result = result.and_(isSubtype(subNorm->nils, superNorm->nils)); + result = result.and_(isSubtype(subNorm->numbers, superNorm->numbers)); + result.isSubtype &= Luau::isSubtype(subNorm->strings, superNorm->strings); + // isSubtype(subNorm->strings, superNorm->tables); + result = result.and_(isSubtype(subNorm->threads, superNorm->threads)); + // isSubtype(subNorm->tables, superNorm->tables); + // isSubtype(subNorm->tables, superNorm->strings); + // isSubtype(subNorm->tables, superNorm->classes); + // isSubtype(subNorm->functions, superNorm->functions); + // isSubtype(subNorm->tyvars, superNorm->tyvars); + + return result; +} + +} // namespace Luau diff --git a/Analysis/src/Type.cpp b/Analysis/src/Type.cpp index fb72bc12..2590e4dc 100644 --- a/Analysis/src/Type.cpp +++ b/Analysis/src/Type.cpp @@ -69,14 +69,24 @@ static LUAU_NOINLINE TypeId unwrapLazy(LazyType* ltv) TypeId follow(TypeId t) { - return follow(t, nullptr, [](const void*, TypeId t) -> TypeId { + return follow(t, FollowOption::Normal); +} + +TypeId follow(TypeId t, FollowOption followOption) +{ + return follow(t, followOption, nullptr, [](const void*, TypeId t) -> TypeId { return t; }); } TypeId follow(TypeId t, const void* context, TypeId (*mapper)(const void*, TypeId)) { - auto advance = [context, mapper](TypeId ty) -> std::optional { + return follow(t, FollowOption::Normal, context, mapper); +} + +TypeId follow(TypeId t, FollowOption followOption, const void* context, TypeId (*mapper)(const void*, TypeId)) +{ + auto advance = [followOption, context, mapper](TypeId ty) -> std::optional { TypeId mapped = mapper(context, ty); if (auto btv = get>(mapped)) @@ -85,7 +95,7 @@ TypeId follow(TypeId t, const void* context, TypeId (*mapper)(const void*, TypeI if (auto ttv = get(mapped)) return ttv->boundTo; - if (auto ltv = getMutable(mapped)) + if (auto ltv = getMutable(mapped); ltv && followOption != FollowOption::DisableLazyTypeThunks) return unwrapLazy(ltv); return std::nullopt; @@ -945,6 +955,7 @@ BuiltinTypes::BuiltinTypes() , truthyType(arena->addType(Type{NegationType{falsyType}, /*persistent*/ true})) , optionalNumberType(arena->addType(Type{UnionType{{numberType, nilType}}, /*persistent*/ true})) , optionalStringType(arena->addType(Type{UnionType{{stringType, nilType}}, /*persistent*/ true})) + , emptyTypePack(arena->addTypePack(TypePackVar{TypePack{{}}, /*persistent*/ true})) , anyTypePack(arena->addTypePack(TypePackVar{VariadicTypePack{anyType}, /*persistent*/ true})) , neverTypePack(arena->addTypePack(TypePackVar{VariadicTypePack{neverType}, /*persistent*/ true})) , uninhabitableTypePack(arena->addTypePack(TypePackVar{TypePack{{neverType}, neverTypePack}, /*persistent*/ true})) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc66a83d..f0f0497d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ project(Luau LANGUAGES CXX C) add_library(Luau.Common INTERFACE) add_library(Luau.Ast STATIC) add_library(Luau.Compiler STATIC) +add_library(Luau.Config STATIC) add_library(Luau.Analysis STATIC) add_library(Luau.CodeGen STATIC) add_library(Luau.VM STATIC) @@ -71,9 +72,13 @@ target_compile_features(Luau.Compiler PUBLIC cxx_std_17) target_include_directories(Luau.Compiler PUBLIC Compiler/include) target_link_libraries(Luau.Compiler PUBLIC Luau.Ast) +target_compile_features(Luau.Config PUBLIC cxx_std_17) +target_include_directories(Luau.Config PUBLIC Config/include) +target_link_libraries(Luau.Config PUBLIC Luau.Ast) + target_compile_features(Luau.Analysis PUBLIC cxx_std_17) target_include_directories(Luau.Analysis PUBLIC Analysis/include) -target_link_libraries(Luau.Analysis PUBLIC Luau.Ast) +target_link_libraries(Luau.Analysis PUBLIC Luau.Ast Luau.Config) target_compile_features(Luau.CodeGen PRIVATE cxx_std_17) target_include_directories(Luau.CodeGen PUBLIC CodeGen/include) diff --git a/CodeGen/include/Luau/IrAnalysis.h b/CodeGen/include/Luau/IrAnalysis.h index ca1eba62..5fcaf46b 100644 --- a/CodeGen/include/Luau/IrAnalysis.h +++ b/CodeGen/include/Luau/IrAnalysis.h @@ -4,6 +4,7 @@ #include "Luau/Common.h" #include +#include #include #include @@ -96,6 +97,46 @@ struct CfgInfo void computeCfgImmediateDominators(IrFunction& function); void computeCfgDominanceTreeChildren(IrFunction& function); +struct IdfContext +{ + struct BlockAndOrdering + { + uint32_t blockIdx; + BlockOrdering ordering; + + bool operator<(const BlockAndOrdering& rhs) const + { + if (ordering.depth != rhs.ordering.depth) + return ordering.depth < rhs.ordering.depth; + + return ordering.preOrder < rhs.ordering.preOrder; + } + }; + + // Using priority queue to work on nodes in the order from the bottom of the dominator tree to the top + // If the depth of keys is equal, DFS order is used to provide strong ordering + std::priority_queue queue; + std::vector worklist; + + struct IdfVisitMarks + { + bool seenInQueue = false; + bool seenInWorklist = false; + }; + + std::vector visits; + + std::vector idf; +}; + +// Compute iterated dominance frontier (IDF or DF+) for a variable, given the set of blocks where that variable is defined +// Providing a set of blocks where the variable is a live-in at the entry helps produce a pruned SSA form (inserted phi nodes will not be dead) +// +// 'Iterated' comes from the definition where we recompute the IDFn+1 = DF(S) while adding IDFn to S until a fixed point is reached +// Iterated dominance frontier has been shown to be equal to the set of nodes where phi instructions have to be inserted +void computeIteratedDominanceFrontierForDefs( + IdfContext& ctx, const IrFunction& function, const std::vector& defBlocks, const std::vector& liveInBlocks); + // Function used to update all CFG data void computeCfgInfo(IrFunction& function); diff --git a/CodeGen/include/Luau/IrData.h b/CodeGen/include/Luau/IrData.h index 1684b478..5ac5b2ac 100644 --- a/CodeGen/include/Luau/IrData.h +++ b/CodeGen/include/Luau/IrData.h @@ -53,12 +53,9 @@ enum class IrCmd : uint8_t // Load a TValue from memory // A: Rn or Kn or pointer (TValue) + // B: int (optional 'A' pointer offset) LOAD_TVALUE, - // Load a TValue from table node value - // A: pointer (LuaNode) - LOAD_NODE_VALUE_TV, // TODO: we should find a way to generalize LOAD_TVALUE - // Load current environment table LOAD_ENV, @@ -113,12 +110,15 @@ enum class IrCmd : uint8_t // Store a TValue into memory // A: Rn or pointer (TValue) // B: TValue + // C: int (optional 'A' pointer offset) STORE_TVALUE, - // Store a TValue into table node value - // A: pointer (LuaNode) - // B: TValue - STORE_NODE_VALUE_TV, // TODO: we should find a way to generalize STORE_TVALUE + // Store a pair of tag and value into memory + // A: Rn or pointer (TValue) + // B: tag (must be a constant) + // C: int/double/pointer + // D: int (optional 'A' pointer offset) + STORE_SPLIT_TVALUE, // Add/Sub two integers together // A, B: int @@ -356,6 +356,7 @@ enum class IrCmd : uint8_t // Store TValue from stack slot into a function upvalue // A: UPn // B: Rn + // C: tag/undef (tag of the value that was written) SET_UPVALUE, // Convert TValues into numbers for a numerical for loop diff --git a/CodeGen/include/Luau/IrUtils.h b/CodeGen/include/Luau/IrUtils.h index fe38cb90..9c077914 100644 --- a/CodeGen/include/Luau/IrUtils.h +++ b/CodeGen/include/Luau/IrUtils.h @@ -145,7 +145,6 @@ inline bool hasResult(IrCmd cmd) case IrCmd::LOAD_DOUBLE: case IrCmd::LOAD_INT: case IrCmd::LOAD_TVALUE: - case IrCmd::LOAD_NODE_VALUE_TV: case IrCmd::LOAD_ENV: case IrCmd::GET_ARR_ADDR: case IrCmd::GET_SLOT_NODE_ADDR: diff --git a/CodeGen/src/CodeGenA64.cpp b/CodeGen/src/CodeGenA64.cpp index 6271e376..2e268d26 100644 --- a/CodeGen/src/CodeGenA64.cpp +++ b/CodeGen/src/CodeGenA64.cpp @@ -225,6 +225,7 @@ static EntryLocations buildEntryFunction(AssemblyBuilderA64& build, UnwindBuilde build.stp(x19, x20, mem(sp, 16)); build.stp(x21, x22, mem(sp, 32)); build.stp(x23, x24, mem(sp, 48)); + build.str(x25, mem(sp, 64)); build.mov(x29, sp); // this is only necessary if we maintain frame pointers, which we do in the JIT for now @@ -235,6 +236,7 @@ static EntryLocations buildEntryFunction(AssemblyBuilderA64& build, UnwindBuilde // Setup native execution environment build.mov(rState, x0); build.mov(rNativeContext, x3); + build.ldr(rGlobalState, mem(x0, offsetof(lua_State, global))); build.ldr(rBase, mem(x0, offsetof(lua_State, base))); // L->base @@ -252,6 +254,7 @@ static EntryLocations buildEntryFunction(AssemblyBuilderA64& build, UnwindBuilde locations.epilogueStart = build.setLabel(); // Cleanup and exit + build.ldr(x25, mem(sp, 64)); build.ldp(x23, x24, mem(sp, 48)); build.ldp(x21, x22, mem(sp, 32)); build.ldp(x19, x20, mem(sp, 16)); @@ -262,7 +265,7 @@ static EntryLocations buildEntryFunction(AssemblyBuilderA64& build, UnwindBuilde // Our entry function is special, it spans the whole remaining code area unwind.startFunction(); - unwind.prologueA64(prologueSize, kStackSize, {x29, x30, x19, x20, x21, x22, x23, x24}); + unwind.prologueA64(prologueSize, kStackSize, {x29, x30, x19, x20, x21, x22, x23, x24, x25}); unwind.finishFunction(build.getLabelOffset(locations.start), kFullBlockFuncton); return locations; diff --git a/CodeGen/src/CodeGenLower.h b/CodeGen/src/CodeGenLower.h index e709a89c..171a8c0e 100644 --- a/CodeGen/src/CodeGenLower.h +++ b/CodeGen/src/CodeGenLower.h @@ -194,7 +194,7 @@ inline bool lowerImpl(AssemblyBuilder& build, IrLowering& lowering, IrFunction& } } - lowering.finishBlock(); + lowering.finishBlock(block, nextBlock); if (options.includeIr) build.logAppend("#\n"); diff --git a/CodeGen/src/EmitCommonA64.h b/CodeGen/src/EmitCommonA64.h index 9e89b1c0..894570d9 100644 --- a/CodeGen/src/EmitCommonA64.h +++ b/CodeGen/src/EmitCommonA64.h @@ -31,23 +31,24 @@ namespace A64 // 1. Constant registers (only loaded during codegen entry) constexpr RegisterA64 rState = x19; // lua_State* L constexpr RegisterA64 rNativeContext = x20; // NativeContext* context +constexpr RegisterA64 rGlobalState = x21; // global_State* L->global // 2. Frame registers (reloaded when call frame changes; rBase is also reloaded after all calls that may reallocate stack) -constexpr RegisterA64 rConstants = x21; // TValue* k -constexpr RegisterA64 rClosure = x22; // Closure* cl -constexpr RegisterA64 rCode = x23; // Instruction* code -constexpr RegisterA64 rBase = x24; // StkId base +constexpr RegisterA64 rConstants = x22; // TValue* k +constexpr RegisterA64 rClosure = x23; // Closure* cl +constexpr RegisterA64 rCode = x24; // Instruction* code +constexpr RegisterA64 rBase = x25; // StkId base // Native code is as stackless as the interpreter, so we can place some data on the stack once and have it accessible at any point // See CodeGenA64.cpp for layout -constexpr unsigned kStashSlots = 8; // stashed non-volatile registers +constexpr unsigned kStashSlots = 9; // stashed non-volatile registers +constexpr unsigned kTempSlots = 1; // 8 bytes of temporary space, such luxury! constexpr unsigned kSpillSlots = 22; // slots for spilling temporary registers -constexpr unsigned kTempSlots = 2; // 16 bytes of temporary space, such luxury! -constexpr unsigned kStackSize = (kStashSlots + kSpillSlots + kTempSlots) * 8; +constexpr unsigned kStackSize = (kStashSlots + kTempSlots + kSpillSlots) * 8; -constexpr AddressA64 sSpillArea = mem(sp, kStashSlots * 8); -constexpr AddressA64 sTemporary = mem(sp, (kStashSlots + kSpillSlots) * 8); +constexpr AddressA64 sSpillArea = mem(sp, (kStashSlots + kTempSlots) * 8); +constexpr AddressA64 sTemporary = mem(sp, kStashSlots * 8); inline void emitUpdateBase(AssemblyBuilderA64& build) { diff --git a/CodeGen/src/EmitCommonX64.h b/CodeGen/src/EmitCommonX64.h index 888f537f..782f2084 100644 --- a/CodeGen/src/EmitCommonX64.h +++ b/CodeGen/src/EmitCommonX64.h @@ -114,11 +114,6 @@ inline OperandX64 luauNodeKeyTag(RegisterX64 node) return dword[node + offsetof(LuaNode, key) + kOffsetOfTKeyTagNext]; } -inline OperandX64 luauNodeValue(RegisterX64 node) -{ - return xmmword[node + offsetof(LuaNode, val)]; -} - inline void setLuauReg(AssemblyBuilderX64& build, RegisterX64 tmp, int ri, OperandX64 op) { LUAU_ASSERT(op.cat == CategoryX64::mem); diff --git a/CodeGen/src/IrAnalysis.cpp b/CodeGen/src/IrAnalysis.cpp index fa108af1..b29927bb 100644 --- a/CodeGen/src/IrAnalysis.cpp +++ b/CodeGen/src/IrAnalysis.cpp @@ -209,6 +209,7 @@ static void visitVmRegDefsUses(T& visitor, IrFunction& function, const IrBlock& case IrCmd::STORE_INT: case IrCmd::STORE_VECTOR: case IrCmd::STORE_TVALUE: + case IrCmd::STORE_SPLIT_TVALUE: visitor.maybeDef(inst.a); // Argument can also be a pointer value break; case IrCmd::CMP_ANY: @@ -897,6 +898,79 @@ void computeCfgDominanceTreeChildren(IrFunction& function) computeBlockOrdering(function, info.domOrdering, /* preOrder */ nullptr, /* postOrder */ nullptr); } +// This algorithm is based on 'A Linear Time Algorithm for Placing Phi-Nodes' [Vugranam C.Sreedhar] +// It uses the optimized form from LLVM that relies an implicit DJ-graph (join edges are edges of the CFG that are not part of the dominance tree) +void computeIteratedDominanceFrontierForDefs( + IdfContext& ctx, const IrFunction& function, const std::vector& defBlocks, const std::vector& liveInBlocks) +{ + LUAU_ASSERT(!function.cfg.domOrdering.empty()); + + LUAU_ASSERT(ctx.queue.empty()); + LUAU_ASSERT(ctx.worklist.empty()); + + ctx.idf.clear(); + + ctx.visits.clear(); + ctx.visits.resize(function.blocks.size()); + + for (uint32_t defBlock : defBlocks) + { + const BlockOrdering& ordering = function.cfg.domOrdering[defBlock]; + ctx.queue.push({defBlock, ordering}); + } + + while (!ctx.queue.empty()) + { + IdfContext::BlockAndOrdering root = ctx.queue.top(); + ctx.queue.pop(); + + LUAU_ASSERT(ctx.worklist.empty()); + ctx.worklist.push_back(root.blockIdx); + ctx.visits[root.blockIdx].seenInWorklist = true; + + while (!ctx.worklist.empty()) + { + uint32_t blockIdx = ctx.worklist.back(); + ctx.worklist.pop_back(); + + // Check if successor node is the node where dominance of the current root ends, making it a part of dominance frontier set + for (uint32_t succIdx : successors(function.cfg, blockIdx)) + { + const BlockOrdering& succOrdering = function.cfg.domOrdering[succIdx]; + + // Nodes in the DF of root always have a level that is less than or equal to the level of root + if (succOrdering.depth > root.ordering.depth) + continue; + + if (ctx.visits[succIdx].seenInQueue) + continue; + + ctx.visits[succIdx].seenInQueue = true; + + // Skip successor block if it doesn't have our variable as a live in there + if (std::find(liveInBlocks.begin(), liveInBlocks.end(), succIdx) == liveInBlocks.end()) + continue; + + ctx.idf.push_back(succIdx); + + // If block doesn't have its own definition of the variable, add it to the queue + if (std::find(defBlocks.begin(), defBlocks.end(), succIdx) == defBlocks.end()) + ctx.queue.push({succIdx, succOrdering}); + } + + // Add dominance tree children that haven't been processed yet to the worklist + for (uint32_t domChildIdx : domChildren(function.cfg, blockIdx)) + { + if (ctx.visits[domChildIdx].seenInWorklist) + continue; + + ctx.visits[domChildIdx].seenInWorklist = true; + ctx.worklist.push_back(domChildIdx); + } + } + } +} + void computeCfgInfo(IrFunction& function) { computeCfgBlockEdges(function); diff --git a/CodeGen/src/IrBuilder.cpp b/CodeGen/src/IrBuilder.cpp index 0dd6f3c6..d34dfb57 100644 --- a/CodeGen/src/IrBuilder.cpp +++ b/CodeGen/src/IrBuilder.cpp @@ -1,6 +1,8 @@ // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details #include "Luau/IrBuilder.h" +#include "Luau/Bytecode.h" +#include "Luau/BytecodeUtils.h" #include "Luau/IrData.h" #include "Luau/IrUtils.h" diff --git a/CodeGen/src/IrDump.cpp b/CodeGen/src/IrDump.cpp index bda36582..50d5012e 100644 --- a/CodeGen/src/IrDump.cpp +++ b/CodeGen/src/IrDump.cpp @@ -89,8 +89,6 @@ const char* getCmdName(IrCmd cmd) return "LOAD_INT"; case IrCmd::LOAD_TVALUE: return "LOAD_TVALUE"; - case IrCmd::LOAD_NODE_VALUE_TV: - return "LOAD_NODE_VALUE_TV"; case IrCmd::LOAD_ENV: return "LOAD_ENV"; case IrCmd::GET_ARR_ADDR: @@ -113,8 +111,8 @@ const char* getCmdName(IrCmd cmd) return "STORE_VECTOR"; case IrCmd::STORE_TVALUE: return "STORE_TVALUE"; - case IrCmd::STORE_NODE_VALUE_TV: - return "STORE_NODE_VALUE_TV"; + case IrCmd::STORE_SPLIT_TVALUE: + return "STORE_SPLIT_TVALUE"; case IrCmd::ADD_INT: return "ADD_INT"; case IrCmd::SUB_INT: diff --git a/CodeGen/src/IrLoweringA64.cpp b/CodeGen/src/IrLoweringA64.cpp index 63d03135..03006e30 100644 --- a/CodeGen/src/IrLoweringA64.cpp +++ b/CodeGen/src/IrLoweringA64.cpp @@ -122,6 +122,7 @@ static void emitFallback(AssemblyBuilderA64& build, int offset, int pcpos) static void emitInvokeLibm1P(AssemblyBuilderA64& build, size_t func, int arg) { + LUAU_ASSERT(kTempSlots >= 1); build.ldr(d0, mem(rBase, arg * sizeof(TValue) + offsetof(TValue, value.n))); build.add(x0, sp, sTemporary.data); // sp-relative offset build.ldr(x1, mem(rNativeContext, uint32_t(func))); @@ -224,16 +225,12 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) case IrCmd::LOAD_TVALUE: { inst.regA64 = regs.allocReg(KindA64::q, index); - AddressA64 addr = tempAddr(inst.a, 0); + + int addrOffset = inst.b.kind != IrOpKind::None ? intOp(inst.b) : 0; + AddressA64 addr = tempAddr(inst.a, addrOffset); build.ldr(inst.regA64, addr); break; } - case IrCmd::LOAD_NODE_VALUE_TV: - { - inst.regA64 = regs.allocReg(KindA64::q, index); - build.ldr(inst.regA64, mem(regOp(inst.a), offsetof(LuaNode, val))); - break; - } case IrCmd::LOAD_ENV: inst.regA64 = regs.allocReg(KindA64::x, index); build.ldr(inst.regA64, mem(rClosure, offsetof(Closure, env))); @@ -322,10 +319,17 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) } case IrCmd::STORE_TAG: { - RegisterA64 temp = regs.allocTemp(KindA64::w); AddressA64 addr = tempAddr(inst.a, offsetof(TValue, tt)); - build.mov(temp, tagOp(inst.b)); - build.str(temp, addr); + if (tagOp(inst.b) == 0) + { + build.str(wzr, addr); + } + else + { + RegisterA64 temp = regs.allocTemp(KindA64::w); + build.mov(temp, tagOp(inst.b)); + build.str(temp, addr); + } break; } case IrCmd::STORE_POINTER: @@ -343,9 +347,16 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) } case IrCmd::STORE_INT: { - RegisterA64 temp = tempInt(inst.b); AddressA64 addr = tempAddr(inst.a, offsetof(TValue, value)); - build.str(temp, addr); + if (inst.b.kind == IrOpKind::Constant && intOp(inst.b) == 0) + { + build.str(wzr, addr); + } + else + { + RegisterA64 temp = tempInt(inst.b); + build.str(temp, addr); + } break; } case IrCmd::STORE_VECTOR: @@ -368,13 +379,48 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) } case IrCmd::STORE_TVALUE: { - AddressA64 addr = tempAddr(inst.a, 0); + int addrOffset = inst.c.kind != IrOpKind::None ? intOp(inst.c) : 0; + AddressA64 addr = tempAddr(inst.a, addrOffset); build.str(regOp(inst.b), addr); break; } - case IrCmd::STORE_NODE_VALUE_TV: - build.str(regOp(inst.b), mem(regOp(inst.a), offsetof(LuaNode, val))); + case IrCmd::STORE_SPLIT_TVALUE: + { + int addrOffset = inst.d.kind != IrOpKind::None ? intOp(inst.d) : 0; + + RegisterA64 tempt = regs.allocTemp(KindA64::w); + AddressA64 addrt = tempAddr(inst.a, offsetof(TValue, tt) + addrOffset); + build.mov(tempt, tagOp(inst.b)); + build.str(tempt, addrt); + + AddressA64 addr = tempAddr(inst.a, offsetof(TValue, value) + addrOffset); + + if (tagOp(inst.b) == LUA_TBOOLEAN) + { + if (inst.c.kind == IrOpKind::Constant) + { + // note: we reuse tag temp register as value for true booleans, and use built-in zero register for false values + LUAU_ASSERT(LUA_TBOOLEAN == 1); + build.str(intOp(inst.c) ? tempt : wzr, addr); + } + else + build.str(regOp(inst.c), addr); + } + else if (tagOp(inst.b) == LUA_TNUMBER) + { + RegisterA64 temp = tempDouble(inst.c); + build.str(temp, addr); + } + else if (isGCO(tagOp(inst.b))) + { + build.str(regOp(inst.c), addr); + } + else + { + LUAU_ASSERT(!"Unsupported instruction form"); + } break; + } case IrCmd::ADD_INT: inst.regA64 = regs.allocReuse(KindA64::w, index, {inst.a, inst.b}); if (inst.b.kind == IrOpKind::Constant && unsigned(intOp(inst.b)) <= AssemblyBuilderA64::kMaxImmediate) @@ -705,15 +751,14 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) build.ldr(x1, mem(rNativeContext, offsetof(NativeContext, luaH_getn))); build.blr(x1); inst.regA64 = regs.allocReg(KindA64::d, index); - build.scvtf(inst.regA64, x0); + build.scvtf(inst.regA64, w0); break; } case IrCmd::STRING_LEN: { - RegisterA64 reg = regOp(inst.a); inst.regA64 = regs.allocReg(KindA64::w, index); - build.ldr(inst.regA64, mem(reg, offsetof(TString, len))); + build.ldr(inst.regA64, mem(regOp(inst.a), offsetof(TString, len))); break; } case IrCmd::NEW_TABLE: @@ -774,8 +819,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) regs.spill(build, index, {temp1}); build.mov(x0, temp1); build.mov(w1, intOp(inst.b)); - build.ldr(x2, mem(rState, offsetof(lua_State, global))); - build.ldr(x2, mem(x2, offsetof(global_State, tmname) + intOp(inst.b) * sizeof(TString*))); + build.ldr(x2, mem(rGlobalState, offsetof(global_State, tmname) + intOp(inst.b) * sizeof(TString*))); build.ldr(x3, mem(rNativeContext, offsetof(NativeContext, luaT_gettm))); build.blr(x3); @@ -972,8 +1016,8 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) case IrCmd::CONCAT: regs.spill(build, index); build.mov(x0, rState); - build.mov(x1, uintOp(inst.b)); - build.mov(x2, vmRegOp(inst.a) + uintOp(inst.b) - 1); + build.mov(w1, uintOp(inst.b)); + build.mov(w2, vmRegOp(inst.a) + uintOp(inst.b) - 1); build.ldr(x3, mem(rNativeContext, offsetof(NativeContext, luaV_concat))); build.blr(x3); @@ -1016,21 +1060,24 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) build.ldr(temp3, mem(rBase, vmRegOp(inst.b) * sizeof(TValue))); build.str(temp3, temp2); - Label skip; - checkObjectBarrierConditions(build, temp1, temp2, vmRegOp(inst.b), /* ratag */ -1, skip); + if (inst.c.kind == IrOpKind::Undef || isGCO(tagOp(inst.c))) + { + Label skip; + checkObjectBarrierConditions(build, temp1, temp2, vmRegOp(inst.b), inst.c.kind == IrOpKind::Undef ? -1 : tagOp(inst.c), skip); - size_t spills = regs.spill(build, index, {temp1}); + size_t spills = regs.spill(build, index, {temp1}); - build.mov(x1, temp1); - build.mov(x0, rState); - build.ldr(x2, mem(rBase, vmRegOp(inst.b) * sizeof(TValue) + offsetof(TValue, value))); - build.ldr(x3, mem(rNativeContext, offsetof(NativeContext, luaC_barrierf))); - build.blr(x3); + build.mov(x1, temp1); + build.mov(x0, rState); + build.ldr(x2, mem(rBase, vmRegOp(inst.b) * sizeof(TValue) + offsetof(TValue, value))); + build.ldr(x3, mem(rNativeContext, offsetof(NativeContext, luaC_barrierf))); + build.blr(x3); - regs.restore(build, spills); // need to restore before skip so that registers are in a consistent state + regs.restore(build, spills); // need to restore before skip so that registers are in a consistent state - // note: no emitUpdateBase necessary because luaC_ barriers do not reallocate stack - build.setLabel(skip); + // note: no emitUpdateBase necessary because luaC_ barriers do not reallocate stack + build.setLabel(skip); + } break; } case IrCmd::PREPARE_FORN: @@ -1213,8 +1260,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) Label self; - build.ldr(x0, mem(rState, offsetof(lua_State, global))); - build.ldr(x0, mem(x0, offsetof(global_State, cb.interrupt))); + build.ldr(x0, mem(rGlobalState, offsetof(global_State, cb.interrupt))); build.cbnz(x0, self); Label next = build.setLabel(); @@ -1227,11 +1273,9 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) RegisterA64 temp1 = regs.allocTemp(KindA64::x); RegisterA64 temp2 = regs.allocTemp(KindA64::x); + LUAU_ASSERT(offsetof(global_State, totalbytes) == offsetof(global_State, GCthreshold) + 8); Label skip; - build.ldr(temp1, mem(rState, offsetof(lua_State, global))); - // TODO: totalbytes and GCthreshold loads can be fused with ldp - build.ldr(temp2, mem(temp1, offsetof(global_State, totalbytes))); - build.ldr(temp1, mem(temp1, offsetof(global_State, GCthreshold))); + build.ldp(temp1, temp2, mem(rGlobalState, offsetof(global_State, GCthreshold))); build.cmp(temp1, temp2); build.b(ConditionA64::UnsignedGreater, skip); @@ -1239,8 +1283,8 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) build.mov(x0, rState); build.mov(w1, 1); - build.ldr(x1, mem(rNativeContext, offsetof(NativeContext, luaC_step))); - build.blr(x1); + build.ldr(x2, mem(rNativeContext, offsetof(NativeContext, luaC_step))); + build.blr(x2); emitUpdateBase(build); @@ -1450,9 +1494,9 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) // clear extra variables since we might have more than two if (intOp(inst.b) > 2) { - build.mov(w0, LUA_TNIL); + LUAU_ASSERT(LUA_TNIL == 0); for (int i = 2; i < intOp(inst.b); ++i) - build.str(w0, mem(rBase, (vmRegOp(inst.a) + 3 + i) * sizeof(TValue) + offsetof(TValue, tt))); + build.str(wzr, mem(rBase, (vmRegOp(inst.a) + 3 + i) * sizeof(TValue) + offsetof(TValue, tt))); } // we use full iter fallback for now; in the future it could be worthwhile to accelerate array iteration here build.mov(x0, rState); @@ -1561,7 +1605,7 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) { emitAddOffset(build, x1, rCode, uintOp(inst.a) * sizeof(Instruction)); build.mov(x2, rBase); - build.mov(x3, vmRegOp(inst.b)); + build.mov(w3, vmRegOp(inst.b)); build.ldr(x4, mem(rNativeContext, offsetof(NativeContext, executeGETVARARGSMultRet))); build.blr(x4); @@ -1570,10 +1614,12 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) else { build.mov(x1, rBase); - build.mov(x2, vmRegOp(inst.b)); - build.mov(x3, intOp(inst.c)); + build.mov(w2, vmRegOp(inst.b)); + build.mov(w3, intOp(inst.c)); build.ldr(x4, mem(rNativeContext, offsetof(NativeContext, executeGETVARARGSConst))); build.blr(x4); + + // note: no emitUpdateBase necessary because executeGETVARARGSConst does not reallocate stack } break; case IrCmd::NEWCLOSURE: @@ -1790,13 +1836,12 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) { inst.regA64 = regs.allocReg(KindA64::x, index); - build.ldr(inst.regA64, mem(rState, offsetof(lua_State, global))); LUAU_ASSERT(sizeof(TString*) == 8); if (inst.a.kind == IrOpKind::Inst) - build.add(inst.regA64, inst.regA64, zextReg(regOp(inst.a)), 3); + build.add(inst.regA64, rGlobalState, zextReg(regOp(inst.a)), 3); else if (inst.a.kind == IrOpKind::Constant) - build.add(inst.regA64, inst.regA64, uint16_t(tagOp(inst.a)) * 8); + build.add(inst.regA64, rGlobalState, uint16_t(tagOp(inst.a)) * 8); else LUAU_ASSERT(!"Unsupported instruction form"); @@ -1836,9 +1881,17 @@ void IrLoweringA64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) regs.freeTempRegs(); } -void IrLoweringA64::finishBlock() +void IrLoweringA64::finishBlock(const IrBlock& curr, const IrBlock& next) { - regs.assertNoSpills(); + if (!regs.spills.empty()) + { + // If we have spills remaining, we have to immediately lower the successor block + for (uint32_t predIdx : predecessors(function.cfg, function.getBlockIndex(next))) + LUAU_ASSERT(predIdx == function.getBlockIndex(curr)); + + // And the next block cannot be a join block in cfg + LUAU_ASSERT(next.useCount == 1); + } } void IrLoweringA64::finishFunction() diff --git a/CodeGen/src/IrLoweringA64.h b/CodeGen/src/IrLoweringA64.h index 344f18b7..5134ceda 100644 --- a/CodeGen/src/IrLoweringA64.h +++ b/CodeGen/src/IrLoweringA64.h @@ -26,7 +26,7 @@ struct IrLoweringA64 IrLoweringA64(AssemblyBuilderA64& build, ModuleHelpers& helpers, IrFunction& function); void lowerInst(IrInst& inst, uint32_t index, const IrBlock& next); - void finishBlock(); + void finishBlock(const IrBlock& curr, const IrBlock& next); void finishFunction(); bool hasError() const; diff --git a/CodeGen/src/IrLoweringX64.cpp b/CodeGen/src/IrLoweringX64.cpp index 2ea48404..ad18b849 100644 --- a/CodeGen/src/IrLoweringX64.cpp +++ b/CodeGen/src/IrLoweringX64.cpp @@ -111,22 +111,21 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) build.mov(inst.regX64, luauRegValueInt(vmRegOp(inst.a))); break; case IrCmd::LOAD_TVALUE: + { inst.regX64 = regs.allocReg(SizeX64::xmmword, index); + int addrOffset = inst.b.kind != IrOpKind::None ? intOp(inst.b) : 0; + if (inst.a.kind == IrOpKind::VmReg) build.vmovups(inst.regX64, luauReg(vmRegOp(inst.a))); else if (inst.a.kind == IrOpKind::VmConst) build.vmovups(inst.regX64, luauConstant(vmConstOp(inst.a))); else if (inst.a.kind == IrOpKind::Inst) - build.vmovups(inst.regX64, xmmword[regOp(inst.a)]); + build.vmovups(inst.regX64, xmmword[regOp(inst.a) + addrOffset]); else LUAU_ASSERT(!"Unsupported instruction form"); break; - case IrCmd::LOAD_NODE_VALUE_TV: - inst.regX64 = regs.allocReg(SizeX64::xmmword, index); - - build.vmovups(inst.regX64, luauNodeValue(regOp(inst.a))); - break; + } case IrCmd::LOAD_ENV: inst.regX64 = regs.allocReg(SizeX64::qword, index); @@ -252,16 +251,59 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) storeDoubleAsFloat(luauRegValueVector(vmRegOp(inst.a), 2), inst.d); break; case IrCmd::STORE_TVALUE: + { + int addrOffset = inst.c.kind != IrOpKind::None ? intOp(inst.c) : 0; + if (inst.a.kind == IrOpKind::VmReg) build.vmovups(luauReg(vmRegOp(inst.a)), regOp(inst.b)); else if (inst.a.kind == IrOpKind::Inst) - build.vmovups(xmmword[regOp(inst.a)], regOp(inst.b)); + build.vmovups(xmmword[regOp(inst.a) + addrOffset], regOp(inst.b)); else LUAU_ASSERT(!"Unsupported instruction form"); break; - case IrCmd::STORE_NODE_VALUE_TV: - build.vmovups(luauNodeValue(regOp(inst.a)), regOp(inst.b)); + } + case IrCmd::STORE_SPLIT_TVALUE: + { + int addrOffset = inst.d.kind != IrOpKind::None ? intOp(inst.d) : 0; + + OperandX64 tagLhs = inst.a.kind == IrOpKind::Inst ? dword[regOp(inst.a) + offsetof(TValue, tt) + addrOffset] : luauRegTag(vmRegOp(inst.a)); + build.mov(tagLhs, tagOp(inst.b)); + + if (tagOp(inst.b) == LUA_TBOOLEAN) + { + OperandX64 valueLhs = + inst.a.kind == IrOpKind::Inst ? dword[regOp(inst.a) + offsetof(TValue, value) + addrOffset] : luauRegValueInt(vmRegOp(inst.a)); + build.mov(valueLhs, inst.c.kind == IrOpKind::Constant ? OperandX64(intOp(inst.c)) : regOp(inst.c)); + } + else if (tagOp(inst.b) == LUA_TNUMBER) + { + OperandX64 valueLhs = + inst.a.kind == IrOpKind::Inst ? qword[regOp(inst.a) + offsetof(TValue, value) + addrOffset] : luauRegValue(vmRegOp(inst.a)); + + if (inst.c.kind == IrOpKind::Constant) + { + ScopedRegX64 tmp{regs, SizeX64::xmmword}; + + build.vmovsd(tmp.reg, build.f64(doubleOp(inst.c))); + build.vmovsd(valueLhs, tmp.reg); + } + else + { + build.vmovsd(valueLhs, regOp(inst.c)); + } + } + else if (isGCO(tagOp(inst.b))) + { + OperandX64 valueLhs = + inst.a.kind == IrOpKind::Inst ? qword[regOp(inst.a) + offsetof(TValue, value) + addrOffset] : luauRegValue(vmRegOp(inst.a)); + build.mov(valueLhs, regOp(inst.c)); + } + else + { + LUAU_ASSERT(!"Unsupported instruction form"); + } break; + } case IrCmd::ADD_INT: { inst.regX64 = regs.allocRegOrReuse(SizeX64::dword, index, {inst.a}); @@ -951,7 +993,8 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) tmp1.free(); - callBarrierObject(regs, build, tmp2.release(), {}, vmRegOp(inst.b), /* ratag */ -1); + if (inst.c.kind == IrOpKind::Undef || isGCO(tagOp(inst.c))) + callBarrierObject(regs, build, tmp2.release(), {}, vmRegOp(inst.b), inst.c.kind == IrOpKind::Undef ? -1 : tagOp(inst.c)); break; } case IrCmd::PREPARE_FORN: @@ -1540,9 +1583,17 @@ void IrLoweringX64::lowerInst(IrInst& inst, uint32_t index, const IrBlock& next) regs.freeLastUseRegs(inst, index); } -void IrLoweringX64::finishBlock() +void IrLoweringX64::finishBlock(const IrBlock& curr, const IrBlock& next) { - regs.assertNoSpills(); + if (!regs.spills.empty()) + { + // If we have spills remaining, we have to immediately lower the successor block + for (uint32_t predIdx : predecessors(function.cfg, function.getBlockIndex(next))) + LUAU_ASSERT(predIdx == function.getBlockIndex(curr)); + + // And the next block cannot be a join block in cfg + LUAU_ASSERT(next.useCount == 1); + } } void IrLoweringX64::finishFunction() diff --git a/CodeGen/src/IrLoweringX64.h b/CodeGen/src/IrLoweringX64.h index c32e3e61..a32e034d 100644 --- a/CodeGen/src/IrLoweringX64.h +++ b/CodeGen/src/IrLoweringX64.h @@ -28,7 +28,7 @@ struct IrLoweringX64 IrLoweringX64(AssemblyBuilderX64& build, ModuleHelpers& helpers, IrFunction& function); void lowerInst(IrInst& inst, uint32_t index, const IrBlock& next); - void finishBlock(); + void finishBlock(const IrBlock& curr, const IrBlock& next); void finishFunction(); bool hasError() const; diff --git a/CodeGen/src/IrRegAllocA64.cpp b/CodeGen/src/IrRegAllocA64.cpp index 02d7df98..5afcc8dd 100644 --- a/CodeGen/src/IrRegAllocA64.cpp +++ b/CodeGen/src/IrRegAllocA64.cpp @@ -411,11 +411,6 @@ void IrRegAllocA64::restoreReg(AssemblyBuilderA64& build, IrInst& inst) LUAU_ASSERT(!"Expected to find a spill record"); } -void IrRegAllocA64::assertNoSpills() const -{ - LUAU_ASSERT(spills.empty()); -} - IrRegAllocA64::Set& IrRegAllocA64::getSet(KindA64 kind) { switch (kind) diff --git a/CodeGen/src/IrRegAllocA64.h b/CodeGen/src/IrRegAllocA64.h index 854a9f10..ae3110d7 100644 --- a/CodeGen/src/IrRegAllocA64.h +++ b/CodeGen/src/IrRegAllocA64.h @@ -43,8 +43,6 @@ struct IrRegAllocA64 // Restores register for a single instruction; may not assign the previously used register! void restoreReg(AssemblyBuilderA64& build, IrInst& inst); - void assertNoSpills() const; - struct Set { // which registers are in the set that the allocator manages (initialized at construction) diff --git a/CodeGen/src/IrRegAllocX64.cpp b/CodeGen/src/IrRegAllocX64.cpp index b81aec8c..607c975f 100644 --- a/CodeGen/src/IrRegAllocX64.cpp +++ b/CodeGen/src/IrRegAllocX64.cpp @@ -54,7 +54,12 @@ RegisterX64 IrRegAllocX64::allocReg(SizeX64 size, uint32_t instIdx) // Out of registers, spill the value with the furthest next use const std::array& regInstUsers = size == SizeX64::xmmword ? xmmInstUsers : gprInstUsers; if (uint32_t furthestUseTarget = findInstructionWithFurthestNextUse(regInstUsers); furthestUseTarget != kInvalidInstIdx) - return takeReg(function.instructions[furthestUseTarget].regX64, instIdx); + { + RegisterX64 reg = function.instructions[furthestUseTarget].regX64; + reg.size = size; // Adjust size to the requested + + return takeReg(reg, instIdx); + } LUAU_ASSERT(!"Out of registers to allocate"); return noreg; diff --git a/CodeGen/src/IrTranslation.cpp b/CodeGen/src/IrTranslation.cpp index 363a1cdb..38922131 100644 --- a/CodeGen/src/IrTranslation.cpp +++ b/CodeGen/src/IrTranslation.cpp @@ -2,6 +2,7 @@ #include "IrTranslation.h" #include "Luau/Bytecode.h" +#include "Luau/BytecodeUtils.h" #include "Luau/IrBuilder.h" #include "Luau/IrUtils.h" @@ -526,7 +527,7 @@ void translateInstSetUpval(IrBuilder& build, const Instruction* pc, int pcpos) int ra = LUAU_INSN_A(*pc); int up = LUAU_INSN_B(*pc); - build.inst(IrCmd::SET_UPVALUE, build.vmUpvalue(up), build.vmReg(ra)); + build.inst(IrCmd::SET_UPVALUE, build.vmUpvalue(up), build.vmReg(ra), build.undef()); } void translateInstCloseUpvals(IrBuilder& build, const Instruction* pc) @@ -988,7 +989,7 @@ void translateInstGetTableKS(IrBuilder& build, const Instruction* pc, int pcpos) build.inst(IrCmd::CHECK_SLOT_MATCH, addrSlotEl, build.vmConst(aux), fallback); - IrOp tvn = build.inst(IrCmd::LOAD_NODE_VALUE_TV, addrSlotEl); + IrOp tvn = build.inst(IrCmd::LOAD_TVALUE, addrSlotEl, build.constInt(offsetof(LuaNode, val))); build.inst(IrCmd::STORE_TVALUE, build.vmReg(ra), tvn); IrOp next = build.blockAtInst(pcpos + 2); @@ -1017,7 +1018,7 @@ void translateInstSetTableKS(IrBuilder& build, const Instruction* pc, int pcpos) build.inst(IrCmd::CHECK_READONLY, vb, fallback); IrOp tva = build.inst(IrCmd::LOAD_TVALUE, build.vmReg(ra)); - build.inst(IrCmd::STORE_NODE_VALUE_TV, addrSlotEl, tva); + build.inst(IrCmd::STORE_TVALUE, addrSlotEl, tva, build.constInt(offsetof(LuaNode, val))); build.inst(IrCmd::BARRIER_TABLE_FORWARD, vb, build.vmReg(ra), build.undef()); @@ -1040,7 +1041,7 @@ void translateInstGetGlobal(IrBuilder& build, const Instruction* pc, int pcpos) build.inst(IrCmd::CHECK_SLOT_MATCH, addrSlotEl, build.vmConst(aux), fallback); - IrOp tvn = build.inst(IrCmd::LOAD_NODE_VALUE_TV, addrSlotEl); + IrOp tvn = build.inst(IrCmd::LOAD_TVALUE, addrSlotEl, build.constInt(offsetof(LuaNode, val))); build.inst(IrCmd::STORE_TVALUE, build.vmReg(ra), tvn); IrOp next = build.blockAtInst(pcpos + 2); @@ -1064,7 +1065,7 @@ void translateInstSetGlobal(IrBuilder& build, const Instruction* pc, int pcpos) build.inst(IrCmd::CHECK_READONLY, env, fallback); IrOp tva = build.inst(IrCmd::LOAD_TVALUE, build.vmReg(ra)); - build.inst(IrCmd::STORE_NODE_VALUE_TV, addrSlotEl, tva); + build.inst(IrCmd::STORE_TVALUE, addrSlotEl, tva, build.constInt(offsetof(LuaNode, val))); build.inst(IrCmd::BARRIER_TABLE_FORWARD, env, build.vmReg(ra), build.undef()); @@ -1136,7 +1137,7 @@ void translateInstNamecall(IrBuilder& build, const Instruction* pc, int pcpos) build.inst(IrCmd::STORE_POINTER, build.vmReg(ra + 1), table); build.inst(IrCmd::STORE_TAG, build.vmReg(ra + 1), build.constTag(LUA_TTABLE)); - IrOp nodeEl = build.inst(IrCmd::LOAD_NODE_VALUE_TV, addrNodeEl); + IrOp nodeEl = build.inst(IrCmd::LOAD_TVALUE, addrNodeEl, build.constInt(offsetof(LuaNode, val))); build.inst(IrCmd::STORE_TVALUE, build.vmReg(ra), nodeEl); build.inst(IrCmd::JUMP, next); @@ -1158,7 +1159,7 @@ void translateInstNamecall(IrBuilder& build, const Instruction* pc, int pcpos) build.inst(IrCmd::STORE_POINTER, build.vmReg(ra + 1), table2); build.inst(IrCmd::STORE_TAG, build.vmReg(ra + 1), build.constTag(LUA_TTABLE)); - IrOp indexNodeEl = build.inst(IrCmd::LOAD_NODE_VALUE_TV, addrIndexNodeEl); + IrOp indexNodeEl = build.inst(IrCmd::LOAD_TVALUE, addrIndexNodeEl, build.constInt(offsetof(LuaNode, val))); build.inst(IrCmd::STORE_TVALUE, build.vmReg(ra), indexNodeEl); build.inst(IrCmd::JUMP, next); diff --git a/CodeGen/src/IrTranslation.h b/CodeGen/src/IrTranslation.h index aff18b30..3736b44d 100644 --- a/CodeGen/src/IrTranslation.h +++ b/CodeGen/src/IrTranslation.h @@ -1,8 +1,6 @@ // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details #pragma once -#include "Luau/Bytecode.h" - #include #include "ltm.h" @@ -67,38 +65,5 @@ void translateInstAndX(IrBuilder& build, const Instruction* pc, int pcpos, IrOp void translateInstOrX(IrBuilder& build, const Instruction* pc, int pcpos, IrOp c); void translateInstNewClosure(IrBuilder& build, const Instruction* pc, int pcpos); -inline int getOpLength(LuauOpcode op) -{ - switch (op) - { - case LOP_GETGLOBAL: - case LOP_SETGLOBAL: - case LOP_GETIMPORT: - case LOP_GETTABLEKS: - case LOP_SETTABLEKS: - case LOP_NAMECALL: - case LOP_JUMPIFEQ: - case LOP_JUMPIFLE: - case LOP_JUMPIFLT: - case LOP_JUMPIFNOTEQ: - case LOP_JUMPIFNOTLE: - case LOP_JUMPIFNOTLT: - case LOP_NEWTABLE: - case LOP_SETLIST: - case LOP_FORGLOOP: - case LOP_LOADKX: - case LOP_FASTCALL2: - case LOP_FASTCALL2K: - case LOP_JUMPXEQKNIL: - case LOP_JUMPXEQKB: - case LOP_JUMPXEQKN: - case LOP_JUMPXEQKS: - return 2; - - default: - return 1; - } -} - } // namespace CodeGen } // namespace Luau diff --git a/CodeGen/src/IrUtils.cpp b/CodeGen/src/IrUtils.cpp index c2d3e1a8..e5a55f11 100644 --- a/CodeGen/src/IrUtils.cpp +++ b/CodeGen/src/IrUtils.cpp @@ -32,7 +32,6 @@ IrValueKind getCmdValueKind(IrCmd cmd) case IrCmd::LOAD_INT: return IrValueKind::Int; case IrCmd::LOAD_TVALUE: - case IrCmd::LOAD_NODE_VALUE_TV: return IrValueKind::Tvalue; case IrCmd::LOAD_ENV: case IrCmd::GET_ARR_ADDR: @@ -46,7 +45,7 @@ IrValueKind getCmdValueKind(IrCmd cmd) case IrCmd::STORE_INT: case IrCmd::STORE_VECTOR: case IrCmd::STORE_TVALUE: - case IrCmd::STORE_NODE_VALUE_TV: + case IrCmd::STORE_SPLIT_TVALUE: return IrValueKind::None; case IrCmd::ADD_INT: case IrCmd::SUB_INT: @@ -216,6 +215,8 @@ void removeUse(IrFunction& function, IrOp op) bool isGCO(uint8_t tag) { + LUAU_ASSERT(tag < LUA_T_COUNT); + // mirrors iscollectable(o) from VM/lobject.h return tag >= LUA_TSTRING; } @@ -388,6 +389,7 @@ void applySubstitutions(IrFunction& function, IrInst& inst) bool compare(double a, double b, IrCondition cond) { + // Note: redundant bool() casts work around invalid MSVC optimization that merges cases in this switch, violating IEEE754 comparison semantics switch (cond) { case IrCondition::Equal: @@ -397,19 +399,19 @@ bool compare(double a, double b, IrCondition cond) case IrCondition::Less: return a < b; case IrCondition::NotLess: - return !(a < b); + return !bool(a < b); case IrCondition::LessEqual: return a <= b; case IrCondition::NotLessEqual: - return !(a <= b); + return !bool(a <= b); case IrCondition::Greater: return a > b; case IrCondition::NotGreater: - return !(a > b); + return !bool(a > b); case IrCondition::GreaterEqual: return a >= b; case IrCondition::NotGreaterEqual: - return !(a >= b); + return !bool(a >= b); default: LUAU_ASSERT(!"Unsupported condition"); } diff --git a/CodeGen/src/IrValueLocationTracking.cpp b/CodeGen/src/IrValueLocationTracking.cpp index 4536630b..e781bda3 100644 --- a/CodeGen/src/IrValueLocationTracking.cpp +++ b/CodeGen/src/IrValueLocationTracking.cpp @@ -28,6 +28,7 @@ void IrValueLocationTracking::beforeInstLowering(IrInst& inst) case IrCmd::STORE_INT: case IrCmd::STORE_VECTOR: case IrCmd::STORE_TVALUE: + case IrCmd::STORE_SPLIT_TVALUE: invalidateRestoreOp(inst.a); break; case IrCmd::ADJUST_STACK_TO_REG: diff --git a/CodeGen/src/OptimizeConstProp.cpp b/CodeGen/src/OptimizeConstProp.cpp index d0ecd7dd..9ef57afa 100644 --- a/CodeGen/src/OptimizeConstProp.cpp +++ b/CodeGen/src/OptimizeConstProp.cpp @@ -9,6 +9,7 @@ #include "lua.h" #include +#include #include LUAU_FASTINTVARIABLE(LuauCodeGenMinLinearBlockPath, 3) @@ -31,6 +32,7 @@ struct RegisterInfo bool knownNotReadonly = false; bool knownNoMetatable = false; + int knownTableArraySize = -1; }; // Load instructions are linked to target register to carry knowledge about the target @@ -95,6 +97,7 @@ struct ConstPropState info->value = value; info->knownNotReadonly = false; info->knownNoMetatable = false; + info->knownTableArraySize = -1; info->version++; } } @@ -112,6 +115,7 @@ struct ConstPropState reg.value = {}; reg.knownNotReadonly = false; reg.knownNoMetatable = false; + reg.knownTableArraySize = -1; } reg.version++; @@ -176,6 +180,7 @@ struct ConstPropState { reg.knownNotReadonly = false; reg.knownNoMetatable = false; + reg.knownTableArraySize = -1; } void invalidateUserCall() @@ -236,28 +241,66 @@ struct ConstPropState return IrInst{loadCmd, op}; } + uint32_t* getPreviousInstIndex(const IrInst& inst) + { + LUAU_ASSERT(useValueNumbering); + + if (uint32_t* prevIdx = valueMap.find(inst)) + { + // Previous load might have been removed as unused + if (function.instructions[*prevIdx].useCount != 0) + return prevIdx; + } + + return nullptr; + } + + uint32_t* getPreviousVersionedLoadIndex(IrCmd cmd, IrOp vmReg) + { + LUAU_ASSERT(vmReg.kind == IrOpKind::VmReg); + return getPreviousInstIndex(versionedVmRegLoad(cmd, vmReg)); + } + + std::pair getPreviousVersionedLoadForTag(uint8_t tag, IrOp vmReg) + { + if (useValueNumbering && !function.cfg.captured.regs.test(vmRegOp(vmReg))) + { + if (tag == LUA_TBOOLEAN) + { + if (uint32_t* prevIdx = getPreviousVersionedLoadIndex(IrCmd::LOAD_INT, vmReg)) + return std::make_pair(IrCmd::LOAD_INT, *prevIdx); + } + else if (tag == LUA_TNUMBER) + { + if (uint32_t* prevIdx = getPreviousVersionedLoadIndex(IrCmd::LOAD_DOUBLE, vmReg)) + return std::make_pair(IrCmd::LOAD_DOUBLE, *prevIdx); + } + else if (isGCO(tag)) + { + if (uint32_t* prevIdx = getPreviousVersionedLoadIndex(IrCmd::LOAD_POINTER, vmReg)) + return std::make_pair(IrCmd::LOAD_POINTER, *prevIdx); + } + } + + return std::make_pair(IrCmd::NOP, kInvalidInstIdx); + } + // Find existing value of the instruction that is exactly the same, or record current on for future lookups void substituteOrRecord(IrInst& inst, uint32_t instIdx) { if (!useValueNumbering) return; - if (uint32_t* prevIdx = valueMap.find(inst)) + if (uint32_t* prevIdx = getPreviousInstIndex(inst)) { - const IrInst& prev = function.instructions[*prevIdx]; - - // Previous load might have been removed as unused - if (prev.useCount != 0) - { - substitute(function, inst, IrOp{IrOpKind::Inst, *prevIdx}); - return; - } + substitute(function, inst, IrOp{IrOpKind::Inst, *prevIdx}); + return; } valueMap[inst] = instIdx; } - // Vm register load can be replaced by a previous load of the same version of the register + // VM register load can be replaced by a previous load of the same version of the register // If there is no previous load, we record the current one for future lookups void substituteOrRecordVmRegLoad(IrInst& loadInst) { @@ -274,22 +317,16 @@ struct ConstPropState IrInst versionedLoad = versionedVmRegLoad(loadInst.cmd, loadInst.a); // Check if there is a value that already has this version of the register - if (uint32_t* prevIdx = valueMap.find(versionedLoad)) + if (uint32_t* prevIdx = getPreviousInstIndex(versionedLoad)) { - const IrInst& prev = function.instructions[*prevIdx]; + // Previous value might not be linked to a register yet + // For example, it could be a NEW_TABLE stored into a register and we might need to track guards made with this value + if (!instLink.contains(*prevIdx)) + createRegLink(*prevIdx, loadInst.a); - // Previous load might have been removed as unused - if (prev.useCount != 0) - { - // Previous value might not be linked to a register yet - // For example, it could be a NEW_TABLE stored into a register and we might need to track guards made with this value - if (!instLink.contains(*prevIdx)) - createRegLink(*prevIdx, loadInst.a); - - // Substitute load instructon with the previous value - substitute(function, loadInst, IrOp{IrOpKind::Inst, *prevIdx}); - return; - } + // Substitute load instructon with the previous value + substitute(function, loadInst, IrOp{IrOpKind::Inst, *prevIdx}); + return; } uint32_t instIdx = function.getInstIndex(loadInst); @@ -403,10 +440,8 @@ static void handleBuiltinEffects(ConstPropState& state, LuauBuiltinFunction bfid case LBF_MATH_CLAMP: case LBF_MATH_SIGN: case LBF_MATH_ROUND: - case LBF_RAWSET: case LBF_RAWGET: case LBF_RAWEQUAL: - case LBF_TABLE_INSERT: case LBF_TABLE_UNPACK: case LBF_VECTOR: case LBF_BIT32_COUNTLZ: @@ -418,6 +453,12 @@ static void handleBuiltinEffects(ConstPropState& state, LuauBuiltinFunction bfid case LBF_TONUMBER: case LBF_TOSTRING: break; + case LBF_TABLE_INSERT: + state.invalidateHeap(); + return; // table.insert does not modify result registers. + case LBF_RAWSET: + state.invalidateHeap(); + break; case LBF_SETMETATABLE: state.invalidateHeap(); // TODO: only knownNoMetatable is affected and we might know which one break; @@ -470,21 +511,18 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& if (inst.a.kind == IrOpKind::VmReg) { const IrOp source = inst.a; - uint32_t activeLoadDoubleValue = kInvalidInstIdx; + + IrCmd activeLoadCmd = IrCmd::NOP; + uint32_t activeLoadValue = kInvalidInstIdx; if (inst.b.kind == IrOpKind::Constant) { uint8_t value = function.tagOp(inst.b); // STORE_TAG usually follows a store of the value, but it also bumps the version of the whole register - // To be able to propagate STORE_DOUBLE into LOAD_DOUBLE, we find active LOAD_DOUBLE value and recreate it with updated version + // To be able to propagate STORE_*** into LOAD_***, we find active LOAD_*** value and recreate it with updated version // Register in this optimization cannot be captured to avoid complications in lowering (IrValueLocationTracking doesn't model it) - // If stored tag is not a number, we can skip the lookup as there won't be future loads of this register as a number - if (value == LUA_TNUMBER && !function.cfg.captured.regs.test(vmRegOp(source))) - { - if (uint32_t* prevIdx = state.valueMap.find(state.versionedVmRegLoad(IrCmd::LOAD_DOUBLE, source))) - activeLoadDoubleValue = *prevIdx; - } + std::tie(activeLoadCmd, activeLoadValue) = state.getPreviousVersionedLoadForTag(value, source); if (state.tryGetTag(source) == value) { @@ -503,9 +541,9 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& state.invalidateTag(source); } - // Future LOAD_DOUBLE instructions can re-use previous register version load - if (activeLoadDoubleValue != kInvalidInstIdx) - state.valueMap[state.versionedVmRegLoad(IrCmd::LOAD_DOUBLE, source)] = activeLoadDoubleValue; + // Future LOAD_*** instructions can re-use previous register version load + if (activeLoadValue != kInvalidInstIdx) + state.valueMap[state.versionedVmRegLoad(activeLoadCmd, source)] = activeLoadValue; } break; case IrCmd::STORE_POINTER: @@ -520,6 +558,7 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& { info->knownNotReadonly = true; info->knownNoMetatable = true; + info->knownTableArraySize = function.uintOp(instOp->a); } } } @@ -562,17 +601,62 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& state.invalidateValue(inst.a); break; case IrCmd::STORE_TVALUE: + if (inst.a.kind == IrOpKind::VmReg || inst.a.kind == IrOpKind::Inst) + { + if (inst.a.kind == IrOpKind::VmReg) + state.invalidate(inst.a); + + uint8_t tag = state.tryGetTag(inst.b); + IrOp value = state.tryGetValue(inst.b); + + if (inst.a.kind == IrOpKind::VmReg) + { + if (tag != 0xff) + state.saveTag(inst.a, tag); + + if (value.kind != IrOpKind::None) + state.saveValue(inst.a, value); + } + + IrCmd activeLoadCmd = IrCmd::NOP; + uint32_t activeLoadValue = kInvalidInstIdx; + + if (tag != 0xff) + { + // If we know the tag, try to extract the value from a register used by LOAD_TVALUE + if (IrInst* arg = function.asInstOp(inst.b); arg && arg->cmd == IrCmd::LOAD_TVALUE && arg->a.kind == IrOpKind::VmReg) + { + std::tie(activeLoadCmd, activeLoadValue) = state.getPreviousVersionedLoadForTag(tag, arg->a); + + if (activeLoadValue != kInvalidInstIdx) + value = IrOp{IrOpKind::Inst, activeLoadValue}; + } + } + + // If we have constant tag and value, replace TValue store with tag/value pair store + if (tag != 0xff && value.kind != IrOpKind::None && (tag == LUA_TBOOLEAN || tag == LUA_TNUMBER || isGCO(tag))) + { + replace(function, block, index, {IrCmd::STORE_SPLIT_TVALUE, inst.a, build.constTag(tag), value, inst.c}); + + // Value can be propagated to future loads of the same register + if (inst.a.kind == IrOpKind::VmReg && activeLoadValue != kInvalidInstIdx) + state.valueMap[state.versionedVmRegLoad(activeLoadCmd, inst.a)] = activeLoadValue; + } + else if (inst.a.kind == IrOpKind::VmReg) + { + state.forwardVmRegStoreToLoad(inst, IrCmd::LOAD_TVALUE); + } + } + break; + case IrCmd::STORE_SPLIT_TVALUE: if (inst.a.kind == IrOpKind::VmReg) { state.invalidate(inst.a); - if (uint8_t tag = state.tryGetTag(inst.b); tag != 0xff) - state.saveTag(inst.a, tag); + state.saveTag(inst.a, function.tagOp(inst.b)); - if (IrOp value = state.tryGetValue(inst.b); value.kind != IrOpKind::None) - state.saveValue(inst.a, value); - - state.forwardVmRegStoreToLoad(inst, IrCmd::LOAD_TVALUE); + if (inst.c.kind == IrOpKind::Constant) + state.saveValue(inst.a, inst.c); } break; case IrCmd::JUMP_IF_TRUTHY: @@ -666,6 +750,15 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& case IrCmd::GET_UPVALUE: state.invalidate(inst.a); break; + case IrCmd::SET_UPVALUE: + if (inst.b.kind == IrOpKind::VmReg) + { + if (uint8_t tag = state.tryGetTag(inst.b); tag != 0xff) + { + replace(function, inst.c, build.constTag(tag)); + } + } + break; case IrCmd::CHECK_TAG: { uint8_t b = function.tagOp(inst.b); @@ -768,8 +861,6 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& // These instructions don't have an effect on register/memory state we are tracking case IrCmd::NOP: - case IrCmd::LOAD_NODE_VALUE_TV: - case IrCmd::STORE_NODE_VALUE_TV: case IrCmd::LOAD_ENV: case IrCmd::GET_ARR_ADDR: case IrCmd::GET_SLOT_NODE_ADDR: @@ -824,12 +915,33 @@ static void constPropInInst(ConstPropState& state, IrBuilder& build, IrFunction& state.substituteOrRecord(inst, index); break; case IrCmd::CHECK_ARRAY_SIZE: + { + std::optional arrayIndex = function.asIntOp(inst.b.kind == IrOpKind::Constant ? inst.b : state.tryGetValue(inst.b)); + + if (RegisterInfo* info = state.tryGetRegisterInfo(inst.a); info && arrayIndex) + { + if (info->knownTableArraySize >= 0) + { + if (unsigned(*arrayIndex) < unsigned(info->knownTableArraySize)) + { + if (FFlag::DebugLuauAbortingChecks) + replace(function, inst.c, build.undef()); + else + kill(function, inst); + } + else + { + replace(function, block, index, {IrCmd::JUMP, inst.c}); + } + } + } + break; + } case IrCmd::CHECK_SLOT_MATCH: case IrCmd::CHECK_NODE_NO_NEXT: case IrCmd::BARRIER_TABLE_BACK: case IrCmd::RETURN: case IrCmd::COVERAGE: - case IrCmd::SET_UPVALUE: case IrCmd::SET_SAVEDPC: // TODO: we may be able to remove some updates to PC case IrCmd::CLOSE_UPVALS: // Doesn't change memory that we track case IrCmd::CAPTURE: diff --git a/Common/include/Luau/BytecodeUtils.h b/Common/include/Luau/BytecodeUtils.h new file mode 100644 index 00000000..957c804c --- /dev/null +++ b/Common/include/Luau/BytecodeUtils.h @@ -0,0 +1,42 @@ +// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details +#pragma once + +#include "Luau/Bytecode.h" + +namespace Luau +{ + +inline int getOpLength(LuauOpcode op) +{ + switch (op) + { + case LOP_GETGLOBAL: + case LOP_SETGLOBAL: + case LOP_GETIMPORT: + case LOP_GETTABLEKS: + case LOP_SETTABLEKS: + case LOP_NAMECALL: + case LOP_JUMPIFEQ: + case LOP_JUMPIFLE: + case LOP_JUMPIFLT: + case LOP_JUMPIFNOTEQ: + case LOP_JUMPIFNOTLE: + case LOP_JUMPIFNOTLT: + case LOP_NEWTABLE: + case LOP_SETLIST: + case LOP_FORGLOOP: + case LOP_LOADKX: + case LOP_FASTCALL2: + case LOP_FASTCALL2K: + case LOP_JUMPXEQKNIL: + case LOP_JUMPXEQKB: + case LOP_JUMPXEQKN: + case LOP_JUMPXEQKS: + return 2; + + default: + return 1; + } +} + +} // namespace Luau diff --git a/Compiler/include/Luau/BytecodeBuilder.h b/Compiler/include/Luau/BytecodeBuilder.h index 3044e448..48b89404 100644 --- a/Compiler/include/Luau/BytecodeBuilder.h +++ b/Compiler/include/Luau/BytecodeBuilder.h @@ -16,6 +16,7 @@ public: virtual ~BytecodeEncoder() {} virtual uint8_t encodeOp(uint8_t op) = 0; + virtual void encode(uint32_t* data, size_t count) = 0; }; class BytecodeBuilder diff --git a/Compiler/src/BytecodeBuilder.cpp b/Compiler/src/BytecodeBuilder.cpp index eeb9c10e..96754569 100644 --- a/Compiler/src/BytecodeBuilder.cpp +++ b/Compiler/src/BytecodeBuilder.cpp @@ -1,12 +1,14 @@ // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details #include "Luau/BytecodeBuilder.h" +#include "Luau/BytecodeUtils.h" #include "Luau/StringUtils.h" #include #include LUAU_FASTFLAGVARIABLE(BytecodeVersion4, false) +LUAU_FASTFLAGVARIABLE(BytecodeEnc, false) namespace Luau { @@ -55,39 +57,6 @@ static void writeVarInt(std::string& ss, unsigned int value) } while (value); } -static int getOpLength(LuauOpcode op) -{ - switch (op) - { - case LOP_GETGLOBAL: - case LOP_SETGLOBAL: - case LOP_GETIMPORT: - case LOP_GETTABLEKS: - case LOP_SETTABLEKS: - case LOP_NAMECALL: - case LOP_JUMPIFEQ: - case LOP_JUMPIFLE: - case LOP_JUMPIFLT: - case LOP_JUMPIFNOTEQ: - case LOP_JUMPIFNOTLE: - case LOP_JUMPIFNOTLT: - case LOP_NEWTABLE: - case LOP_SETLIST: - case LOP_FORGLOOP: - case LOP_LOADKX: - case LOP_FASTCALL2: - case LOP_FASTCALL2K: - case LOP_JUMPXEQKNIL: - case LOP_JUMPXEQKB: - case LOP_JUMPXEQKN: - case LOP_JUMPXEQKS: - return 2; - - default: - return 1; - } -} - inline bool isJumpD(LuauOpcode op) { switch (op) @@ -262,17 +231,20 @@ void BytecodeBuilder::endFunction(uint8_t maxstacksize, uint8_t numupvalues, uin validate(); #endif + // this call is indirect to make sure we only gain link time dependency on dumpCurrentFunction when needed + if (dumpFunctionPtr) + func.dump = (this->*dumpFunctionPtr)(func.dumpinstoffs); + // very approximate: 4 bytes per instruction for code, 1 byte for debug line, and 1-2 bytes for aux data like constants plus overhead func.data.reserve(32 + insns.size() * 7); + if (FFlag::BytecodeEnc && encoder) + encoder->encode(insns.data(), insns.size()); + writeFunction(func.data, currentFunction, flags); currentFunction = ~0u; - // this call is indirect to make sure we only gain link time dependency on dumpCurrentFunction when needed - if (dumpFunctionPtr) - func.dump = (this->*dumpFunctionPtr)(func.dumpinstoffs); - insns.clear(); lines.clear(); constants.clear(); @@ -653,20 +625,28 @@ void BytecodeBuilder::writeFunction(std::string& ss, uint32_t id, uint8_t flags) // instructions writeVarInt(ss, uint32_t(insns.size())); - for (size_t i = 0; i < insns.size();) + if (encoder && !FFlag::BytecodeEnc) { - uint8_t op = LUAU_INSN_OP(insns[i]); - LUAU_ASSERT(op < LOP__COUNT); + for (size_t i = 0; i < insns.size();) + { + uint8_t op = LUAU_INSN_OP(insns[i]); + LUAU_ASSERT(op < LOP__COUNT); - int oplen = getOpLength(LuauOpcode(op)); - uint8_t openc = encoder ? encoder->encodeOp(op) : op; + int oplen = getOpLength(LuauOpcode(op)); + uint8_t openc = encoder->encodeOp(op); - writeInt(ss, openc | (insns[i] & ~0xff)); + writeInt(ss, openc | (insns[i] & ~0xff)); - for (int j = 1; j < oplen; ++j) - writeInt(ss, insns[i + j]); + for (int j = 1; j < oplen; ++j) + writeInt(ss, insns[i + j]); - i += oplen; + i += oplen; + } + } + else + { + for (uint32_t insn : insns) + writeInt(ss, insn); } // constants diff --git a/Compiler/src/Compiler.cpp b/Compiler/src/Compiler.cpp index 226cd2ee..b673ffc2 100644 --- a/Compiler/src/Compiler.cpp +++ b/Compiler/src/Compiler.cpp @@ -26,8 +26,6 @@ LUAU_FASTINTVARIABLE(LuauCompileInlineThreshold, 25) LUAU_FASTINTVARIABLE(LuauCompileInlineThresholdMaxBoost, 300) LUAU_FASTINTVARIABLE(LuauCompileInlineDepth, 5) -LUAU_FASTFLAGVARIABLE(LuauCompileFixBuiltinArity, false) - LUAU_FASTFLAGVARIABLE(LuauCompileFoldMathK, false) namespace Luau @@ -793,15 +791,10 @@ struct Compiler return compileExprFastcallN(expr, target, targetCount, targetTop, multRet, regs, bfid); else if (options.optimizationLevel >= 2) { - if (FFlag::LuauCompileFixBuiltinArity) - { - // when a builtin is none-safe with matching arity, even if the last expression returns 0 or >1 arguments, - // we can rely on the behavior of the function being the same (none-safe means nil and none are interchangeable) - BuiltinInfo info = getBuiltinInfo(bfid); - if (int(expr->args.size) == info.params && (info.flags & BuiltinInfo::Flag_NoneSafe) != 0) - return compileExprFastcallN(expr, target, targetCount, targetTop, multRet, regs, bfid); - } - else if (int(expr->args.size) == getBuiltinInfo(bfid).params) + // when a builtin is none-safe with matching arity, even if the last expression returns 0 or >1 arguments, + // we can rely on the behavior of the function being the same (none-safe means nil and none are interchangeable) + BuiltinInfo info = getBuiltinInfo(bfid); + if (int(expr->args.size) == info.params && (info.flags & BuiltinInfo::Flag_NoneSafe) != 0) return compileExprFastcallN(expr, target, targetCount, targetTop, multRet, regs, bfid); } } diff --git a/Compiler/src/CostModel.cpp b/Compiler/src/CostModel.cpp index 2f7af6ea..04adf3e3 100644 --- a/Compiler/src/CostModel.cpp +++ b/Compiler/src/CostModel.cpp @@ -6,8 +6,6 @@ #include -LUAU_FASTFLAGVARIABLE(LuauAssignmentHasCost, false) - namespace Luau { namespace Compile @@ -308,10 +306,7 @@ struct CostVisitor : AstVisitor { // unconditional 'else' may require a jump after the 'if' body // note: this ignores cases when 'then' always terminates and also assumes comparison requires an extra instruction which may be false - if (!FFlag::LuauAssignmentHasCost) - result += 2; - else - result += 1 + (node->elsebody && !node->elsebody->is()); + result += 1 + (node->elsebody && !node->elsebody->is()); return true; } @@ -337,9 +332,6 @@ struct CostVisitor : AstVisitor for (size_t i = 0; i < node->vars.size; ++i) assign(node->vars.data[i]); - if (!FFlag::LuauAssignmentHasCost) - return true; - for (size_t i = 0; i < node->vars.size || i < node->values.size; ++i) { Cost ac; diff --git a/Analysis/include/Luau/Config.h b/Config/include/Luau/Config.h similarity index 100% rename from Analysis/include/Luau/Config.h rename to Config/include/Luau/Config.h diff --git a/Analysis/include/Luau/LinterConfig.h b/Config/include/Luau/LinterConfig.h similarity index 99% rename from Analysis/include/Luau/LinterConfig.h rename to Config/include/Luau/LinterConfig.h index 0d3b3b91..6b24db17 100644 --- a/Analysis/include/Luau/LinterConfig.h +++ b/Config/include/Luau/LinterConfig.h @@ -7,6 +7,8 @@ #include #include +#include + namespace Luau { diff --git a/Analysis/src/Config.cpp b/Config/src/Config.cpp similarity index 100% rename from Analysis/src/Config.cpp rename to Config/src/Config.cpp diff --git a/Analysis/src/LinterConfig.cpp b/Config/src/LinterConfig.cpp similarity index 100% rename from Analysis/src/LinterConfig.cpp rename to Config/src/LinterConfig.cpp diff --git a/Makefile b/Makefile index 17bae919..d1c2ac90 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,10 @@ COMPILER_SOURCES=$(wildcard Compiler/src/*.cpp) COMPILER_OBJECTS=$(COMPILER_SOURCES:%=$(BUILD)/%.o) COMPILER_TARGET=$(BUILD)/libluaucompiler.a +CONFIG_SOURCES=$(wildcard Config/src/*.cpp) +CONFIG_OBJECTS=$(CONFIG_SOURCES:%=$(BUILD)/%.o) +CONFIG_TARGET=$(BUILD)/libluauconfig.a + ANALYSIS_SOURCES=$(wildcard Analysis/src/*.cpp) ANALYSIS_OBJECTS=$(ANALYSIS_SOURCES:%=$(BUILD)/%.o) ANALYSIS_TARGET=$(BUILD)/libluauanalysis.a @@ -59,7 +63,7 @@ ifneq ($(opt),) TESTS_ARGS+=-O$(opt) endif -OBJECTS=$(AST_OBJECTS) $(COMPILER_OBJECTS) $(ANALYSIS_OBJECTS) $(CODEGEN_OBJECTS) $(VM_OBJECTS) $(ISOCLINE_OBJECTS) $(TESTS_OBJECTS) $(REPL_CLI_OBJECTS) $(ANALYZE_CLI_OBJECTS) $(COMPILE_CLI_OBJECTS) $(FUZZ_OBJECTS) +OBJECTS=$(AST_OBJECTS) $(COMPILER_OBJECTS) $(CONFIG_OBJECTS) $(ANALYSIS_OBJECTS) $(CODEGEN_OBJECTS) $(VM_OBJECTS) $(ISOCLINE_OBJECTS) $(TESTS_OBJECTS) $(REPL_CLI_OBJECTS) $(ANALYZE_CLI_OBJECTS) $(COMPILE_CLI_OBJECTS) $(FUZZ_OBJECTS) EXECUTABLE_ALIASES = luau luau-analyze luau-compile luau-tests # common flags @@ -129,13 +133,14 @@ endif # target-specific flags $(AST_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include $(COMPILER_OBJECTS): CXXFLAGS+=-std=c++17 -ICompiler/include -ICommon/include -IAst/include -$(ANALYSIS_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include -IAnalysis/include +$(CONFIG_OBJECTS): CXXFLAGS+=-std=c++17 -IConfig/include -ICommon/include -IAst/include +$(ANALYSIS_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include -IAnalysis/include -IConfig/include $(CODEGEN_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -ICodeGen/include -IVM/include -IVM/src # Code generation needs VM internals $(VM_OBJECTS): CXXFLAGS+=-std=c++11 -ICommon/include -IVM/include $(ISOCLINE_OBJECTS): CXXFLAGS+=-Wno-unused-function -Iextern/isocline/include -$(TESTS_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include -ICompiler/include -IAnalysis/include -ICodeGen/include -IVM/include -ICLI -Iextern -DDOCTEST_CONFIG_DOUBLE_STRINGIFY +$(TESTS_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include -ICompiler/include -IConfig/include -IAnalysis/include -ICodeGen/include -IVM/include -ICLI -Iextern -DDOCTEST_CONFIG_DOUBLE_STRINGIFY $(REPL_CLI_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include -ICompiler/include -IVM/include -ICodeGen/include -Iextern -Iextern/isocline/include -$(ANALYZE_CLI_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include -IAnalysis/include -Iextern +$(ANALYZE_CLI_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include -IAnalysis/include -IConfig/include -Iextern $(COMPILE_CLI_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include -ICompiler/include -IVM/include -ICodeGen/include $(FUZZ_OBJECTS): CXXFLAGS+=-std=c++17 -ICommon/include -IAst/include -ICompiler/include -IAnalysis/include -IVM/include -ICodeGen/include @@ -205,9 +210,9 @@ luau-tests: $(TESTS_TARGET) ln -fs $^ $@ # executable targets -$(TESTS_TARGET): $(TESTS_OBJECTS) $(ANALYSIS_TARGET) $(COMPILER_TARGET) $(AST_TARGET) $(CODEGEN_TARGET) $(VM_TARGET) $(ISOCLINE_TARGET) +$(TESTS_TARGET): $(TESTS_OBJECTS) $(ANALYSIS_TARGET) $(COMPILER_TARGET) $(CONFIG_TARGET) $(AST_TARGET) $(CODEGEN_TARGET) $(VM_TARGET) $(ISOCLINE_TARGET) $(REPL_CLI_TARGET): $(REPL_CLI_OBJECTS) $(COMPILER_TARGET) $(AST_TARGET) $(CODEGEN_TARGET) $(VM_TARGET) $(ISOCLINE_TARGET) -$(ANALYZE_CLI_TARGET): $(ANALYZE_CLI_OBJECTS) $(ANALYSIS_TARGET) $(AST_TARGET) +$(ANALYZE_CLI_TARGET): $(ANALYZE_CLI_OBJECTS) $(ANALYSIS_TARGET) $(AST_TARGET) $(CONFIG_TARGET) $(COMPILE_CLI_TARGET): $(COMPILE_CLI_OBJECTS) $(COMPILER_TARGET) $(AST_TARGET) $(CODEGEN_TARGET) $(VM_TARGET) $(TESTS_TARGET) $(REPL_CLI_TARGET) $(ANALYZE_CLI_TARGET) $(COMPILE_CLI_TARGET): @@ -223,12 +228,13 @@ fuzz-prototest: $(BUILD)/fuzz/prototest.cpp.o $(BUILD)/fuzz/protoprint.cpp.o $(B # static library targets $(AST_TARGET): $(AST_OBJECTS) $(COMPILER_TARGET): $(COMPILER_OBJECTS) +$(CONFIG_TARGET): $(CONFIG_OBJECTS) $(ANALYSIS_TARGET): $(ANALYSIS_OBJECTS) $(CODEGEN_TARGET): $(CODEGEN_OBJECTS) $(VM_TARGET): $(VM_OBJECTS) $(ISOCLINE_TARGET): $(ISOCLINE_OBJECTS) -$(AST_TARGET) $(COMPILER_TARGET) $(ANALYSIS_TARGET) $(CODEGEN_TARGET) $(VM_TARGET) $(ISOCLINE_TARGET): +$(AST_TARGET) $(COMPILER_TARGET) $(CONFIG_TARGET) $(ANALYSIS_TARGET) $(CODEGEN_TARGET) $(VM_TARGET) $(ISOCLINE_TARGET): ar rcs $@ $^ # object file targets diff --git a/Sources.cmake b/Sources.cmake index 8dcd2431..4776b6b8 100644 --- a/Sources.cmake +++ b/Sources.cmake @@ -4,6 +4,7 @@ if(NOT ${CMAKE_VERSION} VERSION_LESS "3.19") target_sources(Luau.Common PRIVATE Common/include/Luau/Common.h Common/include/Luau/Bytecode.h + Common/include/Luau/BytecodeUtils.h Common/include/Luau/DenseHash.h Common/include/Luau/ExperimentalFlags.h ) @@ -55,6 +56,15 @@ target_sources(Luau.Compiler PRIVATE Compiler/src/ValueTracking.h ) +# Luau.Config Sources +target_sources(Luau.Config PRIVATE + Config/include/Luau/Config.h + Config/include/Luau/LinterConfig.h + + Config/src/Config.cpp + Config/src/LinterConfig.cpp +) + # Luau.CodeGen Sources target_sources(Luau.CodeGen PRIVATE CodeGen/include/Luau/AddressA64.h @@ -145,7 +155,6 @@ target_sources(Luau.Analysis PRIVATE Analysis/include/Luau/BuiltinDefinitions.h Analysis/include/Luau/Cancellation.h Analysis/include/Luau/Clone.h - Analysis/include/Luau/Config.h Analysis/include/Luau/Constraint.h Analysis/include/Luau/ConstraintGraphBuilder.h Analysis/include/Luau/ConstraintSolver.h @@ -163,7 +172,6 @@ target_sources(Luau.Analysis PRIVATE Analysis/include/Luau/IostreamHelpers.h Analysis/include/Luau/JsonEmitter.h Analysis/include/Luau/Linter.h - Analysis/include/Luau/LinterConfig.h Analysis/include/Luau/LValue.h Analysis/include/Luau/Metamethods.h Analysis/include/Luau/Module.h @@ -177,6 +185,7 @@ target_sources(Luau.Analysis PRIVATE Analysis/include/Luau/Scope.h Analysis/include/Luau/Simplify.h Analysis/include/Luau/Substitution.h + Analysis/include/Luau/Subtyping.h Analysis/include/Luau/Symbol.h Analysis/include/Luau/ToDot.h Analysis/include/Luau/TopoSortStatements.h @@ -207,7 +216,6 @@ target_sources(Luau.Analysis PRIVATE Analysis/src/Autocomplete.cpp Analysis/src/BuiltinDefinitions.cpp Analysis/src/Clone.cpp - Analysis/src/Config.cpp Analysis/src/Constraint.cpp Analysis/src/ConstraintGraphBuilder.cpp Analysis/src/ConstraintSolver.cpp @@ -222,7 +230,6 @@ target_sources(Luau.Analysis PRIVATE Analysis/src/IostreamHelpers.cpp Analysis/src/JsonEmitter.cpp Analysis/src/Linter.cpp - Analysis/src/LinterConfig.cpp Analysis/src/LValue.cpp Analysis/src/Module.cpp Analysis/src/Normalize.cpp @@ -232,6 +239,7 @@ target_sources(Luau.Analysis PRIVATE Analysis/src/Scope.cpp Analysis/src/Simplify.cpp Analysis/src/Substitution.cpp + Analysis/src/Subtyping.cpp Analysis/src/Symbol.cpp Analysis/src/ToDot.cpp Analysis/src/TopoSortStatements.cpp @@ -350,33 +358,32 @@ endif() if(TARGET Luau.UnitTest) # Luau.UnitTest Sources target_sources(Luau.UnitTest PRIVATE - tests/AstQueryDsl.cpp - tests/AstQueryDsl.h - tests/ClassFixture.cpp - tests/ClassFixture.h - tests/ConstraintGraphBuilderFixture.cpp - tests/ConstraintGraphBuilderFixture.h - tests/Fixture.cpp - tests/Fixture.h - tests/IostreamOptional.h - tests/ScopedFlags.h tests/AssemblyBuilderA64.test.cpp tests/AssemblyBuilderX64.test.cpp tests/AstJsonEncoder.test.cpp tests/AstQuery.test.cpp + tests/AstQueryDsl.cpp + tests/AstQueryDsl.h tests/AstVisitor.test.cpp tests/Autocomplete.test.cpp tests/BuiltinDefinitions.test.cpp + tests/ClassFixture.cpp + tests/ClassFixture.h tests/CodeAllocator.test.cpp tests/Compiler.test.cpp tests/Config.test.cpp + tests/ConstraintGraphBuilderFixture.cpp + tests/ConstraintGraphBuilderFixture.h tests/ConstraintSolver.test.cpp tests/CostModel.test.cpp tests/DataFlowGraph.test.cpp tests/DenseHash.test.cpp - tests/Differ.test.cpp + tests/Differ.test.cpp tests/Error.test.cpp + tests/Fixture.cpp + tests/Fixture.h tests/Frontend.test.cpp + tests/IostreamOptional.h tests/IrBuilder.test.cpp tests/IrCallWrapperX64.test.cpp tests/IrRegAllocX64.test.cpp @@ -391,8 +398,10 @@ if(TARGET Luau.UnitTest) tests/Parser.test.cpp tests/RequireTracer.test.cpp tests/RuntimeLimits.test.cpp + tests/ScopedFlags.h tests/Simplify.test.cpp tests/StringUtils.test.cpp + tests/Subtyping.test.cpp tests/Symbol.test.cpp tests/ToDot.test.cpp tests/TopoSort.test.cpp diff --git a/VM/src/ldo.cpp b/VM/src/ldo.cpp index e5fde4d4..69d3c128 100644 --- a/VM/src/ldo.cpp +++ b/VM/src/ldo.cpp @@ -17,6 +17,8 @@ #include +LUAU_FASTFLAGVARIABLE(LuauPCallDebuggerFix, false) + /* ** {====================================================== ** Error-recovery functions @@ -576,11 +578,13 @@ int luaD_pcall(lua_State* L, Pfunc func, void* u, ptrdiff_t old_top, ptrdiff_t e if (!oldactive) L->isactive = false; + bool yieldable = L->nCcalls <= L->baseCcalls; // Inlined logic from 'lua_isyieldable' to avoid potential for an out of line call. + // restore nCcalls before calling the debugprotectederror callback which may rely on the proper value to have been restored. L->nCcalls = oldnCcalls; // an error occurred, check if we have a protected error callback - if (L->global->cb.debugprotectederror) + if ((!FFlag::LuauPCallDebuggerFix || yieldable) && L->global->cb.debugprotectederror) { L->global->cb.debugprotectederror(L); diff --git a/VM/src/lmathlib.cpp b/VM/src/lmathlib.cpp index 254fc9db..8a140780 100644 --- a/VM/src/lmathlib.cpp +++ b/VM/src/lmathlib.cpp @@ -288,17 +288,17 @@ static const unsigned char kPerlinHash[257] = {151, 160, 137, 91, 90, 15, 131, 1 const float kPerlinGrad[16][3] = {{1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0}, {1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1}, {0, 1, 1}, {0, -1, 1}, {0, 1, -1}, {0, -1, -1}, {1, 1, 0}, {0, -1, 1}, {-1, 1, 0}, {0, -1, -1}}; -static float perlin_fade(float t) +inline float perlin_fade(float t) { return t * t * t * (t * (t * 6 - 15) + 10); } -static float perlin_lerp(float t, float a, float b) +inline float perlin_lerp(float t, float a, float b) { return a + t * (b - a); } -static float perlin_grad(int hash, float x, float y, float z) +inline float perlin_grad(int hash, float x, float y, float z) { const float* g = kPerlinGrad[hash & 15]; return g[0] * x + g[1] * y + g[2] * z; diff --git a/tests/Autocomplete.test.cpp b/tests/Autocomplete.test.cpp index daa1f81a..b8171a75 100644 --- a/tests/Autocomplete.test.cpp +++ b/tests/Autocomplete.test.cpp @@ -3556,8 +3556,6 @@ TEST_CASE_FIXTURE(ACFixture, "frontend_use_correct_global_scope") TEST_CASE_FIXTURE(ACFixture, "string_completion_outside_quotes") { - ScopedFastFlag flag{"LuauDisableCompletionOutsideQuotes", true}; - loadDefinition(R"( declare function require(path: string): any )"); diff --git a/tests/Compiler.test.cpp b/tests/Compiler.test.cpp index 5e58865b..078b8af6 100644 --- a/tests/Compiler.test.cpp +++ b/tests/Compiler.test.cpp @@ -6978,8 +6978,6 @@ L3: RETURN R0 0 TEST_CASE("BuiltinArity") { - ScopedFastFlag sff("LuauCompileFixBuiltinArity", true); - // by default we can't assume that we know parameter/result count for builtins as they can be overridden at runtime CHECK_EQ("\n" + compileFunction(R"( return math.abs(unknown()) diff --git a/tests/Conformance.test.cpp b/tests/Conformance.test.cpp index 97d4e031..a06138fc 100644 --- a/tests/Conformance.test.cpp +++ b/tests/Conformance.test.cpp @@ -8,7 +8,6 @@ #include "Luau/DenseHash.h" #include "Luau/ModuleResolver.h" #include "Luau/TypeInfer.h" -#include "Luau/StringUtils.h" #include "Luau/BytecodeBuilder.h" #include "Luau/Frontend.h" @@ -24,6 +23,8 @@ extern bool verbose; extern bool codegen; extern int optimizationLevel; +LUAU_FASTFLAG(LuauPCallDebuggerFix); + static lua_CompileOptions defaultOptions() { lua_CompileOptions copts = {}; @@ -279,8 +280,6 @@ TEST_CASE("Assert") TEST_CASE("Basic") { - ScopedFastFlag sff("LuauCompileFixBuiltinArity", true); - runConformance("basic.lua"); } @@ -334,8 +333,6 @@ TEST_CASE("Clear") TEST_CASE("Strings") { - ScopedFastFlag sff("LuauCompileFixBuiltinArity", true); - runConformance("strings.lua"); } @@ -1217,15 +1214,90 @@ TEST_CASE("IfElseExpression") runConformance("ifelseexpr.lua"); } +// Optionally returns debug info for the first Luau stack frame that is encountered on the callstack. +static std::optional getFirstLuauFrameDebugInfo(lua_State* L) +{ + static std::string_view kLua = "Lua"; + lua_Debug ar; + for (int i = 0; lua_getinfo(L, i, "sl", &ar); i++) + { + if (kLua == ar.what) + return ar; + } + return std::nullopt; +} + TEST_CASE("TagMethodError") { - runConformance("tmerror.lua", [](lua_State* L) { - auto* cb = lua_callbacks(L); + static std::vector expectedHits; - cb->debugprotectederror = [](lua_State* L) { - CHECK(lua_isyieldable(L)); - }; - }); + // Loop over two modes: + // when doLuaBreak is false the test only verifies that callbacks occur on the expected lines in the Luau source + // when doLuaBreak is true the test additionally calls lua_break to ensure breaking the debugger doesn't cause the VM to crash + for (bool doLuaBreak : {false, true}) + { + std::optional sff; + if (doLuaBreak) + { + // If doLuaBreak is true then LuauPCallDebuggerFix must be enabled to avoid crashing the tests. + sff = {"LuauPCallDebuggerFix", true}; + } + + if (FFlag::LuauPCallDebuggerFix) + { + expectedHits = {22, 32}; + } + else + { + expectedHits = { + 9, + 17, + 17, + 22, + 27, + 27, + 32, + 37, + }; + } + + static int index; + static bool luaBreak; + index = 0; + luaBreak = doLuaBreak; + + // 'yieldCallback' doesn't do anything, but providing the callback to runConformance + // ensures that the call to lua_break doesn't cause an error to be generated because + // runConformance doesn't expect the VM to be in the state LUA_BREAK. + auto yieldCallback = [](lua_State* L) {}; + + runConformance( + "tmerror.lua", + [](lua_State* L) { + auto* cb = lua_callbacks(L); + + cb->debugprotectederror = [](lua_State* L) { + std::optional ar = getFirstLuauFrameDebugInfo(L); + + CHECK(lua_isyieldable(L)); + REQUIRE(ar.has_value()); + REQUIRE(index < int(std::size(expectedHits))); + CHECK(ar->currentline == expectedHits[index++]); + + if (luaBreak) + { + // Cause luau execution to break when 'error' is called via 'pcall' + // This call to lua_break is a regression test for an issue where debugprotectederror + // was called on a thread that couldn't be yielded even though lua_isyieldable was true. + lua_break(L); + } + }; + }, + yieldCallback); + + // Make sure the number of break points hit was the expected number + CHECK(index == std::size(expectedHits)); + } } TEST_CASE("Coverage") diff --git a/tests/CostModel.test.cpp b/tests/CostModel.test.cpp index 206b83a8..29fffb4f 100644 --- a/tests/CostModel.test.cpp +++ b/tests/CostModel.test.cpp @@ -133,8 +133,6 @@ end TEST_CASE("ControlFlow") { - ScopedFastFlag sff("LuauAssignmentHasCost", true); - uint64_t model = modelFunction(R"( function test(a) while a < 0 do @@ -244,8 +242,6 @@ end TEST_CASE("MultipleAssignments") { - ScopedFastFlag sff("LuauAssignmentHasCost", true); - uint64_t model = modelFunction(R"( function test(a) local x = 0 diff --git a/tests/Error.test.cpp b/tests/Error.test.cpp index 5ba5c112..0a71794f 100644 --- a/tests/Error.test.cpp +++ b/tests/Error.test.cpp @@ -1,6 +1,7 @@ // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details #include "Luau/Error.h" +#include "Fixture.h" #include "doctest.h" using namespace Luau; @@ -13,4 +14,24 @@ TEST_CASE("TypeError_code_should_return_nonzero_code") CHECK_GE(e.code(), 1000); } +TEST_CASE_FIXTURE(BuiltinsFixture, "metatable_names_show_instead_of_tables") +{ + frontend.options.retainFullTypeGraphs = false; + ScopedFastFlag sff{"LuauStacklessTypeClone2", true}; + CheckResult result = check(R"( +--!strict +local Account = {} +Account.__index = Account +function Account.deposit(self: Account, x: number) + self.balance += x +end +type Account = typeof(setmetatable({} :: { balance: number }, Account)) +local x: Account = 5 +)"); + + LUAU_REQUIRE_ERROR_COUNT(1, result); + + CHECK_EQ("Type 'number' could not be converted into 'Account'", toString(result.errors[0])); +} + TEST_SUITE_END(); diff --git a/tests/IrBuilder.test.cpp b/tests/IrBuilder.test.cpp index 57103352..dff13342 100644 --- a/tests/IrBuilder.test.cpp +++ b/tests/IrBuilder.test.cpp @@ -883,8 +883,7 @@ TEST_CASE_FIXTURE(IrBuilderFixture, "PropagateThroughTvalue") bb_0: STORE_TAG R0, tnumber STORE_DOUBLE R0, 0.5 - %2 = LOAD_TVALUE R0 - STORE_TVALUE R1, %2 + STORE_SPLIT_TVALUE R1, tnumber, 0.5 STORE_TAG R3, tnumber STORE_DOUBLE R3, 0.5 RETURN 0u @@ -991,6 +990,52 @@ bb_fallback_1: )"); } +TEST_CASE_FIXTURE(IrBuilderFixture, "RememberNewTableState") +{ + IrOp block = build.block(IrBlockKind::Internal); + IrOp fallback = build.block(IrBlockKind::Fallback); + + build.beginBlock(block); + + IrOp newtable = build.inst(IrCmd::NEW_TABLE, build.constUint(16), build.constUint(32)); + build.inst(IrCmd::STORE_POINTER, build.vmReg(0), newtable); + + IrOp table = build.inst(IrCmd::LOAD_POINTER, build.vmReg(0)); + + build.inst(IrCmd::CHECK_NO_METATABLE, table, fallback); + build.inst(IrCmd::CHECK_READONLY, table, fallback); + build.inst(IrCmd::CHECK_ARRAY_SIZE, table, build.constInt(14), fallback); + + build.inst(IrCmd::SET_TABLE, build.vmReg(1), build.vmReg(0), build.constUint(13)); // Invalidate table knowledge + + build.inst(IrCmd::CHECK_NO_METATABLE, table, fallback); + build.inst(IrCmd::CHECK_READONLY, table, fallback); + build.inst(IrCmd::CHECK_ARRAY_SIZE, table, build.constInt(14), fallback); + + build.inst(IrCmd::RETURN, build.constUint(0)); + + build.beginBlock(fallback); + build.inst(IrCmd::RETURN, build.constUint(1)); + + updateUseCounts(build.function); + constPropInBlockChains(build, true); + + CHECK("\n" + toString(build.function, /* includeUseInfo */ false) == R"( +bb_0: + %0 = NEW_TABLE 16u, 32u + STORE_POINTER R0, %0 + SET_TABLE R1, R0, 13u + CHECK_NO_METATABLE %0, bb_fallback_1 + CHECK_READONLY %0, bb_fallback_1 + CHECK_ARRAY_SIZE %0, 14i, bb_fallback_1 + RETURN 0u + +bb_fallback_1: + RETURN 1u + +)"); +} + TEST_CASE_FIXTURE(IrBuilderFixture, "SkipUselessBarriers") { IrOp block = build.block(IrBlockKind::Internal); @@ -1586,7 +1631,7 @@ TEST_CASE_FIXTURE(IrBuilderFixture, "InvalidateReglinkVersion") build.inst(IrCmd::STORE_TAG, build.vmReg(2), build.constTag(tstring)); IrOp tv2 = build.inst(IrCmd::LOAD_TVALUE, build.vmReg(2)); build.inst(IrCmd::STORE_TVALUE, build.vmReg(1), tv2); - IrOp ft = build.inst(IrCmd::NEW_TABLE); + IrOp ft = build.inst(IrCmd::NEW_TABLE, build.constUint(0), build.constUint(0)); build.inst(IrCmd::STORE_POINTER, build.vmReg(2), ft); build.inst(IrCmd::STORE_TAG, build.vmReg(2), build.constTag(ttable)); IrOp tv1 = build.inst(IrCmd::LOAD_TVALUE, build.vmReg(1)); @@ -1606,7 +1651,7 @@ bb_0: STORE_TAG R2, tstring %1 = LOAD_TVALUE R2 STORE_TVALUE R1, %1 - %3 = NEW_TABLE + %3 = NEW_TABLE 0u, 0u STORE_POINTER R2, %3 STORE_TAG R2, ttable STORE_TVALUE R0, %1 @@ -1811,8 +1856,8 @@ TEST_CASE_FIXTURE(IrBuilderFixture, "PartialStoreInvalidation") build.inst(IrCmd::STORE_TVALUE, build.vmReg(1), build.inst(IrCmd::LOAD_TVALUE, build.vmReg(0))); build.inst(IrCmd::STORE_DOUBLE, build.vmReg(0), build.constDouble(0.5)); build.inst(IrCmd::STORE_TVALUE, build.vmReg(1), build.inst(IrCmd::LOAD_TVALUE, build.vmReg(0))); // Should be reloaded - build.inst(IrCmd::STORE_TAG, build.vmReg(0), build.constTag(tboolean)); - build.inst(IrCmd::STORE_TVALUE, build.vmReg(1), build.inst(IrCmd::LOAD_TVALUE, build.vmReg(0))); // Should be reloaded + build.inst(IrCmd::STORE_TAG, build.vmReg(0), build.constTag(tnumber)); + build.inst(IrCmd::STORE_TVALUE, build.vmReg(1), build.inst(IrCmd::LOAD_TVALUE, build.vmReg(0))); build.inst(IrCmd::RETURN, build.constUint(0)); @@ -1826,9 +1871,8 @@ bb_0: STORE_DOUBLE R0, 0.5 %3 = LOAD_TVALUE R0 STORE_TVALUE R1, %3 - STORE_TAG R0, tboolean - %6 = LOAD_TVALUE R0 - STORE_TVALUE R1, %6 + STORE_TAG R0, tnumber + STORE_SPLIT_TVALUE R1, tnumber, 0.5 RETURN 0u )"); @@ -2239,6 +2283,32 @@ TEST_CASE_FIXTURE(IrBuilderFixture, "DominanceVerification3") CHECK(build.function.cfg.idoms == std::vector{~0u, 0, 0, 0, 2, 0, 4, 0}); } +// 'Static Single Assignment Book' Figure 4.1 +TEST_CASE_FIXTURE(IrBuilderFixture, "DominanceVerification4") +{ + defineCfgTree({{1}, {2, 10}, {3, 7}, {4}, {5}, {4, 6}, {1}, {8}, {5, 9}, {7}, {}}); + + IdfContext ctx; + + computeIteratedDominanceFrontierForDefs(ctx, build.function, {0, 2, 3, 6}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + CHECK(ctx.idf == std::vector{1, 4, 5}); +} + +// 'Static Single Assignment Book' Figure 4.5 +TEST_CASE_FIXTURE(IrBuilderFixture, "DominanceVerification4") +{ + defineCfgTree({{1}, {2}, {3, 7}, {4, 5}, {6}, {6}, {8}, {8}, {9}, {10, 11}, {11}, {9, 12}, {2}}); + + IdfContext ctx; + + computeIteratedDominanceFrontierForDefs(ctx, build.function, {4, 5, 7, 12}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}); + CHECK(ctx.idf == std::vector{2, 6, 8}); + + // Pruned form, when variable is only live-in in limited set of blocks + computeIteratedDominanceFrontierForDefs(ctx, build.function, {4, 5, 7, 12}, {6, 8, 9}); + CHECK(ctx.idf == std::vector{6, 8}); +} + TEST_SUITE_END(); TEST_SUITE_BEGIN("ValueNumbering"); @@ -2484,4 +2554,105 @@ bb_0: )"); } +TEST_CASE_FIXTURE(IrBuilderFixture, "TValueLoadToSplitStore") +{ + IrOp entry = build.block(IrBlockKind::Internal); + IrOp fallback = build.block(IrBlockKind::Fallback); + + build.beginBlock(entry); + IrOp op1 = build.inst(IrCmd::LOAD_DOUBLE, build.vmReg(0)); + IrOp op1v2 = build.inst(IrCmd::ADD_NUM, op1, build.constDouble(4.0)); + build.inst(IrCmd::STORE_DOUBLE, build.vmReg(1), op1v2); + build.inst(IrCmd::STORE_TAG, build.vmReg(1), build.constTag(tnumber)); + + // Check that this TValue store will be replaced by a split store + IrOp tv = build.inst(IrCmd::LOAD_TVALUE, build.vmReg(1)); + build.inst(IrCmd::STORE_TVALUE, build.vmReg(2), tv); + + // Check that tag and value can be extracted from R2 now (removing the fallback) + IrOp tag2 = build.inst(IrCmd::LOAD_TAG, build.vmReg(2)); + build.inst(IrCmd::CHECK_TAG, tag2, build.constTag(tnumber), fallback); + IrOp op2 = build.inst(IrCmd::LOAD_DOUBLE, build.vmReg(2)); + build.inst(IrCmd::STORE_DOUBLE, build.vmReg(3), op2); + build.inst(IrCmd::STORE_TAG, build.vmReg(3), build.constTag(tnumber)); + + build.inst(IrCmd::RETURN, build.vmReg(1), build.constInt(1)); + + build.beginBlock(fallback); + build.inst(IrCmd::RETURN, build.vmReg(2), build.constInt(1)); + + updateUseCounts(build.function); + constPropInBlockChains(build, true); + + CHECK("\n" + toString(build.function, /* includeUseInfo */ false) == R"( +bb_0: + %0 = LOAD_DOUBLE R0 + %1 = ADD_NUM %0, 4 + STORE_DOUBLE R1, %1 + STORE_TAG R1, tnumber + STORE_SPLIT_TVALUE R2, tnumber, %1 + STORE_DOUBLE R3, %1 + STORE_TAG R3, tnumber + RETURN R1, 1i + +)"); +} + +TEST_CASE_FIXTURE(IrBuilderFixture, "TagStoreUpdatesValueVersion") +{ + IrOp entry = build.block(IrBlockKind::Internal); + + build.beginBlock(entry); + + IrOp op1 = build.inst(IrCmd::LOAD_POINTER, build.vmReg(0)); + build.inst(IrCmd::STORE_POINTER, build.vmReg(1), op1); + build.inst(IrCmd::STORE_TAG, build.vmReg(1), build.constTag(tstring)); + + IrOp str = build.inst(IrCmd::LOAD_POINTER, build.vmReg(1)); + build.inst(IrCmd::STORE_POINTER, build.vmReg(2), str); + build.inst(IrCmd::STORE_TAG, build.vmReg(2), build.constTag(tstring)); + + build.inst(IrCmd::RETURN, build.vmReg(1), build.constInt(1)); + + updateUseCounts(build.function); + constPropInBlockChains(build, true); + + CHECK("\n" + toString(build.function, /* includeUseInfo */ false) == R"( +bb_0: + %0 = LOAD_POINTER R0 + STORE_POINTER R1, %0 + STORE_TAG R1, tstring + STORE_POINTER R2, %0 + STORE_TAG R2, tstring + RETURN R1, 1i + +)"); +} + +TEST_CASE_FIXTURE(IrBuilderFixture, "TagStoreUpdatesSetUpval") +{ + IrOp entry = build.block(IrBlockKind::Internal); + + build.beginBlock(entry); + + build.inst(IrCmd::STORE_TAG, build.vmReg(0), build.constTag(tnumber)); + build.inst(IrCmd::STORE_DOUBLE, build.vmReg(0), build.constDouble(0.5)); + + build.inst(IrCmd::SET_UPVALUE, build.vmUpvalue(0), build.vmReg(0), build.undef()); + + build.inst(IrCmd::RETURN, build.vmReg(0), build.constInt(0)); + + updateUseCounts(build.function); + constPropInBlockChains(build, true); + + CHECK("\n" + toString(build.function, /* includeUseInfo */ false) == R"( +bb_0: + STORE_TAG R0, tnumber + STORE_DOUBLE R0, 0.5 + SET_UPVALUE U0, R0, tnumber + RETURN R0, 0i + +)"); +} + TEST_SUITE_END(); diff --git a/tests/Module.test.cpp b/tests/Module.test.cpp index 54a96861..4f489065 100644 --- a/tests/Module.test.cpp +++ b/tests/Module.test.cpp @@ -14,7 +14,7 @@ using namespace Luau; LUAU_FASTFLAG(DebugLuauDeferredConstraintResolution); -LUAU_FASTFLAG(LuauStacklessTypeClone) +LUAU_FASTFLAG(LuauStacklessTypeClone2) TEST_SUITE_BEGIN("ModuleTests"); @@ -150,8 +150,8 @@ TEST_CASE_FIXTURE(Fixture, "deepClone_cyclic_table") REQUIRE(methodReturnType); CHECK_MESSAGE(methodReturnType == cloneTy, toString(methodType, {true}) << " should be pointer identical to " << toString(cloneTy, {true})); - CHECK_EQ(FFlag::LuauStacklessTypeClone ? 1 : 2, dest.typePacks.size()); // one for the function args, and another for its return type - CHECK_EQ(2, dest.types.size()); // One table and one function + CHECK_EQ(2, dest.typePacks.size()); // one for the function args, and another for its return type + CHECK_EQ(2, dest.types.size()); // One table and one function } TEST_CASE_FIXTURE(Fixture, "deepClone_cyclic_table_2") @@ -336,7 +336,7 @@ TEST_CASE_FIXTURE(Fixture, "clone_recursion_limit") int limit = 400; #endif - ScopedFastFlag sff{"LuauStacklessTypeClone", false}; + ScopedFastFlag sff{"LuauStacklessTypeClone2", false}; ScopedFastInt luauTypeCloneRecursionLimit{"LuauTypeCloneRecursionLimit", limit}; TypeArena src; @@ -360,7 +360,7 @@ TEST_CASE_FIXTURE(Fixture, "clone_recursion_limit") TEST_CASE_FIXTURE(Fixture, "clone_iteration_limit") { - ScopedFastFlag sff{"LuauStacklessTypeClone", true}; + ScopedFastFlag sff{"LuauStacklessTypeClone2", true}; ScopedFastInt sfi{"LuauTypeCloneIterationLimit", 500}; TypeArena src; @@ -501,4 +501,32 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "do_not_clone_types_of_reexported_values") CHECK(tableA->props["a"].type() == tableB->props["b"].type()); } +TEST_CASE_FIXTURE(BuiltinsFixture, "clone_table_bound_to_table_bound_to_table") +{ + TypeArena arena; + + TypeId a = arena.addType(TableType{TableState::Free, TypeLevel{}}); + getMutable(a)->name = "a"; + + TypeId b = arena.addType(TableType{TableState::Free, TypeLevel{}}); + getMutable(b)->name = "b"; + + TypeId c = arena.addType(TableType{TableState::Free, TypeLevel{}}); + getMutable(c)->name = "c"; + + getMutable(a)->boundTo = b; + getMutable(b)->boundTo = c; + + TypeArena dest; + CloneState state{builtinTypes}; + TypeId res = clone(a, dest, state); + + REQUIRE(dest.types.size() == 1); + + auto tableA = get(res); + REQUIRE_MESSAGE(tableA, "Expected table, got " << res); + REQUIRE(tableA->name == "c"); + REQUIRE(!tableA->boundTo); +} + TEST_SUITE_END(); diff --git a/tests/Subtyping.test.cpp b/tests/Subtyping.test.cpp new file mode 100644 index 00000000..f7f24d0f --- /dev/null +++ b/tests/Subtyping.test.cpp @@ -0,0 +1,352 @@ +// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details + +#include "doctest.h" +#include "Fixture.h" + +#include "Luau/Subtyping.h" + +using namespace Luau; + +struct SubtypeFixture : Fixture +{ + TypeArena arena; + InternalErrorReporter ice; + UnifierSharedState sharedState{&ice}; + Normalizer normalizer{&arena, builtinTypes, NotNull{&sharedState}}; + Subtyping subtyping{builtinTypes, NotNull{&normalizer}}; + + TypePackId pack(std::initializer_list tys) + { + return arena.addTypePack(tys); + } + + TypePackId pack(std::initializer_list tys, TypePackVariant tail) + { + return arena.addTypePack(tys, arena.addTypePack(std::move(tail))); + } + + TypeId fn(std::initializer_list args, std::initializer_list rets) + { + return arena.addType(FunctionType{pack(args), pack(rets)}); + } + + TypeId fn(std::initializer_list argHead, TypePackVariant argTail, std::initializer_list rets) + { + return arena.addType(FunctionType{pack(argHead, std::move(argTail)), pack(rets)}); + } + + TypeId fn(std::initializer_list args, std::initializer_list retHead, TypePackVariant retTail) + { + return arena.addType(FunctionType{pack(args), pack(retHead, std::move(retTail))}); + } + + TypeId fn(std::initializer_list argHead, TypePackVariant argTail, std::initializer_list retHead, TypePackVariant retTail) + { + return arena.addType(FunctionType{pack(argHead, std::move(argTail)), pack(retHead, std::move(retTail))}); + } + + SubtypingGraph isSubtype(TypeId subTy, TypeId superTy) + { + return subtyping.isSubtype(subTy, superTy); + } + + TypeId helloType = arena.addType(SingletonType{StringSingleton{"hello"}}); + TypeId helloType2 = arena.addType(SingletonType{StringSingleton{"hello"}}); + TypeId worldType = arena.addType(SingletonType{StringSingleton{"world"}}); + + TypeId helloOrWorldType = arena.addType(UnionType{{helloType, worldType}}); + TypeId trueOrFalseType = arena.addType(UnionType{{builtinTypes->trueType, builtinTypes->falseType}}); + + TypeId helloAndWorldType = arena.addType(IntersectionType{{helloType, worldType}}); + TypeId booleanAndTrueType = arena.addType(IntersectionType{{builtinTypes->booleanType, builtinTypes->trueType}}); + + // (number) -> string + const TypeId numberToStringType = fn( + {builtinTypes->numberType}, + {builtinTypes->stringType} + ); + + // (unknown) -> string + const TypeId unknownToStringType = fn( + {builtinTypes->unknownType}, + {builtinTypes->stringType} + ); + + // (number) -> unknown + const TypeId numberToUnknownType = fn( + {builtinTypes->numberType}, + {builtinTypes->unknownType} + ); + + // (number) -> (string, string) + const TypeId numberToTwoStringsType = fn( + {builtinTypes->numberType}, + {builtinTypes->stringType, builtinTypes->stringType} + ); + + // (number) -> (string, unknown) + const TypeId numberToStringAndUnknownType = fn( + {builtinTypes->numberType}, + {builtinTypes->stringType, builtinTypes->unknownType} + ); + + // (number, number) -> string + const TypeId numberNumberToStringType = fn( + {builtinTypes->numberType, builtinTypes->numberType}, + {builtinTypes->stringType} + ); + + // (unknown, number) -> string + const TypeId unknownNumberToStringType = fn( + {builtinTypes->unknownType, builtinTypes->numberType}, + {builtinTypes->stringType} + ); + + // (number, string) -> string + const TypeId numberAndStringToStringType = fn( + {builtinTypes->numberType, builtinTypes->stringType}, + {builtinTypes->stringType} + ); + + // (number, ...string) -> string + const TypeId numberAndStringsToStringType = fn( + {builtinTypes->numberType}, VariadicTypePack{builtinTypes->stringType}, + {builtinTypes->stringType} + ); + + // (number, ...string?) -> string + const TypeId numberAndOptionalStringsToStringType = fn( + {builtinTypes->numberType}, VariadicTypePack{builtinTypes->optionalStringType}, + {builtinTypes->stringType} + ); + +}; + +#define CHECK_IS_SUBTYPE(left, right) \ + do \ + { \ + const auto& leftTy = (left); \ + const auto& rightTy = (right); \ + SubtypingGraph result = isSubtype(leftTy, rightTy); \ + CHECK_MESSAGE(result.isSubtype, "Expected " << leftTy << " <: " << rightTy); \ + } while (0) + +#define CHECK_IS_NOT_SUBTYPE(left, right) \ + do \ + { \ + const auto& leftTy = (left); \ + const auto& rightTy = (right); \ + SubtypingGraph result = isSubtype(leftTy, rightTy); \ + CHECK_MESSAGE(!result.isSubtype, "Expected " << leftTy << " numberType, builtinTypes->anyType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "any anyType, builtinTypes->unknownType); + CHECK(!result.isSubtype); + CHECK(result.isErrorSuppressing); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "number? <: unknown") +{ + CHECK_IS_SUBTYPE(builtinTypes->optionalNumberType, builtinTypes->unknownType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "number <: unknown") +{ + CHECK_IS_SUBTYPE(builtinTypes->numberType, builtinTypes->unknownType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "number <: number") +{ + CHECK_IS_SUBTYPE(builtinTypes->numberType, builtinTypes->numberType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "number numberType, builtinTypes->stringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "number <: number?") +{ + CHECK_IS_SUBTYPE(builtinTypes->numberType, builtinTypes->optionalNumberType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "\"hello\" <: string") +{ + CHECK_IS_SUBTYPE(helloType, builtinTypes->stringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "string stringType, helloType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "\"hello\" <: \"hello\"") +{ + CHECK_IS_SUBTYPE(helloType, helloType2); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "true <: boolean") +{ + CHECK_IS_SUBTYPE(builtinTypes->trueType, builtinTypes->booleanType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "true <: true | false") +{ + CHECK_IS_SUBTYPE(builtinTypes->trueType, trueOrFalseType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "true | false trueType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "true | false <: boolean") +{ + CHECK_IS_SUBTYPE(trueOrFalseType, builtinTypes->booleanType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "true | false <: true | false") +{ + CHECK_IS_SUBTYPE(trueOrFalseType, trueOrFalseType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "\"hello\" | \"world\" <: number") +{ + CHECK_IS_NOT_SUBTYPE(helloOrWorldType, builtinTypes->numberType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "true <: boolean & true") +{ + CHECK_IS_SUBTYPE(builtinTypes->trueType, booleanAndTrueType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "boolean & true <: true") +{ + CHECK_IS_SUBTYPE(booleanAndTrueType, builtinTypes->trueType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "boolean & true <: boolean & true") +{ + CHECK_IS_SUBTYPE(booleanAndTrueType, booleanAndTrueType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "\"hello\" & \"world\" <: number") +{ + CHECK_IS_SUBTYPE(helloAndWorldType, builtinTypes->numberType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "false falseType, booleanAndTrueType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(unknown) -> string <: (number) -> string") +{ + CHECK_IS_SUBTYPE(unknownToStringType, numberToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number) -> string string") +{ + CHECK_IS_NOT_SUBTYPE(numberToStringType, unknownToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number, number) -> string string") +{ + CHECK_IS_NOT_SUBTYPE(numberNumberToStringType, numberToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number) -> string string") +{ + CHECK_IS_NOT_SUBTYPE(numberToStringType, numberNumberToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number, number) -> string string") +{ + CHECK_IS_NOT_SUBTYPE(numberNumberToStringType, unknownNumberToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(unknown, number) -> string <: (number, number) -> string") +{ + CHECK_IS_SUBTYPE(unknownNumberToStringType, numberNumberToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number) -> (string, unknown) (string, string)") +{ + CHECK_IS_NOT_SUBTYPE(numberToStringAndUnknownType, numberToTwoStringsType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number) -> (string, string) <: (number) -> (string, unknown)") +{ + CHECK_IS_SUBTYPE(numberToTwoStringsType, numberToStringAndUnknownType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number) -> (string, string) string") +{ + CHECK_IS_NOT_SUBTYPE(numberToTwoStringsType, numberToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number) -> string (string, string)") +{ + CHECK_IS_NOT_SUBTYPE(numberToStringType, numberToTwoStringsType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number, ...string) -> string <: (number) -> string") +{ + CHECK_IS_SUBTYPE(numberAndStringsToStringType, numberToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number) -> string string") +{ + CHECK_IS_NOT_SUBTYPE(numberToStringType, numberAndStringsToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number, ...string?) -> string <: (number, ...string) -> string") +{ + CHECK_IS_SUBTYPE(numberAndOptionalStringsToStringType, numberAndStringsToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number, ...string) -> string string") +{ + CHECK_IS_NOT_SUBTYPE(numberAndStringsToStringType, numberAndOptionalStringsToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number, ...string) -> string <: (number, string) -> string") +{ + CHECK_IS_SUBTYPE(numberAndStringsToStringType, numberAndStringToStringType); +} + +TEST_CASE_FIXTURE(SubtypeFixture, "(number, string) -> string string") +{ + CHECK_IS_NOT_SUBTYPE(numberAndStringToStringType, numberAndStringsToStringType); +} + +TEST_SUITE_END(); diff --git a/tests/TypeInfer.functions.test.cpp b/tests/TypeInfer.functions.test.cpp index 846d5b53..1c46b91a 100644 --- a/tests/TypeInfer.functions.test.cpp +++ b/tests/TypeInfer.functions.test.cpp @@ -1212,6 +1212,71 @@ f(function(x) return x * 2 end) LUAU_REQUIRE_NO_ERRORS(result); } +TEST_CASE_FIXTURE(BuiltinsFixture, "infer_generic_function_function_argument") +{ + CheckResult result = check(R"( +local function sum(x: a, y: a, f: (a, a) -> a) return f(x, y) end +return sum(2, 3, function(a, b) return a + b end) + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + + result = check(R"( +local function map(arr: {a}, f: (a) -> b) local r = {} for i,v in ipairs(arr) do table.insert(r, f(v)) end return r end +local a = {1, 2, 3} +local r = map(a, function(a) return a + a > 100 end) + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + REQUIRE_EQ("{boolean}", toString(requireType("r"))); + + check(R"( +local function foldl(arr: {a}, init: b, f: (b, a) -> b) local r = init for i,v in ipairs(arr) do r = f(r, v) end return r end +local a = {1, 2, 3} +local r = foldl(a, {s=0,c=0}, function(a, b) return {s = a.s + b, c = a.c + 1} end) + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + REQUIRE_EQ("{ c: number, s: number }", toString(requireType("r"))); +} + +TEST_CASE_FIXTURE(Fixture, "infer_generic_function_function_argument_overloaded") +{ + CheckResult result = check(R"( +local function g1(a: T, f: (T) -> T) return f(a) end +local function g2(a: T, b: T, f: (T, T) -> T) return f(a, b) end + +local g12: typeof(g1) & typeof(g2) + +g12(1, function(x) return x + x end) +g12(1, 2, function(x, y) return x + y end) + )"); + + LUAU_REQUIRE_NO_ERRORS(result); + + result = check(R"( +local function g1(a: T, f: (T) -> T) return f(a) end +local function g2(a: T, b: T, f: (T, T) -> T) return f(a, b) end + +local g12: typeof(g1) & typeof(g2) + +g12({x=1}, function(x) return {x=-x.x} end) +g12({x=1}, {x=2}, function(x, y) return {x=x.x + y.x} end) + )"); + + LUAU_REQUIRE_NO_ERRORS(result); +} + +TEST_CASE_FIXTURE(BuiltinsFixture, "infer_generic_lib_function_function_argument") +{ + CheckResult result = check(R"( +local a = {{x=4}, {x=7}, {x=1}} +table.sort(a, function(x, y) return x.x < y.x end) + )"); + + LUAU_REQUIRE_NO_ERRORS(result); +} + TEST_CASE_FIXTURE(Fixture, "variadic_any_is_compatible_with_a_generic_TypePack") { CheckResult result = check(R"( diff --git a/tests/TypeInfer.oop.test.cpp b/tests/TypeInfer.oop.test.cpp index cc0a79f8..c589f134 100644 --- a/tests/TypeInfer.oop.test.cpp +++ b/tests/TypeInfer.oop.test.cpp @@ -407,7 +407,7 @@ TEST_CASE_FIXTURE(BuiltinsFixture, "cycle_between_object_constructor_and_alias") TEST_CASE_FIXTURE(BuiltinsFixture, "promise_type_error_too_complex") { - ScopedFastFlag sff{"LuauStacklessTypeClone", true}; + ScopedFastFlag sff{"LuauStacklessTypeClone2", true}; frontend.options.retainFullTypeGraphs = false; diff --git a/tests/conformance/native.lua b/tests/conformance/native.lua index ed985c49..9b5bb884 100644 --- a/tests/conformance/native.lua +++ b/tests/conformance/native.lua @@ -112,4 +112,22 @@ end assert(pcall(fuzzfail10) == false) +local function fuzzfail11(x, ...) + return bit32.arshift(bit32.bnot(x),(...)) +end + +assert(fuzzfail11(0xffff0000, 8) == 0xff) + +local function fuzzfail12() + _,_,_,_,_,_,_,_ = not _, not _, not _, not _, not _, not _, not _, not _ +end + +assert(pcall(fuzzfail12) == true) + +local function fuzzfail13() + _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ = not _, not _, not _, not _, not _, not _, not _, not _, not _, not _, not _, not _, not _, not _, not _, not _ +end + +assert(pcall(fuzzfail13) == true) + return('OK') diff --git a/tests/conformance/tmerror.lua b/tests/conformance/tmerror.lua index 1ad4dd16..fef077ea 100644 --- a/tests/conformance/tmerror.lua +++ b/tests/conformance/tmerror.lua @@ -12,4 +12,30 @@ pcall(function() testtable.missingmethod() end) +-- +local testtable2 = {} +setmetatable(testtable2, { __index = function() pcall(function() error("Error") end) end }) + +local m2 = testtable2.missingmethod + +pcall(function() + testtable2.missingmethod() +end) + +-- +local testtable3 = {} +setmetatable(testtable3, { __index = function() pcall(error, "Error") end }) + +local m3 = testtable3.missingmethod + +pcall(function() + testtable3.missingmethod() +end) + +-- +local testtable4 = {} +setmetatable(testtable4, { __index = function() pcall(error) end }) + +local m4 = testtable4.missingmember + return('OK') diff --git a/tools/faillist.txt b/tools/faillist.txt index 390b8b62..f179a63f 100644 --- a/tools/faillist.txt +++ b/tools/faillist.txt @@ -254,6 +254,9 @@ TypeInferFunctions.higher_order_function_2 TypeInferFunctions.higher_order_function_4 TypeInferFunctions.improved_function_arg_mismatch_errors TypeInferFunctions.infer_anonymous_function_arguments +TypeInferFunctions.infer_generic_function_function_argument +TypeInferFunctions.infer_generic_function_function_argument_overloaded +TypeInferFunctions.infer_generic_lib_function_function_argument TypeInferFunctions.infer_anonymous_function_arguments_outside_call TypeInferFunctions.infer_that_function_does_not_return_a_table TypeInferFunctions.luau_subtyping_is_np_hard From d5e37ab367a5c20b6a38f4b089d028f880b335cf Mon Sep 17 00:00:00 2001 From: Alan Jeffrey <403333+asajeffrey@users.noreply.github.com> Date: Mon, 21 Aug 2023 14:21:10 -0500 Subject: [PATCH 2/5] Responding to referee comments on the HATRA 23 paper (#1014) --- papers/hatra23/hatra23.pdf | Bin 399315 -> 415900 bytes papers/hatra23/hatra23.tex | 52 ++++++++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/papers/hatra23/hatra23.pdf b/papers/hatra23/hatra23.pdf index 60201e651322b49b8097d3f533d5da0869124dd4..32e83b9ba8770868167b4160dfaa159a54bd6a6c 100644 GIT binary patch delta 138659 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

^B7>}MP7CduOTDq7mA$g9+5UA; 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 z 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 Zt;`BiR4QyiJ|TW#J`5%%C2eJl{{c4iZJ7W7 delta 122313 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

B^%9{MiqEwizUU77Y1l*3v0 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

#>WI|gw^-Dr4On705VFtnjh#lGFK$f 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%0Ax{NtwAHYN==;yBYMIrbR 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 CFrame) & ((CFrame, Vector3) -> Vector3) +\end{verbatim} +In order to typecheck this program, we check that that type is a subtype of: +\begin{verbatim} + (CFrame, Vector3 | CFrame) -> (Vector3 | CFrame) +\end{verbatim} +In the previous, syntax-driven, implementation of subtyping, this subtype check would fail, resulting in a false positive. +We have now released an implementation of semantic subtyping, which does not suffer from this defect. See our technical blog for more details~\cite{Jef22:SemanticSubtyping}. Rather than the gradual typing approach @@ -94,8 +110,30 @@ an error-suppressing type, and any failures of subtyping involving error-suppressing types are not reported. Users can explicitly suppress type errors by declaring variables with type $\ANY$, and since an expression with a type error has an error-suppressing type we -avoid cascading errors. Error suppression is in production Luau, and is -mechanically verified~\cite{BJ23:agda-typeck}. +avoid cascading errors. + +We do this by defining a \emph{infallible} typing judgment $\Gamma \vdash M : T$ +such that for any $\Gamma$ and $M$, there is a $T$ such that $\Gamma \vdash M : T$. +For example the rule for addition (ignoring overloads for simplicity) is: +\[ + \frac{\Gamma \vdash M : T \quad \Gamma \vdash M : U}{\Gamma \vdash M+N : \NUMBER} +\] +We define which judgments produce warnings, for example that rule produces a warning +when +\begin{itemize} + \item either $T \not<: \NUMBER$ and $T$ is not error-suppressing, + \item or $U \not<: \NUMBER$ and $U$ is not error-suppressing. +\end{itemize} +To retain type soundness (in the absence of user-supplied error-suppressing types) +we show that +if $\Gamma \vdash M : T$ and $T$ is error-suppressing, then either +\begin{itemize} + \item $\Gamma$ or $M$ contains an error-suppressing type, or + \item $\Gamma \vdash M : T$ produces a warning. +\end{itemize} +From this it is straightforward to show the usual ``well typed +programs don't go wrong'' type soundness result for programs without explicit +error-suppressing types~\cite{BJ23:agda-typeck}. \section{Further work} From 5097c60f107659fbd4908401a4dac997838f0322 Mon Sep 17 00:00:00 2001 From: Alan Jeffrey <403333+asajeffrey@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:25:25 -0500 Subject: [PATCH 3/5] Fix HATRA 23 citations (#1015) --- papers/hatra23/bibliography.bib | 2 +- papers/hatra23/hatra23.pdf | Bin 415900 -> 415897 bytes papers/hatra23/hatra23.tex | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/papers/hatra23/bibliography.bib b/papers/hatra23/bibliography.bib index 067bf967..3fbae85e 100644 --- a/papers/hatra23/bibliography.bib +++ b/papers/hatra23/bibliography.bib @@ -1,6 +1,6 @@ @InProceedings{BFJ21:GoalsLuau, author = {L. Brown and A. Friesen and A. S. A. Jeffrey}, - title = {Goals of the Luau Type System}, + title = {Position Paper: Goals of the Luau Type System}, booktitle = {Proc. Human Aspects of Types and Reasoning Assistants}, year = {2021}, url = {https://asaj.org/papers/hatra21.pdf}, diff --git a/papers/hatra23/hatra23.pdf b/papers/hatra23/hatra23.pdf index 32e83b9ba8770868167b4160dfaa159a54bd6a6c..b750ecaee636b26091494a76fd6c879fbe84e97a 100644 GIT binary patch delta 12247 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 R4=3+`FGr%Kl~9yK`hRlxY+(QZ delta 12225 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%0D8xMQbeyzb(8W*obfkP^z5zXj>&D0Rc*L^ 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 D$?ucC diff --git a/papers/hatra23/hatra23.tex b/papers/hatra23/hatra23.tex index 72e1f181..1d73ee53 100644 --- a/papers/hatra23/hatra23.tex +++ b/papers/hatra23/hatra23.tex @@ -49,7 +49,7 @@ error reporting). Roblox has hundreds of millions of users, and millions of creators, ranging from children learning to program for the first time to professional development studios. -In HATRA 2021, we presented \emph{The Goals Of The Luau Type +In HATRA 2021, we presented a position paper on the \emph{Goals Of The Luau Type System}~\cite{BFJ21:GoalsLuau}, describing the human factors issues with designing a type system for a language with a heterogeneous developer community. The design flows from the needs of the different @@ -103,7 +103,7 @@ We have now released an implementation of semantic subtyping, which does not suf See our technical blog for more details~\cite{Jef22:SemanticSubtyping}. Rather than the gradual typing approach -of~\cite{ST07:GradualTyping}, which uses \emph{consistent +of Siek and Taha~\cite{ST07:GradualTyping}, which uses \emph{consistent subtyping} where $\ANY \lesssim T \lesssim \ANY$ for any type $T$, we adopt an approach based on \emph{error suppression}, where $\ANY$ is an error-suppressing type, and any failures of subtyping involving From 535f85ebd334e10edaeb8988913532f260a42115 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 23 Aug 2023 10:55:14 -0700 Subject: [PATCH 4/5] Update performance.md (#1016) Document tostring/tonumber and math.pi/huge optimizations --- docs/_pages/performance.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_pages/performance.md b/docs/_pages/performance.md index d4dc0e8e..c2b4ced3 100644 --- a/docs/_pages/performance.md +++ b/docs/_pages/performance.md @@ -88,7 +88,7 @@ For this mechanism to work, function call must be "obvious" to the compiler - it The mechanism works by directly invoking a highly specialized and optimized implementation of a builtin function from the interpreter core loop without setting up a stack frame and omitting other work; additionally, some fastcall specializations are partial in that they don't support all types of arguments, for example all `math` library builtins are only specialized for numeric arguments, so calling `math.abs` with a string argument will fall back to the slower implementation that will do string->number coercion. -As a result, builtin calls are very fast in Luau - they are still slightly slower than core instructions such as arithmetic operations, but only slightly so. The set of fastcall builtins is slowly expanding over time and as of this writing contains `assert`, `type`, `typeof`, `rawget`/`rawset`/`rawequal`, `getmetatable`/`setmetatable`, all functions from `math` and `bit32`, and some functions from `string` and `table` library. +As a result, builtin calls are very fast in Luau - they are still slightly slower than core instructions such as arithmetic operations, but only slightly so. The set of fastcall builtins is slowly expanding over time and as of this writing contains `assert`, `type`, `typeof`, `rawget`/`rawset`/`rawequal`, `getmetatable`/`setmetatable`, `tonumber`/`tostring`, all functions from `math` (except `noise` and `random`/`randomseed`) and `bit32`, and some functions from `string` and `table` library. Some builtin functions have partial specializations that reduce the cost of the common case further. Notably: @@ -98,7 +98,7 @@ Some builtin functions have partial specializations that reduce the cost of the Some functions from `math` library like `math.floor` can additionally take advantage of advanced SIMD instruction sets like SSE4.1 when available. -In addition to runtime optimizations for builtin calls, many builtin calls can also be constant-folded by the bytecode compiler when using aggressive optimizations (level 2); this currently applies to most builtin calls with constant arguments and a single return value. For builtin calls that can not be constant folded, compiler assumes knowledge of argument/return count (level 2) to produce more efficient bytecode instructions. +In addition to runtime optimizations for builtin calls, many builtin calls, as well as constants like `math.pi`/`math.huge`, can also be constant-folded by the bytecode compiler when using aggressive optimizations (level 2); this currently applies to most builtin calls with constant arguments and a single return value. For builtin calls that can not be constant folded, compiler assumes knowledge of argument/return count (level 2) to produce more efficient bytecode instructions. ## Optimized table iteration From c3fc0d7bc8986d4f5b87688e7f537ca164aad16d Mon Sep 17 00:00:00 2001 From: Andy Friesen Date: Wed, 23 Aug 2023 15:52:59 -0700 Subject: [PATCH 5/5] RFC for local type inference. (#1007) [Rendered](https://github.com/Roblox/luau/blob/0e1082108fd6fb3a32dfdf5f1766ea3fc1391328/rfcs/local-type-inference.md) --- rfcs/local-type-inference.md | 180 +++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 rfcs/local-type-inference.md diff --git a/rfcs/local-type-inference.md b/rfcs/local-type-inference.md new file mode 100644 index 00000000..88cfe3cd --- /dev/null +++ b/rfcs/local-type-inference.md @@ -0,0 +1,180 @@ +# Local Type Inference + +## Summary + +We are going to supplant the current type solver with one based on Benjamin Pierce's Local Type Inference algorithm: + +https://www.cis.upenn.edu/~bcpierce/papers/lti-toplas.pdf + +## Motivation + +Luau's type inference algorithm is used for much more than typechecking scripts. It is also the backbone of an autocomplete algorithm which has to work even for people who don't know what types or type systems are. + +We originally implemented nonstrict mode by making some tactical adjustments to the type inference algorithm. This was great for reducing false positives in untyped code, but carried with it the drawback that the inference result was usually not good enough for the autocomplete system. In order to offer a high quality experience, we've found ourselves to run type inference on nonstrict scripts twice: once for error feedback, and once again to populate the autocomplete database. + +Separately, we would also like more accurate type inference in general. Our current type solver jumps to conclusions a little bit too quickly. For example, it cannot infer an accurate type for an ordinary search function: + +```lua +function index_of(tbl, el) + for i = 0, #tbl do + if tbl[i] == el then + return i + end + end + return nil +end +``` + +Our solver sees two `return` statements and assumes that, because the first statement yields a `number`, so too must the second. + +To fix this, we are going to move to an architecture where type inference and type checking are two separate steps. Whatever mode the user is programming with, we will run an accurate type inference pass over their code and then run one of two typechecking passes over it. + +## Notation + +We'll use the standard notation `A <: B` to indicate that `A` is a subtype of `B`. + +## Design + +At a very high level, local type inference is built around the idea that we track the lower bounds and their upper bounds. The lower bounds of a binding is the set of values that it might conceivably receive. If a binding receives a value outside of its upper bounds, the program will fail. + +At the implementation level, we reencode free types as the space between these bounds. + +Upper bounds arise only from type annotations and certain builtin operations whereas lower bounds arise from assignments, return statements, and uses. + +Free types all start out with bounds `never <: 't <: unknown`. Intuitively, we say that `'t` represents some set of values whose domain is at least `never` and at most `unknown`. This naturally could be any value at all. + +When dispatching a constraint `T <: 't`, we replace the lower bounds of `'t` by the union of its old lower bounds and `T`. When dispatching a constraint `'t <: T`, we replace the upper bounds by its upper bound intersected with `T`. In other words, lower bounds grow from nothing as we see the value used whereas the upper bound initially encompasses everything and shrinks as we constrain it. + +### Constraint Generation Rules + +A return statement expands the lower bounds of the enclosing function's return type. + +```lua +function f(): R + local x: X + return x + -- X <: R +end +``` + +An assignment adds to the lower bounds of the assignee. + +```lua +local a: A +local b: B +a = b +-- B <: A +``` + +A function call adds to the upper bounds of the function being called. + +Equivalently, passing a value to a function adds to the upper bounds of that value and to the lower bounds of its return value. + +```lua +local g +local h: H +local j = g(h) +-- G <: (H) -> I... +-- I... <: J +``` + +Property access is a constraint on a value's upper bounds. +```lua +local a: A +a.b = 2 +-- A <: {b: number} + +a[1] = 3 +-- A <: {number} +``` + +### Generalization + +Generalization is the process by which we infer that a function argument is generic. Broadly speaking, we solve constraints that arise from the function interior, we scan the signature of the function for types that are unconstrained, and we replace those types with generics. This much is all unchanged from the old solver. + +Unlike with the old solver, we never bind free types when dispatching a subtype constraint under local type inference. We only bind free types during generalization. + +If a type only appears in covariant positions in the function's signature, we can replace it by its lower bound. If it only appears in contravariant positions, we replace it by its upper bound. If it appears in both, we'll need to implement bounded generics to get it right. This is beyond the scope of this RFC. + +If a free type has neither upper nor lower bounds, we replace it with a generic. + +Some simple examples: + +```lua +function print_number(n: number) print(n) end + +function f(n) + print_number(n) +end +``` + +We arrive at the solution `never <: 'n <: number`. When we generalize, we can replace `'n` by its upper bound, namely `number`. We infer `f : (number) -> ()`. + +Next example: + +```lua +function index_of(tbl, el) -- index_of : ('a, 'b) -> 'r + for i = 0, #tbl do -- i : number + if tbl[i] == el then -- 'a <: {'c} + return i -- number <: 'r + end + end + return nil -- nil <: 'r +end +``` + +When typechecking this function, we have two constraints on `'r`, the return type. We can combine these constraints by taking the union of the lower bounds, leading us to `number | nil <: 'r <: unknown`. The type `'r` only appears in the return type of the function. The return type of this function is `number | nil`. + +At runtime, Luau allows any two values to be compared. Comparisons of values of mismatched types always return `false`. We therefore cannot produce any interesting constraints about `'b` or `'c`. + +We end up with these bounds: + +``` +never <: 'a <: {'c} +never <: 'b <: unknown +never <: 'c <: unknown +number | nil <: 'r <: unknown +``` + +`'a` appears in the argument position, so we replace it with its upper bound `{'c}`. `'b` and `'c` have no constraints at all so they are replaced by generics `B` and `C`. `'r` appears only in the return position and so is replaced by its lower bound `number | nil`. + +The final inferred type of `index_of` is `({C}, B) -> number | nil`. + +## Drawbacks + +This algorithm requires that we create a lot of union and intersection types. We need to be able to consistently pare down degenerate unions like `number | number`. + +Local type inference is also more permissive than what we have been doing up until now. For instance, the following is perfectly fine: + +```lua +local x = nil +if something then + x = 41 +else + x = "fourty one" +end +``` + +We'll infer `x : number | string | nil`. If the user wishes to constrain a value more tightly, they will have to write an annotation. + +## Alternatives + +### What TypeScript does + +TypeScript very clearly makes it work in what we would call a strict mode context, but we need more in order to offer a high quality nonstrict mode. For instance, TypeScript's autocomplete is completely helpless in the face of this code fragment: + +```ts +let x = null; +x = {a: "a", b: "pickles"}; +x. +``` + +TypeScript will complain that the assignment to `x` is illegal because `x` has type `null`. It will further offer no autocomplete suggestions at all when the user types the final `.`. + +It's not viable for us to require users to write type annotations. Many of our users do not yet know what types are but we are nevertheless committed to providing them a tool that is helpful to them. + +### Success Typing + +Success typing is the algorithm used by the Dialyzer inference engine for Erlang. Instead of attempting to prove that values always flow in sensible ways, it tries to prove that values _could_ flow in sensible ways. + +Success typing is quite nice in that it's very forgiving and can draw surprisingly useful information from untyped code, but that forgiving nature works against us in the case of strict mode.