blob: 024747f9f76fbc83f10848dde57bee6064897c1e [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
15namespace v8 {
16namespace internal {
17namespace compiler {
18
Ben Murdoch097c5b22016-05-18 11:27:45 +010019#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); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027
28static const char kFunctionName[] = "f";
29
30static 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
35static const int SMI_MAX = (1 << 30) - 1;
36static const int SMI_MIN = -(1 << 30);
37
38static 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
45template <class... A>
46static 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
56template <class... A>
57class BytecodeGraphCallable {
58 public:
59 BytecodeGraphCallable(Isolate* isolate, Handle<JSFunction> function)
60 : isolate_(isolate), function_(function) {}
61 virtual ~BytecodeGraphCallable() {}
62
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
73class BytecodeGraphTester {
74 public:
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;
Ben Murdoch097c5b22016-05-18 11:27:45 +010081 i::FLAG_loop_assignment_analysis = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 // Ensure handler table is generated.
83 isolate->interpreter()->Initialize();
84 }
85 virtual ~BytecodeGraphTester() {}
86
87 template <class... A>
88 BytecodeGraphCallable<A...> GetCallable(
89 const char* functionName = kFunctionName) {
90 return BytecodeGraphCallable<A...>(isolate_, GetFunction(functionName));
91 }
92
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
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
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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100124 // TODO(mstarzinger): We should be able to prime CompilationInfo without
125 // having to instantiate a ParseInfo first. Fix this!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 ParseInfo parse_info(zone_, function);
127
Ben Murdochc5610432016-08-08 18:44:38 +0100128 CompilationInfo compilation_info(&parse_info, function);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100129 compilation_info.SetOptimizing();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130 compilation_info.MarkAsDeoptimizationEnabled();
Ben Murdochc5610432016-08-08 18:44:38 +0100131 compilation_info.MarkAsOptimizeFromBytecode();
132 Handle<Code> code = Pipeline::GenerateCodeForTesting(&compilation_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 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
172template <int N, typename T = Handle<Object>>
173struct ExpectedSnippet {
174 const char* code_snippet;
175 T return_value_and_parameters[N + 1];
176
177 inline T return_value() const { return return_value_and_parameters[0]; }
178
179 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
187TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100210 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 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
223TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100237 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 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
250TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100295 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000296 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
310TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100339 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 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
353TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100395 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100409void TestBytecodeGraphBuilderNamedStore(size_t shard) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100444 for (size_t i = 0; i < arraysize(snippets); i++) {
445 if ((i % 2) != shard) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100458SHARD_TEST_BY_2(BytecodeGraphBuilderNamedStore)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000459
Ben Murdoch097c5b22016-05-18 11:27:45 +0100460void TestBytecodeGraphBuilderKeyedStore(size_t shard) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100503 for (size_t i = 0; i < arraysize(snippets); i++) {
504 if ((i % 2) != shard) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100517SHARD_TEST_BY_2(BytecodeGraphBuilderKeyedStore)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518
519TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100539 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540 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
553TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100582 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 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
591TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100620 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 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
629TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100647 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648 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
Ben Murdochda12d292016-06-02 14:46:10 +0100656TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100678void TestBytecodeGraphBuilderGlobals(size_t shard) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100718 for (size_t i = 0; i < arraysize(snippets); i++) {
719 if ((i % 2) != shard) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100727SHARD_TEST_BY_2(BytecodeGraphBuilderGlobals)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000728
729TEST(BytecodeGraphBuilderToObject) {
730 // TODO(mythria): tests for ToObject. Needs ForIn.
731}
732
733
734TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100765 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 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
778TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100796 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797 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
810TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100833 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000834 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
847TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100887 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000888 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
901TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100926 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000927 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
940TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100980 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981 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
992TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001016 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 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
1029TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001057 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001058 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
1070TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001100 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 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
1113TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001130 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131 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
1142TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001182 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001183 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
1194TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001210 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001211 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
1223TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001241 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001242 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
1250bool 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
1276const 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
1301TEST(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
1338TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001372 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001373 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
1387TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001404 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001405 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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001417TEST(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
1446TEST(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
1484TEST(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}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001509
1510TEST(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"}},
Ben Murdoch097c5b22016-05-18 11:27:45 +01001522 {"var a = true; if (a) { throw 'Error'; }", {"Uncaught Error"}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001523 };
1524
Ben Murdoch097c5b22016-05-18 11:27:45 +01001525 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001526 ScopedVector<char> script(1024);
1527 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
1528 snippets[i].code_snippet, kFunctionName);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001529
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001530 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
1540TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001587 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 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
1599TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001652 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001653 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
1665TEST(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()}},
Ben Murdoch097c5b22016-05-18 11:27:45 +01001678 {"function f(...restArgs) {return restArgs[0];}",
1679 {factory->undefined_value()}},
1680 {"function f(a, ...restArgs) {return restArgs[0];}",
1681 {factory->undefined_value()}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001682 };
1683
Ben Murdoch097c5b22016-05-18 11:27:45 +01001684 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001685 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
1696TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001727 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001728 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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001742TEST(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}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001784
1785TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001808 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001809 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
1821TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001848 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001849 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
1861TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01001913 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001914 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
1925TEST(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)}},
Ben Murdoch097c5b22016-05-18 11:27:45 +01001990 {"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)}},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002019 };
2020
Ben Murdoch097c5b22016-05-18 11:27:45 +01002021 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002022 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
2035TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01002052 for (size_t i = 0; i < arraysize(snippets); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002053 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
2066TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01002113TEST(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}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002161
2162TEST(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
2223TEST(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
2264TEST(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
2313TEST(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
2350TEST(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
2431TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01002503TEST(BytecodeGraphBuilderForOf) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002504 HandleAndZoneScope scope;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002505 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
2595void 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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002599 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());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002620
2621 HandleAndZoneScope scope;
2622 auto isolate = scope.main_isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002623 auto factory = isolate->factory();
2624 auto zone = scope.main_zone();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002625 BytecodeGraphTester tester(isolate, zone, script.c_str());
2626 auto callable = tester.GetCallable<Handle<Object>>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002627 for (int a = 0; a < 3; a++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002628 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
Ben Murdoch097c5b22016-05-18 11:27:45 +01002636SHARD_TEST_BY_4(JumpWithConstantsAndWideConstants)
2637
2638TEST(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
2670TEST(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
2707TEST(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
2766TEST(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
2808TEST(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 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002854}
2855
2856TEST(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
Ben Murdoch097c5b22016-05-18 11:27:45 +01002907TEST(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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002938} // namespace compiler
2939} // namespace internal
2940} // namespace v8