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-inl.h"
8 : #include "src/compiler/pipeline.h"
9 : #include "src/debug/debug-interface.h"
10 : #include "src/execution.h"
11 : #include "src/handles.h"
12 : #include "src/interpreter/bytecode-array-builder.h"
13 : #include "src/interpreter/interpreter.h"
14 : #include "src/objects-inl.h"
15 : #include "src/optimized-compilation-info.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 1036 : isolate->factory()->undefined_value(), 0, nullptr);
46 : }
47 :
48 : template <class... A>
49 52 : static MaybeHandle<Object> CallFunction(Isolate* isolate,
50 : Handle<JSFunction> function,
51 : A... args) {
52 2068 : Handle<Object> argv[] = {args...};
53 2068 : return Execution::Call(isolate, function,
54 : isolate->factory()->undefined_value(), sizeof...(args),
55 2120 : argv);
56 : }
57 :
58 : template <class... A>
59 : class BytecodeGraphCallable {
60 : public:
61 : BytecodeGraphCallable(Isolate* isolate, Handle<JSFunction> function)
62 1816 : : isolate_(isolate), function_(function) {}
63 1816 : virtual ~BytecodeGraphCallable() = default;
64 :
65 3052 : MaybeHandle<Object> operator()(A... args) {
66 6156 : 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 1816 : : isolate_(isolate), script_(script) {
79 1816 : i::FLAG_always_opt = false;
80 1816 : i::FLAG_allow_natives_syntax = true;
81 : }
82 1816 : virtual ~BytecodeGraphTester() = default;
83 :
84 : template <class... A>
85 : BytecodeGraphCallable<A...> GetCallable(
86 : const char* functionName = kFunctionName) {
87 1816 : return BytecodeGraphCallable<A...>(isolate_, GetFunction(functionName));
88 : }
89 :
90 76 : Local<Message> CheckThrowsReturnMessage() {
91 152 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
92 : auto callable = GetCallable<>();
93 76 : MaybeHandle<Object> no_result = callable();
94 152 : CHECK(isolate_->has_pending_exception());
95 76 : CHECK(try_catch.HasCaught());
96 76 : CHECK(no_result.is_null());
97 76 : isolate_->OptionalRescheduleException(true);
98 152 : CHECK(!try_catch.Message().IsEmpty());
99 152 : return try_catch.Message();
100 : }
101 :
102 292 : static Handle<Object> NewObject(const char* script) {
103 292 : return v8::Utils::OpenHandle(*CompileRun(script));
104 : }
105 :
106 : private:
107 : Isolate* isolate_;
108 : const char* script_;
109 :
110 1816 : Handle<JSFunction> GetFunction(const char* functionName) {
111 1816 : CompileRun(script_);
112 : Local<Function> api_function = Local<Function>::Cast(
113 3632 : CcTest::global()
114 7264 : ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(functionName))
115 : .ToLocalChecked());
116 : Handle<JSFunction> function =
117 : Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
118 1816 : CHECK(function->shared()->HasBytecodeArray());
119 :
120 3632 : Zone zone(isolate_->allocator(), ZONE_NAME);
121 1816 : Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
122 : OptimizedCompilationInfo compilation_info(&zone, isolate_, shared,
123 3632 : function);
124 :
125 : // Compiler relies on canonicalized handles, let's create
126 : // a canonicalized scope and migrate existing handles there.
127 3632 : CanonicalHandleScope canonical(isolate_);
128 1816 : compilation_info.ReopenHandlesInNewHandleScope(isolate_);
129 :
130 : Handle<Code> code =
131 3632 : Pipeline::GenerateCodeForTesting(&compilation_info, isolate_)
132 : .ToHandleChecked();
133 1816 : function->set_code(*code);
134 :
135 3632 : return function;
136 : }
137 :
138 : DISALLOW_COPY_AND_ASSIGN(BytecodeGraphTester);
139 : };
140 :
141 : #define SPACE()
142 :
143 : #define REPEAT_2(SEP, ...) __VA_ARGS__ SEP() __VA_ARGS__
144 : #define REPEAT_4(SEP, ...) \
145 : REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__)
146 : #define REPEAT_8(SEP, ...) \
147 : REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_4(SEP, __VA_ARGS__)
148 : #define REPEAT_16(SEP, ...) \
149 : REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__)
150 : #define REPEAT_32(SEP, ...) \
151 : REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__)
152 : #define REPEAT_64(SEP, ...) \
153 : REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__)
154 : #define REPEAT_128(SEP, ...) \
155 : REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__)
156 : #define REPEAT_256(SEP, ...) \
157 : REPEAT_128(SEP, __VA_ARGS__) SEP() REPEAT_128(SEP, __VA_ARGS__)
158 :
159 : #define REPEAT_127(SEP, ...) \
160 : REPEAT_64(SEP, __VA_ARGS__) \
161 : SEP() \
162 : REPEAT_32(SEP, __VA_ARGS__) \
163 : SEP() \
164 : REPEAT_16(SEP, __VA_ARGS__) \
165 : SEP() \
166 : REPEAT_8(SEP, __VA_ARGS__) \
167 : SEP() \
168 : REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() __VA_ARGS__
169 :
170 : template <int N, typename T = Handle<Object>>
171 : struct ExpectedSnippet {
172 : const char* code_snippet;
173 : T return_value_and_parameters[N + 1];
174 :
175 : inline T return_value() const { return return_value_and_parameters[0]; }
176 :
177 892 : inline T parameter(int i) const {
178 892 : CHECK_GE(i, 0);
179 892 : CHECK_LT(i, N);
180 892 : return return_value_and_parameters[1 + i];
181 : }
182 : };
183 :
184 26660 : TEST(BytecodeGraphBuilderReturnStatements) {
185 8 : HandleAndZoneScope scope;
186 : Isolate* isolate = scope.main_isolate();
187 : Factory* factory = isolate->factory();
188 :
189 : ExpectedSnippet<0> snippets[] = {
190 : {"return;", {factory->undefined_value()}},
191 : {"return null;", {factory->null_value()}},
192 : {"return true;", {factory->true_value()}},
193 : {"return false;", {factory->false_value()}},
194 : {"return 0;", {factory->NewNumberFromInt(0)}},
195 : {"return +1;", {factory->NewNumberFromInt(1)}},
196 : {"return -1;", {factory->NewNumberFromInt(-1)}},
197 : {"return +127;", {factory->NewNumberFromInt(127)}},
198 : {"return -128;", {factory->NewNumberFromInt(-128)}},
199 : {"return 0.001;", {factory->NewNumber(0.001)}},
200 : {"return 3.7e-60;", {factory->NewNumber(3.7e-60)}},
201 : {"return -3.7e60;", {factory->NewNumber(-3.7e60)}},
202 : {"return '';", {factory->NewStringFromStaticChars("")}},
203 : {"return 'catfood';", {factory->NewStringFromStaticChars("catfood")}},
204 28 : {"return NaN;", {factory->nan_value()}}};
205 :
206 124 : for (size_t i = 0; i < arraysize(snippets); i++) {
207 : ScopedVector<char> script(1024);
208 60 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
209 60 : snippets[i].code_snippet, kFunctionName);
210 :
211 : BytecodeGraphTester tester(isolate, script.start());
212 : auto callable = tester.GetCallable<>();
213 120 : Handle<Object> return_value = callable().ToHandleChecked();
214 120 : CHECK(return_value->SameValue(*snippets[i].return_value()));
215 : }
216 4 : }
217 :
218 26660 : TEST(BytecodeGraphBuilderPrimitiveExpressions) {
219 8 : HandleAndZoneScope scope;
220 : Isolate* isolate = scope.main_isolate();
221 : Factory* factory = isolate->factory();
222 :
223 : ExpectedSnippet<0> snippets[] = {
224 : {"return 1 + 1;", {factory->NewNumberFromInt(2)}},
225 : {"return 20 - 30;", {factory->NewNumberFromInt(-10)}},
226 : {"return 4 * 100;", {factory->NewNumberFromInt(400)}},
227 : {"return 100 / 5;", {factory->NewNumberFromInt(20)}},
228 : {"return 25 % 7;", {factory->NewNumberFromInt(4)}},
229 4 : };
230 :
231 44 : for (size_t i = 0; i < arraysize(snippets); i++) {
232 : ScopedVector<char> script(1024);
233 20 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
234 20 : snippets[i].code_snippet, kFunctionName);
235 :
236 : BytecodeGraphTester tester(isolate, script.start());
237 : auto callable = tester.GetCallable<>();
238 40 : Handle<Object> return_value = callable().ToHandleChecked();
239 40 : CHECK(return_value->SameValue(*snippets[i].return_value()));
240 : }
241 4 : }
242 :
243 26660 : TEST(BytecodeGraphBuilderTwoParameterTests) {
244 8 : HandleAndZoneScope scope;
245 : Isolate* isolate = scope.main_isolate();
246 : Factory* factory = isolate->factory();
247 :
248 : ExpectedSnippet<2> snippets[] = {
249 : // Integers
250 : {"return p1 + p2;",
251 : {factory->NewNumberFromInt(-70), factory->NewNumberFromInt(3),
252 : factory->NewNumberFromInt(-73)}},
253 : {"return p1 + p2 + 3;",
254 : {factory->NewNumberFromInt(1139044), factory->NewNumberFromInt(300),
255 : factory->NewNumberFromInt(1138741)}},
256 : {"return p1 - p2;",
257 : {factory->NewNumberFromInt(1100), factory->NewNumberFromInt(1000),
258 : factory->NewNumberFromInt(-100)}},
259 : {"return p1 * p2;",
260 : {factory->NewNumberFromInt(-100000), factory->NewNumberFromInt(1000),
261 : factory->NewNumberFromInt(-100)}},
262 : {"return p1 / p2;",
263 : {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(1000),
264 : factory->NewNumberFromInt(-100)}},
265 : {"return p1 % p2;",
266 : {factory->NewNumberFromInt(5), factory->NewNumberFromInt(373),
267 : factory->NewNumberFromInt(16)}},
268 : // Doubles
269 : {"return p1 + p2;",
270 : {factory->NewHeapNumber(9.999), factory->NewHeapNumber(3.333),
271 : factory->NewHeapNumber(6.666)}},
272 : {"return p1 - p2;",
273 : {factory->NewHeapNumber(-3.333), factory->NewHeapNumber(3.333),
274 : factory->NewHeapNumber(6.666)}},
275 : {"return p1 * p2;",
276 : {factory->NewHeapNumber(3.333 * 6.666), factory->NewHeapNumber(3.333),
277 : factory->NewHeapNumber(6.666)}},
278 : {"return p1 / p2;",
279 : {factory->NewHeapNumber(2.25), factory->NewHeapNumber(9),
280 : factory->NewHeapNumber(4)}},
281 : // Strings
282 : {"return p1 + p2;",
283 : {factory->NewStringFromStaticChars("abcdef"),
284 : factory->NewStringFromStaticChars("abc"),
285 60 : factory->NewStringFromStaticChars("def")}}};
286 :
287 92 : for (size_t i = 0; i < arraysize(snippets); i++) {
288 : ScopedVector<char> script(1024);
289 44 : SNPrintF(script, "function %s(p1, p2) { %s }\n%s(0, 0);", kFunctionName,
290 44 : snippets[i].code_snippet, kFunctionName);
291 :
292 : BytecodeGraphTester tester(isolate, script.start());
293 : auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
294 : Handle<Object> return_value =
295 88 : callable(snippets[i].parameter(0), snippets[i].parameter(1))
296 : .ToHandleChecked();
297 44 : CHECK(return_value->SameValue(*snippets[i].return_value()));
298 : }
299 4 : }
300 :
301 :
302 26660 : TEST(BytecodeGraphBuilderNamedLoad) {
303 8 : HandleAndZoneScope scope;
304 : Isolate* isolate = scope.main_isolate();
305 : Factory* factory = isolate->factory();
306 :
307 : ExpectedSnippet<1> snippets[] = {
308 : {"return p1.val;",
309 : {factory->NewNumberFromInt(10),
310 : BytecodeGraphTester::NewObject("({val : 10})")}},
311 : {"return p1[\"name\"];",
312 : {factory->NewStringFromStaticChars("abc"),
313 : BytecodeGraphTester::NewObject("({name : 'abc'})")}},
314 : {"'use strict'; return p1.val;",
315 : {factory->NewNumberFromInt(10),
316 : BytecodeGraphTester::NewObject("({val : 10 })")}},
317 : {"'use strict'; return p1[\"val\"];",
318 : {factory->NewNumberFromInt(10),
319 : BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
320 : {"var b;\n" REPEAT_127(SPACE, " b = p1.name; ") " return p1.name;\n",
321 : {factory->NewStringFromStaticChars("abc"),
322 : BytecodeGraphTester::NewObject("({name : 'abc'})")}},
323 : {"'use strict'; var b;\n"
324 : REPEAT_127(SPACE, " b = p1.name; ")
325 : "return p1.name;\n",
326 : {factory->NewStringFromStaticChars("abc"),
327 : BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
328 16 : };
329 :
330 52 : for (size_t i = 0; i < arraysize(snippets); i++) {
331 : ScopedVector<char> script(2048);
332 24 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
333 24 : snippets[i].code_snippet, kFunctionName);
334 :
335 : BytecodeGraphTester tester(isolate, script.start());
336 : auto callable = tester.GetCallable<Handle<Object>>();
337 : Handle<Object> return_value =
338 48 : callable(snippets[i].parameter(0)).ToHandleChecked();
339 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
340 : }
341 4 : }
342 :
343 26660 : TEST(BytecodeGraphBuilderKeyedLoad) {
344 8 : HandleAndZoneScope scope;
345 : Isolate* isolate = scope.main_isolate();
346 : Factory* factory = isolate->factory();
347 :
348 : ExpectedSnippet<2> snippets[] = {
349 : {"return p1[p2];",
350 : {factory->NewNumberFromInt(10),
351 : BytecodeGraphTester::NewObject("({val : 10})"),
352 : factory->NewStringFromStaticChars("val")}},
353 : {"return p1[100];",
354 : {factory->NewStringFromStaticChars("abc"),
355 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
356 : factory->NewNumberFromInt(0)}},
357 : {"var b = 100; return p1[b];",
358 : {factory->NewStringFromStaticChars("abc"),
359 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
360 : factory->NewNumberFromInt(0)}},
361 : {"'use strict'; return p1[p2];",
362 : {factory->NewNumberFromInt(10),
363 : BytecodeGraphTester::NewObject("({val : 10 })"),
364 : factory->NewStringFromStaticChars("val")}},
365 : {"'use strict'; return p1[100];",
366 : {factory->NewNumberFromInt(10),
367 : BytecodeGraphTester::NewObject("({100 : 10})"),
368 : factory->NewNumberFromInt(0)}},
369 : {"'use strict'; var b = p2; return p1[b];",
370 : {factory->NewStringFromStaticChars("abc"),
371 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
372 : factory->NewNumberFromInt(100)}},
373 : {"var b;\n" REPEAT_127(SPACE, " b = p1[p2]; ") " return p1[p2];\n",
374 : {factory->NewStringFromStaticChars("abc"),
375 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
376 : factory->NewNumberFromInt(100)}},
377 : {"'use strict'; var b;\n" REPEAT_127(SPACE,
378 : " b = p1[p2]; ") "return p1[p2];\n",
379 : {factory->NewStringFromStaticChars("abc"),
380 : BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
381 : factory->NewNumberFromInt(100)}},
382 32 : };
383 :
384 68 : for (size_t i = 0; i < arraysize(snippets); i++) {
385 : ScopedVector<char> script(2048);
386 32 : SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0);", kFunctionName,
387 32 : snippets[i].code_snippet, kFunctionName);
388 :
389 : BytecodeGraphTester tester(isolate, script.start());
390 : auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
391 : Handle<Object> return_value =
392 64 : callable(snippets[i].parameter(0), snippets[i].parameter(1))
393 : .ToHandleChecked();
394 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
395 : }
396 4 : }
397 :
398 8 : void TestBytecodeGraphBuilderNamedStore(size_t shard) {
399 16 : HandleAndZoneScope scope;
400 : Isolate* isolate = scope.main_isolate();
401 : Factory* factory = isolate->factory();
402 :
403 : ExpectedSnippet<1> snippets[] = {
404 : {"return p1.val = 20;",
405 : {factory->NewNumberFromInt(20),
406 : BytecodeGraphTester::NewObject("({val : 10})")}},
407 : {"p1.type = 'int'; return p1.type;",
408 : {factory->NewStringFromStaticChars("int"),
409 : BytecodeGraphTester::NewObject("({val : 10})")}},
410 : {"p1.name = 'def'; return p1[\"name\"];",
411 : {factory->NewStringFromStaticChars("def"),
412 : BytecodeGraphTester::NewObject("({name : 'abc'})")}},
413 : {"'use strict'; p1.val = 20; return p1.val;",
414 : {factory->NewNumberFromInt(20),
415 : BytecodeGraphTester::NewObject("({val : 10 })")}},
416 : {"'use strict'; return p1.type = 'int';",
417 : {factory->NewStringFromStaticChars("int"),
418 : BytecodeGraphTester::NewObject("({val : 10})")}},
419 : {"'use strict'; p1.val = 20; return p1[\"val\"];",
420 : {factory->NewNumberFromInt(20),
421 : BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
422 : {"var b = 'abc';\n" REPEAT_127(
423 : SPACE, " p1.name = b; ") " p1.name = 'def'; return p1.name;\n",
424 : {factory->NewStringFromStaticChars("def"),
425 : BytecodeGraphTester::NewObject("({name : 'abc'})")}},
426 : {"'use strict'; var b = 'def';\n" REPEAT_127(
427 : SPACE, " p1.name = 'abc'; ") "p1.name = b; return p1.name;\n",
428 : {factory->NewStringFromStaticChars("def"),
429 : BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
430 48 : };
431 :
432 136 : for (size_t i = 0; i < arraysize(snippets); i++) {
433 96 : if ((i % 2) != shard) continue;
434 : ScopedVector<char> script(3072);
435 32 : SNPrintF(script, "function %s(p1) { %s };\n%s({});", kFunctionName,
436 32 : snippets[i].code_snippet, kFunctionName);
437 :
438 : BytecodeGraphTester tester(isolate, script.start());
439 : auto callable = tester.GetCallable<Handle<Object>>();
440 : Handle<Object> return_value =
441 64 : callable(snippets[i].parameter(0)).ToHandleChecked();
442 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
443 : }
444 8 : }
445 :
446 26664 : SHARD_TEST_BY_2(BytecodeGraphBuilderNamedStore)
447 :
448 8 : void TestBytecodeGraphBuilderKeyedStore(size_t shard) {
449 16 : HandleAndZoneScope scope;
450 : Isolate* isolate = scope.main_isolate();
451 : Factory* factory = isolate->factory();
452 :
453 : ExpectedSnippet<2> snippets[] = {
454 : {"p1[p2] = 20; return p1[p2];",
455 : {factory->NewNumberFromInt(20),
456 : BytecodeGraphTester::NewObject("({val : 10})"),
457 : factory->NewStringFromStaticChars("val")}},
458 : {"return p1[100] = 'def';",
459 : {factory->NewStringFromStaticChars("def"),
460 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
461 : factory->NewNumberFromInt(0)}},
462 : {"var b = 100; p1[b] = 'def'; return p1[b];",
463 : {factory->NewStringFromStaticChars("def"),
464 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
465 : factory->NewNumberFromInt(0)}},
466 : {"'use strict'; p1[p2] = 20; return p1[p2];",
467 : {factory->NewNumberFromInt(20),
468 : BytecodeGraphTester::NewObject("({val : 10 })"),
469 : factory->NewStringFromStaticChars("val")}},
470 : {"'use strict'; return p1[100] = 20;",
471 : {factory->NewNumberFromInt(20),
472 : BytecodeGraphTester::NewObject("({100 : 10})"),
473 : factory->NewNumberFromInt(0)}},
474 : {"'use strict'; var b = p2; p1[b] = 'def'; return p1[b];",
475 : {factory->NewStringFromStaticChars("def"),
476 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
477 : factory->NewNumberFromInt(100)}},
478 : {"var b;\n" REPEAT_127(
479 : SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
480 : {factory->NewStringFromStaticChars("def"),
481 : BytecodeGraphTester::NewObject("({100 : 'abc'})"),
482 : factory->NewNumberFromInt(100)}},
483 : {"'use strict'; var b;\n" REPEAT_127(
484 : SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
485 : {factory->NewStringFromStaticChars("def"),
486 : BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
487 : factory->NewNumberFromInt(100)}},
488 64 : };
489 :
490 136 : for (size_t i = 0; i < arraysize(snippets); i++) {
491 96 : if ((i % 2) != shard) continue;
492 : ScopedVector<char> script(2048);
493 32 : SNPrintF(script, "function %s(p1, p2) { %s };\n%s({});", kFunctionName,
494 32 : snippets[i].code_snippet, kFunctionName);
495 :
496 : BytecodeGraphTester tester(isolate, script.start());
497 : auto callable = tester.GetCallable<Handle<Object>>();
498 : Handle<Object> return_value =
499 64 : callable(snippets[i].parameter(0)).ToHandleChecked();
500 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
501 : }
502 8 : }
503 :
504 26664 : SHARD_TEST_BY_2(BytecodeGraphBuilderKeyedStore)
505 :
506 26660 : TEST(BytecodeGraphBuilderPropertyCall) {
507 8 : HandleAndZoneScope scope;
508 : Isolate* isolate = scope.main_isolate();
509 : Factory* factory = isolate->factory();
510 :
511 : ExpectedSnippet<1> snippets[] = {
512 : {"return p1.func();",
513 : {factory->NewNumberFromInt(25),
514 : BytecodeGraphTester::NewObject("({func() { return 25; }})")}},
515 : {"return p1.func('abc');",
516 : {factory->NewStringFromStaticChars("abc"),
517 : BytecodeGraphTester::NewObject("({func(a) { return a; }})")}},
518 : {"return p1.func(1, 2, 3, 4, 5, 6, 7, 8);",
519 : {factory->NewNumberFromInt(36),
520 : BytecodeGraphTester::NewObject(
521 : "({func(a, b, c, d, e, f, g, h) {\n"
522 : " return a + b + c + d + e + f + g + h;}})")}},
523 8 : };
524 :
525 28 : for (size_t i = 0; i < arraysize(snippets); i++) {
526 : ScopedVector<char> script(2048);
527 12 : SNPrintF(script, "function %s(p1) { %s };\n%s({func() {}});", kFunctionName,
528 12 : snippets[i].code_snippet, kFunctionName);
529 :
530 : BytecodeGraphTester tester(isolate, script.start());
531 : auto callable = tester.GetCallable<Handle<Object>>();
532 : Handle<Object> return_value =
533 24 : callable(snippets[i].parameter(0)).ToHandleChecked();
534 12 : CHECK(return_value->SameValue(*snippets[i].return_value()));
535 : }
536 4 : }
537 :
538 26660 : TEST(BytecodeGraphBuilderCallNew) {
539 8 : HandleAndZoneScope scope;
540 : Isolate* isolate = scope.main_isolate();
541 : Factory* factory = isolate->factory();
542 :
543 : ExpectedSnippet<0> snippets[] = {
544 : {"function counter() { this.count = 20; }\n"
545 : "function f() {\n"
546 : " var c = new counter();\n"
547 : " return c.count;\n"
548 : "}; f()",
549 : {factory->NewNumberFromInt(20)}},
550 : {"function counter(arg0) { this.count = 17; this.x = arg0; }\n"
551 : "function f() {\n"
552 : " var c = new counter(6);\n"
553 : " return c.count + c.x;\n"
554 : "}; f()",
555 : {factory->NewNumberFromInt(23)}},
556 : {"function counter(arg0, arg1) {\n"
557 : " this.count = 17; this.x = arg0; this.y = arg1;\n"
558 : "}\n"
559 : "function f() {\n"
560 : " var c = new counter(3, 5);\n"
561 : " return c.count + c.x + c.y;\n"
562 : "}; f()",
563 : {factory->NewNumberFromInt(25)}},
564 4 : };
565 :
566 28 : for (size_t i = 0; i < arraysize(snippets); i++) {
567 12 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
568 : auto callable = tester.GetCallable<>();
569 24 : Handle<Object> return_value = callable().ToHandleChecked();
570 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
571 : }
572 4 : }
573 :
574 26660 : TEST(BytecodeGraphBuilderCreateClosure) {
575 8 : HandleAndZoneScope scope;
576 : Isolate* isolate = scope.main_isolate();
577 : Factory* factory = isolate->factory();
578 :
579 : ExpectedSnippet<0> snippets[] = {
580 : {"function f() {\n"
581 : " function counter() { this.count = 20; }\n"
582 : " var c = new counter();\n"
583 : " return c.count;\n"
584 : "}; f()",
585 : {factory->NewNumberFromInt(20)}},
586 : {"function f() {\n"
587 : " function counter(arg0) { this.count = 17; this.x = arg0; }\n"
588 : " var c = new counter(6);\n"
589 : " return c.count + c.x;\n"
590 : "}; f()",
591 : {factory->NewNumberFromInt(23)}},
592 : {"function f() {\n"
593 : " function counter(arg0, arg1) {\n"
594 : " this.count = 17; this.x = arg0; this.y = arg1;\n"
595 : " }\n"
596 : " var c = new counter(3, 5);\n"
597 : " return c.count + c.x + c.y;\n"
598 : "}; f()",
599 : {factory->NewNumberFromInt(25)}},
600 4 : };
601 :
602 28 : for (size_t i = 0; i < arraysize(snippets); i++) {
603 12 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
604 : auto callable = tester.GetCallable<>();
605 24 : Handle<Object> return_value = callable().ToHandleChecked();
606 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
607 : }
608 4 : }
609 :
610 26660 : TEST(BytecodeGraphBuilderCallRuntime) {
611 8 : HandleAndZoneScope scope;
612 : Isolate* isolate = scope.main_isolate();
613 : Factory* factory = isolate->factory();
614 :
615 : ExpectedSnippet<1> snippets[] = {
616 : {"function f(arg0) { return %MaxSmi(); }\nf()",
617 : {factory->NewNumberFromInt(Smi::kMaxValue), factory->undefined_value()}},
618 : {"function f(arg0) { return %IsArray(arg0) }\nf(undefined)",
619 : {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
620 : {"function f(arg0) { return %Add(arg0, 2) }\nf(1)",
621 : {factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}},
622 12 : };
623 :
624 28 : for (size_t i = 0; i < arraysize(snippets); i++) {
625 12 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
626 : auto callable = tester.GetCallable<Handle<Object>>();
627 : Handle<Object> return_value =
628 24 : callable(snippets[i].parameter(0)).ToHandleChecked();
629 12 : CHECK(return_value->SameValue(*snippets[i].return_value()));
630 : }
631 4 : }
632 :
633 26660 : TEST(BytecodeGraphBuilderInvokeIntrinsic) {
634 8 : HandleAndZoneScope scope;
635 : Isolate* isolate = scope.main_isolate();
636 : Factory* factory = isolate->factory();
637 :
638 : ExpectedSnippet<1> snippets[] = {
639 : {"function f(arg0) { return %_IsJSReceiver(arg0); }\nf()",
640 : {factory->false_value(), factory->NewNumberFromInt(1)}},
641 : {"function f(arg0) { return %_IsArray(arg0) }\nf(undefined)",
642 : {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
643 12 : };
644 :
645 20 : for (size_t i = 0; i < arraysize(snippets); i++) {
646 8 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
647 : auto callable = tester.GetCallable<Handle<Object>>();
648 : Handle<Object> return_value =
649 16 : callable(snippets[i].parameter(0)).ToHandleChecked();
650 8 : CHECK(return_value->SameValue(*snippets[i].return_value()));
651 : }
652 4 : }
653 :
654 8 : void TestBytecodeGraphBuilderGlobals(size_t shard) {
655 16 : HandleAndZoneScope scope;
656 : Isolate* isolate = scope.main_isolate();
657 : Factory* factory = isolate->factory();
658 :
659 : ExpectedSnippet<0> snippets[] = {
660 : {"var global = 321;\n function f() { return global; };\n f();",
661 : {factory->NewNumberFromInt(321)}},
662 : {"var global = 321;\n"
663 : "function f() { global = 123; return global };\n f();",
664 : {factory->NewNumberFromInt(123)}},
665 : {"var global = function() { return 'abc'};\n"
666 : "function f() { return global(); };\n f();",
667 : {factory->NewStringFromStaticChars("abc")}},
668 : {"var global = 456;\n"
669 : "function f() { 'use strict'; return global; };\n f();",
670 : {factory->NewNumberFromInt(456)}},
671 : {"var global = 987;\n"
672 : "function f() { 'use strict'; global = 789; return global };\n f();",
673 : {factory->NewNumberFromInt(789)}},
674 : {"var global = function() { return 'xyz'};\n"
675 : "function f() { 'use strict'; return global(); };\n f();",
676 : {factory->NewStringFromStaticChars("xyz")}},
677 : {"var global = 'abc'; var global_obj = {val:123};\n"
678 : "function f() {\n" REPEAT_127(
679 : SPACE, " var b = global_obj.name;\n") "return global; };\n f();\n",
680 : {factory->NewStringFromStaticChars("abc")}},
681 : {"var global = 'abc'; var global_obj = {val:123};\n"
682 : "function f() { 'use strict';\n" REPEAT_127(
683 : SPACE, " var b = global_obj.name;\n") "global = 'xyz'; return "
684 : "global };\n f();\n",
685 : {factory->NewStringFromStaticChars("xyz")}},
686 : {"function f() { return typeof(undeclared_var); }\n; f();\n",
687 : {factory->NewStringFromStaticChars("undefined")}},
688 : {"var defined_var = 10; function f() { return typeof(defined_var); }\n; "
689 : "f();\n",
690 : {factory->NewStringFromStaticChars("number")}},
691 48 : };
692 :
693 168 : for (size_t i = 0; i < arraysize(snippets); i++) {
694 120 : if ((i % 2) != shard) continue;
695 40 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
696 : auto callable = tester.GetCallable<>();
697 80 : Handle<Object> return_value = callable().ToHandleChecked();
698 80 : CHECK(return_value->SameValue(*snippets[i].return_value()));
699 : }
700 8 : }
701 :
702 26664 : SHARD_TEST_BY_2(BytecodeGraphBuilderGlobals)
703 :
704 26660 : TEST(BytecodeGraphBuilderToObject) {
705 : // TODO(mythria): tests for ToObject. Needs ForIn.
706 4 : }
707 :
708 26660 : TEST(BytecodeGraphBuilderToName) {
709 8 : HandleAndZoneScope scope;
710 : Isolate* isolate = scope.main_isolate();
711 : Factory* factory = isolate->factory();
712 :
713 : ExpectedSnippet<0> snippets[] = {
714 : {"var a = 'val'; var obj = {[a] : 10}; return obj.val;",
715 : {factory->NewNumberFromInt(10)}},
716 : {"var a = 20; var obj = {[a] : 10}; return obj['20'];",
717 : {factory->NewNumberFromInt(10)}},
718 : {"var a = 20; var obj = {[a] : 10}; return obj[20];",
719 : {factory->NewNumberFromInt(10)}},
720 : {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];",
721 : {factory->NewNumberFromInt(10)}},
722 : {"var a = {val:23}; var obj = {[a] : 10}; return obj['[object Object]'];",
723 : {factory->NewNumberFromInt(10)}},
724 : {"var a = {toString : function() { return 'x'}};\n"
725 : "var obj = {[a] : 10};\n"
726 : "return obj.x;",
727 : {factory->NewNumberFromInt(10)}},
728 : {"var a = {valueOf : function() { return 'x'}};\n"
729 : "var obj = {[a] : 10};\n"
730 : "return obj.x;",
731 : {factory->undefined_value()}},
732 : {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n"
733 : "var obj = {[a] : 10};\n"
734 : "return obj.x;",
735 : {factory->NewNumberFromInt(10)}},
736 8 : };
737 :
738 68 : for (size_t i = 0; i < arraysize(snippets); i++) {
739 : ScopedVector<char> script(1024);
740 32 : SNPrintF(script, "function %s() { %s }\n%s({});", kFunctionName,
741 32 : snippets[i].code_snippet, kFunctionName);
742 :
743 : BytecodeGraphTester tester(isolate, script.start());
744 : auto callable = tester.GetCallable<>();
745 64 : Handle<Object> return_value = callable().ToHandleChecked();
746 64 : CHECK(return_value->SameValue(*snippets[i].return_value()));
747 : }
748 4 : }
749 :
750 26660 : TEST(BytecodeGraphBuilderLogicalNot) {
751 8 : HandleAndZoneScope scope;
752 : Isolate* isolate = scope.main_isolate();
753 : Factory* factory = isolate->factory();
754 :
755 : ExpectedSnippet<1> snippets[] = {
756 : {"return !p1;",
757 : {factory->false_value(),
758 : BytecodeGraphTester::NewObject("({val : 10})")}},
759 : {"return !p1;", {factory->true_value(), factory->NewNumberFromInt(0)}},
760 : {"return !p1;", {factory->true_value(), factory->undefined_value()}},
761 : {"return !p1;", {factory->false_value(), factory->NewNumberFromInt(10)}},
762 : {"return !p1;", {factory->false_value(), factory->true_value()}},
763 : {"return !p1;",
764 : {factory->false_value(), factory->NewStringFromStaticChars("abc")}},
765 28 : };
766 :
767 52 : for (size_t i = 0; i < arraysize(snippets); i++) {
768 : ScopedVector<char> script(1024);
769 24 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
770 24 : snippets[i].code_snippet, kFunctionName);
771 :
772 : BytecodeGraphTester tester(isolate, script.start());
773 : auto callable = tester.GetCallable<Handle<Object>>();
774 : Handle<Object> return_value =
775 48 : callable(snippets[i].parameter(0)).ToHandleChecked();
776 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
777 : }
778 4 : }
779 :
780 26660 : TEST(BytecodeGraphBuilderTypeOf) {
781 8 : HandleAndZoneScope scope;
782 : Isolate* isolate = scope.main_isolate();
783 : Factory* factory = isolate->factory();
784 :
785 : ExpectedSnippet<1> snippets[] = {
786 : {"return typeof p1;",
787 : {factory->NewStringFromStaticChars("object"),
788 : BytecodeGraphTester::NewObject("({val : 10})")}},
789 : {"return typeof p1;",
790 : {factory->NewStringFromStaticChars("undefined"),
791 : factory->undefined_value()}},
792 : {"return typeof p1;",
793 : {factory->NewStringFromStaticChars("number"),
794 : factory->NewNumberFromInt(10)}},
795 : {"return typeof p1;",
796 : {factory->NewStringFromStaticChars("boolean"), factory->true_value()}},
797 : {"return typeof p1;",
798 : {factory->NewStringFromStaticChars("string"),
799 : factory->NewStringFromStaticChars("abc")}},
800 24 : };
801 :
802 44 : for (size_t i = 0; i < arraysize(snippets); i++) {
803 : ScopedVector<char> script(1024);
804 20 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
805 20 : snippets[i].code_snippet, kFunctionName);
806 :
807 : BytecodeGraphTester tester(isolate, script.start());
808 : auto callable = tester.GetCallable<Handle<Object>>();
809 : Handle<Object> return_value =
810 40 : callable(snippets[i].parameter(0)).ToHandleChecked();
811 20 : CHECK(return_value->SameValue(*snippets[i].return_value()));
812 : }
813 4 : }
814 :
815 26660 : TEST(BytecodeGraphBuilderCompareTypeOf) {
816 8 : HandleAndZoneScope scope;
817 : Isolate* isolate = scope.main_isolate();
818 : Factory* factory = isolate->factory();
819 :
820 : ExpectedSnippet<1> snippets[] = {
821 : {"return typeof p1 === 'number';",
822 : {factory->true_value(), factory->NewNumber(1.1)}},
823 : {"return typeof p1 === 'string';",
824 : {factory->false_value(), factory->NewNumber(1.1)}},
825 : {"return typeof p1 === 'string';",
826 : {factory->true_value(), factory->NewStringFromStaticChars("string")}},
827 : {"return typeof p1 === 'string';",
828 : {factory->false_value(), factory->undefined_value()}},
829 : {"return typeof p1 === 'undefined';",
830 : {factory->true_value(), factory->undefined_value()}},
831 : {"return typeof p1 === 'object';",
832 : {factory->true_value(), factory->null_value()}},
833 : {"return typeof p1 === 'object';",
834 : {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
835 : {"return typeof p1 === 'function';",
836 : {factory->false_value(),
837 : BytecodeGraphTester::NewObject("({val : 10})")}},
838 : {"return typeof p1 === 'symbol';",
839 : {factory->true_value(), factory->NewSymbol()}},
840 : {"return typeof p1 === 'symbol';",
841 : {factory->false_value(), factory->NewStringFromStaticChars("string")}},
842 : {"return typeof p1 === 'other';",
843 : {factory->false_value(), factory->NewNumber(1.1)}},
844 60 : };
845 :
846 92 : for (size_t i = 0; i < arraysize(snippets); i++) {
847 : ScopedVector<char> script(1024);
848 44 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
849 44 : snippets[i].code_snippet, kFunctionName);
850 :
851 : BytecodeGraphTester tester(isolate, script.start());
852 : auto callable = tester.GetCallable<Handle<Object>>();
853 : Handle<Object> return_value =
854 88 : callable(snippets[i].parameter(0)).ToHandleChecked();
855 44 : CHECK(return_value->SameValue(*snippets[i].return_value()));
856 : }
857 4 : }
858 :
859 26660 : TEST(BytecodeGraphBuilderCountOperation) {
860 8 : HandleAndZoneScope scope;
861 : Isolate* isolate = scope.main_isolate();
862 : Factory* factory = isolate->factory();
863 :
864 : ExpectedSnippet<1> snippets[] = {
865 : {"return ++p1;",
866 : {factory->NewNumberFromInt(11), factory->NewNumberFromInt(10)}},
867 : {"return p1++;",
868 : {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
869 : {"return p1++ + 10;",
870 : {factory->NewHeapNumber(15.23), factory->NewHeapNumber(5.23)}},
871 : {"return 20 + ++p1;",
872 : {factory->NewHeapNumber(27.23), factory->NewHeapNumber(6.23)}},
873 : {"return --p1;",
874 : {factory->NewHeapNumber(9.8), factory->NewHeapNumber(10.8)}},
875 : {"return p1--;",
876 : {factory->NewHeapNumber(10.8), factory->NewHeapNumber(10.8)}},
877 : {"return p1-- + 10;",
878 : {factory->NewNumberFromInt(20), factory->NewNumberFromInt(10)}},
879 : {"return 20 + --p1;",
880 : {factory->NewNumberFromInt(29), factory->NewNumberFromInt(10)}},
881 : {"return p1.val--;",
882 : {factory->NewNumberFromInt(10),
883 : BytecodeGraphTester::NewObject("({val : 10})")}},
884 : {"return ++p1['val'];",
885 : {factory->NewNumberFromInt(11),
886 : BytecodeGraphTester::NewObject("({val : 10})")}},
887 : {"return ++p1[1];",
888 : {factory->NewNumberFromInt(11),
889 : BytecodeGraphTester::NewObject("({1 : 10})")}},
890 : {" function inner() { return p1 } return --p1;",
891 : {factory->NewNumberFromInt(9), factory->NewNumberFromInt(10)}},
892 : {" function inner() { return p1 } return p1--;",
893 : {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
894 : {"return ++p1;",
895 : {factory->nan_value(), factory->NewStringFromStaticChars("String")}},
896 40 : };
897 :
898 116 : for (size_t i = 0; i < arraysize(snippets); i++) {
899 : ScopedVector<char> script(1024);
900 56 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
901 56 : snippets[i].code_snippet, kFunctionName);
902 :
903 : BytecodeGraphTester tester(isolate, script.start());
904 : auto callable = tester.GetCallable<Handle<Object>>();
905 : Handle<Object> return_value =
906 112 : callable(snippets[i].parameter(0)).ToHandleChecked();
907 56 : CHECK(return_value->SameValue(*snippets[i].return_value()));
908 : }
909 4 : }
910 :
911 26660 : TEST(BytecodeGraphBuilderDelete) {
912 8 : HandleAndZoneScope scope;
913 : Isolate* isolate = scope.main_isolate();
914 : Factory* factory = isolate->factory();
915 :
916 : ExpectedSnippet<1> snippets[] = {
917 : {"return delete p1.val;",
918 : {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
919 : {"delete p1.val; return p1.val;",
920 : {factory->undefined_value(),
921 : BytecodeGraphTester::NewObject("({val : 10})")}},
922 : {"delete p1.name; return p1.val;",
923 : {factory->NewNumberFromInt(10),
924 : BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
925 : {"'use strict'; return delete p1.val;",
926 : {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
927 : {"'use strict'; delete p1.val; return p1.val;",
928 : {factory->undefined_value(),
929 : BytecodeGraphTester::NewObject("({val : 10})")}},
930 : {"'use strict'; delete p1.name; return p1.val;",
931 : {factory->NewNumberFromInt(10),
932 : BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
933 20 : };
934 :
935 52 : for (size_t i = 0; i < arraysize(snippets); i++) {
936 : ScopedVector<char> script(1024);
937 24 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
938 24 : snippets[i].code_snippet, kFunctionName);
939 :
940 : BytecodeGraphTester tester(isolate, script.start());
941 : auto callable = tester.GetCallable<Handle<Object>>();
942 : Handle<Object> return_value =
943 48 : callable(snippets[i].parameter(0)).ToHandleChecked();
944 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
945 : }
946 4 : }
947 :
948 26660 : TEST(BytecodeGraphBuilderDeleteGlobal) {
949 8 : HandleAndZoneScope scope;
950 : Isolate* isolate = scope.main_isolate();
951 : Factory* factory = isolate->factory();
952 :
953 : ExpectedSnippet<0> snippets[] = {
954 : {"var obj = {val : 10, type : 'int'};"
955 : "function f() {return delete obj;};",
956 : {factory->false_value()}},
957 : {"function f() {return delete this;};", {factory->true_value()}},
958 : {"var obj = {val : 10, type : 'int'};"
959 : "function f() {return delete obj.val;};",
960 : {factory->true_value()}},
961 : {"var obj = {val : 10, type : 'int'};"
962 : "function f() {'use strict'; return delete obj.val;};",
963 : {factory->true_value()}},
964 : {"var obj = {val : 10, type : 'int'};"
965 : "function f() {delete obj.val; return obj.val;};",
966 : {factory->undefined_value()}},
967 : {"var obj = {val : 10, type : 'int'};"
968 : "function f() {'use strict'; delete obj.val; return obj.val;};",
969 : {factory->undefined_value()}},
970 : {"var obj = {1 : 10, 2 : 20};"
971 : "function f() { return delete obj[1]; };",
972 : {factory->true_value()}},
973 : {"var obj = {1 : 10, 2 : 20};"
974 : "function f() { 'use strict'; return delete obj[1];};",
975 : {factory->true_value()}},
976 : {"obj = {1 : 10, 2 : 20};"
977 : "function f() { delete obj[1]; return obj[2];};",
978 : {factory->NewNumberFromInt(20)}},
979 : {"function f() {"
980 : " var obj = {1 : 10, 2 : 20};"
981 : " function inner() { return obj[1]; };"
982 : " return delete obj[1];"
983 : "}",
984 : {factory->true_value()}},
985 36 : };
986 :
987 84 : for (size_t i = 0; i < arraysize(snippets); i++) {
988 : ScopedVector<char> script(1024);
989 40 : SNPrintF(script, "%s %s({});", snippets[i].code_snippet, kFunctionName);
990 :
991 : BytecodeGraphTester tester(isolate, script.start());
992 : auto callable = tester.GetCallable<>();
993 80 : Handle<Object> return_value = callable().ToHandleChecked();
994 80 : CHECK(return_value->SameValue(*snippets[i].return_value()));
995 : }
996 4 : }
997 :
998 26660 : TEST(BytecodeGraphBuilderDeleteLookupSlot) {
999 8 : HandleAndZoneScope scope;
1000 : Isolate* isolate = scope.main_isolate();
1001 : Factory* factory = isolate->factory();
1002 :
1003 : // TODO(mythria): Add more tests when we have support for LdaLookupSlot.
1004 : const char* function_prologue = "var f;"
1005 : "var x = 1;"
1006 : "y = 10;"
1007 : "var obj = {val:10};"
1008 : "var z = 30;"
1009 : "function f1() {"
1010 : " var z = 20;"
1011 : " eval(\"function t() {";
1012 : const char* function_epilogue = " }; f = t; t();\");"
1013 : "}"
1014 : "f1();";
1015 :
1016 : ExpectedSnippet<0> snippets[] = {
1017 : {"return delete y;", {factory->true_value()}},
1018 : {"return delete z;", {factory->false_value()}},
1019 8 : };
1020 :
1021 20 : for (size_t i = 0; i < arraysize(snippets); i++) {
1022 : ScopedVector<char> script(1024);
1023 8 : SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
1024 8 : function_epilogue);
1025 :
1026 : BytecodeGraphTester tester(isolate, script.start(), "t");
1027 : auto callable = tester.GetCallable<>();
1028 16 : Handle<Object> return_value = callable().ToHandleChecked();
1029 16 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1030 : }
1031 4 : }
1032 :
1033 26660 : TEST(BytecodeGraphBuilderLookupSlot) {
1034 8 : HandleAndZoneScope scope;
1035 : Isolate* isolate = scope.main_isolate();
1036 : Factory* factory = isolate->factory();
1037 :
1038 : const char* function_prologue = "var f;"
1039 : "var x = 12;"
1040 : "y = 10;"
1041 : "var obj = {val:3.1414};"
1042 : "var z = 30;"
1043 : "function f1() {"
1044 : " var z = 20;"
1045 : " eval(\"function t() {";
1046 : const char* function_epilogue = " }; f = t; t();\");"
1047 : "}"
1048 : "f1();";
1049 :
1050 : ExpectedSnippet<0> snippets[] = {
1051 : {"return x;", {factory->NewNumber(12)}},
1052 : {"return obj.val;", {factory->NewNumber(3.1414)}},
1053 : {"return typeof x;", {factory->NewStringFromStaticChars("number")}},
1054 : {"return typeof dummy;",
1055 : {factory->NewStringFromStaticChars("undefined")}},
1056 : {"x = 23; return x;", {factory->NewNumber(23)}},
1057 : {"'use strict'; obj.val = 23.456; return obj.val;",
1058 12 : {factory->NewNumber(23.456)}}};
1059 :
1060 52 : for (size_t i = 0; i < arraysize(snippets); i++) {
1061 : ScopedVector<char> script(1024);
1062 24 : SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
1063 24 : function_epilogue);
1064 :
1065 : BytecodeGraphTester tester(isolate, script.start(), "t");
1066 : auto callable = tester.GetCallable<>();
1067 48 : Handle<Object> return_value = callable().ToHandleChecked();
1068 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1069 : }
1070 4 : }
1071 :
1072 26660 : TEST(BytecodeGraphBuilderLookupContextSlot) {
1073 8 : HandleAndZoneScope scope;
1074 : Isolate* isolate = scope.main_isolate();
1075 : Factory* factory = isolate->factory();
1076 :
1077 : // Testing with eval called in the current context.
1078 : const char* inner_eval_prologue = "var x = 0; function inner() {";
1079 : const char* inner_eval_epilogue = "}; return inner();";
1080 :
1081 : ExpectedSnippet<0> inner_eval_snippets[] = {
1082 : {"eval(''); return x;", {factory->NewNumber(0)}},
1083 : {"eval('var x = 1'); return x;", {factory->NewNumber(1)}},
1084 4 : {"'use strict'; eval('var x = 1'); return x;", {factory->NewNumber(0)}}};
1085 :
1086 28 : for (size_t i = 0; i < arraysize(inner_eval_snippets); i++) {
1087 : ScopedVector<char> script(1024);
1088 12 : SNPrintF(script, "function %s(p1) { %s %s %s } ; %s() ;", kFunctionName,
1089 : inner_eval_prologue, inner_eval_snippets[i].code_snippet,
1090 12 : inner_eval_epilogue, kFunctionName);
1091 :
1092 : BytecodeGraphTester tester(isolate, script.start());
1093 : auto callable = tester.GetCallable<>();
1094 24 : Handle<Object> return_value = callable().ToHandleChecked();
1095 24 : CHECK(return_value->SameValue(*inner_eval_snippets[i].return_value()));
1096 : }
1097 :
1098 : // Testing with eval called in a parent context.
1099 : const char* outer_eval_prologue = "";
1100 : const char* outer_eval_epilogue =
1101 : "function inner() { return x; }; return inner();";
1102 :
1103 : ExpectedSnippet<0> outer_eval_snippets[] = {
1104 : {"var x = 0; eval('');", {factory->NewNumber(0)}},
1105 : {"var x = 0; eval('var x = 1');", {factory->NewNumber(1)}},
1106 4 : {"'use strict'; var x = 0; eval('var x = 1');", {factory->NewNumber(0)}}};
1107 :
1108 28 : for (size_t i = 0; i < arraysize(outer_eval_snippets); i++) {
1109 : ScopedVector<char> script(1024);
1110 12 : SNPrintF(script, "function %s() { %s %s %s } ; %s() ;", kFunctionName,
1111 : outer_eval_prologue, outer_eval_snippets[i].code_snippet,
1112 12 : outer_eval_epilogue, kFunctionName);
1113 :
1114 : BytecodeGraphTester tester(isolate, script.start());
1115 : auto callable = tester.GetCallable<>();
1116 24 : Handle<Object> return_value = callable().ToHandleChecked();
1117 24 : CHECK(return_value->SameValue(*outer_eval_snippets[i].return_value()));
1118 : }
1119 4 : }
1120 :
1121 26660 : TEST(BytecodeGraphBuilderLookupGlobalSlot) {
1122 8 : HandleAndZoneScope scope;
1123 : Isolate* isolate = scope.main_isolate();
1124 : Factory* factory = isolate->factory();
1125 :
1126 : // Testing with eval called in the current context.
1127 : const char* inner_eval_prologue = "x = 0; function inner() {";
1128 : const char* inner_eval_epilogue = "}; return inner();";
1129 :
1130 : ExpectedSnippet<0> inner_eval_snippets[] = {
1131 : {"eval(''); return x;", {factory->NewNumber(0)}},
1132 : {"eval('var x = 1'); return x;", {factory->NewNumber(1)}},
1133 4 : {"'use strict'; eval('var x = 1'); return x;", {factory->NewNumber(0)}}};
1134 :
1135 28 : for (size_t i = 0; i < arraysize(inner_eval_snippets); i++) {
1136 : ScopedVector<char> script(1024);
1137 12 : SNPrintF(script, "function %s(p1) { %s %s %s } ; %s() ;", kFunctionName,
1138 : inner_eval_prologue, inner_eval_snippets[i].code_snippet,
1139 12 : inner_eval_epilogue, kFunctionName);
1140 :
1141 : BytecodeGraphTester tester(isolate, script.start());
1142 : auto callable = tester.GetCallable<>();
1143 24 : Handle<Object> return_value = callable().ToHandleChecked();
1144 24 : CHECK(return_value->SameValue(*inner_eval_snippets[i].return_value()));
1145 : }
1146 :
1147 : // Testing with eval called in a parent context.
1148 : const char* outer_eval_prologue = "";
1149 : const char* outer_eval_epilogue =
1150 : "function inner() { return x; }; return inner();";
1151 :
1152 : ExpectedSnippet<0> outer_eval_snippets[] = {
1153 : {"x = 0; eval('');", {factory->NewNumber(0)}},
1154 : {"x = 0; eval('var x = 1');", {factory->NewNumber(1)}},
1155 4 : {"'use strict'; x = 0; eval('var x = 1');", {factory->NewNumber(0)}}};
1156 :
1157 28 : for (size_t i = 0; i < arraysize(outer_eval_snippets); i++) {
1158 : ScopedVector<char> script(1024);
1159 12 : SNPrintF(script, "function %s() { %s %s %s } ; %s() ;", kFunctionName,
1160 : outer_eval_prologue, outer_eval_snippets[i].code_snippet,
1161 12 : outer_eval_epilogue, kFunctionName);
1162 :
1163 : BytecodeGraphTester tester(isolate, script.start());
1164 : auto callable = tester.GetCallable<>();
1165 24 : Handle<Object> return_value = callable().ToHandleChecked();
1166 24 : CHECK(return_value->SameValue(*outer_eval_snippets[i].return_value()));
1167 : }
1168 4 : }
1169 :
1170 26660 : TEST(BytecodeGraphBuilderLookupSlotWide) {
1171 8 : HandleAndZoneScope scope;
1172 : Isolate* isolate = scope.main_isolate();
1173 : Factory* factory = isolate->factory();
1174 :
1175 : const char* function_prologue =
1176 : "var f;"
1177 : "var x = 12;"
1178 : "y = 10;"
1179 : "var obj = {val:3.1414};"
1180 : "var z = 30;"
1181 : "function f1() {"
1182 : " var z = 20;"
1183 : " eval(\"function t() {";
1184 : const char* function_epilogue =
1185 : " }; f = t; t();\");"
1186 : "}"
1187 : "f1();";
1188 :
1189 : ExpectedSnippet<0> snippets[] = {
1190 : {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x;",
1191 : {factory->NewNumber(12)}},
1192 : {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return typeof x;",
1193 : {factory->NewStringFromStaticChars("number")}},
1194 : {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x = 23;",
1195 : {factory->NewNumber(23)}},
1196 : {"'use strict';" REPEAT_256(SPACE, "y = 2.3;") "return obj.val = 23.456;",
1197 8 : {factory->NewNumber(23.456)}}};
1198 :
1199 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
1200 : ScopedVector<char> script(3072);
1201 16 : SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
1202 16 : function_epilogue);
1203 :
1204 : BytecodeGraphTester tester(isolate, script.start(), "t");
1205 : auto callable = tester.GetCallable<>();
1206 32 : Handle<Object> return_value = callable().ToHandleChecked();
1207 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1208 : }
1209 4 : }
1210 :
1211 26660 : TEST(BytecodeGraphBuilderCallLookupSlot) {
1212 8 : HandleAndZoneScope scope;
1213 : Isolate* isolate = scope.main_isolate();
1214 :
1215 : ExpectedSnippet<0> snippets[] = {
1216 : {"g = function(){ return 2 }; eval(''); return g();",
1217 : {handle(Smi::FromInt(2), isolate)}},
1218 : {"g = function(){ return 2 }; eval('g = function() {return 3}');\n"
1219 : "return g();",
1220 : {handle(Smi::FromInt(3), isolate)}},
1221 : {"g = { x: function(){ return this.y }, y: 20 };\n"
1222 : "eval('g = { x: g.x, y: 30 }');\n"
1223 : "return g.x();",
1224 : {handle(Smi::FromInt(30), isolate)}},
1225 12 : };
1226 :
1227 28 : for (size_t i = 0; i < arraysize(snippets); i++) {
1228 : ScopedVector<char> script(1024);
1229 12 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1230 12 : snippets[i].code_snippet, kFunctionName);
1231 : BytecodeGraphTester tester(isolate, script.start());
1232 : auto callable = tester.GetCallable<>();
1233 24 : Handle<Object> return_value = callable().ToHandleChecked();
1234 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1235 : }
1236 4 : }
1237 :
1238 26660 : TEST(BytecodeGraphBuilderEval) {
1239 8 : HandleAndZoneScope scope;
1240 : Isolate* isolate = scope.main_isolate();
1241 : Factory* factory = isolate->factory();
1242 :
1243 : ExpectedSnippet<0> snippets[] = {
1244 : {"return eval('1;');", {handle(Smi::FromInt(1), isolate)}},
1245 : {"return eval('100 * 20;');", {handle(Smi::FromInt(2000), isolate)}},
1246 : {"var x = 10; return eval('x + 20;');",
1247 : {handle(Smi::FromInt(30), isolate)}},
1248 : {"var x = 10; eval('x = 33;'); return x;",
1249 : {handle(Smi::FromInt(33), isolate)}},
1250 : {"'use strict'; var x = 20; var z = 0;\n"
1251 : "eval('var x = 33; z = x;'); return x + z;",
1252 : {handle(Smi::FromInt(53), isolate)}},
1253 : {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;",
1254 : {handle(Smi::FromInt(86), isolate)}},
1255 : {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x",
1256 : {handle(Smi::FromInt(11), isolate)}},
1257 : {"var x = 10; eval('var x = 20;'); return x;",
1258 : {handle(Smi::FromInt(20), isolate)}},
1259 : {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;",
1260 : {handle(Smi::FromInt(1), isolate)}},
1261 : {"'use strict'; var x = 1; eval('var x = 2;'); return x;",
1262 : {handle(Smi::FromInt(1), isolate)}},
1263 : {"var x = 10; eval('x + 20;'); return typeof x;",
1264 : {factory->NewStringFromStaticChars("number")}},
1265 : {"eval('var y = 10;'); return typeof unallocated;",
1266 : {factory->NewStringFromStaticChars("undefined")}},
1267 : {"'use strict'; eval('var y = 10;'); return typeof unallocated;",
1268 : {factory->NewStringFromStaticChars("undefined")}},
1269 : {"eval('var x = 10;'); return typeof x;",
1270 : {factory->NewStringFromStaticChars("number")}},
1271 : {"var x = {}; eval('var x = 10;'); return typeof x;",
1272 : {factory->NewStringFromStaticChars("number")}},
1273 : {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;",
1274 : {factory->NewStringFromStaticChars("object")}},
1275 64 : };
1276 :
1277 132 : for (size_t i = 0; i < arraysize(snippets); i++) {
1278 : ScopedVector<char> script(1024);
1279 64 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1280 64 : snippets[i].code_snippet, kFunctionName);
1281 : BytecodeGraphTester tester(isolate, script.start());
1282 : auto callable = tester.GetCallable<>();
1283 128 : Handle<Object> return_value = callable().ToHandleChecked();
1284 128 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1285 : }
1286 4 : }
1287 :
1288 26660 : TEST(BytecodeGraphBuilderEvalParams) {
1289 8 : HandleAndZoneScope scope;
1290 : Isolate* isolate = scope.main_isolate();
1291 :
1292 : ExpectedSnippet<1> snippets[] = {
1293 : {"var x = 10; return eval('x + p1;');",
1294 : {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
1295 : {"var x = 10; eval('p1 = x;'); return p1;",
1296 : {handle(Smi::FromInt(10), isolate), handle(Smi::FromInt(20), isolate)}},
1297 : {"var a = 10;"
1298 : "function inner() { return eval('a + p1;');}"
1299 : "return inner();",
1300 : {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
1301 12 : };
1302 :
1303 28 : for (size_t i = 0; i < arraysize(snippets); i++) {
1304 : ScopedVector<char> script(1024);
1305 12 : SNPrintF(script, "function %s(p1) { %s }\n%s(0);", kFunctionName,
1306 12 : snippets[i].code_snippet, kFunctionName);
1307 : BytecodeGraphTester tester(isolate, script.start());
1308 : auto callable = tester.GetCallable<Handle<Object>>();
1309 : Handle<Object> return_value =
1310 24 : callable(snippets[i].parameter(0)).ToHandleChecked();
1311 12 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1312 : }
1313 4 : }
1314 :
1315 26660 : TEST(BytecodeGraphBuilderEvalGlobal) {
1316 8 : HandleAndZoneScope scope;
1317 : Isolate* isolate = scope.main_isolate();
1318 : Factory* factory = isolate->factory();
1319 :
1320 : ExpectedSnippet<0> snippets[] = {
1321 : {"function add_global() { eval('function f() { z = 33; }; f()'); };"
1322 : "function f() { add_global(); return z; }; f();",
1323 : {handle(Smi::FromInt(33), isolate)}},
1324 : {"function add_global() {\n"
1325 : " eval('\"use strict\"; function f() { y = 33; };"
1326 : " try { f() } catch(e) {}');\n"
1327 : "}\n"
1328 : "function f() { add_global(); return typeof y; } f();",
1329 : {factory->NewStringFromStaticChars("undefined")}},
1330 8 : };
1331 :
1332 20 : for (size_t i = 0; i < arraysize(snippets); i++) {
1333 8 : BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
1334 : auto callable = tester.GetCallable<>();
1335 16 : Handle<Object> return_value = callable().ToHandleChecked();
1336 16 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1337 : }
1338 4 : }
1339 :
1340 1120 : bool get_compare_result(Isolate* isolate, Token::Value opcode,
1341 : Handle<Object> lhs_value, Handle<Object> rhs_value) {
1342 1120 : switch (opcode) {
1343 : case Token::Value::EQ:
1344 280 : return Object::Equals(isolate, lhs_value, rhs_value).FromJust();
1345 : case Token::Value::NE:
1346 280 : return !Object::Equals(isolate, lhs_value, rhs_value).FromJust();
1347 : case Token::Value::EQ_STRICT:
1348 140 : return lhs_value->StrictEquals(*rhs_value);
1349 : case Token::Value::NE_STRICT:
1350 140 : return !lhs_value->StrictEquals(*rhs_value);
1351 : case Token::Value::LT:
1352 280 : return Object::LessThan(isolate, lhs_value, rhs_value).FromJust();
1353 : case Token::Value::LTE:
1354 280 : return Object::LessThanOrEqual(isolate, lhs_value, rhs_value).FromJust();
1355 : case Token::Value::GT:
1356 280 : return Object::GreaterThan(isolate, lhs_value, rhs_value).FromJust();
1357 : case Token::Value::GTE:
1358 280 : return Object::GreaterThanOrEqual(isolate, lhs_value, rhs_value)
1359 : .FromJust();
1360 : default:
1361 0 : UNREACHABLE();
1362 : }
1363 : }
1364 :
1365 32 : const char* get_code_snippet(Token::Value opcode) {
1366 32 : switch (opcode) {
1367 : case Token::Value::EQ:
1368 : return "return p1 == p2;";
1369 : case Token::Value::NE:
1370 4 : return "return p1 != p2;";
1371 : case Token::Value::EQ_STRICT:
1372 4 : return "return p1 === p2;";
1373 : case Token::Value::NE_STRICT:
1374 4 : return "return p1 !== p2;";
1375 : case Token::Value::LT:
1376 4 : return "return p1 < p2;";
1377 : case Token::Value::LTE:
1378 4 : return "return p1 <= p2;";
1379 : case Token::Value::GT:
1380 4 : return "return p1 > p2;";
1381 : case Token::Value::GTE:
1382 4 : return "return p1 >= p2;";
1383 : default:
1384 0 : UNREACHABLE();
1385 : }
1386 : }
1387 :
1388 26660 : TEST(BytecodeGraphBuilderCompare) {
1389 8 : HandleAndZoneScope scope;
1390 : 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 12 : 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 16 : factory->NewNumberFromInt(SMI_MIN)};
1403 :
1404 68 : for (size_t i = 0; i < arraysize(kCompareOperators); i++) {
1405 : ScopedVector<char> script(1024);
1406 32 : SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
1407 64 : get_code_snippet(kCompareOperators[i]), kFunctionName);
1408 :
1409 : BytecodeGraphTester tester(isolate, script.start());
1410 : auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
1411 352 : for (size_t j = 0; j < arraysize(lhs_values); j++) {
1412 2400 : for (size_t k = 0; k < arraysize(rhs_values); k++) {
1413 : Handle<Object> return_value =
1414 2240 : callable(lhs_values[j], rhs_values[k]).ToHandleChecked();
1415 : bool result = get_compare_result(isolate, kCompareOperators[i],
1416 1120 : lhs_values[j], rhs_values[k]);
1417 2240 : CHECK(return_value->SameValue(*factory->ToBoolean(result)));
1418 : }
1419 : }
1420 : }
1421 4 : }
1422 :
1423 26660 : TEST(BytecodeGraphBuilderTestIn) {
1424 8 : HandleAndZoneScope scope;
1425 : 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 56 : };
1455 :
1456 68 : for (size_t i = 0; i < arraysize(snippets); i++) {
1457 : ScopedVector<char> script(1024);
1458 32 : SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
1459 32 : 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 64 : callable(snippets[i].parameter(0), snippets[i].parameter(1))
1465 : .ToHandleChecked();
1466 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1467 : }
1468 4 : }
1469 :
1470 26660 : TEST(BytecodeGraphBuilderTestInstanceOf) {
1471 8 : HandleAndZoneScope scope;
1472 : 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 16 : };
1485 :
1486 28 : for (size_t i = 0; i < arraysize(snippets); i++) {
1487 : ScopedVector<char> script(1024);
1488 12 : SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
1489 12 : 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 24 : callable(snippets[i].parameter(0)).ToHandleChecked();
1495 12 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1496 : }
1497 4 : }
1498 :
1499 26660 : TEST(BytecodeGraphBuilderTryCatch) {
1500 8 : HandleAndZoneScope scope;
1501 : 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 16 : };
1514 :
1515 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
1516 : ScopedVector<char> script(1024);
1517 16 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1518 16 : snippets[i].code_snippet, kFunctionName);
1519 :
1520 : BytecodeGraphTester tester(isolate, script.start());
1521 : auto callable = tester.GetCallable<>();
1522 32 : Handle<Object> return_value = callable().ToHandleChecked();
1523 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1524 : }
1525 4 : }
1526 :
1527 26660 : TEST(BytecodeGraphBuilderTryFinally1) {
1528 8 : HandleAndZoneScope scope;
1529 : 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 24 : };
1551 :
1552 52 : for (size_t i = 0; i < arraysize(snippets); i++) {
1553 : ScopedVector<char> script(1024);
1554 24 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1555 24 : snippets[i].code_snippet, kFunctionName);
1556 :
1557 : BytecodeGraphTester tester(isolate, script.start());
1558 : auto callable = tester.GetCallable<>();
1559 48 : Handle<Object> return_value = callable().ToHandleChecked();
1560 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1561 : }
1562 4 : }
1563 :
1564 26660 : TEST(BytecodeGraphBuilderTryFinally2) {
1565 8 : HandleAndZoneScope scope;
1566 : 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 4 : };
1574 :
1575 20 : for (size_t i = 0; i < arraysize(snippets); i++) {
1576 : ScopedVector<char> script(1024);
1577 8 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1578 8 : snippets[i].code_snippet, kFunctionName);
1579 :
1580 : BytecodeGraphTester tester(isolate, script.start());
1581 16 : v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
1582 8 : v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
1583 24 : CHECK(
1584 : message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
1585 : .FromJust());
1586 : }
1587 4 : }
1588 :
1589 26660 : TEST(BytecodeGraphBuilderThrow) {
1590 8 : HandleAndZoneScope scope;
1591 : 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 4 : };
1602 :
1603 44 : for (size_t i = 0; i < arraysize(snippets); i++) {
1604 : ScopedVector<char> script(1024);
1605 20 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1606 20 : snippets[i].code_snippet, kFunctionName);
1607 :
1608 : BytecodeGraphTester tester(isolate, script.start());
1609 40 : v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
1610 20 : v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
1611 60 : CHECK(
1612 : message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
1613 : .FromJust());
1614 : }
1615 4 : }
1616 :
1617 26660 : TEST(BytecodeGraphBuilderContext) {
1618 8 : HandleAndZoneScope scope;
1619 : 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 12 : };
1662 :
1663 28 : for (size_t i = 0; i < arraysize(snippets); i++) {
1664 : ScopedVector<char> script(1024);
1665 12 : SNPrintF(script, "%s", snippets[i].code_snippet);
1666 :
1667 : BytecodeGraphTester tester(isolate, script.start(), "f");
1668 : auto callable = tester.GetCallable<>("f");
1669 24 : Handle<Object> return_value = callable().ToHandleChecked();
1670 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1671 : }
1672 4 : }
1673 :
1674 26660 : TEST(BytecodeGraphBuilderLoadContext) {
1675 8 : HandleAndZoneScope scope;
1676 : 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 12 : {factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}};
1725 :
1726 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
1727 : ScopedVector<char> script(1024);
1728 16 : 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 32 : callable(snippets[i].parameter(0)).ToHandleChecked();
1734 16 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1735 : }
1736 4 : }
1737 :
1738 26660 : TEST(BytecodeGraphBuilderCreateArgumentsNoParameters) {
1739 8 : HandleAndZoneScope scope;
1740 : 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 24 : };
1755 :
1756 52 : for (size_t i = 0; i < arraysize(snippets); i++) {
1757 : ScopedVector<char> script(1024);
1758 24 : SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
1759 :
1760 : BytecodeGraphTester tester(isolate, script.start());
1761 : auto callable = tester.GetCallable<>();
1762 48 : Handle<Object> return_value = callable().ToHandleChecked();
1763 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1764 : }
1765 4 : }
1766 :
1767 26660 : TEST(BytecodeGraphBuilderCreateArguments) {
1768 8 : HandleAndZoneScope scope;
1769 : 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 12 : };
1796 :
1797 60 : for (size_t i = 0; i < arraysize(snippets); i++) {
1798 : ScopedVector<char> script(1024);
1799 28 : 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 28 : snippets[i].parameter(2))
1807 : .ToHandleChecked();
1808 28 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1809 : }
1810 4 : }
1811 :
1812 26660 : TEST(BytecodeGraphBuilderCreateRestArguments) {
1813 8 : HandleAndZoneScope scope;
1814 : 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 8 : };
1838 :
1839 52 : for (size_t i = 0; i < arraysize(snippets); i++) {
1840 : ScopedVector<char> script(1024);
1841 24 : 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 24 : snippets[i].parameter(2))
1849 : .ToHandleChecked();
1850 24 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1851 : }
1852 4 : }
1853 :
1854 26660 : TEST(BytecodeGraphBuilderRegExpLiterals) {
1855 8 : HandleAndZoneScope scope;
1856 : 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 28 : };
1875 :
1876 60 : for (size_t i = 0; i < arraysize(snippets); i++) {
1877 : ScopedVector<char> script(4096);
1878 28 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1879 28 : snippets[i].code_snippet, kFunctionName);
1880 :
1881 : BytecodeGraphTester tester(isolate, script.start());
1882 : auto callable = tester.GetCallable<>();
1883 56 : Handle<Object> return_value = callable().ToHandleChecked();
1884 56 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1885 : }
1886 4 : }
1887 :
1888 26660 : TEST(BytecodeGraphBuilderArrayLiterals) {
1889 8 : HandleAndZoneScope scope;
1890 : 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 24 : {factory->NewStringFromStaticChars("1t")}}};
1913 :
1914 84 : for (size_t i = 0; i < arraysize(snippets); i++) {
1915 : ScopedVector<char> script(4096);
1916 40 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1917 40 : snippets[i].code_snippet, kFunctionName);
1918 :
1919 : BytecodeGraphTester tester(isolate, script.start());
1920 : auto callable = tester.GetCallable<>();
1921 80 : Handle<Object> return_value = callable().ToHandleChecked();
1922 80 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1923 : }
1924 4 : }
1925 :
1926 26660 : TEST(BytecodeGraphBuilderObjectLiterals) {
1927 8 : HandleAndZoneScope scope;
1928 : 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 48 : };
1976 :
1977 148 : for (size_t i = 0; i < arraysize(snippets); i++) {
1978 : ScopedVector<char> script(4096);
1979 72 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1980 72 : snippets[i].code_snippet, kFunctionName);
1981 : BytecodeGraphTester tester(isolate, script.start());
1982 : auto callable = tester.GetCallable<>();
1983 144 : Handle<Object> return_value = callable().ToHandleChecked();
1984 144 : CHECK(return_value->SameValue(*snippets[i].return_value()));
1985 : }
1986 4 : }
1987 :
1988 26660 : TEST(BytecodeGraphBuilderIf) {
1989 8 : HandleAndZoneScope scope;
1990 : 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 4 : };
2082 :
2083 116 : for (size_t i = 0; i < arraysize(snippets); i++) {
2084 : ScopedVector<char> script(2048);
2085 56 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
2086 56 : 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 112 : callable(snippets[i].parameter(0)).ToHandleChecked();
2092 56 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2093 : }
2094 4 : }
2095 :
2096 26660 : TEST(BytecodeGraphBuilderConditionalOperator) {
2097 8 : HandleAndZoneScope scope;
2098 : 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 4 : };
2111 :
2112 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
2113 : ScopedVector<char> script(2048);
2114 16 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
2115 16 : 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 32 : callable(snippets[i].parameter(0)).ToHandleChecked();
2121 16 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2122 : }
2123 4 : }
2124 :
2125 26660 : TEST(BytecodeGraphBuilderSwitch) {
2126 8 : HandleAndZoneScope scope;
2127 : 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 4 : };
2157 :
2158 60 : for (size_t i = 0; i < arraysize(snippets); i++) {
2159 : ScopedVector<char> script(2048);
2160 28 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
2161 28 : 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 56 : callable(snippets[i].parameter(0)).ToHandleChecked();
2167 28 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2168 : }
2169 4 : }
2170 :
2171 26660 : TEST(BytecodeGraphBuilderSwitchMerge) {
2172 8 : HandleAndZoneScope scope;
2173 : 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 4 : };
2205 :
2206 60 : for (size_t i = 0; i < arraysize(snippets); i++) {
2207 : ScopedVector<char> script(2048);
2208 28 : SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
2209 28 : 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 56 : callable(snippets[i].parameter(0)).ToHandleChecked();
2215 28 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2216 : }
2217 4 : }
2218 :
2219 26660 : TEST(BytecodeGraphBuilderNestedSwitch) {
2220 8 : HandleAndZoneScope scope;
2221 : 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 4 : };
2263 :
2264 68 : for (size_t i = 0; i < arraysize(snippets); i++) {
2265 : ScopedVector<char> script(2048);
2266 32 : SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0, 0);", kFunctionName,
2267 32 : 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 64 : callable(snippets[i].parameter(0), snippets[i].parameter(1))
2273 : .ToHandleChecked();
2274 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2275 : }
2276 4 : }
2277 :
2278 26660 : TEST(BytecodeGraphBuilderBreakableBlocks) {
2279 8 : HandleAndZoneScope scope;
2280 : 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 4 : };
2304 :
2305 20 : for (size_t i = 0; i < arraysize(snippets); i++) {
2306 : ScopedVector<char> script(1024);
2307 8 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2308 8 : snippets[i].code_snippet, kFunctionName);
2309 :
2310 : BytecodeGraphTester tester(isolate, script.start());
2311 : auto callable = tester.GetCallable<>();
2312 16 : Handle<Object> return_value = callable().ToHandleChecked();
2313 16 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2314 : }
2315 4 : }
2316 :
2317 26660 : TEST(BytecodeGraphBuilderWhile) {
2318 8 : HandleAndZoneScope scope;
2319 : 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 4 : {factory->NewNumberFromInt(16)}}};
2351 :
2352 52 : for (size_t i = 0; i < arraysize(snippets); i++) {
2353 : ScopedVector<char> script(1024);
2354 24 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2355 24 : snippets[i].code_snippet, kFunctionName);
2356 :
2357 : BytecodeGraphTester tester(isolate, script.start());
2358 : auto callable = tester.GetCallable<>();
2359 48 : Handle<Object> return_value = callable().ToHandleChecked();
2360 48 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2361 : }
2362 4 : }
2363 :
2364 26660 : TEST(BytecodeGraphBuilderDo) {
2365 8 : HandleAndZoneScope scope;
2366 : 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 4 : {factory->NewNumber(3)}}};
2398 :
2399 44 : for (size_t i = 0; i < arraysize(snippets); i++) {
2400 : ScopedVector<char> script(1024);
2401 20 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2402 20 : snippets[i].code_snippet, kFunctionName);
2403 :
2404 : BytecodeGraphTester tester(isolate, script.start());
2405 : auto callable = tester.GetCallable<>();
2406 40 : Handle<Object> return_value = callable().ToHandleChecked();
2407 40 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2408 : }
2409 4 : }
2410 :
2411 26660 : TEST(BytecodeGraphBuilderFor) {
2412 8 : HandleAndZoneScope scope;
2413 : 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 4 : };
2490 :
2491 92 : for (size_t i = 0; i < arraysize(snippets); i++) {
2492 : ScopedVector<char> script(1024);
2493 44 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2494 44 : snippets[i].code_snippet, kFunctionName);
2495 :
2496 : BytecodeGraphTester tester(isolate, script.start());
2497 : auto callable = tester.GetCallable<>();
2498 88 : Handle<Object> return_value = callable().ToHandleChecked();
2499 88 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2500 : }
2501 4 : }
2502 :
2503 26660 : TEST(BytecodeGraphBuilderForIn) {
2504 8 : HandleAndZoneScope scope;
2505 : 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 4 : };
2560 :
2561 68 : for (size_t i = 0; i < arraysize(snippets); i++) {
2562 : ScopedVector<char> script(1024);
2563 32 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2564 32 : snippets[i].code_snippet, kFunctionName);
2565 :
2566 : BytecodeGraphTester tester(isolate, script.start());
2567 : auto callable = tester.GetCallable<>();
2568 64 : Handle<Object> return_value = callable().ToHandleChecked();
2569 64 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2570 : }
2571 4 : }
2572 :
2573 26660 : TEST(BytecodeGraphBuilderForOf) {
2574 8 : HandleAndZoneScope scope;
2575 : 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 48 : };
2651 :
2652 100 : for (size_t i = 0; i < arraysize(snippets); i++) {
2653 : ScopedVector<char> script(1024);
2654 48 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2655 48 : snippets[i].code_snippet, kFunctionName);
2656 :
2657 : BytecodeGraphTester tester(isolate, script.start());
2658 : auto callable = tester.GetCallable<>();
2659 96 : Handle<Object> return_value = callable().ToHandleChecked();
2660 96 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2661 : }
2662 4 : }
2663 :
2664 16 : void TestJumpWithConstantsAndWideConstants(size_t shard) {
2665 : const int kStep = 46;
2666 16 : int start = static_cast<int>(7 + 17 * shard);
2667 216 : for (int constants = start; constants < 300; constants += kStep) {
2668 200 : std::stringstream filler_os;
2669 : // Generate a string that consumes constant pool entries and
2670 : // spread out branch distances in script below.
2671 30684 : for (int i = 0; i < constants; i++) {
2672 15292 : filler_os << "var x_ = 'x_" << i << "';\n";
2673 : }
2674 : std::string filler(filler_os.str());
2675 :
2676 200 : std::stringstream script_os;
2677 100 : script_os << "function " << kFunctionName << "(a) {\n";
2678 : script_os << " " << filler;
2679 100 : script_os << " for (var i = a; i < 2; i++) {\n";
2680 : script_os << " " << filler;
2681 100 : script_os << " if (i == 0) { " << filler << "i = 10; continue; }\n";
2682 100 : script_os << " else if (i == a) { " << filler << "i = 12; break; }\n";
2683 100 : script_os << " else { " << filler << " }\n";
2684 100 : script_os << " }\n";
2685 100 : script_os << " return i;\n";
2686 100 : script_os << "}\n";
2687 100 : script_os << kFunctionName << "(0);\n";
2688 : std::string script(script_os.str());
2689 :
2690 200 : HandleAndZoneScope scope;
2691 : 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 700 : for (int a = 0; a < 3; a++) {
2696 : Handle<Object> return_val =
2697 600 : callable(factory->NewNumberFromInt(a)).ToHandleChecked();
2698 : static const int results[] = {11, 12, 2};
2699 600 : CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
2700 : }
2701 : }
2702 16 : }
2703 :
2704 26672 : SHARD_TEST_BY_4(JumpWithConstantsAndWideConstants)
2705 :
2706 26660 : TEST(BytecodeGraphBuilderWithStatement) {
2707 8 : HandleAndZoneScope scope;
2708 : Isolate* isolate = scope.main_isolate();
2709 :
2710 : ExpectedSnippet<0> snippets[] = {
2711 : {"with({x:42}) return x;", {handle(Smi::FromInt(42), isolate)}},
2712 : {"with({}) { var y = 10; return y;}",
2713 : {handle(Smi::FromInt(10), isolate)}},
2714 : {"var y = {x:42};"
2715 : " function inner() {"
2716 : " var x = 20;"
2717 : " with(y) return x;"
2718 : "}"
2719 : "return inner();",
2720 : {handle(Smi::FromInt(42), isolate)}},
2721 : {"var y = {x:42};"
2722 : " function inner(o) {"
2723 : " var x = 20;"
2724 : " with(o) return x;"
2725 : "}"
2726 : "return inner(y);",
2727 : {handle(Smi::FromInt(42), isolate)}},
2728 16 : };
2729 :
2730 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
2731 : ScopedVector<char> script(1024);
2732 16 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2733 16 : snippets[i].code_snippet, kFunctionName);
2734 :
2735 : BytecodeGraphTester tester(isolate, script.start());
2736 : auto callable = tester.GetCallable<>();
2737 32 : Handle<Object> return_value = callable().ToHandleChecked();
2738 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2739 : }
2740 4 : }
2741 :
2742 26660 : TEST(BytecodeGraphBuilderConstDeclaration) {
2743 8 : HandleAndZoneScope scope;
2744 : Isolate* isolate = scope.main_isolate();
2745 : Factory* factory = isolate->factory();
2746 :
2747 : ExpectedSnippet<0> snippets[] = {
2748 : {"const x = 3; return x;", {handle(Smi::FromInt(3), isolate)}},
2749 : {"let x = 10; x = x + 20; return x;",
2750 : {handle(Smi::FromInt(30), isolate)}},
2751 : {"let x = 10; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
2752 : {"let x; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
2753 : {"let x; return x;", {factory->undefined_value()}},
2754 : {"var x = 10; { let x = 30; } return x;",
2755 : {handle(Smi::FromInt(10), isolate)}},
2756 : {"let x = 10; { let x = 20; } return x;",
2757 : {handle(Smi::FromInt(10), isolate)}},
2758 : {"var x = 10; eval('let x = 20;'); return x;",
2759 : {handle(Smi::FromInt(10), isolate)}},
2760 : {"var x = 10; eval('const x = 20;'); return x;",
2761 : {handle(Smi::FromInt(10), isolate)}},
2762 : {"var x = 10; { const x = 20; } return x;",
2763 : {handle(Smi::FromInt(10), isolate)}},
2764 : {"var x = 10; { const x = 20; return x;} return -1;",
2765 : {handle(Smi::FromInt(20), isolate)}},
2766 : {"var a = 10;\n"
2767 : "for (var i = 0; i < 10; ++i) {\n"
2768 : " const x = i;\n" // const declarations are block scoped.
2769 : " a = a + x;\n"
2770 : "}\n"
2771 : "return a;\n",
2772 : {handle(Smi::FromInt(55), isolate)}},
2773 48 : };
2774 :
2775 : // Tests for sloppy mode.
2776 100 : for (size_t i = 0; i < arraysize(snippets); i++) {
2777 : ScopedVector<char> script(1024);
2778 48 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2779 48 : snippets[i].code_snippet, kFunctionName);
2780 :
2781 : BytecodeGraphTester tester(isolate, script.start());
2782 : auto callable = tester.GetCallable<>();
2783 96 : Handle<Object> return_value = callable().ToHandleChecked();
2784 96 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2785 : }
2786 :
2787 : // Tests for strict mode.
2788 100 : for (size_t i = 0; i < arraysize(snippets); i++) {
2789 : ScopedVector<char> script(1024);
2790 48 : SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
2791 48 : snippets[i].code_snippet, kFunctionName);
2792 :
2793 : BytecodeGraphTester tester(isolate, script.start());
2794 : auto callable = tester.GetCallable<>();
2795 96 : Handle<Object> return_value = callable().ToHandleChecked();
2796 96 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2797 : }
2798 4 : }
2799 :
2800 26660 : TEST(BytecodeGraphBuilderConstDeclarationLookupSlots) {
2801 8 : HandleAndZoneScope scope;
2802 : Isolate* isolate = scope.main_isolate();
2803 : Factory* factory = isolate->factory();
2804 :
2805 : ExpectedSnippet<0> snippets[] = {
2806 : {"const x = 3; function f1() {return x;}; return x;",
2807 : {handle(Smi::FromInt(3), isolate)}},
2808 : {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
2809 : {handle(Smi::FromInt(30), isolate)}},
2810 : {"let x; x = 20; function f1() {return x;}; return x;",
2811 : {handle(Smi::FromInt(20), isolate)}},
2812 : {"let x; function f1() {return x;}; return x;",
2813 : {factory->undefined_value()}},
2814 16 : };
2815 :
2816 : // Tests for sloppy mode.
2817 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
2818 : ScopedVector<char> script(1024);
2819 16 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2820 16 : snippets[i].code_snippet, kFunctionName);
2821 :
2822 : BytecodeGraphTester tester(isolate, script.start());
2823 : auto callable = tester.GetCallable<>();
2824 32 : Handle<Object> return_value = callable().ToHandleChecked();
2825 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2826 : }
2827 :
2828 : // Tests for strict mode.
2829 36 : for (size_t i = 0; i < arraysize(snippets); i++) {
2830 : ScopedVector<char> script(1024);
2831 16 : SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
2832 16 : snippets[i].code_snippet, kFunctionName);
2833 :
2834 : BytecodeGraphTester tester(isolate, script.start());
2835 : auto callable = tester.GetCallable<>();
2836 32 : Handle<Object> return_value = callable().ToHandleChecked();
2837 32 : CHECK(return_value->SameValue(*snippets[i].return_value()));
2838 : }
2839 4 : }
2840 :
2841 26660 : TEST(BytecodeGraphBuilderConstInLookupContextChain) {
2842 8 : HandleAndZoneScope scope;
2843 : Isolate* isolate = scope.main_isolate();
2844 :
2845 : const char* prologue =
2846 : "function OuterMost() {\n"
2847 : " const outerConst = 10;\n"
2848 : " let outerLet = 20;\n"
2849 : " function Outer() {\n"
2850 : " function Inner() {\n"
2851 : " this.innerFunc = function() { ";
2852 : const char* epilogue =
2853 : " }\n"
2854 : " }\n"
2855 : " this.getInnerFunc ="
2856 : " function() {return new Inner().innerFunc;}\n"
2857 : " }\n"
2858 : " this.getOuterFunc ="
2859 : " function() {return new Outer().getInnerFunc();}"
2860 : "}\n"
2861 : "var f = new OuterMost().getOuterFunc();\n"
2862 : "f();\n";
2863 :
2864 : // Tests for let / constant.
2865 : ExpectedSnippet<0> const_decl[] = {
2866 : {"return outerConst;", {handle(Smi::FromInt(10), isolate)}},
2867 : {"return outerLet;", {handle(Smi::FromInt(20), isolate)}},
2868 : {"outerLet = 30; return outerLet;", {handle(Smi::FromInt(30), isolate)}},
2869 : {"var outerLet = 40; return outerLet;",
2870 : {handle(Smi::FromInt(40), isolate)}},
2871 : {"var outerConst = 50; return outerConst;",
2872 : {handle(Smi::FromInt(50), isolate)}},
2873 : {"try { outerConst = 30 } catch(e) { return -1; }",
2874 24 : {handle(Smi::FromInt(-1), isolate)}}};
2875 :
2876 52 : for (size_t i = 0; i < arraysize(const_decl); i++) {
2877 : ScopedVector<char> script(1024);
2878 24 : SNPrintF(script, "%s %s %s", prologue, const_decl[i].code_snippet,
2879 24 : epilogue);
2880 :
2881 : BytecodeGraphTester tester(isolate, script.start(), "*");
2882 : auto callable = tester.GetCallable<>();
2883 48 : Handle<Object> return_value = callable().ToHandleChecked();
2884 48 : CHECK(return_value->SameValue(*const_decl[i].return_value()));
2885 : }
2886 4 : }
2887 :
2888 26660 : TEST(BytecodeGraphBuilderIllegalConstDeclaration) {
2889 8 : HandleAndZoneScope scope;
2890 : Isolate* isolate = scope.main_isolate();
2891 :
2892 : ExpectedSnippet<0, const char*> illegal_const_decl[] = {
2893 : {"const x = x = 10 + 3; return x;",
2894 : {"Uncaught ReferenceError: Cannot access 'x' before initialization"}},
2895 : {"const x = 10; x = 20; return x;",
2896 : {"Uncaught TypeError: Assignment to constant variable."}},
2897 : {"const x = 10; { x = 20; } return x;",
2898 : {"Uncaught TypeError: Assignment to constant variable."}},
2899 : {"const x = 10; eval('x = 20;'); return x;",
2900 : {"Uncaught TypeError: Assignment to constant variable."}},
2901 : {"let x = x + 10; return x;",
2902 : {"Uncaught ReferenceError: Cannot access 'x' before initialization"}},
2903 : {"'use strict'; (function f1() { f1 = 123; })() ",
2904 : {"Uncaught TypeError: Assignment to constant variable."}},
2905 4 : };
2906 :
2907 : // Tests for sloppy mode.
2908 52 : for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
2909 : ScopedVector<char> script(1024);
2910 24 : SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
2911 24 : illegal_const_decl[i].code_snippet, kFunctionName);
2912 :
2913 : BytecodeGraphTester tester(isolate, script.start());
2914 48 : v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
2915 : v8::Local<v8::String> expected_string =
2916 24 : v8_str(illegal_const_decl[i].return_value());
2917 72 : CHECK(
2918 : message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
2919 : .FromJust());
2920 : }
2921 :
2922 : // Tests for strict mode.
2923 52 : for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
2924 : ScopedVector<char> script(1024);
2925 24 : SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
2926 24 : illegal_const_decl[i].code_snippet, kFunctionName);
2927 :
2928 : BytecodeGraphTester tester(isolate, script.start());
2929 48 : v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
2930 : v8::Local<v8::String> expected_string =
2931 24 : v8_str(illegal_const_decl[i].return_value());
2932 72 : CHECK(
2933 : message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
2934 : .FromJust());
2935 : }
2936 4 : }
2937 :
2938 4 : class CountBreakDebugDelegate : public v8::debug::DebugDelegate {
2939 : public:
2940 8 : void BreakProgramRequested(v8::Local<v8::Context> paused_context,
2941 : const std::vector<int>&) override {
2942 8 : debug_break_count++;
2943 8 : }
2944 : int debug_break_count = 0;
2945 : };
2946 :
2947 26660 : TEST(BytecodeGraphBuilderDebuggerStatement) {
2948 4 : CountBreakDebugDelegate delegate;
2949 8 : HandleAndZoneScope scope;
2950 : Isolate* isolate = scope.main_isolate();
2951 :
2952 4 : v8::debug::SetDebugDelegate(CcTest::isolate(), &delegate);
2953 :
2954 : ExpectedSnippet<0> snippet = {
2955 : "function f() {"
2956 : " debugger;"
2957 : "}"
2958 : "f();",
2959 : {isolate->factory()->undefined_value()}};
2960 :
2961 : BytecodeGraphTester tester(isolate, snippet.code_snippet);
2962 : auto callable = tester.GetCallable<>();
2963 8 : Handle<Object> return_value = callable().ToHandleChecked();
2964 :
2965 4 : v8::debug::SetDebugDelegate(CcTest::isolate(), nullptr);
2966 4 : CHECK(return_value.is_identical_to(snippet.return_value()));
2967 4 : CHECK_EQ(2, delegate.debug_break_count);
2968 4 : }
2969 :
2970 : #undef SHARD_TEST_BY_2
2971 : #undef SHARD_TEST_BY_4
2972 : #undef SPACE
2973 : #undef REPEAT_2
2974 : #undef REPEAT_4
2975 : #undef REPEAT_8
2976 : #undef REPEAT_16
2977 : #undef REPEAT_32
2978 : #undef REPEAT_64
2979 : #undef REPEAT_128
2980 : #undef REPEAT_256
2981 : #undef REPEAT_127
2982 :
2983 : } // namespace compiler
2984 : } // namespace internal
2985 79968 : } // namespace v8
|