Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/tests/CostModel.test.cpp
2723 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#include "Luau/Parser.h"
3
4
#include "ScopedFlags.h"
5
6
#include "doctest.h"
7
8
using namespace Luau;
9
10
namespace Luau
11
{
12
namespace Compile
13
{
14
15
uint64_t modelCost(AstNode* root, AstLocal* const* vars, size_t varCount);
16
int computeCost(uint64_t model, const bool* varsConst, size_t varCount);
17
18
} // namespace Compile
19
} // namespace Luau
20
21
TEST_SUITE_BEGIN("CostModel");
22
23
static uint64_t modelFunction(const char* source)
24
{
25
Allocator allocator;
26
AstNameTable names(allocator);
27
28
ParseResult result = Parser::parse(source, strlen(source), names, allocator);
29
REQUIRE(result.root != nullptr);
30
31
AstStatFunction* func = result.root->body.data[0]->as<AstStatFunction>();
32
REQUIRE(func);
33
34
return Luau::Compile::modelCost(func->func->body, func->func->args.data, func->func->args.size);
35
}
36
37
TEST_CASE("Expression")
38
{
39
uint64_t model = modelFunction(R"(
40
function test(a, b, c)
41
return a + (b + 1) * (b + 1) - c
42
end
43
)");
44
45
const bool args1[] = {false, false, false};
46
const bool args2[] = {false, true, false};
47
48
CHECK_EQ(5, Luau::Compile::computeCost(model, args1, 3));
49
CHECK_EQ(2, Luau::Compile::computeCost(model, args2, 3));
50
}
51
52
TEST_CASE("PropagateVariable")
53
{
54
uint64_t model = modelFunction(R"(
55
function test(a)
56
local b = a * a * a
57
return b * b
58
end
59
)");
60
61
const bool args1[] = {false};
62
const bool args2[] = {true};
63
64
CHECK_EQ(3, Luau::Compile::computeCost(model, args1, 1));
65
CHECK_EQ(0, Luau::Compile::computeCost(model, args2, 1));
66
}
67
68
TEST_CASE("LoopAssign")
69
{
70
uint64_t model = modelFunction(R"(
71
function test(a)
72
for i=1,3 do
73
a[i] = i
74
end
75
end
76
)");
77
78
const bool args1[] = {false};
79
const bool args2[] = {true};
80
81
// loop baseline cost is 5
82
CHECK_EQ(6, Luau::Compile::computeCost(model, args1, 1));
83
CHECK_EQ(6, Luau::Compile::computeCost(model, args2, 1));
84
}
85
86
TEST_CASE("MutableVariable")
87
{
88
uint64_t model = modelFunction(R"(
89
function test(a, b)
90
local x = a * a
91
x += b
92
return x * x
93
end
94
)");
95
96
const bool args1[] = {false};
97
const bool args2[] = {true};
98
99
CHECK_EQ(3, Luau::Compile::computeCost(model, args1, 1));
100
CHECK_EQ(2, Luau::Compile::computeCost(model, args2, 1));
101
}
102
103
TEST_CASE("ImportCall")
104
{
105
uint64_t model = modelFunction(R"(
106
function test(a)
107
return Instance.new(a)
108
end
109
)");
110
111
const bool args1[] = {false};
112
const bool args2[] = {true};
113
114
CHECK_EQ(6, Luau::Compile::computeCost(model, args1, 1));
115
CHECK_EQ(6, Luau::Compile::computeCost(model, args2, 1));
116
}
117
118
TEST_CASE("FastCall")
119
{
120
uint64_t model = modelFunction(R"(
121
function test(a)
122
return math.abs(a + 1)
123
end
124
)");
125
126
const bool args1[] = {false};
127
const bool args2[] = {true};
128
129
// note: we currently don't treat fast calls differently from cost model perspective
130
CHECK_EQ(6, Luau::Compile::computeCost(model, args1, 1));
131
CHECK_EQ(5, Luau::Compile::computeCost(model, args2, 1));
132
}
133
134
TEST_CASE("Conditional")
135
{
136
uint64_t model = modelFunction(R"(
137
function test(a)
138
return if a < 0 then -a else a
139
end
140
)");
141
142
const bool args1[] = {false};
143
const bool args2[] = {true};
144
145
CHECK_EQ(4, Luau::Compile::computeCost(model, args1, 1));
146
CHECK_EQ(2, Luau::Compile::computeCost(model, args2, 1));
147
}
148
149
TEST_CASE("VarArgs")
150
{
151
uint64_t model = modelFunction(R"(
152
function test(...)
153
return select('#', ...) :: number
154
end
155
)");
156
157
CHECK_EQ(8, Luau::Compile::computeCost(model, nullptr, 0));
158
}
159
160
TEST_CASE("TablesFunctions")
161
{
162
uint64_t model = modelFunction(R"(
163
function test()
164
return { 42, op = function() end }
165
end
166
)");
167
168
CHECK_EQ(22, Luau::Compile::computeCost(model, nullptr, 0));
169
}
170
171
TEST_CASE("CostOverflow")
172
{
173
uint64_t model = modelFunction(R"(
174
function test()
175
return {{{{{{{{{{{{{{{}}}}}}}}}}}}}}}
176
end
177
)");
178
179
CHECK_EQ(127, Luau::Compile::computeCost(model, nullptr, 0));
180
}
181
182
TEST_CASE("TableAssign")
183
{
184
uint64_t model = modelFunction(R"(
185
function test(a)
186
for i=1,#a do
187
a[i] = i
188
end
189
end
190
)");
191
192
const bool args1[] = {false};
193
const bool args2[] = {true};
194
195
CHECK_EQ(7, Luau::Compile::computeCost(model, args1, 1));
196
CHECK_EQ(6, Luau::Compile::computeCost(model, args2, 1));
197
}
198
199
TEST_CASE("InterpString")
200
{
201
uint64_t model = modelFunction(R"(
202
function test(a)
203
return `hello, {a}!`
204
end
205
)");
206
207
const bool args1[] = {false};
208
const bool args2[] = {true};
209
210
CHECK_EQ(3, Luau::Compile::computeCost(model, args1, 1));
211
CHECK_EQ(3, Luau::Compile::computeCost(model, args2, 1));
212
}
213
214
TEST_CASE("MultipleAssignments")
215
{
216
uint64_t model = modelFunction(R"(
217
function test(a)
218
local x = 0
219
x = a
220
x = a + 1
221
x, x, x = a
222
x = a, a, a
223
end
224
)");
225
226
const bool args1[] = {false};
227
const bool args2[] = {true};
228
229
CHECK_EQ(8, Luau::Compile::computeCost(model, args1, 1));
230
CHECK_EQ(7, Luau::Compile::computeCost(model, args2, 1));
231
}
232
233
TEST_SUITE_END();
234
235