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