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