mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 14:25:44 +08:00
Sync to upstream/release/606
This commit is contained in:
parent
557e77a676
commit
69728e87cf
@ -150,7 +150,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
ScopePtr childScope(AstNode* node, const ScopePtr& parent);
|
ScopePtr childScope(AstNode* node, const ScopePtr& parent);
|
||||||
|
|
||||||
std::optional<TypeId> lookup(Scope* scope, DefId def);
|
std::optional<TypeId> lookup(Scope* scope, DefId def, bool prototype = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new constraint with no dependencies to a given scope.
|
* Adds a new constraint with no dependencies to a given scope.
|
||||||
|
@ -74,8 +74,15 @@ private:
|
|||||||
|
|
||||||
struct DfgScope
|
struct DfgScope
|
||||||
{
|
{
|
||||||
|
enum ScopeType
|
||||||
|
{
|
||||||
|
Linear,
|
||||||
|
Loop,
|
||||||
|
Function,
|
||||||
|
};
|
||||||
|
|
||||||
DfgScope* parent;
|
DfgScope* parent;
|
||||||
bool isLoopScope;
|
ScopeType scopeType;
|
||||||
|
|
||||||
using Bindings = DenseHashMap<Symbol, const Def*>;
|
using Bindings = DenseHashMap<Symbol, const Def*>;
|
||||||
using Props = DenseHashMap<const Def*, std::unordered_map<std::string, const Def*>>;
|
using Props = DenseHashMap<const Def*, std::unordered_map<std::string, const Def*>>;
|
||||||
@ -117,7 +124,17 @@ private:
|
|||||||
|
|
||||||
std::vector<std::unique_ptr<DfgScope>> scopes;
|
std::vector<std::unique_ptr<DfgScope>> scopes;
|
||||||
|
|
||||||
DfgScope* childScope(DfgScope* scope, bool isLoopScope = false);
|
struct FunctionCapture
|
||||||
|
{
|
||||||
|
std::vector<DefId> captureDefs;
|
||||||
|
std::vector<DefId> allVersions;
|
||||||
|
size_t versionOffset = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
DenseHashMap<Symbol, FunctionCapture> captures{Symbol{}};
|
||||||
|
void resolveCaptures();
|
||||||
|
|
||||||
|
DfgScope* childScope(DfgScope* scope, DfgScope::ScopeType scopeType = DfgScope::Linear);
|
||||||
|
|
||||||
void join(DfgScope* p, DfgScope* a, DfgScope* b);
|
void join(DfgScope* p, DfgScope* a, DfgScope* b);
|
||||||
void joinBindings(DfgScope::Bindings& p, const DfgScope::Bindings& a, const DfgScope::Bindings& b);
|
void joinBindings(DfgScope::Bindings& p, const DfgScope::Bindings& a, const DfgScope::Bindings& b);
|
||||||
@ -167,11 +184,11 @@ private:
|
|||||||
DataFlowResult visitExpr(DfgScope* scope, AstExprError* error);
|
DataFlowResult visitExpr(DfgScope* scope, AstExprError* error);
|
||||||
|
|
||||||
void visitLValue(DfgScope* scope, AstExpr* e, DefId incomingDef, bool isCompoundAssignment = false);
|
void visitLValue(DfgScope* scope, AstExpr* e, DefId incomingDef, bool isCompoundAssignment = false);
|
||||||
void visitLValue(DfgScope* scope, AstExprLocal* l, DefId incomingDef, bool isCompoundAssignment);
|
DefId visitLValue(DfgScope* scope, AstExprLocal* l, DefId incomingDef, bool isCompoundAssignment);
|
||||||
void visitLValue(DfgScope* scope, AstExprGlobal* g, DefId incomingDef, bool isCompoundAssignment);
|
DefId visitLValue(DfgScope* scope, AstExprGlobal* g, DefId incomingDef, bool isCompoundAssignment);
|
||||||
void visitLValue(DfgScope* scope, AstExprIndexName* i, DefId incomingDef);
|
DefId visitLValue(DfgScope* scope, AstExprIndexName* i, DefId incomingDef);
|
||||||
void visitLValue(DfgScope* scope, AstExprIndexExpr* i, DefId incomingDef);
|
DefId visitLValue(DfgScope* scope, AstExprIndexExpr* i, DefId incomingDef);
|
||||||
void visitLValue(DfgScope* scope, AstExprError* e, DefId incomingDef);
|
DefId visitLValue(DfgScope* scope, AstExprError* e, DefId incomingDef);
|
||||||
|
|
||||||
void visitType(DfgScope* scope, AstType* t);
|
void visitType(DfgScope* scope, AstType* t);
|
||||||
void visitType(DfgScope* scope, AstTypeReference* r);
|
void visitType(DfgScope* scope, AstTypeReference* r);
|
||||||
|
@ -73,6 +73,7 @@ const T* get(DefId def)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool containsSubscriptedDefinition(DefId def);
|
bool containsSubscriptedDefinition(DefId def);
|
||||||
|
void collectOperands(DefId def, std::vector<DefId>* operands);
|
||||||
|
|
||||||
struct DefArena
|
struct DefArena
|
||||||
{
|
{
|
||||||
|
@ -205,7 +205,7 @@ ScopePtr ConstraintGenerator::childScope(AstNode* node, const ScopePtr& parent)
|
|||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<TypeId> ConstraintGenerator::lookup(Scope* scope, DefId def)
|
std::optional<TypeId> ConstraintGenerator::lookup(Scope* scope, DefId def, bool prototype)
|
||||||
{
|
{
|
||||||
if (get<Cell>(def))
|
if (get<Cell>(def))
|
||||||
return scope->lookup(def);
|
return scope->lookup(def);
|
||||||
@ -213,22 +213,24 @@ std::optional<TypeId> ConstraintGenerator::lookup(Scope* scope, DefId def)
|
|||||||
{
|
{
|
||||||
if (auto found = scope->lookup(def))
|
if (auto found = scope->lookup(def))
|
||||||
return *found;
|
return *found;
|
||||||
|
else if (!prototype)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
TypeId res = builtinTypes->neverType;
|
TypeId res = builtinTypes->neverType;
|
||||||
|
|
||||||
for (DefId operand : phi->operands)
|
for (DefId operand : phi->operands)
|
||||||
{
|
{
|
||||||
// `scope->lookup(operand)` may return nothing because it could be a phi node of globals, but one of
|
// `scope->lookup(operand)` may return nothing because we only bind a type to that operand
|
||||||
// the operand of that global has never been assigned a type, and so it should be an error.
|
// once we've seen that particular `DefId`. In this case, we need to prototype those types
|
||||||
// e.g.
|
// and use those at a later time.
|
||||||
// ```
|
std::optional<TypeId> ty = lookup(scope, operand, /*prototype*/false);
|
||||||
// if foo() then
|
if (!ty)
|
||||||
// g = 5
|
{
|
||||||
// end
|
ty = arena->addType(BlockedType{});
|
||||||
// -- `g` here is a phi node of the assignment to `g`, or the original revision of `g` before the branch.
|
rootScope->lvalueTypes[operand] = *ty;
|
||||||
// ```
|
}
|
||||||
TypeId ty = scope->lookup(operand).value_or(builtinTypes->errorRecoveryType());
|
|
||||||
res = simplifyUnion(builtinTypes, arena, res, ty).result;
|
res = simplifyUnion(builtinTypes, arena, res, *ty).result;
|
||||||
}
|
}
|
||||||
|
|
||||||
scope->lvalueTypes[def] = res;
|
scope->lvalueTypes[def] = res;
|
||||||
@ -861,7 +863,7 @@ ControlFlow ConstraintGenerator::visit(const ScopePtr& scope, AstStatFunction* f
|
|||||||
DenseHashSet<Constraint*> excludeList{nullptr};
|
DenseHashSet<Constraint*> excludeList{nullptr};
|
||||||
|
|
||||||
DefId def = dfg->getDef(function->name);
|
DefId def = dfg->getDef(function->name);
|
||||||
std::optional<TypeId> existingFunctionTy = scope->lookup(def);
|
std::optional<TypeId> existingFunctionTy = lookup(scope.get(), def);
|
||||||
|
|
||||||
if (AstExprLocal* localName = function->name->as<AstExprLocal>())
|
if (AstExprLocal* localName = function->name->as<AstExprLocal>())
|
||||||
{
|
{
|
||||||
@ -1724,16 +1726,14 @@ Inference ConstraintGenerator::check(const ScopePtr& scope, AstExprGlobal* globa
|
|||||||
/* prepopulateGlobalScope() has already added all global functions to the environment by this point, so any
|
/* prepopulateGlobalScope() has already added all global functions to the environment by this point, so any
|
||||||
* global that is not already in-scope is definitely an unknown symbol.
|
* global that is not already in-scope is definitely an unknown symbol.
|
||||||
*/
|
*/
|
||||||
if (auto ty = lookup(scope.get(), def))
|
if (auto ty = lookup(scope.get(), def, /*prototype=*/false))
|
||||||
return Inference{*ty, refinementArena.proposition(key, builtinTypes->truthyType)};
|
|
||||||
else if (auto ty = scope->lookup(global->name))
|
|
||||||
{
|
{
|
||||||
rootScope->lvalueTypes[def] = *ty;
|
rootScope->lvalueTypes[def] = *ty;
|
||||||
return Inference{*ty, refinementArena.proposition(key, builtinTypes->truthyType)};
|
return Inference{*ty, refinementArena.proposition(key, builtinTypes->truthyType)};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
reportError(global->location, UnknownSymbol{global->name.value});
|
reportError(global->location, UnknownSymbol{global->name.value, UnknownSymbol::Binding});
|
||||||
return Inference{builtinTypes->errorRecoveryType()};
|
return Inference{builtinTypes->errorRecoveryType()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3110,6 +3110,16 @@ struct GlobalPrepopulator : AstVisitor
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool visit(AstType*) override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool visit(class AstTypePack* node) override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void ConstraintGenerator::prepopulateGlobalScope(const ScopePtr& globalScope, AstStatBlock* program)
|
void ConstraintGenerator::prepopulateGlobalScope(const ScopePtr& globalScope, AstStatBlock* program)
|
||||||
|
@ -116,7 +116,7 @@ bool DfgScope::canUpdateDefinition(Symbol symbol) const
|
|||||||
{
|
{
|
||||||
if (current->bindings.find(symbol))
|
if (current->bindings.find(symbol))
|
||||||
return true;
|
return true;
|
||||||
else if (current->isLoopScope)
|
else if (current->scopeType == DfgScope::Loop)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ bool DfgScope::canUpdateDefinition(DefId def, const std::string& key) const
|
|||||||
{
|
{
|
||||||
if (auto props = current->props.find(def))
|
if (auto props = current->props.find(def))
|
||||||
return true;
|
return true;
|
||||||
else if (current->isLoopScope)
|
else if (current->scopeType == DfgScope::Loop)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +144,7 @@ DataFlowGraph DataFlowGraphBuilder::build(AstStatBlock* block, NotNull<InternalE
|
|||||||
builder.handle = handle;
|
builder.handle = handle;
|
||||||
builder.moduleScope = builder.childScope(nullptr); // nullptr is the root DFG scope.
|
builder.moduleScope = builder.childScope(nullptr); // nullptr is the root DFG scope.
|
||||||
builder.visitBlockWithoutChildScope(builder.moduleScope, block);
|
builder.visitBlockWithoutChildScope(builder.moduleScope, block);
|
||||||
|
builder.resolveCaptures();
|
||||||
|
|
||||||
if (FFlag::DebugLuauFreezeArena)
|
if (FFlag::DebugLuauFreezeArena)
|
||||||
{
|
{
|
||||||
@ -154,9 +155,27 @@ DataFlowGraph DataFlowGraphBuilder::build(AstStatBlock* block, NotNull<InternalE
|
|||||||
return std::move(builder.graph);
|
return std::move(builder.graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
DfgScope* DataFlowGraphBuilder::childScope(DfgScope* scope, bool isLoopScope)
|
void DataFlowGraphBuilder::resolveCaptures()
|
||||||
{
|
{
|
||||||
return scopes.emplace_back(new DfgScope{scope, isLoopScope}).get();
|
for (const auto& [_, capture] : captures)
|
||||||
|
{
|
||||||
|
std::vector<DefId> operands;
|
||||||
|
for (size_t i = capture.versionOffset; i < capture.allVersions.size(); ++i)
|
||||||
|
collectOperands(capture.allVersions[i], &operands);
|
||||||
|
|
||||||
|
for (DefId captureDef : capture.captureDefs)
|
||||||
|
{
|
||||||
|
Phi* phi = const_cast<Phi*>(get<Phi>(captureDef));
|
||||||
|
LUAU_ASSERT(phi);
|
||||||
|
LUAU_ASSERT(phi->operands.empty());
|
||||||
|
phi->operands = operands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DfgScope* DataFlowGraphBuilder::childScope(DfgScope* scope, DfgScope::ScopeType scopeType)
|
||||||
|
{
|
||||||
|
return scopes.emplace_back(new DfgScope{scope, scopeType}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFlowGraphBuilder::join(DfgScope* p, DfgScope* a, DfgScope* b)
|
void DataFlowGraphBuilder::join(DfgScope* p, DfgScope* a, DfgScope* b)
|
||||||
@ -227,24 +246,44 @@ void DataFlowGraphBuilder::joinProps(DfgScope::Props& p, const DfgScope::Props&
|
|||||||
|
|
||||||
DefId DataFlowGraphBuilder::lookup(DfgScope* scope, Symbol symbol)
|
DefId DataFlowGraphBuilder::lookup(DfgScope* scope, Symbol symbol)
|
||||||
{
|
{
|
||||||
if (auto found = scope->lookup(symbol))
|
for (DfgScope* current = scope; current; current = current->parent)
|
||||||
return *found;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
DefId result = defArena->freshCell();
|
if (auto found = current->bindings.find(symbol))
|
||||||
if (symbol.local)
|
return NotNull{*found};
|
||||||
scope->bindings[symbol] = result;
|
else if (current->scopeType == DfgScope::Function)
|
||||||
else
|
{
|
||||||
moduleScope->bindings[symbol] = result;
|
FunctionCapture& capture = captures[symbol];
|
||||||
return result;
|
DefId captureDef = defArena->phi({});
|
||||||
|
capture.captureDefs.push_back(captureDef);
|
||||||
|
scope->bindings[symbol] = captureDef;
|
||||||
|
return NotNull{captureDef};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DefId result = defArena->freshCell();
|
||||||
|
scope->bindings[symbol] = result;
|
||||||
|
captures[symbol].allVersions.push_back(result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DefId DataFlowGraphBuilder::lookup(DfgScope* scope, DefId def, const std::string& key)
|
DefId DataFlowGraphBuilder::lookup(DfgScope* scope, DefId def, const std::string& key)
|
||||||
{
|
{
|
||||||
if (auto found = scope->lookup(def, key))
|
for (DfgScope* current = scope; current; current = current->parent)
|
||||||
return *found;
|
{
|
||||||
else if (auto phi = get<Phi>(def))
|
if (auto props = current->props.find(def))
|
||||||
|
{
|
||||||
|
if (auto it = props->find(key); it != props->end())
|
||||||
|
return NotNull{it->second};
|
||||||
|
}
|
||||||
|
else if (auto phi = get<Phi>(def); phi && phi->operands.empty()) // Unresolved phi nodes
|
||||||
|
{
|
||||||
|
DefId result = defArena->freshCell();
|
||||||
|
scope->props[def][key] = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto phi = get<Phi>(def))
|
||||||
{
|
{
|
||||||
std::vector<DefId> defs;
|
std::vector<DefId> defs;
|
||||||
for (DefId operand : phi->operands)
|
for (DefId operand : phi->operands)
|
||||||
@ -361,7 +400,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatIf* i)
|
|||||||
ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatWhile* w)
|
ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatWhile* w)
|
||||||
{
|
{
|
||||||
// TODO(controlflow): entry point has a back edge from exit point
|
// TODO(controlflow): entry point has a back edge from exit point
|
||||||
DfgScope* whileScope = childScope(scope, /*isLoopScope=*/true);
|
DfgScope* whileScope = childScope(scope, DfgScope::Loop);
|
||||||
visitExpr(whileScope, w->condition);
|
visitExpr(whileScope, w->condition);
|
||||||
visit(whileScope, w->body);
|
visit(whileScope, w->body);
|
||||||
|
|
||||||
@ -373,7 +412,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatWhile* w)
|
|||||||
ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatRepeat* r)
|
ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatRepeat* r)
|
||||||
{
|
{
|
||||||
// TODO(controlflow): entry point has a back edge from exit point
|
// TODO(controlflow): entry point has a back edge from exit point
|
||||||
DfgScope* repeatScope = childScope(scope, /*isLoopScope=*/true);
|
DfgScope* repeatScope = childScope(scope, DfgScope::Loop);
|
||||||
visitBlockWithoutChildScope(repeatScope, r->body);
|
visitBlockWithoutChildScope(repeatScope, r->body);
|
||||||
visitExpr(repeatScope, r->condition);
|
visitExpr(repeatScope, r->condition);
|
||||||
|
|
||||||
@ -429,6 +468,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatLocal* l)
|
|||||||
DefId def = defArena->freshCell(subscripted);
|
DefId def = defArena->freshCell(subscripted);
|
||||||
graph.localDefs[local] = def;
|
graph.localDefs[local] = def;
|
||||||
scope->bindings[local] = def;
|
scope->bindings[local] = def;
|
||||||
|
captures[local].allVersions.push_back(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ControlFlow::None;
|
return ControlFlow::None;
|
||||||
@ -436,7 +476,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatLocal* l)
|
|||||||
|
|
||||||
ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatFor* f)
|
ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatFor* f)
|
||||||
{
|
{
|
||||||
DfgScope* forScope = childScope(scope, /*isLoopScope=*/true);
|
DfgScope* forScope = childScope(scope, DfgScope::Loop);
|
||||||
|
|
||||||
visitExpr(scope, f->from);
|
visitExpr(scope, f->from);
|
||||||
visitExpr(scope, f->to);
|
visitExpr(scope, f->to);
|
||||||
@ -449,6 +489,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatFor* f)
|
|||||||
DefId def = defArena->freshCell();
|
DefId def = defArena->freshCell();
|
||||||
graph.localDefs[f->var] = def;
|
graph.localDefs[f->var] = def;
|
||||||
scope->bindings[f->var] = def;
|
scope->bindings[f->var] = def;
|
||||||
|
captures[f->var].allVersions.push_back(def);
|
||||||
|
|
||||||
// TODO(controlflow): entry point has a back edge from exit point
|
// TODO(controlflow): entry point has a back edge from exit point
|
||||||
visit(forScope, f->body);
|
visit(forScope, f->body);
|
||||||
@ -460,7 +501,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatFor* f)
|
|||||||
|
|
||||||
ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatForIn* f)
|
ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatForIn* f)
|
||||||
{
|
{
|
||||||
DfgScope* forScope = childScope(scope, /*isLoopScope=*/true);
|
DfgScope* forScope = childScope(scope, DfgScope::Loop);
|
||||||
|
|
||||||
for (AstLocal* local : f->vars)
|
for (AstLocal* local : f->vars)
|
||||||
{
|
{
|
||||||
@ -470,6 +511,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatForIn* f)
|
|||||||
DefId def = defArena->freshCell();
|
DefId def = defArena->freshCell();
|
||||||
graph.localDefs[local] = def;
|
graph.localDefs[local] = def;
|
||||||
forScope->bindings[local] = def;
|
forScope->bindings[local] = def;
|
||||||
|
captures[local].allVersions.push_back(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(controlflow): entry point has a back edge from exit point
|
// TODO(controlflow): entry point has a back edge from exit point
|
||||||
@ -527,10 +569,21 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatFunction* f)
|
|||||||
//
|
//
|
||||||
// which is evidence that references to variables must be a phi node of all possible definitions,
|
// which is evidence that references to variables must be a phi node of all possible definitions,
|
||||||
// but for bug compatibility, we'll assume the same thing here.
|
// but for bug compatibility, we'll assume the same thing here.
|
||||||
DefId prototype = defArena->freshCell();
|
visitLValue(scope, f->name, defArena->freshCell());
|
||||||
visitLValue(scope, f->name, prototype);
|
|
||||||
visitExpr(scope, f->func);
|
visitExpr(scope, f->func);
|
||||||
|
|
||||||
|
if (auto local = f->name->as<AstExprLocal>())
|
||||||
|
{
|
||||||
|
// local f
|
||||||
|
// function f()
|
||||||
|
// if cond() then
|
||||||
|
// f() -- should reference only the function version and other future version, and nothing prior
|
||||||
|
// end
|
||||||
|
// end
|
||||||
|
FunctionCapture& capture = captures[local->local];
|
||||||
|
capture.versionOffset = capture.allVersions.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
return ControlFlow::None;
|
return ControlFlow::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,6 +592,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatLocalFunction* l
|
|||||||
DefId def = defArena->freshCell();
|
DefId def = defArena->freshCell();
|
||||||
graph.localDefs[l->name] = def;
|
graph.localDefs[l->name] = def;
|
||||||
scope->bindings[l->name] = def;
|
scope->bindings[l->name] = def;
|
||||||
|
captures[l->name].allVersions.push_back(def);
|
||||||
visitExpr(scope, l->func);
|
visitExpr(scope, l->func);
|
||||||
|
|
||||||
return ControlFlow::None;
|
return ControlFlow::None;
|
||||||
@ -559,6 +613,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatDeclareGlobal* d
|
|||||||
DefId def = defArena->freshCell();
|
DefId def = defArena->freshCell();
|
||||||
graph.declaredDefs[d] = def;
|
graph.declaredDefs[d] = def;
|
||||||
scope->bindings[d->name] = def;
|
scope->bindings[d->name] = def;
|
||||||
|
captures[d->name].allVersions.push_back(def);
|
||||||
|
|
||||||
visitType(scope, d->type);
|
visitType(scope, d->type);
|
||||||
|
|
||||||
@ -570,6 +625,7 @@ ControlFlow DataFlowGraphBuilder::visit(DfgScope* scope, AstStatDeclareFunction*
|
|||||||
DefId def = defArena->freshCell();
|
DefId def = defArena->freshCell();
|
||||||
graph.declaredDefs[d] = def;
|
graph.declaredDefs[d] = def;
|
||||||
scope->bindings[d->name] = def;
|
scope->bindings[d->name] = def;
|
||||||
|
captures[d->name].allVersions.push_back(def);
|
||||||
|
|
||||||
DfgScope* unreachable = childScope(scope);
|
DfgScope* unreachable = childScope(scope);
|
||||||
visitGenerics(unreachable, d->generics);
|
visitGenerics(unreachable, d->generics);
|
||||||
@ -669,14 +725,9 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprGroup* gr
|
|||||||
|
|
||||||
DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprLocal* l)
|
DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprLocal* l)
|
||||||
{
|
{
|
||||||
// DfgScope::lookup is intentional here: we want to be able to ice.
|
DefId def = lookup(scope, l->local);
|
||||||
if (auto def = scope->lookup(l->local))
|
const RefinementKey* key = keyArena->leaf(def);
|
||||||
{
|
return {def, key};
|
||||||
const RefinementKey* key = keyArena->leaf(*def);
|
|
||||||
return {*def, key};
|
|
||||||
}
|
|
||||||
|
|
||||||
handle->ice("DFG: AstExprLocal came before its declaration?");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprGlobal* g)
|
DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprGlobal* g)
|
||||||
@ -723,7 +774,7 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprIndexExpr
|
|||||||
|
|
||||||
DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprFunction* f)
|
DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprFunction* f)
|
||||||
{
|
{
|
||||||
DfgScope* signatureScope = childScope(scope);
|
DfgScope* signatureScope = childScope(scope, DfgScope::Function);
|
||||||
|
|
||||||
if (AstLocal* self = f->self)
|
if (AstLocal* self = f->self)
|
||||||
{
|
{
|
||||||
@ -733,6 +784,7 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprFunction*
|
|||||||
DefId def = defArena->freshCell();
|
DefId def = defArena->freshCell();
|
||||||
graph.localDefs[self] = def;
|
graph.localDefs[self] = def;
|
||||||
signatureScope->bindings[self] = def;
|
signatureScope->bindings[self] = def;
|
||||||
|
captures[self].allVersions.push_back(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (AstLocal* param : f->args)
|
for (AstLocal* param : f->args)
|
||||||
@ -743,6 +795,7 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprFunction*
|
|||||||
DefId def = defArena->freshCell();
|
DefId def = defArena->freshCell();
|
||||||
graph.localDefs[param] = def;
|
graph.localDefs[param] = def;
|
||||||
signatureScope->bindings[param] = def;
|
signatureScope->bindings[param] = def;
|
||||||
|
captures[param].allVersions.push_back(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->varargAnnotation)
|
if (f->varargAnnotation)
|
||||||
@ -827,41 +880,46 @@ DataFlowResult DataFlowGraphBuilder::visitExpr(DfgScope* scope, AstExprError* er
|
|||||||
|
|
||||||
void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExpr* e, DefId incomingDef, bool isCompoundAssignment)
|
void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExpr* e, DefId incomingDef, bool isCompoundAssignment)
|
||||||
{
|
{
|
||||||
if (auto l = e->as<AstExprLocal>())
|
auto go = [&]() {
|
||||||
return visitLValue(scope, l, incomingDef, isCompoundAssignment);
|
if (auto l = e->as<AstExprLocal>())
|
||||||
else if (auto g = e->as<AstExprGlobal>())
|
return visitLValue(scope, l, incomingDef, isCompoundAssignment);
|
||||||
return visitLValue(scope, g, incomingDef, isCompoundAssignment);
|
else if (auto g = e->as<AstExprGlobal>())
|
||||||
else if (auto i = e->as<AstExprIndexName>())
|
return visitLValue(scope, g, incomingDef, isCompoundAssignment);
|
||||||
return visitLValue(scope, i, incomingDef);
|
else if (auto i = e->as<AstExprIndexName>())
|
||||||
else if (auto i = e->as<AstExprIndexExpr>())
|
return visitLValue(scope, i, incomingDef);
|
||||||
return visitLValue(scope, i, incomingDef);
|
else if (auto i = e->as<AstExprIndexExpr>())
|
||||||
else if (auto error = e->as<AstExprError>())
|
return visitLValue(scope, i, incomingDef);
|
||||||
return visitLValue(scope, error, incomingDef);
|
else if (auto error = e->as<AstExprError>())
|
||||||
else
|
return visitLValue(scope, error, incomingDef);
|
||||||
handle->ice("Unknown AstExpr in DataFlowGraphBuilder::visitLValue");
|
else
|
||||||
|
handle->ice("Unknown AstExpr in DataFlowGraphBuilder::visitLValue");
|
||||||
|
};
|
||||||
|
|
||||||
|
graph.astDefs[e] = go();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprLocal* l, DefId incomingDef, bool isCompoundAssignment)
|
DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprLocal* l, DefId incomingDef, bool isCompoundAssignment)
|
||||||
{
|
{
|
||||||
// We need to keep the previous def around for a compound assignment.
|
// We need to keep the previous def around for a compound assignment.
|
||||||
if (isCompoundAssignment)
|
if (isCompoundAssignment)
|
||||||
{
|
{
|
||||||
if (auto def = scope->lookup(l->local))
|
DefId def = lookup(scope, l->local);
|
||||||
graph.compoundAssignDefs[l] = *def;
|
graph.compoundAssignDefs[l] = def;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In order to avoid alias tracking, we need to clip the reference to the parent def.
|
// In order to avoid alias tracking, we need to clip the reference to the parent def.
|
||||||
if (scope->canUpdateDefinition(l->local))
|
if (scope->canUpdateDefinition(l->local))
|
||||||
{
|
{
|
||||||
DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef));
|
DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef));
|
||||||
graph.astDefs[l] = updated;
|
|
||||||
scope->bindings[l->local] = updated;
|
scope->bindings[l->local] = updated;
|
||||||
|
captures[l->local].allVersions.push_back(updated);
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
visitExpr(scope, static_cast<AstExpr*>(l));
|
return visitExpr(scope, static_cast<AstExpr*>(l)).def;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprGlobal* g, DefId incomingDef, bool isCompoundAssignment)
|
DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprGlobal* g, DefId incomingDef, bool isCompoundAssignment)
|
||||||
{
|
{
|
||||||
// We need to keep the previous def around for a compound assignment.
|
// We need to keep the previous def around for a compound assignment.
|
||||||
if (isCompoundAssignment)
|
if (isCompoundAssignment)
|
||||||
@ -874,28 +932,29 @@ void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprGlobal* g, DefId
|
|||||||
if (scope->canUpdateDefinition(g->name))
|
if (scope->canUpdateDefinition(g->name))
|
||||||
{
|
{
|
||||||
DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef));
|
DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef));
|
||||||
graph.astDefs[g] = updated;
|
|
||||||
scope->bindings[g->name] = updated;
|
scope->bindings[g->name] = updated;
|
||||||
|
captures[g->name].allVersions.push_back(updated);
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
visitExpr(scope, static_cast<AstExpr*>(g));
|
return visitExpr(scope, static_cast<AstExpr*>(g)).def;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexName* i, DefId incomingDef)
|
DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexName* i, DefId incomingDef)
|
||||||
{
|
{
|
||||||
DefId parentDef = visitExpr(scope, i->expr).def;
|
DefId parentDef = visitExpr(scope, i->expr).def;
|
||||||
|
|
||||||
if (scope->canUpdateDefinition(parentDef, i->index.value))
|
if (scope->canUpdateDefinition(parentDef, i->index.value))
|
||||||
{
|
{
|
||||||
DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef));
|
DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef));
|
||||||
graph.astDefs[i] = updated;
|
|
||||||
scope->props[parentDef][i->index.value] = updated;
|
scope->props[parentDef][i->index.value] = updated;
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
visitExpr(scope, static_cast<AstExpr*>(i));
|
return visitExpr(scope, static_cast<AstExpr*>(i)).def;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexExpr* i, DefId incomingDef)
|
DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexExpr* i, DefId incomingDef)
|
||||||
{
|
{
|
||||||
DefId parentDef = visitExpr(scope, i->expr).def;
|
DefId parentDef = visitExpr(scope, i->expr).def;
|
||||||
visitExpr(scope, i->index);
|
visitExpr(scope, i->index);
|
||||||
@ -905,20 +964,19 @@ void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprIndexExpr* i, Def
|
|||||||
if (scope->canUpdateDefinition(parentDef, string->value.data))
|
if (scope->canUpdateDefinition(parentDef, string->value.data))
|
||||||
{
|
{
|
||||||
DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef));
|
DefId updated = defArena->freshCell(containsSubscriptedDefinition(incomingDef));
|
||||||
graph.astDefs[i] = updated;
|
|
||||||
scope->props[parentDef][string->value.data] = updated;
|
scope->props[parentDef][string->value.data] = updated;
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
visitExpr(scope, static_cast<AstExpr*>(i));
|
return visitExpr(scope, static_cast<AstExpr*>(i)).def;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
graph.astDefs[i] = defArena->freshCell();
|
return defArena->freshCell(/*subscripted=*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprError* error, DefId incomingDef)
|
DefId DataFlowGraphBuilder::visitLValue(DfgScope* scope, AstExprError* error, DefId incomingDef)
|
||||||
{
|
{
|
||||||
DefId def = visitExpr(scope, error).def;
|
return visitExpr(scope, error).def;
|
||||||
graph.astDefs[error] = def;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataFlowGraphBuilder::visitType(DfgScope* scope, AstType* t)
|
void DataFlowGraphBuilder::visitType(DfgScope* scope, AstType* t)
|
||||||
|
@ -19,17 +19,13 @@ bool containsSubscriptedDefinition(DefId def)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DefId DefArena::freshCell(bool subscripted)
|
void collectOperands(DefId def, std::vector<DefId>* operands)
|
||||||
{
|
{
|
||||||
return NotNull{allocator.allocate(Def{Cell{subscripted}})};
|
LUAU_ASSERT(operands);
|
||||||
}
|
if (std::find(operands->begin(), operands->end(), def) != operands->end())
|
||||||
|
|
||||||
static void collectOperands(DefId def, std::vector<DefId>& operands)
|
|
||||||
{
|
|
||||||
if (std::find(operands.begin(), operands.end(), def) != operands.end())
|
|
||||||
return;
|
return;
|
||||||
else if (get<Cell>(def))
|
else if (get<Cell>(def))
|
||||||
operands.push_back(def);
|
operands->push_back(def);
|
||||||
else if (auto phi = get<Phi>(def))
|
else if (auto phi = get<Phi>(def))
|
||||||
{
|
{
|
||||||
for (const Def* operand : phi->operands)
|
for (const Def* operand : phi->operands)
|
||||||
@ -37,6 +33,11 @@ static void collectOperands(DefId def, std::vector<DefId>& operands)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DefId DefArena::freshCell(bool subscripted)
|
||||||
|
{
|
||||||
|
return NotNull{allocator.allocate(Def{Cell{subscripted}})};
|
||||||
|
}
|
||||||
|
|
||||||
DefId DefArena::phi(DefId a, DefId b)
|
DefId DefArena::phi(DefId a, DefId b)
|
||||||
{
|
{
|
||||||
return phi({a, b});
|
return phi({a, b});
|
||||||
@ -46,7 +47,7 @@ DefId DefArena::phi(const std::vector<DefId>& defs)
|
|||||||
{
|
{
|
||||||
std::vector<DefId> operands;
|
std::vector<DefId> operands;
|
||||||
for (DefId operand : defs)
|
for (DefId operand : defs)
|
||||||
collectOperands(operand, operands);
|
collectOperands(operand, &operands);
|
||||||
|
|
||||||
// There's no need to allocate a Phi node for a singleton set.
|
// There's no need to allocate a Phi node for a singleton set.
|
||||||
if (operands.size() == 1)
|
if (operands.size() == 1)
|
||||||
|
@ -32,11 +32,9 @@ LUAU_FASTINT(LuauTypeInferRecursionLimit)
|
|||||||
LUAU_FASTINT(LuauTarjanChildLimit)
|
LUAU_FASTINT(LuauTarjanChildLimit)
|
||||||
LUAU_FASTFLAG(LuauInferInNoCheckMode)
|
LUAU_FASTFLAG(LuauInferInNoCheckMode)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauKnowsTheDataModel3, false)
|
LUAU_FASTFLAGVARIABLE(LuauKnowsTheDataModel3, false)
|
||||||
LUAU_FASTINTVARIABLE(LuauAutocompleteCheckTimeoutMs, 100) // TODO: Remove with FFlagLuauTypecheckLimitControls
|
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauDeferredConstraintResolution, false)
|
LUAU_FASTFLAGVARIABLE(DebugLuauDeferredConstraintResolution, false)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJson, false)
|
LUAU_FASTFLAGVARIABLE(DebugLuauLogSolverToJson, false)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugLuauReadWriteProperties, false)
|
LUAU_FASTFLAGVARIABLE(DebugLuauReadWriteProperties, false)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauTypecheckLimitControls, false)
|
|
||||||
LUAU_FASTFLAGVARIABLE(CorrectEarlyReturnInMarkDirty, false)
|
LUAU_FASTFLAGVARIABLE(CorrectEarlyReturnInMarkDirty, false)
|
||||||
LUAU_FASTFLAGVARIABLE(LuauDefinitionFileSetModuleName, false)
|
LUAU_FASTFLAGVARIABLE(LuauDefinitionFileSetModuleName, false)
|
||||||
|
|
||||||
@ -902,82 +900,41 @@ void Frontend::checkBuildQueueItem(BuildQueueItem& item)
|
|||||||
|
|
||||||
TypeCheckLimits typeCheckLimits;
|
TypeCheckLimits typeCheckLimits;
|
||||||
|
|
||||||
if (FFlag::LuauTypecheckLimitControls)
|
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 (item.options.applyInternalLimitScaling)
|
||||||
{
|
{
|
||||||
if (item.options.moduleTimeLimitSec)
|
if (FInt::LuauTarjanChildLimit > 0)
|
||||||
typeCheckLimits.finishTime = TimeTrace::getClock() + *item.options.moduleTimeLimitSec;
|
typeCheckLimits.instantiationChildLimit = std::max(1, int(FInt::LuauTarjanChildLimit * sourceNode.autocompleteLimitsMult));
|
||||||
else
|
else
|
||||||
typeCheckLimits.finishTime = std::nullopt;
|
typeCheckLimits.instantiationChildLimit = std::nullopt;
|
||||||
|
|
||||||
// TODO: This is a dirty ad hoc solution for autocomplete timeouts
|
if (FInt::LuauTypeInferIterationLimit > 0)
|
||||||
// We are trying to dynamically adjust our existing limits to lower total typechecking time under the limit
|
typeCheckLimits.unifierIterationLimit = std::max(1, int(FInt::LuauTypeInferIterationLimit * sourceNode.autocompleteLimitsMult));
|
||||||
// so that we'll have type information for the whole file at lower quality instead of a full abort in the middle
|
else
|
||||||
if (item.options.applyInternalLimitScaling)
|
typeCheckLimits.unifierIterationLimit = std::nullopt;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typeCheckLimits.cancellationToken = item.options.cancellationToken;
|
||||||
|
|
||||||
if (item.options.forAutocomplete)
|
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
|
|
||||||
|
|
||||||
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
|
// 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,
|
ModulePtr moduleForAutocomplete = check(sourceModule, Mode::Strict, requireCycles, environmentScope, /*forAutocomplete*/ true,
|
||||||
/*recordJsonLog*/ false, typeCheckLimits);
|
/*recordJsonLog*/ false, typeCheckLimits);
|
||||||
|
|
||||||
double duration = getTimestamp() - timestamp;
|
double duration = getTimestamp() - timestamp;
|
||||||
|
|
||||||
if (FFlag::LuauTypecheckLimitControls)
|
moduleForAutocomplete->checkDurationSec = duration;
|
||||||
{
|
|
||||||
moduleForAutocomplete->checkDurationSec = duration;
|
|
||||||
|
|
||||||
if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling)
|
if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling)
|
||||||
applyInternalLimitScaling(sourceNode, moduleForAutocomplete, *item.options.moduleTimeLimitSec);
|
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.timeCheck += duration;
|
||||||
item.stats.filesStrict += 1;
|
item.stats.filesStrict += 1;
|
||||||
@ -986,29 +943,16 @@ void Frontend::checkBuildQueueItem(BuildQueueItem& item)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FFlag::LuauTypecheckLimitControls)
|
|
||||||
{
|
|
||||||
typeCheckLimits.cancellationToken = item.options.cancellationToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModulePtr module = check(sourceModule, mode, requireCycles, environmentScope, /*forAutocomplete*/ false, item.recordJsonLog, typeCheckLimits);
|
ModulePtr module = check(sourceModule, mode, requireCycles, environmentScope, /*forAutocomplete*/ false, item.recordJsonLog, typeCheckLimits);
|
||||||
|
|
||||||
if (FFlag::LuauTypecheckLimitControls)
|
double duration = getTimestamp() - timestamp;
|
||||||
{
|
|
||||||
double duration = getTimestamp() - timestamp;
|
|
||||||
|
|
||||||
module->checkDurationSec = duration;
|
module->checkDurationSec = duration;
|
||||||
|
|
||||||
if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling)
|
if (item.options.moduleTimeLimitSec && item.options.applyInternalLimitScaling)
|
||||||
applyInternalLimitScaling(sourceNode, module, *item.options.moduleTimeLimitSec);
|
applyInternalLimitScaling(sourceNode, module, *item.options.moduleTimeLimitSec);
|
||||||
|
|
||||||
item.stats.timeCheck += duration;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item.stats.timeCheck += getTimestamp() - timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
item.stats.timeCheck += duration;
|
||||||
item.stats.filesStrict += mode == Mode::Strict;
|
item.stats.filesStrict += mode == Mode::Strict;
|
||||||
item.stats.filesNonstrict += mode == Mode::Nonstrict;
|
item.stats.filesNonstrict += mode == Mode::Nonstrict;
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ static bool analyzeFile(const char* name, const unsigned nestingLimit, std::vect
|
|||||||
{
|
{
|
||||||
Luau::BytecodeBuilder bcb;
|
Luau::BytecodeBuilder bcb;
|
||||||
|
|
||||||
compileOrThrow(bcb, source.value(), copts());
|
compileOrThrow(bcb, *source, copts());
|
||||||
|
|
||||||
const std::string& bytecode = bcb.getBytecode();
|
const std::string& bytecode = bcb.getBytecode();
|
||||||
|
|
||||||
|
@ -42,8 +42,18 @@
|
|||||||
LUAU_FASTFLAGVARIABLE(DebugCodegenNoOpt, false)
|
LUAU_FASTFLAGVARIABLE(DebugCodegenNoOpt, false)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugCodegenOptSize, false)
|
LUAU_FASTFLAGVARIABLE(DebugCodegenOptSize, false)
|
||||||
LUAU_FASTFLAGVARIABLE(DebugCodegenSkipNumbering, false)
|
LUAU_FASTFLAGVARIABLE(DebugCodegenSkipNumbering, false)
|
||||||
|
|
||||||
|
// Per-module IR instruction count limit
|
||||||
LUAU_FASTINTVARIABLE(CodegenHeuristicsInstructionLimit, 1'048'576) // 1 M
|
LUAU_FASTINTVARIABLE(CodegenHeuristicsInstructionLimit, 1'048'576) // 1 M
|
||||||
LUAU_FASTINTVARIABLE(CodegenHeuristicsBlockLimit, 65'536) // 64 K
|
|
||||||
|
// Per-function IR block limit
|
||||||
|
// Current value is based on some member variables being limited to 16 bits
|
||||||
|
// Because block check is made before optimization passes and optimization can generate new blocks, limit is lowered 2x
|
||||||
|
// The limit will probably be adjusted in the future to avoid performance issues with analysis that's more complex than O(n)
|
||||||
|
LUAU_FASTINTVARIABLE(CodegenHeuristicsBlockLimit, 32'768) // 32 K
|
||||||
|
|
||||||
|
// Per-function IR instruction limit
|
||||||
|
// Current value is based on some member variables being limited to 16 bits
|
||||||
LUAU_FASTINTVARIABLE(CodegenHeuristicsBlockInstructionLimit, 65'536) // 64 K
|
LUAU_FASTINTVARIABLE(CodegenHeuristicsBlockInstructionLimit, 65'536) // 64 K
|
||||||
|
|
||||||
namespace Luau
|
namespace Luau
|
||||||
@ -104,11 +114,18 @@ static void logPerfFunction(Proto* p, uintptr_t addr, unsigned size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename AssemblyBuilder>
|
template<typename AssemblyBuilder>
|
||||||
static std::optional<NativeProto> createNativeFunction(AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto)
|
static std::optional<NativeProto> createNativeFunction(AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto, uint32_t& totalIrInstCount)
|
||||||
{
|
{
|
||||||
IrBuilder ir;
|
IrBuilder ir;
|
||||||
ir.buildFunctionIr(proto);
|
ir.buildFunctionIr(proto);
|
||||||
|
|
||||||
|
unsigned instCount = unsigned(ir.function.instructions.size());
|
||||||
|
|
||||||
|
if (totalIrInstCount + instCount >= unsigned(FInt::CodegenHeuristicsInstructionLimit.value))
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
totalIrInstCount += instCount;
|
||||||
|
|
||||||
if (!lowerFunction(ir, build, helpers, proto, {}, /* stats */ nullptr))
|
if (!lowerFunction(ir, build, helpers, proto, {}, /* stats */ nullptr))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
@ -291,9 +308,13 @@ CodeGenCompilationResult compile(lua_State* L, int idx, unsigned int flags, Comp
|
|||||||
std::vector<NativeProto> results;
|
std::vector<NativeProto> results;
|
||||||
results.reserve(protos.size());
|
results.reserve(protos.size());
|
||||||
|
|
||||||
|
uint32_t totalIrInstCount = 0;
|
||||||
|
|
||||||
for (Proto* p : protos)
|
for (Proto* p : protos)
|
||||||
if (std::optional<NativeProto> np = createNativeFunction(build, helpers, p))
|
{
|
||||||
|
if (std::optional<NativeProto> np = createNativeFunction(build, helpers, p, totalIrInstCount))
|
||||||
results.push_back(*np);
|
results.push_back(*np);
|
||||||
|
}
|
||||||
|
|
||||||
// Very large modules might result in overflowing a jump offset; in this case we currently abandon the entire module
|
// Very large modules might result in overflowing a jump offset; in this case we currently abandon the entire module
|
||||||
if (!build.finalize())
|
if (!build.finalize())
|
||||||
|
@ -253,11 +253,6 @@ inline bool lowerIr(A64::AssemblyBuilderA64& build, IrBuilder& ir, const std::ve
|
|||||||
template<typename AssemblyBuilder>
|
template<typename AssemblyBuilder>
|
||||||
inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto, AssemblyOptions options, LoweringStats* stats)
|
inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers& helpers, Proto* proto, AssemblyOptions options, LoweringStats* stats)
|
||||||
{
|
{
|
||||||
helpers.bytecodeInstructionCount += unsigned(ir.function.instructions.size());
|
|
||||||
|
|
||||||
if (helpers.bytecodeInstructionCount >= unsigned(FInt::CodegenHeuristicsInstructionLimit.value))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
killUnusedBlocks(ir.function);
|
killUnusedBlocks(ir.function);
|
||||||
|
|
||||||
unsigned preOptBlockCount = 0;
|
unsigned preOptBlockCount = 0;
|
||||||
@ -268,9 +263,7 @@ inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers&
|
|||||||
preOptBlockCount += (block.kind != IrBlockKind::Dead);
|
preOptBlockCount += (block.kind != IrBlockKind::Dead);
|
||||||
unsigned blockInstructions = block.finish - block.start;
|
unsigned blockInstructions = block.finish - block.start;
|
||||||
maxBlockInstructions = std::max(maxBlockInstructions, blockInstructions);
|
maxBlockInstructions = std::max(maxBlockInstructions, blockInstructions);
|
||||||
};
|
}
|
||||||
|
|
||||||
helpers.preOptBlockCount += preOptBlockCount;
|
|
||||||
|
|
||||||
// we update stats before checking the heuristic so that even if we bail out
|
// we update stats before checking the heuristic so that even if we bail out
|
||||||
// our stats include information about the limit that was exceeded.
|
// our stats include information about the limit that was exceeded.
|
||||||
@ -280,9 +273,7 @@ inline bool lowerFunction(IrBuilder& ir, AssemblyBuilder& build, ModuleHelpers&
|
|||||||
stats->maxBlockInstructions = maxBlockInstructions;
|
stats->maxBlockInstructions = maxBlockInstructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we use helpers.blocksPreOpt instead of stats.blocksPreOpt since
|
if (preOptBlockCount >= unsigned(FInt::CodegenHeuristicsBlockLimit.value))
|
||||||
// stats can be null across some code paths.
|
|
||||||
if (helpers.preOptBlockCount >= unsigned(FInt::CodegenHeuristicsBlockLimit.value))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (maxBlockInstructions >= unsigned(FInt::CodegenHeuristicsBlockInstructionLimit.value))
|
if (maxBlockInstructions >= unsigned(FInt::CodegenHeuristicsBlockInstructionLimit.value))
|
||||||
|
@ -31,9 +31,6 @@ struct ModuleHelpers
|
|||||||
|
|
||||||
// A64
|
// A64
|
||||||
Label continueCall; // x0: closure
|
Label continueCall; // x0: closure
|
||||||
|
|
||||||
unsigned bytecodeInstructionCount = 0;
|
|
||||||
unsigned preOptBlockCount = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CodeGen
|
} // namespace CodeGen
|
||||||
|
@ -66,7 +66,8 @@ end
|
|||||||
-- and 'false' otherwise.
|
-- and 'false' otherwise.
|
||||||
--
|
--
|
||||||
-- Example usage:
|
-- Example usage:
|
||||||
-- local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
-- local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
-- local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
-- function testFunc()
|
-- function testFunc()
|
||||||
-- ...
|
-- ...
|
||||||
-- end
|
-- end
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
--!nonstrict
|
--!nonstrict
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
local stretchTreeDepth = 18 -- about 16Mb
|
local stretchTreeDepth = 18 -- about 16Mb
|
||||||
local longLivedTreeDepth = 16 -- about 4Mb
|
local longLivedTreeDepth = 16 -- about 4Mb
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
local count = 1
|
local count = 1
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
local count = 1
|
local count = 1
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
local count = 1
|
local count = 1
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
local t = {}
|
local t = {}
|
||||||
|
@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
]]
|
]]
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
bench.runCode(function()
|
bench.runCode(function()
|
||||||
for j=1,1e6 do
|
for j=1,1e6 do
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
local t = table.create(250001, 0)
|
local t = table.create(250001, 0)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
local t = table.create(5000001, 0)
|
local t = table.create(5000001, 0)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
local t = table.create(250001, 0)
|
local t = table.create(250001, 0)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
local arr_months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
|
local arr_months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
bench.runCode(function()
|
bench.runCode(function()
|
||||||
for j=1,1e6 do
|
for j=1,1e6 do
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
bench.runCode(function()
|
bench.runCode(function()
|
||||||
local src = string.rep("abcdefghijklmnopqrstuvwxyz", 100)
|
local src = string.rep("abcdefghijklmnopqrstuvwxyz", 100)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
bench.runCode(function()
|
bench.runCode(function()
|
||||||
for outer=1,28,3 do
|
for outer=1,28,3 do
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
local RANKS = "12345678"
|
local RANKS = "12345678"
|
||||||
local FILES = "abcdefgh"
|
local FILES = "abcdefgh"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
local function mmul(matrix1, matrix2)
|
local function mmul(matrix1, matrix2)
|
||||||
local shapeRows = #matrix1
|
local shapeRows = #matrix1
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
--!strict
|
--!strict
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
local samples = 100_000
|
local samples = 100_000
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ SOFTWARE.
|
|||||||
]]
|
]]
|
||||||
-- http://www.bagley.org/~doug/shootout/
|
-- http://www.bagley.org/~doug/shootout/
|
||||||
|
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ SOFTWARE.
|
|||||||
-- http://benchmarksgame.alioth.debian.org/
|
-- http://benchmarksgame.alioth.debian.org/
|
||||||
-- contributed by Mike Pall
|
-- contributed by Mike Pall
|
||||||
|
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ SOFTWARE.
|
|||||||
-- http://benchmarksgame.alioth.debian.org/
|
-- http://benchmarksgame.alioth.debian.org/
|
||||||
-- contributed by Mike Pall
|
-- contributed by Mike Pall
|
||||||
|
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ SOFTWARE.
|
|||||||
]]
|
]]
|
||||||
-- Julia sets via interval cell-mapping (quadtree version)
|
-- Julia sets via interval cell-mapping (quadtree version)
|
||||||
|
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
local bench = script and require(script.Parent.bench_support) or require("bench_support")
|
local function prequire(name) local success, result = pcall(require, name); return if success then result else nil end
|
||||||
|
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support")
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user