Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include <utility>
6 :
7 : #include "src/api.h"
8 : #include "src/compilation-info.h"
9 : #include "src/compiler/pipeline.h"
10 : #include "src/debug/debug-interface.h"
11 : #include "src/execution.h"
12 : #include "src/handles.h"
13 : #include "src/interpreter/bytecode-array-builder.h"
14 : #include "src/interpreter/interpreter.h"
15 : #include "src/objects-inl.h"
16 : #include "src/parsing/parse-info.h"
17 : #include "test/cctest/cctest.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 : namespace compiler {
22 :
23 : #define SHARD_TEST_BY_2(x) \
24 : TEST(x##_0) { Test##x(0); } \
25 : TEST(x##_1) { Test##x(1); }
26 : #define SHARD_TEST_BY_4(x) \
27 : TEST(x##_0) { Test##x(0); } \
28 : TEST(x##_1) { Test##x(1); } \
29 : TEST(x##_2) { Test##x(2); } \
30 : TEST(x##_3) { Test##x(3); }
31 :
32 : static const char kFunctionName[] = "f";
33 :
34 : static const Token::Value kCompareOperators[] = {
35 : Token::Value::EQ, Token::Value::NE, Token::Value::EQ_STRICT,
36 : Token::Value::NE_STRICT, Token::Value::LT, Token::Value::LTE,
37 : Token::Value::GT, Token::Value::GTE};
38 :
39 : static const int SMI_MAX = (1 << 30) - 1;
40 : static const int SMI_MIN = -(1 << 30);
41 :
42 : static MaybeHandle<Object> CallFunction(Isolate* isolate,
43 : Handle<JSFunction> function) {
44 : return Execution::Call(isolate, function,
45 1584 : isolate->factory()->undefined_value(), 0, nullptr);
46 : }
47 :
48 : template <class... A>
49 3108 : static MaybeHandle<Object> CallFunction(Isolate* isolate,
50 : Handle<JSFunction> function,
51 : A... args) {
52 3108 : Handle<Object> argv[] = {args...};
53 : return Execution::Call(isolate, function,
54 : isolate->factory()->undefined_value(), sizeof...(args),
55 3108 : argv);
56 : }
57 :
58 : template <class... A>
59 : class BytecodeGraphCallable {
60 : public:
61 : BytecodeGraphCallable(Isolate* isolate, Handle<JSFunction> function)
62 2760 : : isolate_(isolate), function_(function) {}
63 1584 : virtual ~BytecodeGraphCallable() {}
64 :
65 1584 : MaybeHandle<Object> operator()(A... args) {
66 6276 : return CallFunction(isolate_, function_, args...);
67 : }
68 :
69 : private:
70 : Isolate* isolate_;
71 : Handle<JSFunction> function_;
72 : };
73 :
74 : class BytecodeGraphTester {
75 : public:
76 : BytecodeGraphTester(Isolate* isolate, const char* script,
77 : const char* filter = kFunctionName)
78 2760 : : isolate_(isolate), script_(script) {
79 2760 : i::FLAG_always_opt = false;
80 2760 : i::FLAG_allow_natives_syntax = true;
81 : }
82 2760 : virtual ~BytecodeGraphTester() {}
83 :
84 : template <class... A>
85 : BytecodeGraphCallable<A...> GetCallable(
86 : const char* functionName = kFunctionName) {
87 2760 : return BytecodeGraphCallable<A...>(isolate_, GetFunction(functionName));
88 : }
89 :
90 114 : Local<Message> CheckThrowsReturnMessage() {
91 114 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
92 : auto callable = GetCallable<>();
93 114 : MaybeHandle<Object> no_result = callable();
94 114 : CHECK(isolate_->has_pending_exception());
95 114 : CHECK(try_catch.HasCaught());
96 114 : CHECK(no_result.is_null());
97 114 : isolate_->OptionalRescheduleException(true);
98 228 : CHECK(!try_catch.Message().IsEmpty());
99 228 : return try_catch.Message();
100 : }
101 :
102 444 : static Handle<Object> NewObject(const char* script) {
103 444 : return v8::Utils::OpenHandle(*CompileRun(script));
104 : }
105 :
106 : private:
107 : Isolate* isolate_;
108 : const char* script_;
109 :
110 2760 : Handle<JSFunction> GetFunction(const char* functionName) {
111 2760 : CompileRun(script_);
112 : Local<Function> api_function = Local<Function>::Cast(
113 : CcTest::global()
114 8280 : ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(functionName))
115 2760 : .ToLocalChecked());
116 : Handle<JSFunction> function =
117 : Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
118 2760 : CHECK(function->shared()->HasBytecodeArray());
119 :
120 2760 : Zone zone(function->GetIsolate()->allocator(), ZONE_NAME);
121 : Handle<SharedFunctionInfo> shared(function->shared());
122 : CompilationInfo compilation_info(&zone, function->GetIsolate(), shared,
123 5520 : function);
124 :
125 : // Compiler relies on canonicalized handles, let's create
126 : // a canonicalized scope and migrate existing handles there.
127 5520 : CanonicalHandleScope canonical(isolate_);
128 2760 : compilation_info.ReopenHandlesInNewHandleScope();
129 :
130 2760 : Handle<Code> code = Pipeline::GenerateCodeForTesting(&compilation_info);
131 2760 : function->set_code(*code);
132 :
133 5520 : return function;
134 : }
135 :
136 : DISALLOW_COPY_AND_ASSIGN(BytecodeGraphTester);
137 : };
138 :
139 : #define SPACE()
140 :
141 : #define REPEAT_2(SEP, ...) __VA_ARGS__ SEP() __VA_ARGS__
142 : #define REPEAT_4(SEP, ...) \
143 : REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__)
144 : #define REPEAT_8(SEP, ...) \
145 : REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_4(SEP, __VA_ARGS__)
146 : #define REPEAT_16(SEP, ...) \
147 : REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__)
148 : #define REPEAT_32(SEP, ...) \
149 : REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__)
150 : #define REPEAT_64(SEP, ...) \
151 : REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__)
152 : #define REPEAT_128(SEP, ...) \
153 : REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__)
154 : #define REPEAT_256(SEP, ...) \
155 : REPEAT_128(SEP, __VA_ARGS__) SEP() REPEAT_128(SEP, __VA_ARGS__)
156 :
157 : #define REPEAT_127(SEP, ...) \
158 : REPEAT_64(SEP, __VA_ARGS__) \
159 : SEP() \
160 : REPEAT_32(SEP, __VA_ARGS__) \
161 : SEP() \
162 : REPEAT_16(SEP, __VA_ARGS__) \
163 : SEP() \
164 : REPEAT_8(SEP, __VA_ARGS__) \
165 : SEP() \
166 : REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() __VA_ARGS__
167 :
168 : template <int N, typename T = Handle<Object>>
169 : struct ExpectedSnippet {
170 : const char* code_snippet;
171 : T return_value_and_parameters[N + 1];
172 :
173 : inline T return_value() const { return return_value_and_parameters[0]; }
174 :
175 1344 : inline T parameter(int i) const {
176 1344 : CHECK_GE(i, 0);
177 1344 : CHECK_LT(i, N);
178 1344 : return return_value_and_parameters[1 + i];
179 : }
180 : };
181 :
182 23724 : TEST(BytecodeGraphBuilderReturnStatements) {
183 6 : HandleAndZoneScope scope;
184 6 : Isolate* isolate = scope.main_isolate();
185 : Factory* factory = isolate->factory();
186 :
187 : ExpectedSnippet<0> snippets[] = {
188 : {"return;", {factory->undefined_value()}},
189 : {"return null;", {factory->null_value()}},
190 : {"return true;", {factory->true_value()}},
191 : {"return false;", {factory->false_value()}},
192 : {"return 0;", {factory->NewNumberFromInt(0)}},
193 : {"return +1;", {factory->NewNumberFromInt(1)}},
194 : {"return -1;", {factory->NewNumberFromInt(-1)}},
195 : {"return +127;", {factory->NewNumberFromInt(127)}},
196 : {"return -128;", {factory->NewNumberFromInt(-128)}},
197 : {"return 0.001;", {factory->NewNumber(0.001)}},
198 : {"return 3.7e-60;", {factory->NewNumber(3.7e-60)}},
199 : {"return -3.7e60;", {factory->NewNumber(-3.7e60)}},
200 : {"return '';", {factory->NewStringFromStaticChars("")}},
201 : {"return 'catfood';", {factory->NewStringFromStaticChars("catfood")}},
202 42 : {"return NaN;", {factory->nan_value()}}};
203 :
204 96 : for (size_t i = 0; i < arraysize(snippets); i++) {
205 : ScopedVector<char> script(1024);
206 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
207 90 : snippets[i].code_snippet, kFunctionName);
208 :
209 : BytecodeGraphTester tester(isolate, script.start());
210 : auto callable = tester.GetCallable<>();
211 180 : Handle<Object> return_value = callable().ToHandleChecked();
212 180 : CHECK(return_value->SameValue(*snippets[i].return_value()));
213 6 : }
214 6 : }
215 :
216 23724 : TEST(BytecodeGraphBuilderPrimitiveExpressions) {
217 6 : HandleAndZoneScope scope;
218 6 : Isolate* isolate = scope.main_isolate();
219 : Factory* factory = isolate->factory();
220 :
221 : ExpectedSnippet<0> snippets[] = {
222 : {"return 1 + 1;", {factory->NewNumberFromInt(2)}},
223 : {"return 20 - 30;", {factory->NewNumberFromInt(-10)}},
224 : {"return 4 * 100;", {factory->NewNumberFromInt(400)}},
225 : {"return 100 / 5;", {factory->NewNumberFromInt(20)}},
226 : {"return 25 % 7;", {factory->NewNumberFromInt(4)}},
227 6 : };
228 :
229 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
230 : ScopedVector<char> script(1024);
231 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
232 30 : snippets[i].code_snippet, kFunctionName);
233 :
234 : BytecodeGraphTester tester(isolate, script.start());
235 : auto callable = tester.GetCallable<>();
236 60 : Handle<Object> return_value = callable().ToHandleChecked();
237 60 : CHECK(return_value->SameValue(*snippets[i].return_value()));
238 6 : }
239 6 : }
240 :
241 23724 : TEST(BytecodeGraphBuilderTwoParameterTests) {
242 6 : HandleAndZoneScope scope;
243 6 : Isolate* isolate = scope.main_isolate();
244 : Factory* factory = isolate->factory();
245 :
246 : ExpectedSnippet<2> snippets[] = {
247 : // Integers
248 : {"return p1 + p2;",
249 : {factory->NewNumberFromInt(-70), factory->NewNumberFromInt(3),
250 : factory->NewNumberFromInt(-73)}},
251 : {"return p1 + p2 + 3;",
252 : {factory->NewNumberFromInt(1139044), factory->NewNumberFromInt(300),
253 : factory->NewNumberFromInt(1138741)}},
254 : {"return p1 - p2;",
255 : {factory->NewNumberFromInt(1100), factory->NewNumberFromInt(1000),
256 : factory->NewNumberFromInt(-100)}},
257 : {"return p1 * p2;",
258 : {factory->NewNumberFromInt(-100000), factory->NewNumberFromInt(1000),
259 : factory->NewNumberFromInt(-100)}},
260 : {"return p1 / p2;",
261 : {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(1000),
262 : factory->NewNumberFromInt(-100)}},
263 : {"return p1 % p2;",
264 : {factory->NewNumberFromInt(5), factory->NewNumberFromInt(373),
265 : factory->NewNumberFromInt(16)}},
266 : // Doubles
267 : {"return p1 + p2;",
268 : {factory->NewHeapNumber(9.999), factory->NewHeapNumber(3.333),
269 : factory->NewHeapNumber(6.666)}},
270 : {"return p1 - p2;",
271 : {factory->NewHeapNumber(-3.333), factory->NewHeapNumber(3.333),
272 : factory->NewHeapNumber(6.666)}},
273 : {"return p1 * p2;",
274 : {factory->NewHeapNumber(3.333 * 6.666), factory->NewHeapNumber(3.333),
275 : factory->NewHeapNumber(6.666)}},
276 : {"return p1 / p2;",
277 : {factory->NewHeapNumber(2.25), factory->NewHeapNumber(9),
278 : factory->NewHeapNumber(4)}},
279 : // Strings
280 : {"return p1 + p2;",
281 : {factory->NewStringFromStaticChars("abcdef"),
282 : factory->NewStringFromStaticChars("abc"),
283 42 : factory->NewStringFromStaticChars("def")}}};
284 :
285 72 : for (size_t i = 0; i < arraysize(snippets); i++) {
286 : ScopedVector<char> script(1024);
287 : SNPrintF(script, "function %s(p1, p2) { %s }\n%s(0, 0);", kFunctionName,
288 66 : snippets[i].code_snippet, kFunctionName);
289 :
290 : BytecodeGraphTester tester(isolate, script.start());
291 : auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
292 : Handle<Object> return_value =
293 66 : callable(snippets[i].parameter(0), snippets[i].parameter(1))
294 : .ToHandleChecked();
295 66 : CHECK(return_value->SameValue(*snippets[i].return_value()));
296 6 : }
297 6 : }
298 :
299 :
300 23724 : TEST(BytecodeGraphBuilderNamedLoad) {
301 6 : HandleAndZoneScope scope;
302 6 : Isolate* isolate = scope.main_isolate();
303 : Factory* factory = isolate->factory();
304 :
305 : ExpectedSnippet<1> snippets[] = {
306 : {"return p1.val;",
307 : {factory->NewNumberFromInt(10),
308 : BytecodeGraphTester::NewObject("({val : 10})")}},
309 : {"return p1[\"name\"];",
310 : {factory->NewStringFromStaticChars("abc"),
311 : BytecodeGraphTester::NewObject("({name : 'abc'})")}},
312 : {"'use strict'; return p1.val;",
313 : {factory->NewNumberFromInt(10),
314 : BytecodeGraphTester::NewObject("({val : 10 })")}},
315 : {"'use strict'; return p1[\"val\"];",
316 : {factory->NewNumberFromInt(10),
317 : BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
318 : {"var b;\n" REPEAT_127(SPACE, " b = p1.name; ") " return p1.name;\n",
319 : {factory->NewStringFromStaticChars("abc"),
320 : BytecodeGraphTester::NewObject("({name : 'abc'})")}},
321 : {"'use strict'; var b;\n"
322 : REPEAT_127(SPACE, " b = p1.name; ")
323 : "return p1.name;\n",
324 : {factory->NewStringFromStaticChars("abc"),
325 : BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
326 24 : };
327 :
328 42 : for (size_t i = 0; i < arraysize(snippets); i++) {
329 : ScopedVector<char> script(2048);
330 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
331 36 : snippets[i].code_snippet, kFunctionName);
332 :
333 : BytecodeGraphTester tester(isolate, script.start());
334 : auto callable = tester.GetCallable<Handle<Object>>();
335 : Handle<Object> return_value =
336 36 : callable(snippets[i].parameter(0)).ToHandleChecked();
337 36 : CHECK(return_value->SameValue(*snippets[i].return_value()));
338 6 : }
339 6 : }
340 :
341 23724 : TEST(BytecodeGraphBuilderKeyedLoad) {
342 6 : HandleAndZoneScope scope;
343 6 : Isolate* isolate = scope.main_isolate();
344 : Factory* factory = isolate->factory();
345 :
346 : ExpectedSnippet<2> snippets[] = {
347 : {"return p1[p2];",
348 : {factory->NewNumberFromInt(10),
349 : BytecodeGraphTester::NewObject("({val : 10})"),
350 : factory->NewStringFromStaticChars("val")}},
351 : {"return p1[100];",
352 : {factory->NewStringFromStaticChars("abc"),
353 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
354 : factory->NewNumberFromInt(0)}},
355 : {"var b = 100; return p1[b];",
356 : {factory->NewStringFromStaticChars("abc"),
357 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
358 : factory->NewNumberFromInt(0)}},
359 : {"'use strict'; return p1[p2];",
360 : {factory->NewNumberFromInt(10),
361 : BytecodeGraphTester::NewObject("({val : 10 })"),
362 : factory->NewStringFromStaticChars("val")}},
363 : {"'use strict'; return p1[100];",
364 : {factory->NewNumberFromInt(10),
365 : BytecodeGraphTester::NewObject("({100 : 10})"),
366 : factory->NewNumberFromInt(0)}},
367 : {"'use strict'; var b = p2; return p1[b];",
368 : {factory->NewStringFromStaticChars("abc"),
369 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
370 : factory->NewNumberFromInt(100)}},
371 : {"var b;\n" REPEAT_127(SPACE, " b = p1[p2]; ") " return p1[p2];\n",
372 : {factory->NewStringFromStaticChars("abc"),
373 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
374 : factory->NewNumberFromInt(100)}},
375 : {"'use strict'; var b;\n" REPEAT_127(SPACE,
376 : " b = p1[p2]; ") "return p1[p2];\n",
377 : {factory->NewStringFromStaticChars("abc"),
378 : BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
379 : factory->NewNumberFromInt(100)}},
380 48 : };
381 :
382 54 : for (size_t i = 0; i < arraysize(snippets); i++) {
383 : ScopedVector<char> script(2048);
384 : SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0);", kFunctionName,
385 48 : snippets[i].code_snippet, kFunctionName);
386 :
387 : BytecodeGraphTester tester(isolate, script.start());
388 : auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
389 : Handle<Object> return_value =
390 48 : callable(snippets[i].parameter(0), snippets[i].parameter(1))
391 : .ToHandleChecked();
392 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
393 6 : }
394 6 : }
395 :
396 12 : void TestBytecodeGraphBuilderNamedStore(size_t shard) {
397 12 : HandleAndZoneScope scope;
398 12 : Isolate* isolate = scope.main_isolate();
399 : Factory* factory = isolate->factory();
400 :
401 : ExpectedSnippet<1> snippets[] = {
402 : {"return p1.val = 20;",
403 : {factory->NewNumberFromInt(20),
404 : BytecodeGraphTester::NewObject("({val : 10})")}},
405 : {"p1.type = 'int'; return p1.type;",
406 : {factory->NewStringFromStaticChars("int"),
407 : BytecodeGraphTester::NewObject("({val : 10})")}},
408 : {"p1.name = 'def'; return p1[\"name\"];",
409 : {factory->NewStringFromStaticChars("def"),
410 : BytecodeGraphTester::NewObject("({name : 'abc'})")}},
411 : {"'use strict'; p1.val = 20; return p1.val;",
412 : {factory->NewNumberFromInt(20),
413 : BytecodeGraphTester::NewObject("({val : 10 })")}},
414 : {"'use strict'; return p1.type = 'int';",
415 : {factory->NewStringFromStaticChars("int"),
416 : BytecodeGraphTester::NewObject("({val : 10})")}},
417 : {"'use strict'; p1.val = 20; return p1[\"val\"];",
418 : {factory->NewNumberFromInt(20),
419 : BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
420 : {"var b = 'abc';\n" REPEAT_127(
421 : SPACE, " p1.name = b; ") " p1.name = 'def'; return p1.name;\n",
422 : {factory->NewStringFromStaticChars("def"),
423 : BytecodeGraphTester::NewObject("({name : 'abc'})")}},
424 : {"'use strict'; var b = 'def';\n" REPEAT_127(
425 : SPACE, " p1.name = 'abc'; ") "p1.name = b; return p1.name;\n",
426 : {factory->NewStringFromStaticChars("def"),
427 : BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
428 72 : };
429 :
430 108 : for (size_t i = 0; i < arraysize(snippets); i++) {
431 144 : if ((i % 2) != shard) continue;
432 : ScopedVector<char> script(3072);
433 : SNPrintF(script, "function %s(p1) { %s };\n%s({});", kFunctionName,
434 48 : snippets[i].code_snippet, kFunctionName);
435 :
436 : BytecodeGraphTester tester(isolate, script.start());
437 : auto callable = tester.GetCallable<Handle<Object>>();
438 : Handle<Object> return_value =
439 48 : callable(snippets[i].parameter(0)).ToHandleChecked();
440 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
441 12 : }
442 12 : }
443 :
444 23730 : SHARD_TEST_BY_2(BytecodeGraphBuilderNamedStore)
445 :
446 12 : void TestBytecodeGraphBuilderKeyedStore(size_t shard) {
447 12 : HandleAndZoneScope scope;
448 12 : Isolate* isolate = scope.main_isolate();
449 : Factory* factory = isolate->factory();
450 :
451 : ExpectedSnippet<2> snippets[] = {
452 : {"p1[p2] = 20; return p1[p2];",
453 : {factory->NewNumberFromInt(20),
454 : BytecodeGraphTester::NewObject("({val : 10})"),
455 : factory->NewStringFromStaticChars("val")}},
456 : {"return p1[100] = 'def';",
457 : {factory->NewStringFromStaticChars("def"),
458 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
459 : factory->NewNumberFromInt(0)}},
460 : {"var b = 100; p1[b] = 'def'; return p1[b];",
461 : {factory->NewStringFromStaticChars("def"),
462 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
463 : factory->NewNumberFromInt(0)}},
464 : {"'use strict'; p1[p2] = 20; return p1[p2];",
465 : {factory->NewNumberFromInt(20),
466 : BytecodeGraphTester::NewObject("({val : 10 })"),
467 : factory->NewStringFromStaticChars("val")}},
468 : {"'use strict'; return p1[100] = 20;",
469 : {factory->NewNumberFromInt(20),
470 : BytecodeGraphTester::NewObject("({100 : 10})"),
471 : factory->NewNumberFromInt(0)}},
472 : {"'use strict'; var b = p2; p1[b] = 'def'; return p1[b];",
473 : {factory->NewStringFromStaticChars("def"),
474 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
475 : factory->NewNumberFromInt(100)}},
476 : {"var b;\n" REPEAT_127(
477 : SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
478 : {factory->NewStringFromStaticChars("def"),
479 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
480 : factory->NewNumberFromInt(100)}},
481 : {"'use strict'; var b;\n" REPEAT_127(
482 : SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
483 : {factory->NewStringFromStaticChars("def"),
484 : BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
485 : factory->NewNumberFromInt(100)}},
486 96 : };
487 :
488 108 : for (size_t i = 0; i < arraysize(snippets); i++) {
489 144 : if ((i % 2) != shard) continue;
490 : ScopedVector<char> script(2048);
491 : SNPrintF(script, "function %s(p1, p2) { %s };\n%s({});", kFunctionName,
492 48 : snippets[i].code_snippet, kFunctionName);
493 :
494 : BytecodeGraphTester tester(isolate, script.start());
495 : auto callable = tester.GetCallable<Handle<Object>>();
496 : Handle<Object> return_value =
497 48 : callable(snippets[i].parameter(0)).ToHandleChecked();
498 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
499 12 : }
500 12 : }
501 :
502 23730 : SHARD_TEST_BY_2(BytecodeGraphBuilderKeyedStore)
503 :
504 23724 : TEST(BytecodeGraphBuilderPropertyCall) {
505 6 : HandleAndZoneScope scope;
506 6 : Isolate* isolate = scope.main_isolate();
507 : Factory* factory = isolate->factory();
508 :
509 : ExpectedSnippet<1> snippets[] = {
510 : {"return p1.func();",
511 : {factory->NewNumberFromInt(25),
512 : BytecodeGraphTester::NewObject("({func() { return 25; }})")}},
513 : {"return p1.func('abc');",
514 : {factory->NewStringFromStaticChars("abc"),
515 : BytecodeGraphTester::NewObject("({func(a) { return a; }})")}},
516 : {"return p1.func(1, 2, 3, 4, 5, 6, 7, 8);",
517 : {factory->NewNumberFromInt(36),
518 : BytecodeGraphTester::NewObject(
519 : "({func(a, b, c, d, e, f, g, h) {\n"
520 : " return a + b + c + d + e + f + g + h;}})")}},
521 12 : };
522 :
523 24 : for (size_t i = 0; i < arraysize(snippets); i++) {
524 : ScopedVector<char> script(2048);
525 : SNPrintF(script, "function %s(p1) { %s };\n%s({func() {}});", kFunctionName,
526 18 : snippets[i].code_snippet, kFunctionName);
527 :
528 : BytecodeGraphTester tester(isolate, script.start());
529 : auto callable = tester.GetCallable<Handle<Object>>();
530 : Handle<Object> return_value =
531 18 : callable(snippets[i].parameter(0)).ToHandleChecked();
532 18 : CHECK(return_value->SameValue(*snippets[i].return_value()));
533 6 : }
534 6 : }
535 :
536 23724 : TEST(BytecodeGraphBuilderCallNew) {
537 6 : HandleAndZoneScope scope;
538 6 : Isolate* isolate = scope.main_isolate();
539 : Factory* factory = isolate->factory();
540 :
541 : ExpectedSnippet<0> snippets[] = {
542 : {"function counter() { this.count = 20; }\n"
543 : "function f() {\n"
544 : " var c = new counter();\n"
545 : " return c.count;\n"
546 : "}; f()",
547 : {factory->NewNumberFromInt(20)}},
548 : {"function counter(arg0) { this.count = 17; this.x = arg0; }\n"
549 : "function f() {\n"
550 : " var c = new counter(6);\n"
551 : " return c.count + c.x;\n"
552 : "}; f()",
553 : {factory->NewNumberFromInt(23)}},
554 : {"function counter(arg0, arg1) {\n"
555 : " this.count = 17; this.x = arg0; this.y = arg1;\n"
556 : "}\n"
557 : "function f() {\n"
558 : " var c = new counter(3, 5);\n"
559 : " return c.count + c.x + c.y;\n"
560 : "}; f()",
561 : {factory->NewNumberFromInt(25)}},
562 6 : };
563 :
564 24 : for (size_t i = 0; i < arraysize(snippets); i++) {
565 18 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
566 : auto callable = tester.GetCallable<>();
567 36 : Handle<Object> return_value = callable().ToHandleChecked();
568 36 : CHECK(return_value->SameValue(*snippets[i].return_value()));
569 6 : }
570 6 : }
571 :
572 23724 : TEST(BytecodeGraphBuilderCreateClosure) {
573 6 : HandleAndZoneScope scope;
574 6 : Isolate* isolate = scope.main_isolate();
575 : Factory* factory = isolate->factory();
576 :
577 : ExpectedSnippet<0> snippets[] = {
578 : {"function f() {\n"
579 : " function counter() { this.count = 20; }\n"
580 : " var c = new counter();\n"
581 : " return c.count;\n"
582 : "}; f()",
583 : {factory->NewNumberFromInt(20)}},
584 : {"function f() {\n"
585 : " function counter(arg0) { this.count = 17; this.x = arg0; }\n"
586 : " var c = new counter(6);\n"
587 : " return c.count + c.x;\n"
588 : "}; f()",
589 : {factory->NewNumberFromInt(23)}},
590 : {"function f() {\n"
591 : " function counter(arg0, arg1) {\n"
592 : " this.count = 17; this.x = arg0; this.y = arg1;\n"
593 : " }\n"
594 : " var c = new counter(3, 5);\n"
595 : " return c.count + c.x + c.y;\n"
596 : "}; f()",
597 : {factory->NewNumberFromInt(25)}},
598 6 : };
599 :
600 24 : for (size_t i = 0; i < arraysize(snippets); i++) {
601 18 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
602 : auto callable = tester.GetCallable<>();
603 36 : Handle<Object> return_value = callable().ToHandleChecked();
604 36 : CHECK(return_value->SameValue(*snippets[i].return_value()));
605 6 : }
606 6 : }
607 :
608 23724 : TEST(BytecodeGraphBuilderCallRuntime) {
609 6 : HandleAndZoneScope scope;
610 6 : Isolate* isolate = scope.main_isolate();
611 : Factory* factory = isolate->factory();
612 :
613 : ExpectedSnippet<1> snippets[] = {
614 : {"function f(arg0) { return %MaxSmi(); }\nf()",
615 : {factory->NewNumberFromInt(Smi::kMaxValue), factory->undefined_value()}},
616 : {"function f(arg0) { return %IsArray(arg0) }\nf(undefined)",
617 : {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
618 : {"function f(arg0) { return %Add(arg0, 2) }\nf(1)",
619 : {factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}},
620 : {"function f(arg0) { return %spread_arguments(arg0).length }\nf([])",
621 : {factory->NewNumberFromInt(3),
622 : BytecodeGraphTester::NewObject("[1, 2, 3]")}},
623 18 : };
624 :
625 30 : for (size_t i = 0; i < arraysize(snippets); i++) {
626 24 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
627 : auto callable = tester.GetCallable<Handle<Object>>();
628 : Handle<Object> return_value =
629 24 : callable(snippets[i].parameter(0)).ToHandleChecked();
630 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
631 6 : }
632 6 : }
633 :
634 23724 : TEST(BytecodeGraphBuilderInvokeIntrinsic) {
635 6 : HandleAndZoneScope scope;
636 6 : Isolate* isolate = scope.main_isolate();
637 : Factory* factory = isolate->factory();
638 :
639 : ExpectedSnippet<1> snippets[] = {
640 : {"function f(arg0) { return %_IsJSReceiver(arg0); }\nf()",
641 : {factory->false_value(), factory->NewNumberFromInt(1)}},
642 : {"function f(arg0) { return %_IsArray(arg0) }\nf(undefined)",
643 : {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
644 18 : };
645 :
646 18 : for (size_t i = 0; i < arraysize(snippets); i++) {
647 12 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
648 : auto callable = tester.GetCallable<Handle<Object>>();
649 : Handle<Object> return_value =
650 12 : callable(snippets[i].parameter(0)).ToHandleChecked();
651 12 : CHECK(return_value->SameValue(*snippets[i].return_value()));
652 6 : }
653 6 : }
654 :
655 12 : void TestBytecodeGraphBuilderGlobals(size_t shard) {
656 12 : HandleAndZoneScope scope;
657 12 : Isolate* isolate = scope.main_isolate();
658 : Factory* factory = isolate->factory();
659 :
660 : ExpectedSnippet<0> snippets[] = {
661 : {"var global = 321;\n function f() { return global; };\n f();",
662 : {factory->NewNumberFromInt(321)}},
663 : {"var global = 321;\n"
664 : "function f() { global = 123; return global };\n f();",
665 : {factory->NewNumberFromInt(123)}},
666 : {"var global = function() { return 'abc'};\n"
667 : "function f() { return global(); };\n f();",
668 : {factory->NewStringFromStaticChars("abc")}},
669 : {"var global = 456;\n"
670 : "function f() { 'use strict'; return global; };\n f();",
671 : {factory->NewNumberFromInt(456)}},
672 : {"var global = 987;\n"
673 : "function f() { 'use strict'; global = 789; return global };\n f();",
674 : {factory->NewNumberFromInt(789)}},
675 : {"var global = function() { return 'xyz'};\n"
676 : "function f() { 'use strict'; return global(); };\n f();",
677 : {factory->NewStringFromStaticChars("xyz")}},
678 : {"var global = 'abc'; var global_obj = {val:123};\n"
679 : "function f() {\n" REPEAT_127(
680 : SPACE, " var b = global_obj.name;\n") "return global; };\n f();\n",
681 : {factory->NewStringFromStaticChars("abc")}},
682 : {"var global = 'abc'; var global_obj = {val:123};\n"
683 : "function f() { 'use strict';\n" REPEAT_127(
684 : SPACE, " var b = global_obj.name;\n") "global = 'xyz'; return "
685 : "global };\n f();\n",
686 : {factory->NewStringFromStaticChars("xyz")}},
687 : {"function f() { return typeof(undeclared_var); }\n; f();\n",
688 : {factory->NewStringFromStaticChars("undefined")}},
689 : {"var defined_var = 10; function f() { return typeof(defined_var); }\n; "
690 : "f();\n",
691 : {factory->NewStringFromStaticChars("number")}},
692 72 : };
693 :
694 132 : for (size_t i = 0; i < arraysize(snippets); i++) {
695 180 : if ((i % 2) != shard) continue;
696 60 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
697 : auto callable = tester.GetCallable<>();
698 120 : Handle<Object> return_value = callable().ToHandleChecked();
699 120 : CHECK(return_value->SameValue(*snippets[i].return_value()));
700 12 : }
701 12 : }
702 :
703 23730 : SHARD_TEST_BY_2(BytecodeGraphBuilderGlobals)
704 :
705 23724 : TEST(BytecodeGraphBuilderToObject) {
706 : // TODO(mythria): tests for ToObject. Needs ForIn.
707 6 : }
708 :
709 23724 : TEST(BytecodeGraphBuilderToName) {
710 6 : HandleAndZoneScope scope;
711 6 : Isolate* isolate = scope.main_isolate();
712 : Factory* factory = isolate->factory();
713 :
714 : ExpectedSnippet<0> snippets[] = {
715 : {"var a = 'val'; var obj = {[a] : 10}; return obj.val;",
716 : {factory->NewNumberFromInt(10)}},
717 : {"var a = 20; var obj = {[a] : 10}; return obj['20'];",
718 : {factory->NewNumberFromInt(10)}},
719 : {"var a = 20; var obj = {[a] : 10}; return obj[20];",
720 : {factory->NewNumberFromInt(10)}},
721 : {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];",
722 : {factory->NewNumberFromInt(10)}},
723 : {"var a = {val:23}; var obj = {[a] : 10}; return obj['[object Object]'];",
724 : {factory->NewNumberFromInt(10)}},
725 : {"var a = {toString : function() { return 'x'}};\n"
726 : "var obj = {[a] : 10};\n"
727 : "return obj.x;",
728 : {factory->NewNumberFromInt(10)}},
729 : {"var a = {valueOf : function() { return 'x'}};\n"
730 : "var obj = {[a] : 10};\n"
731 : "return obj.x;",
732 : {factory->undefined_value()}},
733 : {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n"
734 : "var obj = {[a] : 10};\n"
735 : "return obj.x;",
736 : {factory->NewNumberFromInt(10)}},
737 12 : };
738 :
739 54 : for (size_t i = 0; i < arraysize(snippets); i++) {
740 : ScopedVector<char> script(1024);
741 : SNPrintF(script, "function %s() { %s }\n%s({});", kFunctionName,
742 48 : snippets[i].code_snippet, kFunctionName);
743 :
744 : BytecodeGraphTester tester(isolate, script.start());
745 : auto callable = tester.GetCallable<>();
746 96 : Handle<Object> return_value = callable().ToHandleChecked();
747 96 : CHECK(return_value->SameValue(*snippets[i].return_value()));
748 6 : }
749 6 : }
750 :
751 23724 : TEST(BytecodeGraphBuilderLogicalNot) {
752 6 : HandleAndZoneScope scope;
753 6 : Isolate* isolate = scope.main_isolate();
754 : Factory* factory = isolate->factory();
755 :
756 : ExpectedSnippet<1> snippets[] = {
757 : {"return !p1;",
758 : {factory->false_value(),
759 : BytecodeGraphTester::NewObject("({val : 10})")}},
760 : {"return !p1;", {factory->true_value(), factory->NewNumberFromInt(0)}},
761 : {"return !p1;", {factory->true_value(), factory->undefined_value()}},
762 : {"return !p1;", {factory->false_value(), factory->NewNumberFromInt(10)}},
763 : {"return !p1;", {factory->false_value(), factory->true_value()}},
764 : {"return !p1;",
765 : {factory->false_value(), factory->NewStringFromStaticChars("abc")}},
766 42 : };
767 :
768 42 : for (size_t i = 0; i < arraysize(snippets); i++) {
769 : ScopedVector<char> script(1024);
770 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
771 36 : snippets[i].code_snippet, kFunctionName);
772 :
773 : BytecodeGraphTester tester(isolate, script.start());
774 : auto callable = tester.GetCallable<Handle<Object>>();
775 : Handle<Object> return_value =
776 36 : callable(snippets[i].parameter(0)).ToHandleChecked();
777 36 : CHECK(return_value->SameValue(*snippets[i].return_value()));
778 6 : }
779 6 : }
780 :
781 23724 : TEST(BytecodeGraphBuilderTypeOf) {
782 6 : HandleAndZoneScope scope;
783 6 : Isolate* isolate = scope.main_isolate();
784 : Factory* factory = isolate->factory();
785 :
786 : ExpectedSnippet<1> snippets[] = {
787 : {"return typeof p1;",
788 : {factory->NewStringFromStaticChars("object"),
789 : BytecodeGraphTester::NewObject("({val : 10})")}},
790 : {"return typeof p1;",
791 : {factory->NewStringFromStaticChars("undefined"),
792 : factory->undefined_value()}},
793 : {"return typeof p1;",
794 : {factory->NewStringFromStaticChars("number"),
795 : factory->NewNumberFromInt(10)}},
796 : {"return typeof p1;",
797 : {factory->NewStringFromStaticChars("boolean"), factory->true_value()}},
798 : {"return typeof p1;",
799 : {factory->NewStringFromStaticChars("string"),
800 : factory->NewStringFromStaticChars("abc")}},
801 36 : };
802 :
803 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
804 : ScopedVector<char> script(1024);
805 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
806 30 : snippets[i].code_snippet, kFunctionName);
807 :
808 : BytecodeGraphTester tester(isolate, script.start());
809 : auto callable = tester.GetCallable<Handle<Object>>();
810 : Handle<Object> return_value =
811 30 : callable(snippets[i].parameter(0)).ToHandleChecked();
812 30 : CHECK(return_value->SameValue(*snippets[i].return_value()));
813 6 : }
814 6 : }
815 :
816 23724 : TEST(BytecodeGraphBuilderCompareTypeOf) {
817 6 : HandleAndZoneScope scope;
818 6 : Isolate* isolate = scope.main_isolate();
819 : Factory* factory = isolate->factory();
820 :
821 : ExpectedSnippet<1> snippets[] = {
822 : {"return typeof p1 === 'number';",
823 : {factory->true_value(), factory->NewNumber(1.1)}},
824 : {"return typeof p1 === 'string';",
825 : {factory->false_value(), factory->NewNumber(1.1)}},
826 : {"return typeof p1 === 'string';",
827 : {factory->true_value(), factory->NewStringFromStaticChars("string")}},
828 : {"return typeof p1 === 'string';",
829 : {factory->false_value(), factory->undefined_value()}},
830 : {"return typeof p1 === 'undefined';",
831 : {factory->true_value(), factory->undefined_value()}},
832 : {"return typeof p1 === 'object';",
833 : {factory->true_value(), factory->null_value()}},
834 : {"return typeof p1 === 'object';",
835 : {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
836 : {"return typeof p1 === 'function';",
837 : {factory->false_value(),
838 : BytecodeGraphTester::NewObject("({val : 10})")}},
839 : {"return typeof p1 === 'symbol';",
840 : {factory->true_value(), factory->NewSymbol()}},
841 : {"return typeof p1 === 'symbol';",
842 : {factory->false_value(), factory->NewStringFromStaticChars("string")}},
843 : {"return typeof p1 === 'other';",
844 : {factory->false_value(), factory->NewNumber(1.1)}},
845 90 : };
846 :
847 72 : for (size_t i = 0; i < arraysize(snippets); i++) {
848 : ScopedVector<char> script(1024);
849 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
850 66 : snippets[i].code_snippet, kFunctionName);
851 :
852 : BytecodeGraphTester tester(isolate, script.start());
853 : auto callable = tester.GetCallable<Handle<Object>>();
854 : Handle<Object> return_value =
855 66 : callable(snippets[i].parameter(0)).ToHandleChecked();
856 66 : CHECK(return_value->SameValue(*snippets[i].return_value()));
857 6 : }
858 6 : }
859 :
860 23724 : TEST(BytecodeGraphBuilderCountOperation) {
861 6 : HandleAndZoneScope scope;
862 6 : Isolate* isolate = scope.main_isolate();
863 : Factory* factory = isolate->factory();
864 :
865 : ExpectedSnippet<1> snippets[] = {
866 : {"return ++p1;",
867 : {factory->NewNumberFromInt(11), factory->NewNumberFromInt(10)}},
868 : {"return p1++;",
869 : {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
870 : {"return p1++ + 10;",
871 : {factory->NewHeapNumber(15.23), factory->NewHeapNumber(5.23)}},
872 : {"return 20 + ++p1;",
873 : {factory->NewHeapNumber(27.23), factory->NewHeapNumber(6.23)}},
874 : {"return --p1;",
875 : {factory->NewHeapNumber(9.8), factory->NewHeapNumber(10.8)}},
876 : {"return p1--;",
877 : {factory->NewHeapNumber(10.8), factory->NewHeapNumber(10.8)}},
878 : {"return p1-- + 10;",
879 : {factory->NewNumberFromInt(20), factory->NewNumberFromInt(10)}},
880 : {"return 20 + --p1;",
881 : {factory->NewNumberFromInt(29), factory->NewNumberFromInt(10)}},
882 : {"return p1.val--;",
883 : {factory->NewNumberFromInt(10),
884 : BytecodeGraphTester::NewObject("({val : 10})")}},
885 : {"return ++p1['val'];",
886 : {factory->NewNumberFromInt(11),
887 : BytecodeGraphTester::NewObject("({val : 10})")}},
888 : {"return ++p1[1];",
889 : {factory->NewNumberFromInt(11),
890 : BytecodeGraphTester::NewObject("({1 : 10})")}},
891 : {" function inner() { return p1 } return --p1;",
892 : {factory->NewNumberFromInt(9), factory->NewNumberFromInt(10)}},
893 : {" function inner() { return p1 } return p1--;",
894 : {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
895 : {"return ++p1;",
896 : {factory->nan_value(), factory->NewStringFromStaticChars("String")}},
897 36 : };
898 :
899 90 : for (size_t i = 0; i < arraysize(snippets); i++) {
900 : ScopedVector<char> script(1024);
901 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
902 84 : snippets[i].code_snippet, kFunctionName);
903 :
904 : BytecodeGraphTester tester(isolate, script.start());
905 : auto callable = tester.GetCallable<Handle<Object>>();
906 : Handle<Object> return_value =
907 84 : callable(snippets[i].parameter(0)).ToHandleChecked();
908 84 : CHECK(return_value->SameValue(*snippets[i].return_value()));
909 6 : }
910 6 : }
911 :
912 23724 : TEST(BytecodeGraphBuilderDelete) {
913 6 : HandleAndZoneScope scope;
914 6 : Isolate* isolate = scope.main_isolate();
915 : Factory* factory = isolate->factory();
916 :
917 : ExpectedSnippet<1> snippets[] = {
918 : {"return delete p1.val;",
919 : {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
920 : {"delete p1.val; return p1.val;",
921 : {factory->undefined_value(),
922 : BytecodeGraphTester::NewObject("({val : 10})")}},
923 : {"delete p1.name; return p1.val;",
924 : {factory->NewNumberFromInt(10),
925 : BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
926 : {"'use strict'; return delete p1.val;",
927 : {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
928 : {"'use strict'; delete p1.val; return p1.val;",
929 : {factory->undefined_value(),
930 : BytecodeGraphTester::NewObject("({val : 10})")}},
931 : {"'use strict'; delete p1.name; return p1.val;",
932 : {factory->NewNumberFromInt(10),
933 : BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
934 30 : };
935 :
936 42 : for (size_t i = 0; i < arraysize(snippets); i++) {
937 : ScopedVector<char> script(1024);
938 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
939 36 : snippets[i].code_snippet, kFunctionName);
940 :
941 : BytecodeGraphTester tester(isolate, script.start());
942 : auto callable = tester.GetCallable<Handle<Object>>();
943 : Handle<Object> return_value =
944 36 : callable(snippets[i].parameter(0)).ToHandleChecked();
945 36 : CHECK(return_value->SameValue(*snippets[i].return_value()));
946 6 : }
947 6 : }
948 :
949 23724 : TEST(BytecodeGraphBuilderDeleteGlobal) {
950 6 : HandleAndZoneScope scope;
951 6 : Isolate* isolate = scope.main_isolate();
952 : Factory* factory = isolate->factory();
953 :
954 : ExpectedSnippet<0> snippets[] = {
955 : {"var obj = {val : 10, type : 'int'};"
956 : "function f() {return delete obj;};",
957 : {factory->false_value()}},
958 : {"function f() {return delete this;};", {factory->true_value()}},
959 : {"var obj = {val : 10, type : 'int'};"
960 : "function f() {return delete obj.val;};",
961 : {factory->true_value()}},
962 : {"var obj = {val : 10, type : 'int'};"
963 : "function f() {'use strict'; return delete obj.val;};",
964 : {factory->true_value()}},
965 : {"var obj = {val : 10, type : 'int'};"
966 : "function f() {delete obj.val; return obj.val;};",
967 : {factory->undefined_value()}},
968 : {"var obj = {val : 10, type : 'int'};"
969 : "function f() {'use strict'; delete obj.val; return obj.val;};",
970 : {factory->undefined_value()}},
971 : {"var obj = {1 : 10, 2 : 20};"
972 : "function f() { return delete obj[1]; };",
973 : {factory->true_value()}},
974 : {"var obj = {1 : 10, 2 : 20};"
975 : "function f() { 'use strict'; return delete obj[1];};",
976 : {factory->true_value()}},
977 : {"obj = {1 : 10, 2 : 20};"
978 : "function f() { delete obj[1]; return obj[2];};",
979 : {factory->NewNumberFromInt(20)}},
980 : {"function f() {"
981 : " var obj = {1 : 10, 2 : 20};"
982 : " function inner() { return obj[1]; };"
983 : " return delete obj[1];"
984 : "}",
985 : {factory->true_value()}},
986 54 : };
987 :
988 66 : for (size_t i = 0; i < arraysize(snippets); i++) {
989 : ScopedVector<char> script(1024);
990 60 : SNPrintF(script, "%s %s({});", snippets[i].code_snippet, kFunctionName);
991 :
992 : BytecodeGraphTester tester(isolate, script.start());
993 : auto callable = tester.GetCallable<>();
994 120 : Handle<Object> return_value = callable().ToHandleChecked();
995 120 : CHECK(return_value->SameValue(*snippets[i].return_value()));
996 6 : }
997 6 : }
998 :
999 23724 : TEST(BytecodeGraphBuilderDeleteLookupSlot) {
1000 6 : HandleAndZoneScope scope;
1001 6 : Isolate* isolate = scope.main_isolate();
1002 : Factory* factory = isolate->factory();
1003 :
1004 : // TODO(mythria): Add more tests when we have support for LdaLookupSlot.
1005 : const char* function_prologue = "var f;"
1006 : "var x = 1;"
1007 : "y = 10;"
1008 : "var obj = {val:10};"
1009 : "var z = 30;"
1010 : "function f1() {"
1011 : " var z = 20;"
1012 : " eval(\"function t() {";
1013 : const char* function_epilogue = " }; f = t; t();\");"
1014 : "}"
1015 : "f1();";
1016 :
1017 : ExpectedSnippet<0> snippets[] = {
1018 : {"return delete y;", {factory->true_value()}},
1019 : {"return delete z;", {factory->false_value()}},
1020 12 : };
1021 :
1022 18 : for (size_t i = 0; i < arraysize(snippets); i++) {
1023 : ScopedVector<char> script(1024);
1024 : SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
1025 12 : function_epilogue);
1026 :
1027 : BytecodeGraphTester tester(isolate, script.start(), "t");
1028 : auto callable = tester.GetCallable<>();
1029 24 : Handle<Object> return_value = callable().ToHandleChecked();
1030 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1031 6 : }
1032 6 : }
1033 :
1034 23724 : TEST(BytecodeGraphBuilderLookupSlot) {
1035 6 : HandleAndZoneScope scope;
1036 6 : Isolate* isolate = scope.main_isolate();
1037 : Factory* factory = isolate->factory();
1038 :
1039 : const char* function_prologue = "var f;"
1040 : "var x = 12;"
1041 : "y = 10;"
1042 : "var obj = {val:3.1414};"
1043 : "var z = 30;"
1044 : "function f1() {"
1045 : " var z = 20;"
1046 : " eval(\"function t() {";
1047 : const char* function_epilogue = " }; f = t; t();\");"
1048 : "}"
1049 : "f1();";
1050 :
1051 : ExpectedSnippet<0> snippets[] = {
1052 : {"return x;", {factory->NewNumber(12)}},
1053 : {"return obj.val;", {factory->NewNumber(3.1414)}},
1054 : {"return typeof x;", {factory->NewStringFromStaticChars("number")}},
1055 : {"return typeof dummy;",
1056 : {factory->NewStringFromStaticChars("undefined")}},
1057 : {"x = 23; return x;", {factory->NewNumber(23)}},
1058 : {"'use strict'; obj.val = 23.456; return obj.val;",
1059 18 : {factory->NewNumber(23.456)}}};
1060 :
1061 42 : for (size_t i = 0; i < arraysize(snippets); i++) {
1062 : ScopedVector<char> script(1024);
1063 : SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
1064 36 : function_epilogue);
1065 :
1066 : BytecodeGraphTester tester(isolate, script.start(), "t");
1067 : auto callable = tester.GetCallable<>();
1068 72 : Handle<Object> return_value = callable().ToHandleChecked();
1069 72 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1070 6 : }
1071 6 : }
1072 :
1073 23724 : TEST(BytecodeGraphBuilderLookupContextSlot) {
1074 6 : HandleAndZoneScope scope;
1075 6 : Isolate* isolate = scope.main_isolate();
1076 : Factory* factory = isolate->factory();
1077 :
1078 : // Testing with eval called in the current context.
1079 : const char* inner_eval_prologue = "var x = 0; function inner() {";
1080 : const char* inner_eval_epilogue = "}; return inner();";
1081 :
1082 : ExpectedSnippet<0> inner_eval_snippets[] = {
1083 : {"eval(''); return x;", {factory->NewNumber(0)}},
1084 : {"eval('var x = 1'); return x;", {factory->NewNumber(1)}},
1085 6 : {"'use strict'; eval('var x = 1'); return x;", {factory->NewNumber(0)}}};
1086 :
1087 24 : for (size_t i = 0; i < arraysize(inner_eval_snippets); i++) {
1088 : ScopedVector<char> script(1024);
1089 : SNPrintF(script, "function %s(p1) { %s %s %s } ; %s() ;", kFunctionName,
1090 : inner_eval_prologue, inner_eval_snippets[i].code_snippet,
1091 18 : inner_eval_epilogue, kFunctionName);
1092 :
1093 : BytecodeGraphTester tester(isolate, script.start());
1094 : auto callable = tester.GetCallable<>();
1095 36 : Handle<Object> return_value = callable().ToHandleChecked();
1096 36 : CHECK(return_value->SameValue(*inner_eval_snippets[i].return_value()));
1097 : }
1098 :
1099 : // Testing with eval called in a parent context.
1100 : const char* outer_eval_prologue = "";
1101 : const char* outer_eval_epilogue =
1102 : "function inner() { return x; }; return inner();";
1103 :
1104 : ExpectedSnippet<0> outer_eval_snippets[] = {
1105 : {"var x = 0; eval('');", {factory->NewNumber(0)}},
1106 : {"var x = 0; eval('var x = 1');", {factory->NewNumber(1)}},
1107 6 : {"'use strict'; var x = 0; eval('var x = 1');", {factory->NewNumber(0)}}};
1108 :
1109 24 : for (size_t i = 0; i < arraysize(outer_eval_snippets); i++) {
1110 : ScopedVector<char> script(1024);
1111 : SNPrintF(script, "function %s() { %s %s %s } ; %s() ;", kFunctionName,
1112 : outer_eval_prologue, outer_eval_snippets[i].code_snippet,
1113 18 : outer_eval_epilogue, kFunctionName);
1114 :
1115 : BytecodeGraphTester tester(isolate, script.start());
1116 : auto callable = tester.GetCallable<>();
1117 36 : Handle<Object> return_value = callable().ToHandleChecked();
1118 36 : CHECK(return_value->SameValue(*outer_eval_snippets[i].return_value()));
1119 6 : }
1120 6 : }
1121 :
1122 23724 : TEST(BytecodeGraphBuilderLookupGlobalSlot) {
1123 6 : HandleAndZoneScope scope;
1124 6 : Isolate* isolate = scope.main_isolate();
1125 : Factory* factory = isolate->factory();
1126 :
1127 : // Testing with eval called in the current context.
1128 : const char* inner_eval_prologue = "x = 0; function inner() {";
1129 : const char* inner_eval_epilogue = "}; return inner();";
1130 :
1131 : ExpectedSnippet<0> inner_eval_snippets[] = {
1132 : {"eval(''); return x;", {factory->NewNumber(0)}},
1133 : {"eval('var x = 1'); return x;", {factory->NewNumber(1)}},
1134 6 : {"'use strict'; eval('var x = 1'); return x;", {factory->NewNumber(0)}}};
1135 :
1136 24 : for (size_t i = 0; i < arraysize(inner_eval_snippets); i++) {
1137 : ScopedVector<char> script(1024);
1138 : SNPrintF(script, "function %s(p1) { %s %s %s } ; %s() ;", kFunctionName,
1139 : inner_eval_prologue, inner_eval_snippets[i].code_snippet,
1140 18 : inner_eval_epilogue, kFunctionName);
1141 :
1142 : BytecodeGraphTester tester(isolate, script.start());
1143 : auto callable = tester.GetCallable<>();
1144 36 : Handle<Object> return_value = callable().ToHandleChecked();
1145 36 : CHECK(return_value->SameValue(*inner_eval_snippets[i].return_value()));
1146 : }
1147 :
1148 : // Testing with eval called in a parent context.
1149 : const char* outer_eval_prologue = "";
1150 : const char* outer_eval_epilogue =
1151 : "function inner() { return x; }; return inner();";
1152 :
1153 : ExpectedSnippet<0> outer_eval_snippets[] = {
1154 : {"x = 0; eval('');", {factory->NewNumber(0)}},
1155 : {"x = 0; eval('var x = 1');", {factory->NewNumber(1)}},
1156 6 : {"'use strict'; x = 0; eval('var x = 1');", {factory->NewNumber(0)}}};
1157 :
1158 24 : for (size_t i = 0; i < arraysize(outer_eval_snippets); i++) {
1159 : ScopedVector<char> script(1024);
1160 : SNPrintF(script, "function %s() { %s %s %s } ; %s() ;", kFunctionName,
1161 : outer_eval_prologue, outer_eval_snippets[i].code_snippet,
1162 18 : outer_eval_epilogue, kFunctionName);
1163 :
1164 : BytecodeGraphTester tester(isolate, script.start());
1165 : auto callable = tester.GetCallable<>();
1166 36 : Handle<Object> return_value = callable().ToHandleChecked();
1167 36 : CHECK(return_value->SameValue(*outer_eval_snippets[i].return_value()));
1168 6 : }
1169 6 : }
1170 :
1171 23724 : TEST(BytecodeGraphBuilderLookupSlotWide) {
1172 6 : HandleAndZoneScope scope;
1173 6 : Isolate* isolate = scope.main_isolate();
1174 : Factory* factory = isolate->factory();
1175 :
1176 : const char* function_prologue =
1177 : "var f;"
1178 : "var x = 12;"
1179 : "y = 10;"
1180 : "var obj = {val:3.1414};"
1181 : "var z = 30;"
1182 : "function f1() {"
1183 : " var z = 20;"
1184 : " eval(\"function t() {";
1185 : const char* function_epilogue =
1186 : " }; f = t; t();\");"
1187 : "}"
1188 : "f1();";
1189 :
1190 : ExpectedSnippet<0> snippets[] = {
1191 : {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x;",
1192 : {factory->NewNumber(12)}},
1193 : {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return typeof x;",
1194 : {factory->NewStringFromStaticChars("number")}},
1195 : {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x = 23;",
1196 : {factory->NewNumber(23)}},
1197 : {"'use strict';" REPEAT_256(SPACE, "y = 2.3;") "return obj.val = 23.456;",
1198 12 : {factory->NewNumber(23.456)}}};
1199 :
1200 30 : for (size_t i = 0; i < arraysize(snippets); i++) {
1201 : ScopedVector<char> script(3072);
1202 : SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
1203 24 : function_epilogue);
1204 :
1205 : BytecodeGraphTester tester(isolate, script.start(), "t");
1206 : auto callable = tester.GetCallable<>();
1207 48 : Handle<Object> return_value = callable().ToHandleChecked();
1208 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1209 6 : }
1210 6 : }
1211 :
1212 23724 : TEST(BytecodeGraphBuilderCallLookupSlot) {
1213 6 : HandleAndZoneScope scope;
1214 6 : Isolate* isolate = scope.main_isolate();
1215 :
1216 : ExpectedSnippet<0> snippets[] = {
1217 : {"g = function(){ return 2 }; eval(''); return g();",
1218 : {handle(Smi::FromInt(2), isolate)}},
1219 : {"g = function(){ return 2 }; eval('g = function() {return 3}');\n"
1220 : "return g();",
1221 : {handle(Smi::FromInt(3), isolate)}},
1222 : {"g = { x: function(){ return this.y }, y: 20 };\n"
1223 : "eval('g = { x: g.x, y: 30 }');\n"
1224 : "return g.x();",
1225 : {handle(Smi::FromInt(30), isolate)}},
1226 18 : };
1227 :
1228 24 : for (size_t i = 0; i < arraysize(snippets); i++) {
1229 : ScopedVector<char> script(1024);
1230 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1231 18 : snippets[i].code_snippet, kFunctionName);
1232 : BytecodeGraphTester tester(isolate, script.start());
1233 : auto callable = tester.GetCallable<>();
1234 36 : Handle<Object> return_value = callable().ToHandleChecked();
1235 36 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1236 6 : }
1237 6 : }
1238 :
1239 23724 : TEST(BytecodeGraphBuilderEval) {
1240 6 : HandleAndZoneScope scope;
1241 6 : Isolate* isolate = scope.main_isolate();
1242 : Factory* factory = isolate->factory();
1243 :
1244 : ExpectedSnippet<0> snippets[] = {
1245 : {"return eval('1;');", {handle(Smi::FromInt(1), isolate)}},
1246 : {"return eval('100 * 20;');", {handle(Smi::FromInt(2000), isolate)}},
1247 : {"var x = 10; return eval('x + 20;');",
1248 : {handle(Smi::FromInt(30), isolate)}},
1249 : {"var x = 10; eval('x = 33;'); return x;",
1250 : {handle(Smi::FromInt(33), isolate)}},
1251 : {"'use strict'; var x = 20; var z = 0;\n"
1252 : "eval('var x = 33; z = x;'); return x + z;",
1253 : {handle(Smi::FromInt(53), isolate)}},
1254 : {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;",
1255 : {handle(Smi::FromInt(86), isolate)}},
1256 : {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x",
1257 : {handle(Smi::FromInt(11), isolate)}},
1258 : {"var x = 10; eval('var x = 20;'); return x;",
1259 : {handle(Smi::FromInt(20), isolate)}},
1260 : {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;",
1261 : {handle(Smi::FromInt(1), isolate)}},
1262 : {"'use strict'; var x = 1; eval('var x = 2;'); return x;",
1263 : {handle(Smi::FromInt(1), isolate)}},
1264 : {"var x = 10; eval('x + 20;'); return typeof x;",
1265 : {factory->NewStringFromStaticChars("number")}},
1266 : {"eval('var y = 10;'); return typeof unallocated;",
1267 : {factory->NewStringFromStaticChars("undefined")}},
1268 : {"'use strict'; eval('var y = 10;'); return typeof unallocated;",
1269 : {factory->NewStringFromStaticChars("undefined")}},
1270 : {"eval('var x = 10;'); return typeof x;",
1271 : {factory->NewStringFromStaticChars("number")}},
1272 : {"var x = {}; eval('var x = 10;'); return typeof x;",
1273 : {factory->NewStringFromStaticChars("number")}},
1274 : {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;",
1275 : {factory->NewStringFromStaticChars("object")}},
1276 96 : };
1277 :
1278 102 : for (size_t i = 0; i < arraysize(snippets); i++) {
1279 : ScopedVector<char> script(1024);
1280 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1281 96 : snippets[i].code_snippet, kFunctionName);
1282 : BytecodeGraphTester tester(isolate, script.start());
1283 : auto callable = tester.GetCallable<>();
1284 192 : Handle<Object> return_value = callable().ToHandleChecked();
1285 192 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1286 6 : }
1287 6 : }
1288 :
1289 23724 : TEST(BytecodeGraphBuilderEvalParams) {
1290 6 : HandleAndZoneScope scope;
1291 6 : Isolate* isolate = scope.main_isolate();
1292 :
1293 : ExpectedSnippet<1> snippets[] = {
1294 : {"var x = 10; return eval('x + p1;');",
1295 : {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
1296 : {"var x = 10; eval('p1 = x;'); return p1;",
1297 : {handle(Smi::FromInt(10), isolate), handle(Smi::FromInt(20), isolate)}},
1298 : {"var a = 10;"
1299 : "function inner() { return eval('a + p1;');}"
1300 : "return inner();",
1301 : {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
1302 18 : };
1303 :
1304 24 : for (size_t i = 0; i < arraysize(snippets); i++) {
1305 : ScopedVector<char> script(1024);
1306 : SNPrintF(script, "function %s(p1) { %s }\n%s(0);", kFunctionName,
1307 18 : snippets[i].code_snippet, kFunctionName);
1308 : BytecodeGraphTester tester(isolate, script.start());
1309 : auto callable = tester.GetCallable<Handle<Object>>();
1310 : Handle<Object> return_value =
1311 18 : callable(snippets[i].parameter(0)).ToHandleChecked();
1312 18 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1313 6 : }
1314 6 : }
1315 :
1316 23724 : TEST(BytecodeGraphBuilderEvalGlobal) {
1317 6 : HandleAndZoneScope scope;
1318 6 : Isolate* isolate = scope.main_isolate();
1319 : Factory* factory = isolate->factory();
1320 :
1321 : ExpectedSnippet<0> snippets[] = {
1322 : {"function add_global() { eval('function f() { z = 33; }; f()'); };"
1323 : "function f() { add_global(); return z; }; f();",
1324 : {handle(Smi::FromInt(33), isolate)}},
1325 : {"function add_global() {\n"
1326 : " eval('\"use strict\"; function f() { y = 33; };"
1327 : " try { f() } catch(e) {}');\n"
1328 : "}\n"
1329 : "function f() { add_global(); return typeof y; } f();",
1330 : {factory->NewStringFromStaticChars("undefined")}},
1331 12 : };
1332 :
1333 18 : for (size_t i = 0; i < arraysize(snippets); i++) {
1334 12 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
1335 : auto callable = tester.GetCallable<>();
1336 24 : Handle<Object> return_value = callable().ToHandleChecked();
1337 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1338 6 : }
1339 6 : }
1340 :
1341 1680 : bool get_compare_result(Token::Value opcode, Handle<Object> lhs_value,
1342 : Handle<Object> rhs_value) {
1343 1680 : switch (opcode) {
1344 : case Token::Value::EQ:
1345 420 : return Object::Equals(lhs_value, rhs_value).FromJust();
1346 : case Token::Value::NE:
1347 420 : return !Object::Equals(lhs_value, rhs_value).FromJust();
1348 : case Token::Value::EQ_STRICT:
1349 210 : return lhs_value->StrictEquals(*rhs_value);
1350 : case Token::Value::NE_STRICT:
1351 210 : return !lhs_value->StrictEquals(*rhs_value);
1352 : case Token::Value::LT:
1353 420 : return Object::LessThan(lhs_value, rhs_value).FromJust();
1354 : case Token::Value::LTE:
1355 420 : return Object::LessThanOrEqual(lhs_value, rhs_value).FromJust();
1356 : case Token::Value::GT:
1357 420 : return Object::GreaterThan(lhs_value, rhs_value).FromJust();
1358 : case Token::Value::GTE:
1359 420 : return Object::GreaterThanOrEqual(lhs_value, rhs_value).FromJust();
1360 : default:
1361 0 : UNREACHABLE();
1362 : }
1363 : }
1364 :
1365 48 : const char* get_code_snippet(Token::Value opcode) {
1366 48 : switch (opcode) {
1367 : case Token::Value::EQ:
1368 : return "return p1 == p2;";
1369 : case Token::Value::NE:
1370 6 : return "return p1 != p2;";
1371 : case Token::Value::EQ_STRICT:
1372 6 : return "return p1 === p2;";
1373 : case Token::Value::NE_STRICT:
1374 6 : return "return p1 !== p2;";
1375 : case Token::Value::LT:
1376 6 : return "return p1 < p2;";
1377 : case Token::Value::LTE:
1378 6 : return "return p1 <= p2;";
1379 : case Token::Value::GT:
1380 6 : return "return p1 > p2;";
1381 : case Token::Value::GTE:
1382 6 : return "return p1 >= p2;";
1383 : default:
1384 0 : UNREACHABLE();
1385 : }
1386 : }
1387 :
1388 23724 : TEST(BytecodeGraphBuilderCompare) {
1389 6 : HandleAndZoneScope scope;
1390 6 : Isolate* isolate = scope.main_isolate();
1391 : Factory* factory = isolate->factory();
1392 : Handle<Object> lhs_values[] = {
1393 : factory->NewNumberFromInt(10), factory->NewHeapNumber(3.45),
1394 : factory->NewStringFromStaticChars("abc"),
1395 18 : factory->NewNumberFromInt(SMI_MAX), factory->NewNumberFromInt(SMI_MIN)};
1396 : Handle<Object> rhs_values[] = {factory->NewNumberFromInt(10),
1397 : factory->NewStringFromStaticChars("10"),
1398 : factory->NewNumberFromInt(20),
1399 : factory->NewStringFromStaticChars("abc"),
1400 : factory->NewHeapNumber(3.45),
1401 : factory->NewNumberFromInt(SMI_MAX),
1402 18 : factory->NewNumberFromInt(SMI_MIN)};
1403 :
1404 54 : for (size_t i = 0; i < arraysize(kCompareOperators); i++) {
1405 : ScopedVector<char> script(1024);
1406 : SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
1407 48 : get_code_snippet(kCompareOperators[i]), kFunctionName);
1408 :
1409 : BytecodeGraphTester tester(isolate, script.start());
1410 : auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
1411 288 : for (size_t j = 0; j < arraysize(lhs_values); j++) {
1412 1680 : for (size_t k = 0; k < arraysize(rhs_values); k++) {
1413 : Handle<Object> return_value =
1414 : callable(lhs_values[j], rhs_values[k]).ToHandleChecked();
1415 : bool result = get_compare_result(kCompareOperators[i], lhs_values[j],
1416 1680 : rhs_values[k]);
1417 3360 : CHECK(return_value->SameValue(*factory->ToBoolean(result)));
1418 : }
1419 : }
1420 6 : }
1421 6 : }
1422 :
1423 23724 : TEST(BytecodeGraphBuilderTestIn) {
1424 6 : HandleAndZoneScope scope;
1425 6 : Isolate* isolate = scope.main_isolate();
1426 : Factory* factory = isolate->factory();
1427 :
1428 : ExpectedSnippet<2> snippets[] = {
1429 : {"return p2 in p1;",
1430 : {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})"),
1431 : factory->NewStringFromStaticChars("val")}},
1432 : {"return p2 in p1;",
1433 : {factory->true_value(), BytecodeGraphTester::NewObject("[]"),
1434 : factory->NewStringFromStaticChars("length")}},
1435 : {"return p2 in p1;",
1436 : {factory->true_value(), BytecodeGraphTester::NewObject("[]"),
1437 : factory->NewStringFromStaticChars("toString")}},
1438 : {"return p2 in p1;",
1439 : {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})"),
1440 : factory->NewStringFromStaticChars("toString")}},
1441 : {"return p2 in p1;",
1442 : {factory->false_value(), BytecodeGraphTester::NewObject("({val : 10})"),
1443 : factory->NewStringFromStaticChars("abc")}},
1444 : {"return p2 in p1;",
1445 : {factory->false_value(), BytecodeGraphTester::NewObject("({val : 10})"),
1446 : factory->NewNumberFromInt(10)}},
1447 : {"return p2 in p1;",
1448 : {factory->true_value(), BytecodeGraphTester::NewObject("({10 : 'val'})"),
1449 : factory->NewNumberFromInt(10)}},
1450 : {"return p2 in p1;",
1451 : {factory->false_value(),
1452 : BytecodeGraphTester::NewObject("({10 : 'val'})"),
1453 : factory->NewNumberFromInt(1)}},
1454 84 : };
1455 :
1456 54 : for (size_t i = 0; i < arraysize(snippets); i++) {
1457 : ScopedVector<char> script(1024);
1458 : SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
1459 48 : snippets[i].code_snippet, kFunctionName);
1460 :
1461 : BytecodeGraphTester tester(isolate, script.start());
1462 : auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
1463 : Handle<Object> return_value =
1464 48 : callable(snippets[i].parameter(0), snippets[i].parameter(1))
1465 : .ToHandleChecked();
1466 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1467 6 : }
1468 6 : }
1469 :
1470 23724 : TEST(BytecodeGraphBuilderTestInstanceOf) {
1471 6 : HandleAndZoneScope scope;
1472 6 : Isolate* isolate = scope.main_isolate();
1473 : Factory* factory = isolate->factory();
1474 :
1475 : ExpectedSnippet<1> snippets[] = {
1476 : {"return p1 instanceof Object;",
1477 : {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
1478 : {"return p1 instanceof String;",
1479 : {factory->false_value(), factory->NewStringFromStaticChars("string")}},
1480 : {"var cons = function() {};"
1481 : "var obj = new cons();"
1482 : "return obj instanceof cons;",
1483 : {factory->true_value(), factory->undefined_value()}},
1484 24 : };
1485 :
1486 24 : for (size_t i = 0; i < arraysize(snippets); i++) {
1487 : ScopedVector<char> script(1024);
1488 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
1489 18 : snippets[i].code_snippet, kFunctionName);
1490 :
1491 : BytecodeGraphTester tester(isolate, script.start());
1492 : auto callable = tester.GetCallable<Handle<Object>>();
1493 : Handle<Object> return_value =
1494 18 : callable(snippets[i].parameter(0)).ToHandleChecked();
1495 18 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1496 6 : }
1497 6 : }
1498 :
1499 23724 : TEST(BytecodeGraphBuilderTryCatch) {
1500 6 : HandleAndZoneScope scope;
1501 6 : Isolate* isolate = scope.main_isolate();
1502 :
1503 : ExpectedSnippet<0> snippets[] = {
1504 : {"var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
1505 : {handle(Smi::FromInt(2), isolate)}},
1506 : {"var a; try { undef.x } catch(e) { a = 2 }; return a;",
1507 : {handle(Smi::FromInt(2), isolate)}},
1508 : {"var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
1509 : {handle(Smi::FromInt(3), isolate)}},
1510 : {"var a; try { throw 1 } catch(e) { a = e + 2 };"
1511 : " try { throw a } catch(e) { a = e + 3 }; return a;",
1512 : {handle(Smi::FromInt(6), isolate)}},
1513 24 : };
1514 :
1515 30 : for (size_t i = 0; i < arraysize(snippets); i++) {
1516 : ScopedVector<char> script(1024);
1517 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1518 24 : snippets[i].code_snippet, kFunctionName);
1519 :
1520 : BytecodeGraphTester tester(isolate, script.start());
1521 : auto callable = tester.GetCallable<>();
1522 48 : Handle<Object> return_value = callable().ToHandleChecked();
1523 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1524 6 : }
1525 6 : }
1526 :
1527 23724 : TEST(BytecodeGraphBuilderTryFinally1) {
1528 6 : HandleAndZoneScope scope;
1529 6 : Isolate* isolate = scope.main_isolate();
1530 :
1531 : ExpectedSnippet<0> snippets[] = {
1532 : {"var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
1533 : {handle(Smi::FromInt(4), isolate)}},
1534 : {"var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
1535 : {handle(Smi::FromInt(23), isolate)}},
1536 : {"var a = 1; try { a = 2; throw 23; } finally { return a; };",
1537 : {handle(Smi::FromInt(2), isolate)}},
1538 : {"var a = 1; for (var i = 10; i < 20; i += 5) {"
1539 : " try { a = 2; break; } finally { a = 3; }"
1540 : "} return a + i;",
1541 : {handle(Smi::FromInt(13), isolate)}},
1542 : {"var a = 1; for (var i = 10; i < 20; i += 5) {"
1543 : " try { a = 2; continue; } finally { a = 3; }"
1544 : "} return a + i;",
1545 : {handle(Smi::FromInt(23), isolate)}},
1546 : {"var a = 1; try { a = 2;"
1547 : " try { a = 3; throw 23; } finally { a = 4; }"
1548 : "} catch(e) { a = a + e; } return a;",
1549 : {handle(Smi::FromInt(27), isolate)}},
1550 36 : };
1551 :
1552 42 : for (size_t i = 0; i < arraysize(snippets); i++) {
1553 : ScopedVector<char> script(1024);
1554 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1555 36 : snippets[i].code_snippet, kFunctionName);
1556 :
1557 : BytecodeGraphTester tester(isolate, script.start());
1558 : auto callable = tester.GetCallable<>();
1559 72 : Handle<Object> return_value = callable().ToHandleChecked();
1560 72 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1561 6 : }
1562 6 : }
1563 :
1564 23724 : TEST(BytecodeGraphBuilderTryFinally2) {
1565 6 : HandleAndZoneScope scope;
1566 6 : Isolate* isolate = scope.main_isolate();
1567 :
1568 : ExpectedSnippet<0, const char*> snippets[] = {
1569 : {"var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
1570 : {"Uncaught 23"}},
1571 : {"var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
1572 : {"Uncaught 42"}},
1573 6 : };
1574 :
1575 18 : for (size_t i = 0; i < arraysize(snippets); i++) {
1576 : ScopedVector<char> script(1024);
1577 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1578 12 : snippets[i].code_snippet, kFunctionName);
1579 :
1580 : BytecodeGraphTester tester(isolate, script.start());
1581 24 : v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
1582 12 : v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
1583 36 : CHECK(
1584 : message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
1585 : .FromJust());
1586 6 : }
1587 6 : }
1588 :
1589 23724 : TEST(BytecodeGraphBuilderThrow) {
1590 6 : HandleAndZoneScope scope;
1591 6 : Isolate* isolate = scope.main_isolate();
1592 :
1593 : // TODO(mythria): Add more tests when real try-catch and deoptimization
1594 : // information are supported.
1595 : ExpectedSnippet<0, const char*> snippets[] = {
1596 : {"throw undefined;", {"Uncaught undefined"}},
1597 : {"throw 1;", {"Uncaught 1"}},
1598 : {"throw 'Error';", {"Uncaught Error"}},
1599 : {"throw 'Error1'; throw 'Error2'", {"Uncaught Error1"}},
1600 : {"var a = true; if (a) { throw 'Error'; }", {"Uncaught Error"}},
1601 6 : };
1602 :
1603 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
1604 : ScopedVector<char> script(1024);
1605 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1606 30 : snippets[i].code_snippet, kFunctionName);
1607 :
1608 : BytecodeGraphTester tester(isolate, script.start());
1609 60 : v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
1610 30 : v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
1611 90 : CHECK(
1612 : message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
1613 : .FromJust());
1614 6 : }
1615 6 : }
1616 :
1617 23724 : TEST(BytecodeGraphBuilderContext) {
1618 6 : HandleAndZoneScope scope;
1619 6 : Isolate* isolate = scope.main_isolate();
1620 : Factory* factory = isolate->factory();
1621 :
1622 : ExpectedSnippet<0> snippets[] = {
1623 : {"var x = 'outer';"
1624 : "function f() {"
1625 : " 'use strict';"
1626 : " {"
1627 : " let x = 'inner';"
1628 : " (function() {x});"
1629 : " }"
1630 : "return(x);"
1631 : "}"
1632 : "f();",
1633 : {factory->NewStringFromStaticChars("outer")}},
1634 : {"var x = 'outer';"
1635 : "function f() {"
1636 : " 'use strict';"
1637 : " {"
1638 : " let x = 'inner ';"
1639 : " var innerFunc = function() {return x};"
1640 : " }"
1641 : "return(innerFunc() + x);"
1642 : "}"
1643 : "f();",
1644 : {factory->NewStringFromStaticChars("inner outer")}},
1645 : {"var x = 'outer';"
1646 : "function f() {"
1647 : " 'use strict';"
1648 : " {"
1649 : " let x = 'inner ';"
1650 : " var innerFunc = function() {return x;};"
1651 : " {"
1652 : " let x = 'innermost ';"
1653 : " var innerMostFunc = function() {return x + innerFunc();};"
1654 : " }"
1655 : " x = 'inner_changed ';"
1656 : " }"
1657 : " return(innerMostFunc() + x);"
1658 : "}"
1659 : "f();",
1660 : {factory->NewStringFromStaticChars("innermost inner_changed outer")}},
1661 18 : };
1662 :
1663 24 : for (size_t i = 0; i < arraysize(snippets); i++) {
1664 : ScopedVector<char> script(1024);
1665 18 : SNPrintF(script, "%s", snippets[i].code_snippet);
1666 :
1667 : BytecodeGraphTester tester(isolate, script.start(), "f");
1668 : auto callable = tester.GetCallable<>("f");
1669 36 : Handle<Object> return_value = callable().ToHandleChecked();
1670 36 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1671 6 : }
1672 6 : }
1673 :
1674 23724 : TEST(BytecodeGraphBuilderLoadContext) {
1675 6 : HandleAndZoneScope scope;
1676 6 : Isolate* isolate = scope.main_isolate();
1677 : Factory* factory = isolate->factory();
1678 :
1679 : ExpectedSnippet<1> snippets[] = {
1680 : {"function Outer() {"
1681 : " var outerVar = 2;"
1682 : " function Inner(innerArg) {"
1683 : " this.innerFunc = function () {"
1684 : " return outerVar * innerArg;"
1685 : " };"
1686 : " };"
1687 : " this.getInnerFunc = function GetInner() {"
1688 : " return new Inner(3).innerFunc;"
1689 : " }"
1690 : "}"
1691 : "var f = new Outer().getInnerFunc();"
1692 : "f();",
1693 : {factory->NewNumberFromInt(6), factory->undefined_value()}},
1694 : {"function Outer() {"
1695 : " var outerVar = 2;"
1696 : " function Inner(innerArg) {"
1697 : " this.innerFunc = function () {"
1698 : " outerVar = innerArg; return outerVar;"
1699 : " };"
1700 : " };"
1701 : " this.getInnerFunc = function GetInner() {"
1702 : " return new Inner(10).innerFunc;"
1703 : " }"
1704 : "}"
1705 : "var f = new Outer().getInnerFunc();"
1706 : "f();",
1707 : {factory->NewNumberFromInt(10), factory->undefined_value()}},
1708 : {"function testOuter(outerArg) {"
1709 : " this.testinnerFunc = function testInner(innerArg) {"
1710 : " return innerArg + outerArg;"
1711 : " }"
1712 : "}"
1713 : "var f = new testOuter(10).testinnerFunc;"
1714 : "f(0);",
1715 : {factory->NewNumberFromInt(14), factory->NewNumberFromInt(4)}},
1716 : {"function testOuter(outerArg) {"
1717 : " var outerVar = outerArg * 2;"
1718 : " this.testinnerFunc = function testInner(innerArg) {"
1719 : " outerVar = outerVar + innerArg; return outerVar;"
1720 : " }"
1721 : "}"
1722 : "var f = new testOuter(10).testinnerFunc;"
1723 : "f(0);",
1724 18 : {factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}};
1725 :
1726 30 : for (size_t i = 0; i < arraysize(snippets); i++) {
1727 : ScopedVector<char> script(1024);
1728 24 : SNPrintF(script, "%s", snippets[i].code_snippet);
1729 :
1730 : BytecodeGraphTester tester(isolate, script.start(), "*");
1731 : auto callable = tester.GetCallable<Handle<Object>>("f");
1732 : Handle<Object> return_value =
1733 24 : callable(snippets[i].parameter(0)).ToHandleChecked();
1734 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1735 6 : }
1736 6 : }
1737 :
1738 23724 : TEST(BytecodeGraphBuilderCreateArgumentsNoParameters) {
1739 6 : HandleAndZoneScope scope;
1740 6 : Isolate* isolate = scope.main_isolate();
1741 : Factory* factory = isolate->factory();
1742 :
1743 : ExpectedSnippet<0> snippets[] = {
1744 : {"function f() {return arguments[0];}", {factory->undefined_value()}},
1745 : {"function f(a) {return arguments[0];}", {factory->undefined_value()}},
1746 : {"function f() {'use strict'; return arguments[0];}",
1747 : {factory->undefined_value()}},
1748 : {"function f(a) {'use strict'; return arguments[0];}",
1749 : {factory->undefined_value()}},
1750 : {"function f(...restArgs) {return restArgs[0];}",
1751 : {factory->undefined_value()}},
1752 : {"function f(a, ...restArgs) {return restArgs[0];}",
1753 : {factory->undefined_value()}},
1754 36 : };
1755 :
1756 42 : for (size_t i = 0; i < arraysize(snippets); i++) {
1757 : ScopedVector<char> script(1024);
1758 36 : SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
1759 :
1760 : BytecodeGraphTester tester(isolate, script.start());
1761 : auto callable = tester.GetCallable<>();
1762 72 : Handle<Object> return_value = callable().ToHandleChecked();
1763 72 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1764 6 : }
1765 6 : }
1766 :
1767 23724 : TEST(BytecodeGraphBuilderCreateArguments) {
1768 6 : HandleAndZoneScope scope;
1769 6 : Isolate* isolate = scope.main_isolate();
1770 : Factory* factory = isolate->factory();
1771 :
1772 : ExpectedSnippet<3> snippets[] = {
1773 : {"function f(a, b, c) {return arguments[0];}",
1774 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
1775 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1776 : {"function f(a, b, c) {return arguments[3];}",
1777 : {factory->undefined_value(), factory->NewNumberFromInt(1),
1778 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1779 : {"function f(a, b, c) { b = c; return arguments[1];}",
1780 : {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
1781 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1782 : {"function f(a, b, c) {'use strict'; return arguments[0];}",
1783 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
1784 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1785 : {"function f(a, b, c) {'use strict'; return arguments[3];}",
1786 : {factory->undefined_value(), factory->NewNumberFromInt(1),
1787 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1788 : {"function f(a, b, c) {'use strict'; b = c; return arguments[1];}",
1789 : {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1),
1790 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1791 : {"function inline_func(a, b) { return arguments[0] }"
1792 : "function f(a, b, c) {return inline_func(b, c) + arguments[0];}",
1793 : {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
1794 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
1795 18 : };
1796 :
1797 48 : for (size_t i = 0; i < arraysize(snippets); i++) {
1798 : ScopedVector<char> script(1024);
1799 42 : SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
1800 :
1801 : BytecodeGraphTester tester(isolate, script.start());
1802 : auto callable =
1803 : tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
1804 : Handle<Object> return_value =
1805 : callable(snippets[i].parameter(0), snippets[i].parameter(1),
1806 42 : snippets[i].parameter(2))
1807 : .ToHandleChecked();
1808 42 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1809 6 : }
1810 6 : }
1811 :
1812 23724 : TEST(BytecodeGraphBuilderCreateRestArguments) {
1813 6 : HandleAndZoneScope scope;
1814 6 : Isolate* isolate = scope.main_isolate();
1815 : Factory* factory = isolate->factory();
1816 :
1817 : ExpectedSnippet<3> snippets[] = {
1818 : {"function f(...restArgs) {return restArgs[0];}",
1819 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
1820 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1821 : {"function f(a, b, ...restArgs) {return restArgs[0];}",
1822 : {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
1823 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1824 : {"function f(a, b, ...restArgs) {return arguments[2];}",
1825 : {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
1826 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1827 : {"function f(a, ...restArgs) { return restArgs[2];}",
1828 : {factory->undefined_value(), factory->NewNumberFromInt(1),
1829 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1830 : {"function f(a, ...restArgs) { return arguments[0] + restArgs[1];}",
1831 : {factory->NewNumberFromInt(4), factory->NewNumberFromInt(1),
1832 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
1833 : {"function inline_func(a, ...restArgs) { return restArgs[0] }"
1834 : "function f(a, b, c) {return inline_func(b, c) + arguments[0];}",
1835 : {factory->NewNumberFromInt(31), factory->NewNumberFromInt(1),
1836 : factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
1837 12 : };
1838 :
1839 42 : for (size_t i = 0; i < arraysize(snippets); i++) {
1840 : ScopedVector<char> script(1024);
1841 36 : SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
1842 :
1843 : BytecodeGraphTester tester(isolate, script.start());
1844 : auto callable =
1845 : tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
1846 : Handle<Object> return_value =
1847 : callable(snippets[i].parameter(0), snippets[i].parameter(1),
1848 36 : snippets[i].parameter(2))
1849 : .ToHandleChecked();
1850 36 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1851 6 : }
1852 6 : }
1853 :
1854 23724 : TEST(BytecodeGraphBuilderRegExpLiterals) {
1855 6 : HandleAndZoneScope scope;
1856 6 : Isolate* isolate = scope.main_isolate();
1857 : Factory* factory = isolate->factory();
1858 :
1859 : ExpectedSnippet<0> snippets[] = {
1860 : {"return /abd/.exec('cccabbdd');", {factory->null_value()}},
1861 : {"return /ab+d/.exec('cccabbdd')[0];",
1862 : {factory->NewStringFromStaticChars("abbd")}},
1863 : {"var a = 3.1414;"
1864 : REPEAT_256(SPACE, "a = 3.1414;")
1865 : "return /ab+d/.exec('cccabbdd')[0];",
1866 : {factory->NewStringFromStaticChars("abbd")}},
1867 : {"return /ab+d/.exec('cccabbdd')[1];", {factory->undefined_value()}},
1868 : {"return /AbC/i.exec('ssaBC')[0];",
1869 : {factory->NewStringFromStaticChars("aBC")}},
1870 : {"return 'ssaBC'.match(/AbC/i)[0];",
1871 : {factory->NewStringFromStaticChars("aBC")}},
1872 : {"return 'ssaBCtAbC'.match(/(AbC)/gi)[1];",
1873 : {factory->NewStringFromStaticChars("AbC")}},
1874 42 : };
1875 :
1876 48 : for (size_t i = 0; i < arraysize(snippets); i++) {
1877 : ScopedVector<char> script(4096);
1878 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1879 42 : snippets[i].code_snippet, kFunctionName);
1880 :
1881 : BytecodeGraphTester tester(isolate, script.start());
1882 : auto callable = tester.GetCallable<>();
1883 84 : Handle<Object> return_value = callable().ToHandleChecked();
1884 84 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1885 6 : }
1886 6 : }
1887 :
1888 23724 : TEST(BytecodeGraphBuilderArrayLiterals) {
1889 6 : HandleAndZoneScope scope;
1890 6 : Isolate* isolate = scope.main_isolate();
1891 : Factory* factory = isolate->factory();
1892 :
1893 : ExpectedSnippet<0> snippets[] = {
1894 : {"return [][0];", {factory->undefined_value()}},
1895 : {"return [1, 3, 2][1];", {factory->NewNumberFromInt(3)}},
1896 : {"var a;" REPEAT_256(SPACE, "a = 9.87;") "return [1, 3, 2][1];",
1897 : {factory->NewNumberFromInt(3)}},
1898 : {"return ['a', 'b', 'c'][2];", {factory->NewStringFromStaticChars("c")}},
1899 : {"var a = 100; return [a, a++, a + 2, a + 3][2];",
1900 : {factory->NewNumberFromInt(103)}},
1901 : {"var a = 100; return [a, ++a, a + 2, a + 3][1];",
1902 : {factory->NewNumberFromInt(101)}},
1903 : {"var a = 9.2;"
1904 : REPEAT_256(SPACE, "a = 9.34;")
1905 : "return [a, ++a, a + 2, a + 3][2];",
1906 : {factory->NewHeapNumber(12.34)}},
1907 : {"return [[1, 2, 3], ['a', 'b', 'c']][1][0];",
1908 : {factory->NewStringFromStaticChars("a")}},
1909 : {"var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];",
1910 : {factory->NewStringFromStaticChars("test")}},
1911 : {"var t = 't'; return [[t, t + 'est'], [1 + t]][1][0];",
1912 36 : {factory->NewStringFromStaticChars("1t")}}};
1913 :
1914 66 : for (size_t i = 0; i < arraysize(snippets); i++) {
1915 : ScopedVector<char> script(4096);
1916 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1917 60 : snippets[i].code_snippet, kFunctionName);
1918 :
1919 : BytecodeGraphTester tester(isolate, script.start());
1920 : auto callable = tester.GetCallable<>();
1921 120 : Handle<Object> return_value = callable().ToHandleChecked();
1922 120 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1923 6 : }
1924 6 : }
1925 :
1926 23724 : TEST(BytecodeGraphBuilderObjectLiterals) {
1927 6 : HandleAndZoneScope scope;
1928 6 : Isolate* isolate = scope.main_isolate();
1929 : Factory* factory = isolate->factory();
1930 :
1931 : ExpectedSnippet<0> snippets[] = {
1932 : {"return { }.name;", {factory->undefined_value()}},
1933 : {"return { name: 'string', val: 9.2 }.name;",
1934 : {factory->NewStringFromStaticChars("string")}},
1935 : {"var a;\n"
1936 : REPEAT_256(SPACE, "a = 1.23;\n")
1937 : "return { name: 'string', val: 9.2 }.name;",
1938 : {factory->NewStringFromStaticChars("string")}},
1939 : {"return { name: 'string', val: 9.2 }['name'];",
1940 : {factory->NewStringFromStaticChars("string")}},
1941 : {"var a = 15; return { name: 'string', val: a }.val;",
1942 : {factory->NewNumberFromInt(15)}},
1943 : {"var a;"
1944 : REPEAT_256(SPACE, "a = 1.23;")
1945 : "return { name: 'string', val: a }.val;",
1946 : {factory->NewHeapNumber(1.23)}},
1947 : {"var a = 15; var b = 'val'; return { name: 'string', val: a }[b];",
1948 : {factory->NewNumberFromInt(15)}},
1949 : {"var a = 5; return { val: a, val: a + 1 }.val;",
1950 : {factory->NewNumberFromInt(6)}},
1951 : {"return { func: function() { return 'test' } }.func();",
1952 : {factory->NewStringFromStaticChars("test")}},
1953 : {"return { func(a) { return a + 'st'; } }.func('te');",
1954 : {factory->NewStringFromStaticChars("test")}},
1955 : {"return { get a() { return 22; } }.a;", {factory->NewNumberFromInt(22)}},
1956 : {"var a = { get b() { return this.x + 't'; },\n"
1957 : " set b(val) { this.x = val + 's' } };\n"
1958 : "a.b = 'te';\n"
1959 : "return a.b;",
1960 : {factory->NewStringFromStaticChars("test")}},
1961 : {"var a = 123; return { 1: a }[1];", {factory->NewNumberFromInt(123)}},
1962 : {"return Object.getPrototypeOf({ __proto__: null });",
1963 : {factory->null_value()}},
1964 : {"var a = 'test'; return { [a]: 1 }.test;",
1965 : {factory->NewNumberFromInt(1)}},
1966 : {"var a = 'test'; return { b: a, [a]: a + 'ing' }['test']",
1967 : {factory->NewStringFromStaticChars("testing")}},
1968 : {"var a = 'proto_str';\n"
1969 : "var b = { [a]: 1, __proto__: { var : a } };\n"
1970 : "return Object.getPrototypeOf(b).var",
1971 : {factory->NewStringFromStaticChars("proto_str")}},
1972 : {"var n = 'name';\n"
1973 : "return { [n]: 'val', get a() { return 987 } }['a'];",
1974 : {factory->NewNumberFromInt(987)}},
1975 72 : };
1976 :
1977 114 : for (size_t i = 0; i < arraysize(snippets); i++) {
1978 : ScopedVector<char> script(4096);
1979 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1980 108 : snippets[i].code_snippet, kFunctionName);
1981 : BytecodeGraphTester tester(isolate, script.start());
1982 : auto callable = tester.GetCallable<>();
1983 216 : Handle<Object> return_value = callable().ToHandleChecked();
1984 216 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1985 6 : }
1986 6 : }
1987 :
1988 23724 : TEST(BytecodeGraphBuilderIf) {
1989 6 : HandleAndZoneScope scope;
1990 6 : Isolate* isolate = scope.main_isolate();
1991 : Factory* factory = isolate->factory();
1992 :
1993 : ExpectedSnippet<1> snippets[] = {
1994 : {"if (p1 > 1) return 1;\n"
1995 : "return -1;",
1996 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
1997 : {"if (p1 > 1) return 1;\n"
1998 : "return -1;",
1999 : {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(1)}},
2000 : {"if (p1 > 1) { return 1; } else { return -1; }",
2001 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
2002 : {"if (p1 > 1) { return 1; } else { return -1; }",
2003 : {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(1)}},
2004 : {"if (p1 > 50) {\n"
2005 : " return 1;\n"
2006 : "} else if (p1 < 10) {\n"
2007 : " return 10;\n"
2008 : "} else {\n"
2009 : " return -10;\n"
2010 : "}",
2011 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(51)}},
2012 : {"if (p1 > 50) {\n"
2013 : " return 1;\n"
2014 : "} else if (p1 < 10) {\n"
2015 : " return 10;\n"
2016 : "} else {\n"
2017 : " return 100;\n"
2018 : "}",
2019 : {factory->NewNumberFromInt(10), factory->NewNumberFromInt(9)}},
2020 : {"if (p1 > 50) {\n"
2021 : " return 1;\n"
2022 : "} else if (p1 < 10) {\n"
2023 : " return 10;\n"
2024 : "} else {\n"
2025 : " return 100;\n"
2026 : "}",
2027 : {factory->NewNumberFromInt(100), factory->NewNumberFromInt(10)}},
2028 : {"if (p1 >= 0) {\n"
2029 : " if (p1 > 10) { return 2; } else { return 1; }\n"
2030 : "} else {\n"
2031 : " if (p1 < -10) { return -2; } else { return -1; }\n"
2032 : "}",
2033 : {factory->NewNumberFromInt(2), factory->NewNumberFromInt(100)}},
2034 : {"if (p1 >= 0) {\n"
2035 : " if (p1 > 10) { return 2; } else { return 1; }\n"
2036 : "} else {\n"
2037 : " if (p1 < -10) { return -2; } else { return -1; }\n"
2038 : "}",
2039 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(10)}},
2040 : {"if (p1 >= 0) {\n"
2041 : " if (p1 > 10) { return 2; } else { return 1; }\n"
2042 : "} else {\n"
2043 : " if (p1 < -10) { return -2; } else { return -1; }\n"
2044 : "}",
2045 : {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(-11)}},
2046 : {"if (p1 >= 0) {\n"
2047 : " if (p1 > 10) { return 2; } else { return 1; }\n"
2048 : "} else {\n"
2049 : " if (p1 < -10) { return -2; } else { return -1; }\n"
2050 : "}",
2051 : {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-10)}},
2052 : {"var b = 20, c;"
2053 : "if (p1 >= 0) {\n"
2054 : " if (b > 0) { c = 2; } else { c = 3; }\n"
2055 : "} else {\n"
2056 : " if (b < -10) { c = -2; } else { c = -1; }\n"
2057 : "}"
2058 : "return c;",
2059 : {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-1)}},
2060 : {"var b = 20, c = 10;"
2061 : "if (p1 >= 0) {\n"
2062 : " if (b < 0) { c = 2; }\n"
2063 : "} else {\n"
2064 : " if (b < -10) { c = -2; } else { c = -1; }\n"
2065 : "}"
2066 : "return c;",
2067 : {factory->NewNumberFromInt(10), factory->NewNumberFromInt(1)}},
2068 : {"var x = 2, a = 10, b = 20, c, d;"
2069 : "x = 0;"
2070 : "if (a) {\n"
2071 : " b = x;"
2072 : " if (b > 0) { c = 2; } else { c = 3; }\n"
2073 : " x = 4; d = 2;"
2074 : "} else {\n"
2075 : " d = 3;\n"
2076 : "}"
2077 : "x = d;"
2078 : "function f1() {x}"
2079 : "return x + c;",
2080 : {factory->NewNumberFromInt(5), factory->NewNumberFromInt(-1)}},
2081 6 : };
2082 :
2083 90 : for (size_t i = 0; i < arraysize(snippets); i++) {
2084 : ScopedVector<char> script(2048);
2085 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
2086 84 : snippets[i].code_snippet, kFunctionName);
2087 :
2088 : BytecodeGraphTester tester(isolate, script.start());
2089 : auto callable = tester.GetCallable<Handle<Object>>();
2090 : Handle<Object> return_value =
2091 84 : callable(snippets[i].parameter(0)).ToHandleChecked();
2092 84 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2093 6 : }
2094 6 : }
2095 :
2096 23724 : TEST(BytecodeGraphBuilderConditionalOperator) {
2097 6 : HandleAndZoneScope scope;
2098 6 : Isolate* isolate = scope.main_isolate();
2099 : Factory* factory = isolate->factory();
2100 :
2101 : ExpectedSnippet<1> snippets[] = {
2102 : {"return (p1 > 1) ? 1 : -1;",
2103 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
2104 : {"return (p1 > 1) ? 1 : -1;",
2105 : {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0)}},
2106 : {"return (p1 > 50) ? 1 : ((p1 < 10) ? 10 : -10);",
2107 : {factory->NewNumberFromInt(10), factory->NewNumberFromInt(2)}},
2108 : {"return (p1 > 50) ? 1 : ((p1 < 10) ? 10 : -10);",
2109 : {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(20)}},
2110 6 : };
2111 :
2112 30 : for (size_t i = 0; i < arraysize(snippets); i++) {
2113 : ScopedVector<char> script(2048);
2114 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
2115 24 : snippets[i].code_snippet, kFunctionName);
2116 :
2117 : BytecodeGraphTester tester(isolate, script.start());
2118 : auto callable = tester.GetCallable<Handle<Object>>();
2119 : Handle<Object> return_value =
2120 24 : callable(snippets[i].parameter(0)).ToHandleChecked();
2121 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2122 6 : }
2123 6 : }
2124 :
2125 23724 : TEST(BytecodeGraphBuilderSwitch) {
2126 6 : HandleAndZoneScope scope;
2127 6 : Isolate* isolate = scope.main_isolate();
2128 : Factory* factory = isolate->factory();
2129 :
2130 : const char* switch_code =
2131 : "switch (p1) {\n"
2132 : " case 1: return 0;\n"
2133 : " case 2: return 1;\n"
2134 : " case 3:\n"
2135 : " case 4: return 2;\n"
2136 : " case 9: break;\n"
2137 : " default: return 3;\n"
2138 : "}\n"
2139 : "return 9;";
2140 :
2141 : ExpectedSnippet<1> snippets[] = {
2142 : {switch_code,
2143 : {factory->NewNumberFromInt(0), factory->NewNumberFromInt(1)}},
2144 : {switch_code,
2145 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
2146 : {switch_code,
2147 : {factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
2148 : {switch_code,
2149 : {factory->NewNumberFromInt(2), factory->NewNumberFromInt(4)}},
2150 : {switch_code,
2151 : {factory->NewNumberFromInt(9), factory->NewNumberFromInt(9)}},
2152 : {switch_code,
2153 : {factory->NewNumberFromInt(3), factory->NewNumberFromInt(5)}},
2154 : {switch_code,
2155 : {factory->NewNumberFromInt(3), factory->NewNumberFromInt(6)}},
2156 6 : };
2157 :
2158 48 : for (size_t i = 0; i < arraysize(snippets); i++) {
2159 : ScopedVector<char> script(2048);
2160 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
2161 42 : snippets[i].code_snippet, kFunctionName);
2162 :
2163 : BytecodeGraphTester tester(isolate, script.start());
2164 : auto callable = tester.GetCallable<Handle<Object>>();
2165 : Handle<Object> return_value =
2166 42 : callable(snippets[i].parameter(0)).ToHandleChecked();
2167 42 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2168 6 : }
2169 6 : }
2170 :
2171 23724 : TEST(BytecodeGraphBuilderSwitchMerge) {
2172 6 : HandleAndZoneScope scope;
2173 6 : Isolate* isolate = scope.main_isolate();
2174 : Factory* factory = isolate->factory();
2175 :
2176 : const char* switch_code =
2177 : "var x = 10;"
2178 : "switch (p1) {\n"
2179 : " case 1: x = 0;\n"
2180 : " case 2: x = 1;\n"
2181 : " case 3:\n"
2182 : " case 4: x = 2; break;\n"
2183 : " case 5: x = 3;\n"
2184 : " case 9: break;\n"
2185 : " default: x = 4;\n"
2186 : "}\n"
2187 : "return x;";
2188 :
2189 : ExpectedSnippet<1> snippets[] = {
2190 : {switch_code,
2191 : {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1)}},
2192 : {switch_code,
2193 : {factory->NewNumberFromInt(2), factory->NewNumberFromInt(2)}},
2194 : {switch_code,
2195 : {factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
2196 : {switch_code,
2197 : {factory->NewNumberFromInt(2), factory->NewNumberFromInt(4)}},
2198 : {switch_code,
2199 : {factory->NewNumberFromInt(3), factory->NewNumberFromInt(5)}},
2200 : {switch_code,
2201 : {factory->NewNumberFromInt(10), factory->NewNumberFromInt(9)}},
2202 : {switch_code,
2203 : {factory->NewNumberFromInt(4), factory->NewNumberFromInt(6)}},
2204 6 : };
2205 :
2206 48 : for (size_t i = 0; i < arraysize(snippets); i++) {
2207 : ScopedVector<char> script(2048);
2208 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
2209 42 : snippets[i].code_snippet, kFunctionName);
2210 :
2211 : BytecodeGraphTester tester(isolate, script.start());
2212 : auto callable = tester.GetCallable<Handle<Object>>();
2213 : Handle<Object> return_value =
2214 42 : callable(snippets[i].parameter(0)).ToHandleChecked();
2215 42 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2216 6 : }
2217 6 : }
2218 :
2219 23724 : TEST(BytecodeGraphBuilderNestedSwitch) {
2220 6 : HandleAndZoneScope scope;
2221 6 : Isolate* isolate = scope.main_isolate();
2222 : Factory* factory = isolate->factory();
2223 :
2224 : const char* switch_code =
2225 : "switch (p1) {\n"
2226 : " case 0: {"
2227 : " switch (p2) { case 0: return 0; case 1: return 1; case 2: break; }\n"
2228 : " return -1;"
2229 : " }\n"
2230 : " case 1: {"
2231 : " switch (p2) { case 0: return 2; case 1: return 3; }\n"
2232 : " }\n"
2233 : " case 2: break;"
2234 : " }\n"
2235 : "return -2;";
2236 :
2237 : ExpectedSnippet<2> snippets[] = {
2238 : {switch_code,
2239 : {factory->NewNumberFromInt(0), factory->NewNumberFromInt(0),
2240 : factory->NewNumberFromInt(0)}},
2241 : {switch_code,
2242 : {factory->NewNumberFromInt(1), factory->NewNumberFromInt(0),
2243 : factory->NewNumberFromInt(1)}},
2244 : {switch_code,
2245 : {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0),
2246 : factory->NewNumberFromInt(2)}},
2247 : {switch_code,
2248 : {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0),
2249 : factory->NewNumberFromInt(3)}},
2250 : {switch_code,
2251 : {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1),
2252 : factory->NewNumberFromInt(0)}},
2253 : {switch_code,
2254 : {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
2255 : factory->NewNumberFromInt(1)}},
2256 : {switch_code,
2257 : {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(1),
2258 : factory->NewNumberFromInt(2)}},
2259 : {switch_code,
2260 : {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(2),
2261 : factory->NewNumberFromInt(0)}},
2262 6 : };
2263 :
2264 54 : for (size_t i = 0; i < arraysize(snippets); i++) {
2265 : ScopedVector<char> script(2048);
2266 : SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0, 0);", kFunctionName,
2267 48 : snippets[i].code_snippet, kFunctionName);
2268 :
2269 : BytecodeGraphTester tester(isolate, script.start());
2270 : auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
2271 : Handle<Object> return_value =
2272 48 : callable(snippets[i].parameter(0), snippets[i].parameter(1))
2273 : .ToHandleChecked();
2274 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2275 6 : }
2276 6 : }
2277 :
2278 23724 : TEST(BytecodeGraphBuilderBreakableBlocks) {
2279 6 : HandleAndZoneScope scope;
2280 6 : Isolate* isolate = scope.main_isolate();
2281 : Factory* factory = isolate->factory();
2282 :
2283 : ExpectedSnippet<0> snippets[] = {
2284 : {"var x = 0;\n"
2285 : "my_heart: {\n"
2286 : " x = x + 1;\n"
2287 : " break my_heart;\n"
2288 : " x = x + 2;\n"
2289 : "}\n"
2290 : "return x;\n",
2291 : {factory->NewNumberFromInt(1)}},
2292 : {"var sum = 0;\n"
2293 : "outta_here: {\n"
2294 : " for (var x = 0; x < 10; ++x) {\n"
2295 : " for (var y = 0; y < 3; ++y) {\n"
2296 : " ++sum;\n"
2297 : " if (x + y == 12) { break outta_here; }\n"
2298 : " }\n"
2299 : " }\n"
2300 : "}\n"
2301 : "return sum;",
2302 : {factory->NewNumber(30)}},
2303 6 : };
2304 :
2305 18 : for (size_t i = 0; i < arraysize(snippets); i++) {
2306 : ScopedVector<char> script(1024);
2307 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2308 12 : snippets[i].code_snippet, kFunctionName);
2309 :
2310 : BytecodeGraphTester tester(isolate, script.start());
2311 : auto callable = tester.GetCallable<>();
2312 24 : Handle<Object> return_value = callable().ToHandleChecked();
2313 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2314 6 : }
2315 6 : }
2316 :
2317 23724 : TEST(BytecodeGraphBuilderWhile) {
2318 6 : HandleAndZoneScope scope;
2319 6 : Isolate* isolate = scope.main_isolate();
2320 : Factory* factory = isolate->factory();
2321 :
2322 : ExpectedSnippet<0> snippets[] = {
2323 : {"var x = 1; while (x < 1) { x *= 100; } return x;",
2324 : {factory->NewNumberFromInt(1)}},
2325 : {"var x = 1, y = 0; while (x < 7) { y += x * x; x += 1; } return y;",
2326 : {factory->NewNumberFromInt(91)}},
2327 : {"var x = 1; while (true) { x += 1; if (x == 10) break; } return x;",
2328 : {factory->NewNumberFromInt(10)}},
2329 : {"var x = 1; while (false) { x += 1; } return x;",
2330 : {factory->NewNumberFromInt(1)}},
2331 : {"var x = 0;\n"
2332 : "while (true) {\n"
2333 : " while (x < 10) {\n"
2334 : " x = x * x + 1;\n"
2335 : " }"
2336 : " x += 1;\n"
2337 : " break;\n"
2338 : "}\n"
2339 : "return x;",
2340 : {factory->NewNumberFromInt(27)}},
2341 : {"var x = 1, y = 0;\n"
2342 : "while (x < 7) {\n"
2343 : " x += 1;\n"
2344 : " if (x == 2) continue;\n"
2345 : " if (x == 3) continue;\n"
2346 : " y += x * x;\n"
2347 : " if (x == 4) break;\n"
2348 : "}\n"
2349 : "return y;",
2350 6 : {factory->NewNumberFromInt(16)}}};
2351 :
2352 42 : for (size_t i = 0; i < arraysize(snippets); i++) {
2353 : ScopedVector<char> script(1024);
2354 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2355 36 : snippets[i].code_snippet, kFunctionName);
2356 :
2357 : BytecodeGraphTester tester(isolate, script.start());
2358 : auto callable = tester.GetCallable<>();
2359 72 : Handle<Object> return_value = callable().ToHandleChecked();
2360 72 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2361 6 : }
2362 6 : }
2363 :
2364 23724 : TEST(BytecodeGraphBuilderDo) {
2365 6 : HandleAndZoneScope scope;
2366 6 : Isolate* isolate = scope.main_isolate();
2367 : Factory* factory = isolate->factory();
2368 :
2369 : ExpectedSnippet<0> snippets[] = {
2370 : {"var x = 1; do { x *= 100; } while (x < 100); return x;",
2371 : {factory->NewNumberFromInt(100)}},
2372 : {"var x = 1; do { x = x * x + 1; } while (x < 7) return x;",
2373 : {factory->NewNumberFromInt(26)}},
2374 : {"var x = 1; do { x += 1; } while (false); return x;",
2375 : {factory->NewNumberFromInt(2)}},
2376 : {"var x = 1, y = 0;\n"
2377 : "do {\n"
2378 : " x += 1;\n"
2379 : " if (x == 2) continue;\n"
2380 : " if (x == 3) continue;\n"
2381 : " y += x * x;\n"
2382 : " if (x == 4) break;\n"
2383 : "} while (x < 7);\n"
2384 : "return y;",
2385 : {factory->NewNumberFromInt(16)}},
2386 : {"var x = 0, sum = 0;\n"
2387 : "do {\n"
2388 : " do {\n"
2389 : " ++sum;\n"
2390 : " ++x;\n"
2391 : " } while (sum < 1 || x < 2)\n"
2392 : " do {\n"
2393 : " ++x;\n"
2394 : " } while (x < 1)\n"
2395 : "} while (sum < 3)\n"
2396 : "return sum;",
2397 6 : {factory->NewNumber(3)}}};
2398 :
2399 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
2400 : ScopedVector<char> script(1024);
2401 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2402 30 : snippets[i].code_snippet, kFunctionName);
2403 :
2404 : BytecodeGraphTester tester(isolate, script.start());
2405 : auto callable = tester.GetCallable<>();
2406 60 : Handle<Object> return_value = callable().ToHandleChecked();
2407 60 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2408 6 : }
2409 6 : }
2410 :
2411 23724 : TEST(BytecodeGraphBuilderFor) {
2412 6 : HandleAndZoneScope scope;
2413 6 : Isolate* isolate = scope.main_isolate();
2414 : Factory* factory = isolate->factory();
2415 :
2416 : ExpectedSnippet<0> snippets[] = {
2417 : {"for (var x = 0;; x = 2 * x + 1) { if (x > 10) return x; }",
2418 : {factory->NewNumberFromInt(15)}},
2419 : {"for (var x = 0; true; x = 2 * x + 1) { if (x > 100) return x; }",
2420 : {factory->NewNumberFromInt(127)}},
2421 : {"for (var x = 0; false; x = 2 * x + 1) { if (x > 100) return x; } "
2422 : "return 0;",
2423 : {factory->NewNumberFromInt(0)}},
2424 : {"for (var x = 0; x < 200; x = 2 * x + 1) { x = x; } return x;",
2425 : {factory->NewNumberFromInt(255)}},
2426 : {"for (var x = 0; x < 200; x = 2 * x + 1) {} return x;",
2427 : {factory->NewNumberFromInt(255)}},
2428 : {"var sum = 0;\n"
2429 : "for (var x = 0; x < 200; x += 1) {\n"
2430 : " if (x % 2) continue;\n"
2431 : " if (sum > 10) break;\n"
2432 : " sum += x;\n"
2433 : "}\n"
2434 : "return sum;",
2435 : {factory->NewNumberFromInt(12)}},
2436 : {"var sum = 0;\n"
2437 : "for (var w = 0; w < 2; w++) {\n"
2438 : " for (var x = 0; x < 200; x += 1) {\n"
2439 : " if (x % 2) continue;\n"
2440 : " if (x > 4) break;\n"
2441 : " sum += x + w;\n"
2442 : " }\n"
2443 : "}\n"
2444 : "return sum;",
2445 : {factory->NewNumberFromInt(15)}},
2446 : {"var sum = 0;\n"
2447 : "for (var w = 0; w < 2; w++) {\n"
2448 : " if (w == 1) break;\n"
2449 : " for (var x = 0; x < 200; x += 1) {\n"
2450 : " if (x % 2) continue;\n"
2451 : " if (x > 4) break;\n"
2452 : " sum += x + w;\n"
2453 : " }\n"
2454 : "}\n"
2455 : "return sum;",
2456 : {factory->NewNumberFromInt(6)}},
2457 : {"var sum = 0;\n"
2458 : "for (var w = 0; w < 3; w++) {\n"
2459 : " if (w == 1) continue;\n"
2460 : " for (var x = 0; x < 200; x += 1) {\n"
2461 : " if (x % 2) continue;\n"
2462 : " if (x > 4) break;\n"
2463 : " sum += x + w;\n"
2464 : " }\n"
2465 : "}\n"
2466 : "return sum;",
2467 : {factory->NewNumberFromInt(18)}},
2468 : {"var sum = 0;\n"
2469 : "for (var x = 1; x < 10; x += 2) {\n"
2470 : " for (var y = x; y < x + 2; y++) {\n"
2471 : " sum += y * y;\n"
2472 : " }\n"
2473 : "}\n"
2474 : "return sum;",
2475 : {factory->NewNumberFromInt(385)}},
2476 : {"var sum = 0;\n"
2477 : "for (var x = 0; x < 5; x++) {\n"
2478 : " for (var y = 0; y < 5; y++) {\n"
2479 : " ++sum;\n"
2480 : " }\n"
2481 : "}\n"
2482 : "for (var x = 0; x < 5; x++) {\n"
2483 : " for (var y = 0; y < 5; y++) {\n"
2484 : " ++sum;\n"
2485 : " }\n"
2486 : "}\n"
2487 : "return sum;",
2488 : {factory->NewNumberFromInt(50)}},
2489 6 : };
2490 :
2491 72 : for (size_t i = 0; i < arraysize(snippets); i++) {
2492 : ScopedVector<char> script(1024);
2493 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2494 66 : snippets[i].code_snippet, kFunctionName);
2495 :
2496 : BytecodeGraphTester tester(isolate, script.start());
2497 : auto callable = tester.GetCallable<>();
2498 132 : Handle<Object> return_value = callable().ToHandleChecked();
2499 132 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2500 6 : }
2501 6 : }
2502 :
2503 23724 : TEST(BytecodeGraphBuilderForIn) {
2504 6 : HandleAndZoneScope scope;
2505 6 : Isolate* isolate = scope.main_isolate();
2506 : Factory* factory = isolate->factory();
2507 : ExpectedSnippet<0> snippets[] = {
2508 : {"var sum = 0;\n"
2509 : "var empty = null;\n"
2510 : "for (var x in empty) { sum++; }\n"
2511 : "return sum;",
2512 : {factory->NewNumberFromInt(0)}},
2513 : {"var sum = 100;\n"
2514 : "var empty = 1;\n"
2515 : "for (var x in empty) { sum++; }\n"
2516 : "return sum;",
2517 : {factory->NewNumberFromInt(100)}},
2518 : {"for (var x in [ 10, 20, 30 ]) {}\n"
2519 : "return 2;",
2520 : {factory->NewNumberFromInt(2)}},
2521 : {"var last = 0;\n"
2522 : "for (var x in [ 10, 20, 30 ]) {\n"
2523 : " last = x;\n"
2524 : "}\n"
2525 : "return +last;",
2526 : {factory->NewNumberFromInt(2)}},
2527 : {"var first = -1;\n"
2528 : "for (var x in [ 10, 20, 30 ]) {\n"
2529 : " first = +x;\n"
2530 : " if (first > 0) break;\n"
2531 : "}\n"
2532 : "return first;",
2533 : {factory->NewNumberFromInt(1)}},
2534 : {"var first = -1;\n"
2535 : "for (var x in [ 10, 20, 30 ]) {\n"
2536 : " if (first >= 0) continue;\n"
2537 : " first = x;\n"
2538 : "}\n"
2539 : "return +first;",
2540 : {factory->NewNumberFromInt(0)}},
2541 : {"var sum = 0;\n"
2542 : "for (var x in [ 10, 20, 30 ]) {\n"
2543 : " for (var y in [ 11, 22, 33, 44, 55, 66, 77 ]) {\n"
2544 : " sum += 1;\n"
2545 : " }\n"
2546 : "}\n"
2547 : "return sum;",
2548 : {factory->NewNumberFromInt(21)}},
2549 : {"var sum = 0;\n"
2550 : "for (var x in [ 10, 20, 30 ]) {\n"
2551 : " for (var y in [ 11, 22, 33, 44, 55, 66, 77 ]) {\n"
2552 : " if (sum == 7) break;\n"
2553 : " if (sum == 6) continue;\n"
2554 : " sum += 1;\n"
2555 : " }\n"
2556 : "}\n"
2557 : "return sum;",
2558 : {factory->NewNumberFromInt(6)}},
2559 6 : };
2560 :
2561 54 : for (size_t i = 0; i < arraysize(snippets); i++) {
2562 : ScopedVector<char> script(1024);
2563 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2564 48 : snippets[i].code_snippet, kFunctionName);
2565 :
2566 : BytecodeGraphTester tester(isolate, script.start());
2567 : auto callable = tester.GetCallable<>();
2568 96 : Handle<Object> return_value = callable().ToHandleChecked();
2569 96 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2570 6 : }
2571 6 : }
2572 :
2573 23724 : TEST(BytecodeGraphBuilderForOf) {
2574 6 : HandleAndZoneScope scope;
2575 6 : Isolate* isolate = scope.main_isolate();
2576 : Factory* factory = isolate->factory();
2577 : ExpectedSnippet<0> snippets[] = {
2578 : {" var r = 0;\n"
2579 : " for (var a of [0,6,7,9]) { r += a; }\n"
2580 : " return r;\n",
2581 : {handle(Smi::FromInt(22), isolate)}},
2582 : {" var r = '';\n"
2583 : " for (var a of 'foobar') { r = a + r; }\n"
2584 : " return r;\n",
2585 : {factory->NewStringFromStaticChars("raboof")}},
2586 : {" var a = [1, 2, 3];\n"
2587 : " a.name = 4;\n"
2588 : " var r = 0;\n"
2589 : " for (var x of a) { r += x; }\n"
2590 : " return r;\n",
2591 : {handle(Smi::FromInt(6), isolate)}},
2592 : {" var r = '';\n"
2593 : " var data = [1, 2, 3]; \n"
2594 : " for (a of data) { delete data[0]; r += a; } return r;",
2595 : {factory->NewStringFromStaticChars("123")}},
2596 : {" var r = '';\n"
2597 : " var data = [1, 2, 3]; \n"
2598 : " for (a of data) { delete data[2]; r += a; } return r;",
2599 : {factory->NewStringFromStaticChars("12undefined")}},
2600 : {" var r = '';\n"
2601 : " var data = [1, 2, 3]; \n"
2602 : " for (a of data) { delete data; r += a; } return r;",
2603 : {factory->NewStringFromStaticChars("123")}},
2604 : {" var r = '';\n"
2605 : " var input = 'foobar';\n"
2606 : " for (var a of input) {\n"
2607 : " if (a == 'b') break;\n"
2608 : " r += a;\n"
2609 : " }\n"
2610 : " return r;\n",
2611 : {factory->NewStringFromStaticChars("foo")}},
2612 : {" var r = '';\n"
2613 : " var input = 'foobar';\n"
2614 : " for (var a of input) {\n"
2615 : " if (a == 'b') continue;\n"
2616 : " r += a;\n"
2617 : " }\n"
2618 : " return r;\n",
2619 : {factory->NewStringFromStaticChars("fooar")}},
2620 : {" var r = '';\n"
2621 : " var data = [1, 2, 3, 4]; \n"
2622 : " for (a of data) { data[2] = 567; r += a; }\n"
2623 : " return r;\n",
2624 : {factory->NewStringFromStaticChars("125674")}},
2625 : {" var r = '';\n"
2626 : " var data = [1, 2, 3, 4]; \n"
2627 : " for (a of data) { data[4] = 567; r += a; }\n"
2628 : " return r;\n",
2629 : {factory->NewStringFromStaticChars("1234567")}},
2630 : {" var r = '';\n"
2631 : " var data = [1, 2, 3, 4]; \n"
2632 : " for (a of data) { data[5] = 567; r += a; }\n"
2633 : " return r;\n",
2634 : {factory->NewStringFromStaticChars("1234undefined567")}},
2635 : {" var r = '';\n"
2636 : " var obj = new Object();\n"
2637 : " obj[Symbol.iterator] = function() { return {\n"
2638 : " index: 3,\n"
2639 : " data: ['a', 'b', 'c', 'd'],"
2640 : " next: function() {"
2641 : " return {"
2642 : " done: this.index == -1,\n"
2643 : " value: this.index < 0 ? undefined : this.data[this.index--]\n"
2644 : " }\n"
2645 : " }\n"
2646 : " }}\n"
2647 : " for (a of obj) { r += a }\n"
2648 : " return r;\n",
2649 : {factory->NewStringFromStaticChars("dcba")}},
2650 72 : };
2651 :
2652 78 : for (size_t i = 0; i < arraysize(snippets); i++) {
2653 : ScopedVector<char> script(1024);
2654 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2655 72 : snippets[i].code_snippet, kFunctionName);
2656 :
2657 : BytecodeGraphTester tester(isolate, script.start());
2658 : auto callable = tester.GetCallable<>();
2659 144 : Handle<Object> return_value = callable().ToHandleChecked();
2660 144 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2661 6 : }
2662 6 : }
2663 :
2664 24 : void TestJumpWithConstantsAndWideConstants(size_t shard) {
2665 : const int kStep = 46;
2666 24 : int start = static_cast<int>(7 + 17 * shard);
2667 174 : for (int constants = start; constants < 300; constants += kStep) {
2668 150 : std::stringstream filler_os;
2669 : // Generate a string that consumes constant pool entries and
2670 : // spread out branch distances in script below.
2671 23088 : for (int i = 0; i < constants; i++) {
2672 22938 : filler_os << "var x_ = 'x_" << i << "';\n";
2673 : }
2674 : std::string filler(filler_os.str());
2675 :
2676 300 : std::stringstream script_os;
2677 150 : script_os << "function " << kFunctionName << "(a) {\n";
2678 150 : script_os << " " << filler;
2679 150 : script_os << " for (var i = a; i < 2; i++) {\n";
2680 150 : script_os << " " << filler;
2681 300 : script_os << " if (i == 0) { " << filler << "i = 10; continue; }\n";
2682 300 : script_os << " else if (i == a) { " << filler << "i = 12; break; }\n";
2683 300 : script_os << " else { " << filler << " }\n";
2684 150 : script_os << " }\n";
2685 150 : script_os << " return i;\n";
2686 150 : script_os << "}\n";
2687 150 : script_os << kFunctionName << "(0);\n";
2688 : std::string script(script_os.str());
2689 :
2690 300 : HandleAndZoneScope scope;
2691 150 : auto isolate = scope.main_isolate();
2692 : auto factory = isolate->factory();
2693 : BytecodeGraphTester tester(isolate, script.c_str());
2694 : auto callable = tester.GetCallable<Handle<Object>>();
2695 600 : for (int a = 0; a < 3; a++) {
2696 : Handle<Object> return_val =
2697 450 : callable(factory->NewNumberFromInt(a)).ToHandleChecked();
2698 : static const int results[] = {11, 12, 2};
2699 900 : CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
2700 : }
2701 150 : }
2702 24 : }
2703 :
2704 23742 : SHARD_TEST_BY_4(JumpWithConstantsAndWideConstants)
2705 :
2706 23724 : TEST(BytecodeGraphBuilderDoExpressions) {
2707 6 : bool old_flag = FLAG_harmony_do_expressions;
2708 6 : FLAG_harmony_do_expressions = true;
2709 6 : HandleAndZoneScope scope;
2710 6 : Isolate* isolate = scope.main_isolate();
2711 : Factory* factory = isolate->factory();
2712 : ExpectedSnippet<0> snippets[] = {
2713 : {"var a = do {}; return a;", {factory->undefined_value()}},
2714 : {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
2715 : {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
2716 : {"var a = do { var x = 100; x++; }; return a;",
2717 : {handle(Smi::FromInt(100), isolate)}},
2718 : {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
2719 : "return i;",
2720 : {handle(Smi::FromInt(3), isolate)}},
2721 30 : };
2722 :
2723 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
2724 : ScopedVector<char> script(1024);
2725 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2726 30 : snippets[i].code_snippet, kFunctionName);
2727 :
2728 : BytecodeGraphTester tester(isolate, script.start());
2729 : auto callable = tester.GetCallable<>();
2730 60 : Handle<Object> return_value = callable().ToHandleChecked();
2731 60 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2732 : }
2733 :
2734 6 : FLAG_harmony_do_expressions = old_flag;
2735 6 : }
2736 :
2737 23724 : TEST(BytecodeGraphBuilderWithStatement) {
2738 6 : HandleAndZoneScope scope;
2739 6 : Isolate* isolate = scope.main_isolate();
2740 :
2741 : ExpectedSnippet<0> snippets[] = {
2742 : {"with({x:42}) return x;", {handle(Smi::FromInt(42), isolate)}},
2743 : {"with({}) { var y = 10; return y;}",
2744 : {handle(Smi::FromInt(10), isolate)}},
2745 : {"var y = {x:42};"
2746 : " function inner() {"
2747 : " var x = 20;"
2748 : " with(y) return x;"
2749 : "}"
2750 : "return inner();",
2751 : {handle(Smi::FromInt(42), isolate)}},
2752 : {"var y = {x:42};"
2753 : " function inner(o) {"
2754 : " var x = 20;"
2755 : " with(o) return x;"
2756 : "}"
2757 : "return inner(y);",
2758 : {handle(Smi::FromInt(42), isolate)}},
2759 24 : };
2760 :
2761 30 : for (size_t i = 0; i < arraysize(snippets); i++) {
2762 : ScopedVector<char> script(1024);
2763 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2764 24 : snippets[i].code_snippet, kFunctionName);
2765 :
2766 : BytecodeGraphTester tester(isolate, script.start());
2767 : auto callable = tester.GetCallable<>();
2768 48 : Handle<Object> return_value = callable().ToHandleChecked();
2769 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2770 6 : }
2771 6 : }
2772 :
2773 23724 : TEST(BytecodeGraphBuilderConstDeclaration) {
2774 6 : HandleAndZoneScope scope;
2775 6 : Isolate* isolate = scope.main_isolate();
2776 : Factory* factory = isolate->factory();
2777 :
2778 : ExpectedSnippet<0> snippets[] = {
2779 : {"const x = 3; return x;", {handle(Smi::FromInt(3), isolate)}},
2780 : {"let x = 10; x = x + 20; return x;",
2781 : {handle(Smi::FromInt(30), isolate)}},
2782 : {"let x = 10; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
2783 : {"let x; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
2784 : {"let x; return x;", {factory->undefined_value()}},
2785 : {"var x = 10; { let x = 30; } return x;",
2786 : {handle(Smi::FromInt(10), isolate)}},
2787 : {"let x = 10; { let x = 20; } return x;",
2788 : {handle(Smi::FromInt(10), isolate)}},
2789 : {"var x = 10; eval('let x = 20;'); return x;",
2790 : {handle(Smi::FromInt(10), isolate)}},
2791 : {"var x = 10; eval('const x = 20;'); return x;",
2792 : {handle(Smi::FromInt(10), isolate)}},
2793 : {"var x = 10; { const x = 20; } return x;",
2794 : {handle(Smi::FromInt(10), isolate)}},
2795 : {"var x = 10; { const x = 20; return x;} return -1;",
2796 : {handle(Smi::FromInt(20), isolate)}},
2797 : {"var a = 10;\n"
2798 : "for (var i = 0; i < 10; ++i) {\n"
2799 : " const x = i;\n" // const declarations are block scoped.
2800 : " a = a + x;\n"
2801 : "}\n"
2802 : "return a;\n",
2803 : {handle(Smi::FromInt(55), isolate)}},
2804 72 : };
2805 :
2806 : // Tests for sloppy mode.
2807 78 : for (size_t i = 0; i < arraysize(snippets); i++) {
2808 : ScopedVector<char> script(1024);
2809 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2810 72 : snippets[i].code_snippet, kFunctionName);
2811 :
2812 : BytecodeGraphTester tester(isolate, script.start());
2813 : auto callable = tester.GetCallable<>();
2814 144 : Handle<Object> return_value = callable().ToHandleChecked();
2815 144 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2816 : }
2817 :
2818 : // Tests for strict mode.
2819 72 : for (size_t i = 0; i < arraysize(snippets); i++) {
2820 : ScopedVector<char> script(1024);
2821 : SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
2822 72 : snippets[i].code_snippet, kFunctionName);
2823 :
2824 : BytecodeGraphTester tester(isolate, script.start());
2825 : auto callable = tester.GetCallable<>();
2826 144 : Handle<Object> return_value = callable().ToHandleChecked();
2827 144 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2828 6 : }
2829 6 : }
2830 :
2831 23724 : TEST(BytecodeGraphBuilderConstDeclarationLookupSlots) {
2832 6 : HandleAndZoneScope scope;
2833 6 : Isolate* isolate = scope.main_isolate();
2834 : Factory* factory = isolate->factory();
2835 :
2836 : ExpectedSnippet<0> snippets[] = {
2837 : {"const x = 3; function f1() {return x;}; return x;",
2838 : {handle(Smi::FromInt(3), isolate)}},
2839 : {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
2840 : {handle(Smi::FromInt(30), isolate)}},
2841 : {"let x; x = 20; function f1() {return x;}; return x;",
2842 : {handle(Smi::FromInt(20), isolate)}},
2843 : {"let x; function f1() {return x;}; return x;",
2844 : {factory->undefined_value()}},
2845 24 : };
2846 :
2847 : // Tests for sloppy mode.
2848 30 : for (size_t i = 0; i < arraysize(snippets); i++) {
2849 : ScopedVector<char> script(1024);
2850 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2851 24 : snippets[i].code_snippet, kFunctionName);
2852 :
2853 : BytecodeGraphTester tester(isolate, script.start());
2854 : auto callable = tester.GetCallable<>();
2855 48 : Handle<Object> return_value = callable().ToHandleChecked();
2856 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2857 : }
2858 :
2859 : // Tests for strict mode.
2860 24 : for (size_t i = 0; i < arraysize(snippets); i++) {
2861 : ScopedVector<char> script(1024);
2862 : SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
2863 24 : snippets[i].code_snippet, kFunctionName);
2864 :
2865 : BytecodeGraphTester tester(isolate, script.start());
2866 : auto callable = tester.GetCallable<>();
2867 48 : Handle<Object> return_value = callable().ToHandleChecked();
2868 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2869 6 : }
2870 6 : }
2871 :
2872 23724 : TEST(BytecodeGraphBuilderConstInLookupContextChain) {
2873 6 : HandleAndZoneScope scope;
2874 6 : Isolate* isolate = scope.main_isolate();
2875 :
2876 : const char* prologue =
2877 : "function OuterMost() {\n"
2878 : " const outerConst = 10;\n"
2879 : " let outerLet = 20;\n"
2880 : " function Outer() {\n"
2881 : " function Inner() {\n"
2882 : " this.innerFunc = function() { ";
2883 : const char* epilogue =
2884 : " }\n"
2885 : " }\n"
2886 : " this.getInnerFunc ="
2887 : " function() {return new Inner().innerFunc;}\n"
2888 : " }\n"
2889 : " this.getOuterFunc ="
2890 : " function() {return new Outer().getInnerFunc();}"
2891 : "}\n"
2892 : "var f = new OuterMost().getOuterFunc();\n"
2893 : "f();\n";
2894 :
2895 : // Tests for let / constant.
2896 : ExpectedSnippet<0> const_decl[] = {
2897 : {"return outerConst;", {handle(Smi::FromInt(10), isolate)}},
2898 : {"return outerLet;", {handle(Smi::FromInt(20), isolate)}},
2899 : {"outerLet = 30; return outerLet;", {handle(Smi::FromInt(30), isolate)}},
2900 : {"var outerLet = 40; return outerLet;",
2901 : {handle(Smi::FromInt(40), isolate)}},
2902 : {"var outerConst = 50; return outerConst;",
2903 : {handle(Smi::FromInt(50), isolate)}},
2904 : {"try { outerConst = 30 } catch(e) { return -1; }",
2905 36 : {handle(Smi::FromInt(-1), isolate)}}};
2906 :
2907 42 : for (size_t i = 0; i < arraysize(const_decl); i++) {
2908 : ScopedVector<char> script(1024);
2909 : SNPrintF(script, "%s %s %s", prologue, const_decl[i].code_snippet,
2910 36 : epilogue);
2911 :
2912 : BytecodeGraphTester tester(isolate, script.start(), "*");
2913 : auto callable = tester.GetCallable<>();
2914 72 : Handle<Object> return_value = callable().ToHandleChecked();
2915 72 : CHECK(return_value->SameValue(*const_decl[i].return_value()));
2916 6 : }
2917 6 : }
2918 :
2919 23724 : TEST(BytecodeGraphBuilderIllegalConstDeclaration) {
2920 6 : HandleAndZoneScope scope;
2921 6 : Isolate* isolate = scope.main_isolate();
2922 :
2923 : ExpectedSnippet<0, const char*> illegal_const_decl[] = {
2924 : {"const x = x = 10 + 3; return x;",
2925 : {"Uncaught ReferenceError: x is not defined"}},
2926 : {"const x = 10; x = 20; return x;",
2927 : {"Uncaught TypeError: Assignment to constant variable."}},
2928 : {"const x = 10; { x = 20; } return x;",
2929 : {"Uncaught TypeError: Assignment to constant variable."}},
2930 : {"const x = 10; eval('x = 20;'); return x;",
2931 : {"Uncaught TypeError: Assignment to constant variable."}},
2932 : {"let x = x + 10; return x;",
2933 : {"Uncaught ReferenceError: x is not defined"}},
2934 : {"'use strict'; (function f1() { f1 = 123; })() ",
2935 : {"Uncaught TypeError: Assignment to constant variable."}},
2936 6 : };
2937 :
2938 : // Tests for sloppy mode.
2939 42 : for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
2940 : ScopedVector<char> script(1024);
2941 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2942 36 : illegal_const_decl[i].code_snippet, kFunctionName);
2943 :
2944 : BytecodeGraphTester tester(isolate, script.start());
2945 72 : v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
2946 : v8::Local<v8::String> expected_string =
2947 36 : v8_str(illegal_const_decl[i].return_value());
2948 108 : CHECK(
2949 : message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
2950 : .FromJust());
2951 : }
2952 :
2953 : // Tests for strict mode.
2954 36 : for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
2955 : ScopedVector<char> script(1024);
2956 : SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
2957 36 : illegal_const_decl[i].code_snippet, kFunctionName);
2958 :
2959 : BytecodeGraphTester tester(isolate, script.start());
2960 72 : v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
2961 : v8::Local<v8::String> expected_string =
2962 36 : v8_str(illegal_const_decl[i].return_value());
2963 108 : CHECK(
2964 : message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
2965 : .FromJust());
2966 6 : }
2967 6 : }
2968 :
2969 0 : class CountBreakDebugDelegate : public v8::debug::DebugDelegate {
2970 : public:
2971 12 : void BreakProgramRequested(v8::Local<v8::Context> paused_context,
2972 : v8::Local<v8::Object> exec_state,
2973 : v8::Local<v8::Value> break_points_hit,
2974 : const std::vector<int>&) override {
2975 12 : debug_break_count++;
2976 12 : }
2977 : int debug_break_count = 0;
2978 : };
2979 :
2980 23724 : TEST(BytecodeGraphBuilderDebuggerStatement) {
2981 6 : CountBreakDebugDelegate delegate;
2982 12 : HandleAndZoneScope scope;
2983 6 : Isolate* isolate = scope.main_isolate();
2984 :
2985 6 : v8::debug::SetDebugDelegate(CcTest::isolate(), &delegate);
2986 :
2987 : ExpectedSnippet<0> snippet = {
2988 : "function f() {"
2989 : " debugger;"
2990 : "}"
2991 : "f();",
2992 : {isolate->factory()->undefined_value()}};
2993 :
2994 : BytecodeGraphTester tester(isolate, snippet.code_snippet);
2995 : auto callable = tester.GetCallable<>();
2996 12 : Handle<Object> return_value = callable().ToHandleChecked();
2997 :
2998 6 : v8::debug::SetDebugDelegate(CcTest::isolate(), nullptr);
2999 6 : CHECK(return_value.is_identical_to(snippet.return_value()));
3000 6 : CHECK_EQ(2, delegate.debug_break_count);
3001 6 : }
3002 :
3003 : #undef SHARD_TEST_BY_2
3004 : #undef SHARD_TEST_BY_4
3005 : #undef SPACE
3006 : #undef REPEAT_2
3007 : #undef REPEAT_4
3008 : #undef REPEAT_8
3009 : #undef REPEAT_16
3010 : #undef REPEAT_32
3011 : #undef REPEAT_64
3012 : #undef REPEAT_128
3013 : #undef REPEAT_256
3014 : #undef REPEAT_127
3015 :
3016 : } // namespace compiler
3017 : } // namespace internal
3018 71154 : } // namespace v8
|